Begin setting up authentication and secrets engine
Some checks failed
/ dev-shell (push) Successful in 1m9s
/ rust-packages (push) Successful in 4m36s
/ check (push) Failing after 5m57s
/ systems (push) Successful in 27m33s
/ terraform-providers (push) Successful in 12m41s

This commit is contained in:
Kaare Hoff Skovgaard 2025-07-17 01:20:19 +02:00
parent 81551dd791
commit f3175b9b03
Signed by: khs
GPG key ID: C7D890804F01E9F0
20 changed files with 430 additions and 258 deletions

172
flake.lock generated
View file

@ -16,58 +16,6 @@
"type": "github"
}
},
"authentik-nix": {
"inputs": {
"authentik-src": "authentik-src",
"flake-compat": "flake-compat",
"flake-parts": [
"flake-parts"
],
"flake-utils": [
"flake-utils"
],
"napalm": "napalm",
"nixpkgs": [
"nixpkgs"
],
"pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix",
"systems": [
"systems"
],
"uv2nix": "uv2nix"
},
"locked": {
"lastModified": 1751033152,
"narHash": "sha256-0ANu9OLQJszcEyvnfDB7G957uqskZwCrTzRXz/yfAmE=",
"owner": "nix-community",
"repo": "authentik-nix",
"rev": "1a4d6a5dd6fef39b99eb7ea4db79c5d5c7d7f1bf",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "authentik-nix",
"type": "github"
}
},
"authentik-src": {
"flake": false,
"locked": {
"lastModified": 1751031262,
"narHash": "sha256-SNgRMQUjL3DTlWkMyRMan+pY1FfIV+DMeq5BiTM0N0k=",
"owner": "goauthentik",
"repo": "authentik",
"rev": "b34665fabd8d938d81ce871a4e86ca528c5f253b",
"type": "github"
},
"original": {
"owner": "goauthentik",
"ref": "version/2025.4.3",
"repo": "authentik",
"type": "github"
}
},
"base16": {
"inputs": {
"fromYaml": "fromYaml"
@ -237,22 +185,6 @@
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1650374568,
@ -397,32 +329,6 @@
"type": "github"
}
},
"napalm": {
"inputs": {
"flake-utils": [
"authentik-nix",
"flake-utils"
],
"nixpkgs": [
"authentik-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1725806412,
"narHash": "sha256-lGZjkjds0p924QEhm/r0BhAxbHBJE1xMOldB/HmQH04=",
"owner": "willibutz",
"repo": "napalm",
"rev": "b492440d9e64ae20736d3bec5c7715ffcbde83f5",
"type": "github"
},
"original": {
"owner": "willibutz",
"ref": "avoid-foldl-stack-overflow",
"repo": "napalm",
"type": "github"
}
},
"nix-vm-test": {
"inputs": {
"nixpkgs": [
@ -575,60 +481,9 @@
"type": "github"
}
},
"pyproject-build-systems": {
"inputs": {
"nixpkgs": [
"authentik-nix",
"nixpkgs"
],
"pyproject-nix": [
"authentik-nix",
"pyproject-nix"
],
"uv2nix": [
"authentik-nix",
"uv2nix"
]
},
"locked": {
"lastModified": 1749519371,
"narHash": "sha256-UJONN7mA2stweZCoRcry2aa1XTTBL0AfUOY84Lmqhos=",
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"rev": "7c06967eca687f3482624250428cc12f43c92523",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"type": "github"
}
},
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"authentik-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1750499893,
"narHash": "sha256-ThKBd8XSvITAh2JqU7enOp8AfKeQgf9u7zYC41cnBE4=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "e824458bd917b44bf4c38795dea2650336b2f55d",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github"
}
},
"root": {
"inputs": {
"advisory-db": "advisory-db",
"authentik-nix": "authentik-nix",
"cosmic-manager": "cosmic-manager",
"crane": "crane",
"disko": "disko",
@ -668,7 +523,7 @@
},
"snowfall-lib": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-compat": "flake-compat",
"flake-utils-plus": "flake-utils-plus",
"nixpkgs": [
"flake-base",
@ -945,31 +800,6 @@
"repo": "treefmt-nix",
"type": "github"
}
},
"uv2nix": {
"inputs": {
"nixpkgs": [
"authentik-nix",
"nixpkgs"
],
"pyproject-nix": [
"authentik-nix",
"pyproject-nix"
]
},
"locked": {
"lastModified": 1750987094,
"narHash": "sha256-GujDElxLgYatnNvuL1U6qd18lcuG6anJMjpfYRScV08=",
"owner": "pyproject-nix",
"repo": "uv2nix",
"rev": "4b703d851b61e664a70238711a8ff0efa1aa2f52",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "uv2nix",
"type": "github"
}
}
},
"root": "root",

View file

@ -2,15 +2,6 @@
description = "A very basic flake";
inputs = {
authentik-nix = {
url = "github:nix-community/authentik-nix";
inputs = {
flake-utils.follows = "flake-utils";
nixpkgs.follows = "nixpkgs";
flake-parts.follows = "flake-parts";
systems.follows = "systems";
};
};
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
flake-base = {
url = "git+https://khs.codes/nix/flake-base";
@ -108,7 +99,6 @@
inputNixosModules = [
inputs.disko.nixosModules.disko
inputs.stylix.nixosModules.stylix
inputs.authentik-nix.nixosModules.default
];
inputHomeModules = [
inputs.cosmic-manager.homeManagerModules.cosmic-manager

View file

@ -3,7 +3,7 @@
options.khscodes.infrastructure.openbao = {
domain = lib.mkOption {
type = lib.types.str;
default = "vault.kaareskovgaard.net";
default = "secrets.kaareskovgaard.net";
};
};
}

View file

@ -100,6 +100,7 @@ in
role_name = config.khscodes.vault.output.approle_auth_backend_role.${cfg.role_name}.role_name;
# Should only be 5-10 mins once done testing
wrapping_ttl = 5 * 60;
num_uses = 0;
# This should simply mean that we never attempt to recreate the secret id, as we don't want a rerun of the
# provisioning to invalidate the existing secret id, nor recreate the entire server.

View file

@ -0,0 +1,31 @@
{ pkgs, ... }:
pkgs.writeShellApplication {
name = "bao-import-secret";
runtimeInputs = [
pkgs.openbao
pkgs.uutils-coreutils-noprefix
];
text = ''
role_id="''${1:-}"
wrapped_secret_id="''${2:-}"
if [[ "$role_id" == "" || "$wrapped_secret_id" == "" ]]; then
>&2 echo "Usage: bao-import-secret <role-id> <wrapped-secret-id>"
exit 1
fi
if [[ "$(id -u)" != "0" ]]; then
>&2 echo "Must run as root"
exit 2
fi
secret_id="$(bao unwrap -field=secret_id "$wrapped_secret_id")"
mkdir -p /var/lib/vault-agent
touch /var/lib/vault-agent/role-id
touch /var/lib/vault-agent/secret-id
chmod 0600 /var/lib/vault-agent/role-id
chmod 0600 /var/lib/vault-agent/secret-id
echo -n "$role_id" > /var/lib/vault-agent/role-id
echo -n "$secret_id" > /var/lib/vault-agent/secret-id
systemctl restart vault-agent-openbao.service
'';
}

View file

@ -25,7 +25,7 @@
"AUTHENTIK_TOKEN" = "Admin API Token";
"TF_VAR_authentik_username" = "login.username";
};
"vault.kaareskovgaard.net" = {
"secrets.kaareskovgaard.net" = {
"VAULT_TOKEN" = "Initial root token";
};
}

View file

@ -0,0 +1,10 @@
{ pkgs, ... }:
pkgs.writeShellApplication {
name = "configure-instance";
runtimeInputs = [ pkgs.khscodes.post-provisioning ];
text = ''
instance="''${1:-}"
cmd="''${2:-apply}"
post-provisioning "$instance" "$cmd"
'';
}

View file

@ -5,4 +5,5 @@ pkgs.opentofu.withPlugins (p: [
pkgs.khscodes.terraform-provider-hcloud
pkgs.khscodes.terraform-provider-openstack
pkgs.khscodes.terraform-provider-vault
pkgs.khscodes.terraform-provider-random
])

View file

@ -3,7 +3,7 @@
pkgs,
}:
pkgs.writeShellApplication {
name = "pre-provisioning";
name = "post-provisioning";
runtimeInputs = [
pkgs.nix
pkgs.khscodes.bw-opentofu
@ -19,7 +19,7 @@ pkgs.writeShellApplication {
secretsSource="$(nix eval --raw "''${baseAttr}.post.secretsSource")"
endpoints="$(nix eval --show-trace --json "''${baseAttr}.postEndpoints")"
if [[ "$config" == "null" ]]; then
echo "No preprovisioning needed"
echo "No postprovisioning needed"
exit 0
fi
if [[ "$secretsSource" == "vault" ]]; then

View file

@ -0,0 +1,10 @@
{ pkgs }:
pkgs.terraform-providers.mkProvider {
hash = "sha256-tdTVqSJmQ6Ht3kdoYMxhoRN+XJqvu8BPVB0VQghcDVs=";
homepage = "https://registry.terraform.io/providers/hashicorp/random";
owner = "hashicorp";
repo = "terraform-provider-random";
rev = "v3.7.2";
spdx = "MPL-2.0";
vendorHash = "sha256-jyfzk3vbgZwHlyiFFw1mhD+us/7WNatUQTGN4WsrfgE=";
}

View file

@ -1,7 +1,12 @@
{ pkgs, config, ... }:
{
pkgs,
config,
lib,
...
}:
{
imports = [ ./nix-base.nix ];
snowfallorg.users.khs.admin = true;
snowfallorg.users.khs.admin = lib.mkDefault true;
users.users.khs = {
# TODO: Figure out how to provision password changes to servers from VAULT
initialPassword = "changeme";

View file

@ -1,6 +1,6 @@
{ lib, pkgs, ... }:
{
imports = [ ./nix-base.nix ];
imports = [ ./khs-base.nix ];
config = {
khscodes = {
services.openssh.enable = true;

View file

@ -9,6 +9,6 @@
mapRdns = true;
server_type = "cax11";
};
khscodes.networking.fqdn = "khs.codes";
khscodes.networking.fqdn = "kas.codes";
system.stateVersion = "25.05";
}

View file

@ -1,7 +1,25 @@
# After creating the instance
Open https://vault.kaareskovgaard.net and initialize OpenBAO. Remember to get some sort of auto unsealing set up afterwards, currently this is implemented with a cronjob on TrueNAS. Doing it this way allows various certificates to continue getting issued, even as OpenBAO gets sealed (due to auto updates).
Open https://secrets.kaareskovgaard.net and initialize OpenBAO. Remember to get some sort of auto unsealing set up afterwards, currently this is implemented with a cronjob on TrueNAS. Doing it this way allows various certificates to continue getting issued, even as OpenBAO gets sealed (due to auto updates).
After this, run the post provisioning script to initialize the various OpenBAO parts needed.
In order for `security.kaareskovgaard.net` to authenticate itself with OpenBAO
Then `nix run '.#bitwarden-to-vault` can transfer the needed Bitwarden secrets to vault.
After this, configure the OpenBAO instance with:
```bash
nix run '.#configure-instance` -- security.kaareskovgaard.net
```
In order for `security.kaareskovgaard.net` to authenticate itself with OpenBAO, the printed credentials needs to be passed to the server with (on the server):
```bash
sudo bao-import-secret <role-id> <wrapped-secret-id>
```
While still SSH'ed into the server, reset the user (khs) password for kanidm:
```bash
kanidm-reset-password <user>
```
Open https://login.kaareskovgaard.net - and log into the account, setting up the Yubikey (Passkey) auth, as well as Bitwarden based TOTP/password auth.
Then `nix run '.#bitwarden-to-vault` can transfer the needed Bitwarden secrets to vault, enabling other instances to not rely on Bitwarden.

View file

@ -1,60 +0,0 @@
{ config, ... }:
let
secretsFile = "/var/lib/authentik/authentik-env";
domain = "auth-test.kaareskovgaard.net";
in
{
config = {
khscodes.nix.nix-community.enable = true;
services.authentik = {
enable = true;
environmentFile = secretsFile;
settings = {
email = {
host = "smtp.soverin.net";
port = 587;
username = "kaare@kaareskovgaard.net";
use_tls = true;
use_ssl = false;
from = "kaare@kaareskovgaard.net";
};
disable_startup_analytics = true;
avatars = "initials";
};
};
khscodes.services.nginx.virtualHosts.${domain} = {
locations."/" = {
proxyPass = "https://localhost:9443";
recommendedProxySettings = true;
};
};
services.postgresqlBackup = {
enable = true;
databases = [ "authentik" ];
};
systemd.services = {
authentik-migrate = {
unitConfig = {
ConditionPathExists = secretsFile;
};
};
authentik-worker = {
unitConfig = {
ConditionPathExists = secretsFile;
};
serviceConfig = {
LoadCredential = [
"${domain}.pem:${config.security.acme.certs.${domain}.directory}/fullchain.pem"
"${domain}.key:${config.security.acme.certs.${domain}.directory}/key.pem"
];
};
};
authentik = {
unitConfig = {
ConditionPathExists = secretsFile;
};
};
};
};
}

View file

@ -1,14 +1,16 @@
{
inputs,
pkgs,
...
}:
{
imports = [
"${inputs.self}/nix/profiles/nixos/hetzner-server.nix"
./authentik.nix
./kanidm.nix
./openbao.nix
./post/openbao
./post
];
environment.systemPackages = [ pkgs.khscodes.bao-import-secret ];
khscodes.services.nginx.enable = true;
khscodes.infrastructure.hetzner-instance = {
enable = true;
@ -25,6 +27,6 @@
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqY0FHnWFKfLG2yfgr4qka5sR9CK+EMAhzlHUkaQyWHTKD+G0/vC/fNPyL1VV3Dxc/ajxGuPzVE+mBMoyxazL3EtuCDOVvHJ5CR+MUSEckg/DDwcGHqy6rC8BvVVpTAVL04ByQdwFnpE1qNSBaQLkxaFVdtriGKkgMkc7+UNeYX/bv7yn+APqfP1a3xr6wdkSSdO8x4N2jsSygOIMx10hLyCV4Ueu7Kp8Ww4rGY8j5o7lKJhbgfItBfSOuQHdppHVF/GKYRhdnK6Y2fZVYbhq4KipUtclbZ6O/VYd8/sOO98+LMm7cOX+K35PQjUpYgcoNy5+Sw3CNS/NHn4JvOtTaUEYP7fK6c9LhMULOO3T7Cm6TMdiFjUKHkyG+s2Mu/LXJJoilw571zwuh6chkeitW8+Ht7k0aPV96kNEvTdoXwLhBifVEaChlAsLAzSUjUq+YYCiXVk0VIXCZQWKj8LoVNTmaqDksWwbcT64fw/FpVC0N18WHbKcFUEIW/O4spJMa30CQwf9FeqpoWoaF1oRClCSDPvX0AauCu0JcmRinz1/JmlXljnXWbSfm20/V+WyvktlI0wTD0cdpNuSasT9vS77YfJ8nutcWWZKSkCj4R4uHeCNpDTX5YXzapy7FxpM9ANCXLIvoGX7Yafba2Po+er7SSsUIY1AsnBBr8ZoDVw=="
];
};
khscodes.infrastructure.openbao.domain = "vault-test.kaareskovgaard.net";
khscodes.infrastructure.openbao.domain = "secrets.kaareskovgaard.net";
system.stateVersion = "25.05";
}

View file

@ -0,0 +1,314 @@
{ config, pkgs, ... }:
let
domain = "login.kaareskovgaard.net";
openbaoAppBasicSecretFile = "/var/lib/vault-agent/kanidm/openbao_basic_secret";
openbaoDomain = config.khscodes.infrastructure.openbao.domain;
openbaoAllowedRedirectUrls = [
"https://${openbaoDomain}/ui/vault/auth/oidc/oidc/callback"
"https://${openbaoDomain}/oidc/callback"
"http://localhost:8250/oidc/callback"
];
kanidm-reset-password = pkgs.writeShellApplication {
name = "kanidm-reset-password";
runtimeInputs = [
config.services.kanidm.package
pkgs.jq
pkgs.gnugrep
pkgs.expect
];
text = ''
username="''${1:-}"
if [[ "$username" == "" ]]; then
>&2 echo "Usage kanidm-reset-password <username>"
exit 1
fi
echo "Resetting password for idm_admin, please provide sudo password"
password="$(sudo -u kanidm kanidmd recover-account -c /etc/kanidm/server.toml -o json idm_admin 2> /dev/null | grep '^{' | jq --raw-output '.password')"
expect <<EOD
spawn kanidm login --url https://login.kaareskovgaard.net --name idm_admin
expect "Enter password"
send "$password\n"
expect eof
EOD
kanidm person credential create-reset-token --url https://login.kaareskovgaard.net "$username"
trap "kanidm logout --url https://login.kaareskovgaard.net" EXIT
'';
};
in
{
services.kanidm = {
enableServer = true;
# Verify upgrade will be successful by running `kanidmd domain upgrade-check` before bumping package version.
package = pkgs.kanidmWithSecretProvisioning_1_6;
serverSettings = {
inherit domain;
tls_chain = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
tls_key = "${config.security.acme.certs.${domain}.directory}/key.pem";
origin = "https://${domain}";
trust_x_forward_for = true;
};
provision = {
enable = true;
idmAdminPasswordFile = null;
adminPasswordFile = null;
acceptInvalidCerts = true;
persons.khs = {
present = true;
mailAddresses = [ "kaare@kaareskovgaard.net" ];
legalName = "Kaare Skovgaard";
displayName = "khs";
};
groups.openbao_admin = {
present = true;
members = [ "khs" ];
};
systems.oauth2.openbao = {
present = true;
public = false;
preferShortUsername = true;
basicSecretFile = openbaoAppBasicSecretFile;
originUrl = openbaoAllowedRedirectUrls;
originLanding = "https://${openbaoDomain}";
displayName = "OpenBAO";
scopeMaps = {
"openbao_admin" = [
"profile"
"email"
"openid"
];
};
claimMaps.groups = {
joinType = "array";
valuesByGroup = {
"openbao_admin" = [
"openbao_reader"
"openbao_writer"
"openbao_sudo"
];
};
};
};
};
};
systemd.services.kanidm = {
unitConfig = {
ConditionPathExists = [
openbaoAppBasicSecretFile
];
};
};
# Allow the server to read the secrets for its own apps
khscodes.infrastructure.vault-server-approle.policy."kanidm/data/apps/*" = {
capabilities = [ "read" ];
};
khscodes.infrastructure.provisioning.post.modules = [
# Creates mount for kanidm apps and generates random passwords for the apps
(
{ config, ... }:
{
terraform.required_providers.random = {
source = "hashicorp/random";
version = "3.7.2";
};
provider.random = { };
# NOTE: This gets stored in the state file
resource.random_password.openbao_secret = {
length = 48;
numeric = true;
lower = true;
upper = true;
special = false;
};
khscodes.vault = {
enable = true;
mount.kanidm = {
path = "kanidm";
type = "kv";
options = {
version = "2";
};
description = "Secrets used for kanidm";
};
};
resource.vault_kv_secret_v2.openbao_secret = {
mount = config.khscodes.vault.output.mount.kanidm.path;
name = "apps/openbao";
data_json = ''
{ "basic_secret": "''${ resource.random_password.openbao_secret.result }" }
'';
};
}
)
# Sets up OIDC authentication within OpenBAO
{
resource.vault_jwt_auth_backend.oidc = {
description = "Kanidm auth backend";
path = "oidc";
type = "oidc";
oidc_discovery_url = "https://${domain}/oauth2/openid/openbao";
oidc_client_id = "openbao";
oidc_client_secret = "\${ resource.random_password.openbao_secret.result }";
jwt_supported_algs = [
"ES256"
];
tune = [
{
listing_visibility = "unauth";
default_lease_ttl = "2h";
max_lease_ttl = "2h";
token_type = "default-service";
passthrough_request_headers = [ ];
allowed_response_headers = [ ];
audit_non_hmac_request_keys = [ ];
audit_non_hmac_response_keys = [ ];
}
];
};
resource.vault_jwt_auth_backend_role.oidc_reader = {
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
role_name = "reader";
bound_audiences = [ "openbao" ];
allowed_redirect_uris = openbaoAllowedRedirectUrls;
user_claim = "sub";
token_policies = [ "reader" ];
groups_claim = "groups";
oidc_scopes = [
"openid"
"profile"
"email"
];
};
resource.vault_jwt_auth_backend_role.oidc_writer = {
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
role_name = "writer";
bound_audiences = [ "openbao" ];
allowed_redirect_uris = openbaoAllowedRedirectUrls;
user_claim = "sub";
token_policies = [ "writer" ];
groups_claim = "groups";
oidc_scopes = [
"openid"
"profile"
"email"
];
};
resource.vault_jwt_auth_backend_role.oidc_sudo = {
backend = "\${ resource.vault_jwt_auth_backend.oidc.path }";
role_name = "sudo";
bound_audiences = [ "openbao" ];
allowed_redirect_uris = openbaoAllowedRedirectUrls;
user_claim = "sub";
token_policies = [ "sudo" ];
groups_claim = "groups";
oidc_scopes = [
"openid"
"profile"
"email"
];
};
resource.vault_identity_group.reader = {
name = "reader";
policies = [ "reader" ];
type = "external";
};
resource.vault_identity_group.writer = {
name = "writer";
policies = [ "writer" ];
type = "external";
};
resource.vault_identity_group.sudo = {
name = "sudo";
policies = [ "sudo" ];
type = "external";
};
resource.vault_identity_group_alias.reader = {
name = "openbao_reader";
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
canonical_id = "\${ vault_identity_group.reader.id }";
};
resource.vault_identity_group_alias.writer = {
name = "openbao_writer";
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
canonical_id = "\${ vault_identity_group.writer.id }";
};
resource.vault_identity_group_alias.sudo = {
name = "openbao_sudo";
mount_accessor = "\${ vault_jwt_auth_backend.oidc.accessor }";
canonical_id = "\${ vault_identity_group.writer.id }";
};
resource.vault_policy.reader = {
name = "reader";
policy = ''
path "*" {
capabilities = ["read", "list"]
}
'';
};
resource.vault_policy.writer = {
name = "writer";
policy = ''
path "*" {
capabilities = ["create", "update", "patch", "read", "delete", "list"]
}
'';
};
resource.vault_policy.sudo = {
name = "sudo";
policy = ''
path "auth/token/create" {
capabilities = ["create", "update", "sudo"]
}
'';
};
}
];
khscodes.services.vault-agent.templates = [
{
contents = ''
{{- with secret "kanidm/data/apps/openbao" -}}
{{ .Data.data.basic_secret }}
{{- end -}}
'';
destination = openbaoAppBasicSecretFile;
perms = "0600";
owner = "kanidm";
group = "kanidm";
reloadOrRestartUnits = [ "kanidm.service" ];
}
];
security.acme.certs.${domain}.reloadServices = [ "kanidm.service" ];
# Allow kanidm to read the certificate file
users.groups.nginx.members = [ "kanidm" ];
khscodes.services.nginx.virtualHosts.${domain} = {
locations."/" = {
proxyPass = "https://${config.services.kanidm.serverSettings.bindaddress}/";
recommendedProxySettings = true;
};
};
environment.systemPackages = [
kanidm-reset-password
];
}

View file

@ -0,0 +1,17 @@
{ inputs, ... }:
{
imports = [ ./openbao ];
khscodes.infrastructure.provisioning.post.modules = [
{
imports = [
inputs.self.terranixModules.s3
];
khscodes.s3 = {
enable = true;
bucket = {
key = "security.kaareskovgaard.net-configuration.tfstate";
};
};
}
];
}

View file

@ -51,7 +51,10 @@ fn configure() -> anyhow::Result<()> {
if ipv4.is_some_and(|v| v) {
cmd.arg("-4");
}
cmd.args(["addr", "add", &address, "dev", &m.name]);
// Apparently the configuration used renames the eth0 device to enp1s0, I should really figure out why this happens, but for now
// this will do.
let dev_name = if m.name == "eth0" { "enp1s0" } else { &m.name };
cmd.args(["addr", "add", &address, "dev", dev_name]);
cmd.try_spawn_to_string()?;
let mut cmd = common::proc::Command::new("ip");
if ipv6.is_some_and(|v| v) {
@ -60,7 +63,7 @@ fn configure() -> anyhow::Result<()> {
if ipv4.is_some_and(|v| v) {
cmd.arg("-4");
}
cmd.args(["route", "add", "default", "via", &gateway, "dev", &m.name]);
cmd.args(["route", "add", "default", "via", &gateway, "dev", dev_name]);
cmd.try_spawn_to_string()?;
}
metadata::InstanceNetworkConfigConfigSubnet::Dhcp {} => continue,