dotfiles/hosts/h001/mods/openbao.nix
RingOfStorms (Joshua Bell) 1b4a53b10e attempt auto unseal
2025-12-07 22:45:53 -06:00

132 lines
3.5 KiB
Nix

{
config,
pkgs,
...
}:
{
environment.variables = {
# For CLI
BAO_ADDR = "http://127.0.0.1:8200";
};
services.nginx = {
virtualHosts = {
"sec.joshuabell.xyz" = {
addSSL = true;
sslCertificate = "/var/lib/acme/joshuabell.xyz/fullchain.pem";
sslCertificateKey = "/var/lib/acme/joshuabell.xyz/key.pem";
locations."/" = {
proxyWebsockets = true;
proxyPass = "http://localhost:8200";
recommendedProxySettings = true;
};
};
};
};
services.openbao = {
enable = true;
package = pkgs.openbao;
settings = {
ui = true;
listener.default = {
type = "tcp";
address = "127.0.0.1:8200";
tls_disable = true; # nginx will handle TLS
};
storage.file = {
path = "/var/lib/openbao";
};
# Disable mlock requirement for development
# In production, you may want to enable this
disable_mlock = true;
};
};
# Ensure the data directory exists with proper permissions
# systemd.tmpfiles.rules = [
# "d /var/lib/openbao 0700 openbao openbao - -"
# ];
# Additional systemd service hardening
systemd.services.openbao = {
serviceConfig = {
# Security hardening
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [ "/var/lib/openbao" ];
# Resource limits
LimitNOFILE = 65536;
LimitNPROC = 4096;
};
};
# AUTO UNSEAL
systemd.services.openbao-auto-unseal = {
description = "Auto-unseal OpenBao using stored unseal key shares";
after = [ "openbao.service" ];
wants = [ "openbao.service" ];
# Run once at boot; doesn't restart
serviceConfig = {
Type = "oneshot";
# run as the same user as the openbao service
# User = config.systemd.services.openbao.User;
# Group = config.systemd.services.openbao.Group;
# /run/keys/... are usually readable by root only; you might prefer to run as root
User = "root";
Group = "root";
# Only needs network access to 127.0.0.1
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadOnlyPaths = [ "/" ];
# allow reading /run/keys and talking to localhost
ReadWritePaths = [ "/run" ];
NoNewPrivileges = true;
ExecStart = pkgs.writeShellScript "openbao-auto-unseal" ''
#!/usr/bin/env bash
set -euo pipefail
export BAO_ADDR="http://127.0.0.1:8200"
# Wait for OpenBao to be listening
# (systemd "after" ensures start order but not readiness)
for i in {1..30}; do
if bao status >/dev/null 2>&1; then
break
fi
sleep 1
done
# If it's already unsealed, exit
if bao status 2>/dev/null | grep -q 'sealed *false'; then
exit 0
fi
# Apply each unseal key share; ignore "already unsealed" errors
# TODO change this back to /run/agenix instead of /root/bao-keys
for key in /root/bao-keys/openbao-unseal-*; do
if [ -f "$key" ]; then
bao operator unseal "$(cat "$key")" || true
fi
done
# Check final status; fail if still sealed
if bao status 2>/dev/null | grep -q 'sealed *true'; then
echo "OpenBao is still sealed after applying unseal keys" >&2
exit 1
fi
'';
};
wantedBy = [ "multi-user.target" ];
};
}