sops instructions

This commit is contained in:
John Lancaster
2026-07-04 00:30:15 -05:00
parent dccdc15851
commit 3f767dfc43
4 changed files with 99 additions and 18 deletions
+21 -3
View File
@@ -13,7 +13,6 @@ STEPPATH=/tmp/janus-step-ca-bootstrap/step step ca init --name Janus --dns janus
Insert generated runtime CA material into `modules/hosts/janus/secrets.yaml` under `janus`:
- `/tmp/janus-step-ca-bootstrap/ca_password.txt` -> `ca_password`
- `/tmp/janus-step-ca-bootstrap/step/certs/intermediate_ca.crt` -> `intermediate_ca_crt`
- `/tmp/janus-step-ca-bootstrap/step/secrets/intermediate_ca_key` -> `intermediate_ca_key`
- `/tmp/janus-step-ca-bootstrap/step/secrets/ssh_host_ca_key` -> `ssh_host_ca_key`
- `/tmp/janus-step-ca-bootstrap/step/secrets/ssh_user_ca_key` -> `ssh_user_ca_key`
@@ -27,14 +26,33 @@ If rotating provisioner password, also set:
Secret source-of-truth after this split:
- `modules/hosts/janus/secrets.yaml`: Janus runtime CA secrets (`ca_password`, `intermediate_ca_crt`, `intermediate_ca_key`, `ssh_host_ca_key`, `ssh_user_ca_key`, `admin_provisioner_encrypted_key`)
- `modules/hosts/janus/secrets.yaml`: Janus runtime CA secrets (`ca_password`, `intermediate_ca_key`, `ssh_host_ca_key`, `ssh_user_ca_key`, `admin_provisioner_encrypted_key`)
- `keys/secrets.yaml`: shared Janus provisioner secret (`janus.admin_jwk`) consumed by `step-ssh-host` across hosts
Then update public artifacts in repo from generated output:
- `modules/hosts/janus/root_ca.crt` from `/tmp/janus-step-ca-bootstrap/step/certs/root_ca.crt`
- `modules/hosts/janus/intermediate_ca.crt` from `/tmp/janus-step-ca-bootstrap/step/certs/intermediate_ca.crt` (public certificate; intentionally committed, not stored in SOPS)
- `modules/hosts/janus/fingerprint` from:
```shell
step certificate fingerprint /tmp/janus-step-ca-bootstrap/step/certs/root_ca.crt
```
- `modules/hosts/janus/ssh_user_ca.pub` from `/tmp/janus-step-ca-bootstrap/step/certs/ssh_user_ca_key.pub`
- `modules/hosts/janus/ssh_user_ca.pub` from `/tmp/janus-step-ca-bootstrap/step/certs/ssh_user_ca_key.pub`
## Back up the root CA key offline
The root CA private key is **not** deployed and is never needed by the running CA.
It is only used to sign/rotate intermediates. Store it offline (e.g. 1Password)
before wiping the bootstrap directory, otherwise intermediate rotation becomes
impossible and any future rotation forces a full root rotation (redistributing
`root_ca.crt` + `fingerprint` to every client).
Back up, then wipe the bootstrap material:
- `/tmp/janus-step-ca-bootstrap/step/secrets/root_ca_key` -> offline secret store
- `/tmp/janus-step-ca-bootstrap/ca_password.txt` -> offline secret store (root/intermediate key password)
```shell
shred -u /tmp/janus-step-ca-bootstrap/step/secrets/root_ca_key 2>/dev/null || true
rm -rf /tmp/janus-step-ca-bootstrap
```
+1 -1
View File
@@ -28,6 +28,7 @@ in
};
step-ca = {
rootCertPath = ./root_ca.crt;
intermediateCertPath = ./intermediate_ca.crt;
dnsNames = [
"${hostname}.john-stream.com"
"192.168.1.244"
@@ -35,7 +36,6 @@ in
secrets = {
sopsFile = ./secrets.yaml;
caPassword = "janus/ca_password";
intermediateCrt = "janus/intermediate_ca_crt";
intermediateKey = "janus/intermediate_ca_key";
sshHostCaKey = "janus/ssh_host_ca_key";
sshUserCaKey = "janus/ssh_user_ca_key";
+5 -14
View File
@@ -7,7 +7,6 @@
caPort = 443;
caPasswordPath = (lib.getAttr cfg.secrets.caPassword config.sops.secrets).path;
intermediateCrtPath = (lib.getAttr cfg.secrets.intermediateCrt config.sops.secrets).path;
intermediateKeyPath = (lib.getAttr cfg.secrets.intermediateKey config.sops.secrets).path;
sshHostCaKeyPath = (lib.getAttr cfg.secrets.sshHostCaKey config.sops.secrets).path;
sshUserCaKeyPath = (lib.getAttr cfg.secrets.sshUserCaKey config.sops.secrets).path;
@@ -16,7 +15,7 @@
renderedStepCaConfig = builtins.toJSON {
root = cfg.rootCertPath;
crt = intermediateCrtPath;
crt = cfg.intermediateCertPath;
key = intermediateKeyPath;
address = "${caAddress}:${toString caPort}";
dnsNames = cfg.dnsNames;
@@ -87,6 +86,10 @@
description = "Path to the Step CA root certificate served by this host.";
type = lib.types.path;
};
intermediateCertPath = lib.mkOption {
description = "Path to the Step CA intermediate certificate served by this host. This is public material and does not need to be stored in SOPS.";
type = lib.types.path;
};
dnsNames = lib.mkOption {
description = "DNS names and IP SANs advertised by this Step CA instance.";
type = with lib.types; listOf str;
@@ -100,10 +103,6 @@
description = "SOPS key for the Step CA intermediate password.";
type = lib.types.str;
};
intermediateCrt = lib.mkOption {
description = "SOPS key for the Step CA intermediate certificate.";
type = lib.types.str;
};
intermediateKey = lib.mkOption {
description = "SOPS key for the Step CA intermediate private key.";
type = lib.types.str;
@@ -132,13 +131,6 @@
mode = "0400";
restartUnits = [ "step-ca.service" ];
};
sops.secrets."${cfg.secrets.intermediateCrt}" = {
sopsFile = cfg.secrets.sopsFile;
owner = "step-ca";
group = "step-ca";
mode = "0400";
restartUnits = [ "step-ca.service" ];
};
sops.secrets."${cfg.secrets.intermediateKey}" = {
sopsFile = cfg.secrets.sopsFile;
owner = "step-ca";
@@ -184,7 +176,6 @@
intermediatePasswordFile = caPasswordPath;
};
# Keep modules/services/step-ca/ca.json as reference-only; runtime config comes from SOPS template.
environment.etc."smallstep/ca.json".source =
lib.mkForce config.sops.templates."step-ca-config".path;
systemd.services.step-ca.restartTriggers =