vault: add auto-unseal
All checks were successful
Run nix flake check / flake-check (push) Successful in 2m16s

This commit is contained in:
2026-02-01 23:39:11 +01:00
parent 3f2f91aedd
commit c694b9889a
3 changed files with 302 additions and 1 deletions

38
services/vault/README.md Normal file
View File

@@ -0,0 +1,38 @@
# OpenBao Service Module
NixOS service module for OpenBao (open-source Vault fork) with TPM2-based auto-unsealing.
## Features
- TLS-enabled TCP listener on `0.0.0.0:8200`
- Unix socket listener at `/run/openbao/openbao.sock`
- File-based storage at `/var/lib/openbao`
- TPM2 auto-unseal on service start
## Configuration
The module expects:
- TLS certificate: `/var/lib/openbao/cert.pem`
- TLS private key: `/var/lib/openbao/key.pem`
- TPM2-encrypted unseal key: `/var/lib/openbao/unseal-key.cred`
Certificates are loaded via systemd `LoadCredential`, and the unseal key via `LoadCredentialEncrypted`.
## Setup
For initial setup and configuration instructions, see:
- **Auto-unseal setup**: `/docs/vault/auto-unseal.md`
- **Terraform configuration**: `/terraform/vault/README.md`
## Usage
```bash
# Check seal status
bao status
# Manually seal (for maintenance)
bao operator seal
# Service will auto-unseal on restart
systemctl restart openbao
```

View File

@@ -1,4 +1,83 @@
{ ... }:
{ pkgs, ... }:
let
unsealScript = pkgs.writeShellApplication {
name = "openbao-unseal";
runtimeInputs = with pkgs; [
openbao
coreutils
gnugrep
getent
];
text = ''
# Set environment to use Unix socket
export BAO_ADDR='unix:///run/openbao/openbao.sock'
SOCKET_PATH="/run/openbao/openbao.sock"
CREDS_DIR="''${CREDENTIALS_DIRECTORY:-}"
# Wait for socket to exist
echo "Waiting for OpenBao socket..."
for _ in {1..30}; do
if [ -S "$SOCKET_PATH" ]; then
echo "Socket exists"
break
fi
sleep 1
done
# Wait for OpenBao to accept connections
echo "Waiting for OpenBao to be ready..."
for _ in {1..30}; do
output=$(timeout 2 bao status 2>&1 || true)
if echo "$output" | grep -q "Sealed.*false"; then
# Already unsealed
echo "OpenBao is already unsealed"
exit 0
elif echo "$output" | grep -qE "(Sealed|Initialized)"; then
# Got a valid response, OpenBao is ready (sealed)
echo "OpenBao is ready"
break
fi
sleep 1
done
# Check if already unsealed
if output=$(timeout 2 bao status 2>&1 || true); then
if echo "$output" | grep -q "Sealed.*false"; then
echo "OpenBao is already unsealed"
exit 0
fi
fi
# Unseal using the TPM-decrypted keys (one per line)
if [ -n "$CREDS_DIR" ] && [ -f "$CREDS_DIR/unseal-key" ]; then
echo "Unsealing OpenBao..."
while IFS= read -r key; do
# Skip empty lines
[ -z "$key" ] && continue
echo "Applying unseal key..."
bao operator unseal "$key"
# Check if unsealed after each key
if output=$(timeout 2 bao status 2>&1 || true); then
if echo "$output" | grep -q "Sealed.*false"; then
echo "OpenBao unsealed successfully"
exit 0
fi
fi
done < "$CREDS_DIR/unseal-key"
echo "WARNING: Applied all keys but OpenBao is still sealed"
exit 0
else
echo "WARNING: Unseal key credential not found, OpenBao remains sealed"
exit 0
fi
'';
};
in
{
services.openbao = {
enable = true;
@@ -25,5 +104,11 @@
"key.pem:/var/lib/openbao/key.pem"
"cert.pem:/var/lib/openbao/cert.pem"
];
# TPM2-encrypted unseal key (created manually, see setup instructions)
LoadCredentialEncrypted = [
"unseal-key:/var/lib/openbao/unseal-key.cred"
];
# Auto-unseal on service start
ExecStartPost = "${unsealScript}/bin/openbao-unseal";
};
}