Begin moving openbao and authentik server to new setup

Former-commit-id: 8cd2737aca
This commit is contained in:
Kaare Hoff Skovgaard 2025-07-14 23:34:02 +02:00
parent 3a42f156f7
commit 7a995baca4
43 changed files with 1006 additions and 481 deletions

View file

@ -0,0 +1,5 @@
# 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).
After this, run the post provisioning script to initialize the various OpenBAO parts needed. Then `nix run '.#bitwarden-to-vault` can transfer the needed Bitwarden secrets to vault.

View file

@ -0,0 +1,61 @@
# { 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

@ -0,0 +1,33 @@
{
inputs,
...
}:
{
imports = [
"${inputs.self}/nix/profiles/nixos/hetzner-server.nix"
./authentik.nix
./openbao.nix
./post/openbao
];
khscodes.services.nginx.enable = true;
khscodes.infrastructure.hetzner-instance = {
enable = true;
server_type = "cax11";
};
virtualisation.vmVariant.virtualisation.host.pkgs = import inputs.nixpkgs {
system = "aarch64-darwin";
};
# Cannot use vault for secrets source, as this is the server containing vault.
khscodes.infrastructure.provisioning.pre.secretsSource = "bitwarden";
khscodes.infrastructure.provisioning.post.secretsSource = "bitwarden";
khscodes.infrastructure.vault-server-approle.stage = "post";
khscodes.networking.fqdn = "security.kaareskovgaard.net";
users.users.khs = {
initialPassword = "changeme";
openssh.authorizedKeys.keys = [
"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";
system.stateVersion = "25.05";
}

View file

@ -0,0 +1,51 @@
{ pkgs, config, ... }:
let
domain = "vault-test.kaareskovgaard.net";
in
{
config = {
services.openbao = {
enable = true;
package = pkgs.openbao;
settings = {
ui = true;
listener.tcp = {
type = "tcp";
tls_cert_file = "${config.security.acme.certs.${domain}.directory}/fullchain.pem";
tls_key_file = "${config.security.acme.certs.${domain}.directory}/key.pem";
};
api_addr = "https://${domain}";
storage.postgresql.connection_url = "postgres://openbao?host=/run/postgresql";
};
};
security.acme.certs.${domain}.reloadServices = [ "openbao.service" ];
systemd.services.openbao.after = [ "postgresql.service" ];
# Allow openbao to read the certificate file
users.groups.nginx.members = [ "openbao" ];
services.postgresql = {
enable = true;
ensureDatabases = [ "openbao" ];
ensureUsers = [
{
name = "openbao";
ensureDBOwnership = true;
}
];
};
services.postgresqlBackup = {
enable = true;
databases = [ "openbao" ];
};
khscodes.services.nginx.virtualHosts.${domain} = {
locations."/" = {
proxyPass = "https://${config.services.openbao.settings.listener.tcp.address}/";
recommendedProxySettings = true;
};
};
};
}

View file

@ -0,0 +1,10 @@
{
khscodes.infrastructure.vault-server-approle.path = "\${ vault_auth_backend.approle.path }";
khscodes.infrastructure.provisioning.post.modules = [
{
resource.vault_auth_backend.approle = {
type = "approle";
};
}
];
}

View file

@ -0,0 +1,29 @@
{
imports = [
./approle.nix
./ssh-host.nix
./loki-mtls.nix
./prometheus-mtls.nix
];
khscodes.infrastructure.vault-server-approle.path = "\${ vault_auth_backend.approle.path }";
khscodes.infrastructure.provisioning.post.modules = [
(
{ config, ... }:
{
khscodes.vault.mount.opentofu = {
path = "opentofu";
type = "kv";
options = {
version = "2";
};
description = "Secrets used during provisioning";
};
resource.vault_kv_secret_backend_v2.opentofu = {
mount = config.khscodes.vault.output.mount.opentofu.path;
max_versions = 5;
cas_required = false;
};
}
)
];
}

View file

@ -0,0 +1,26 @@
# This should go into the setup of the vault server itself, as the vault server also needs stuff that depends on this.
{
khscodes.infrastructure.vault-loki-sender = {
terranixBackendName = "\${ vault_mount.loki-mtls.path }";
};
khscodes.infrastructure.provisioning.post.modules = [
(
{ config, ... }:
{
khscodes.vault.enable = true;
khscodes.vault.mount.loki-mtls = {
type = "pki";
path = "loki-mtls";
max_lease_ttl_seconds = 10 * 365 * 24 * 60 * 60;
default_lease_ttl_seconds = 60 * 60;
};
khscodes.vault.pki_secret_backend_root_cert.loki-mtls = {
backend = config.khscodes.vault.output.mount.loki-mtls.path;
type = "internal";
common_name = "loki.kaareskovgaard.net";
issuer_name = "loki-mtls-root-ca";
};
}
)
];
}

View file

@ -0,0 +1,27 @@
# This should go into the setup of the vault server itself, as the vault server also needs stuff that depends on this.
{
khscodes.infrastructure.vault-prometheus-sender = {
# This is quite ugly, but should get the job done. Sadly I cannot reference the output from here.
terranixBackendName = "\${ vault_mount.prometheus-mtls.path }";
};
khscodes.infrastructure.provisioning.post.modules = [
(
{ config, ... }:
{
khscodes.vault.enable = true;
khscodes.vault.mount.prometheus-mtls = {
type = "pki";
path = "prometheus-mtls";
max_lease_ttl_seconds = 10 * 365 * 24 * 60 * 60;
default_lease_ttl_seconds = 60 * 60;
};
khscodes.vault.pki_secret_backend_root_cert.prometheus-mtls = {
backend = config.khscodes.vault.output.mount.prometheus-mtls.path;
type = "internal";
common_name = "prometheus.kaareskovgaard.net";
issuer_name = "prometheus-mtls-root-ca";
};
}
)
];
}

View file

@ -0,0 +1,22 @@
{
khscodes.services.openssh.hostCertificate.path = "\${ vault_mount.ssh-host.path }";
khscodes.infrastructure.provisioning.post.modules = [
(
{ config, ... }:
{
khscodes.vault.mount.ssh-host = {
type = "ssh";
path = "ssh-host";
default_lease_ttl_seconds = 24 * 60 * 60;
max_lease_ttl_seconds = 24 * 60 * 60;
};
resource.vault_ssh_secret_backend_ca.ssh-host = {
backend = config.khscodes.vault.output.mount.ssh-host.path;
generate_signing_key = true;
key_type = "ed25519";
};
}
)
];
}