WIP with placeholder secrets
This commit is contained in:
+12
@@ -4,6 +4,18 @@ keys:
|
|||||||
- &test-nix age1gvplss0ddmyf6vpjy363wu3n057vhm0j6n7tc94cxd8kadapypws5mtaj0
|
- &test-nix age1gvplss0ddmyf6vpjy363wu3n057vhm0j6n7tc94cxd8kadapypws5mtaj0
|
||||||
- &soteria age1h0prahyukq4l564yqwgcpg3g6gdrjflk0suklussjjrjstxd9uesws8633
|
- &soteria age1h0prahyukq4l564yqwgcpg3g6gdrjflk0suklussjjrjstxd9uesws8633
|
||||||
creation_rules:
|
creation_rules:
|
||||||
|
- path_regex: modules/hosts/janus/secrets\.yaml$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *john-pc
|
||||||
|
- *test-nix
|
||||||
|
- path_regex: keys/secrets\.yaml$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *john-p14s
|
||||||
|
- *john-pc
|
||||||
|
- *test-nix
|
||||||
|
- *soteria
|
||||||
- path_regex: soteria/secrets\.yaml$
|
- path_regex: soteria/secrets\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
|
|||||||
+30
-21
@@ -9,33 +9,42 @@ api:
|
|||||||
gmail_client_secret: ENC[AES256_GCM,data:du2gEY5TQIwpUEvJKDWKY3noLRGeiKek4IMwPUusVx8NMys=,iv:hIYi1xQYf6+hDhK0pNprBYu6wXwRH2yOTwQg6pzQa0A=,tag:sqmQ5GCkKbHpIy2R+Y5G/A==,type:str]
|
gmail_client_secret: ENC[AES256_GCM,data:du2gEY5TQIwpUEvJKDWKY3noLRGeiKek4IMwPUusVx8NMys=,iv:hIYi1xQYf6+hDhK0pNprBYu6wXwRH2yOTwQg6pzQa0A=,tag:sqmQ5GCkKbHpIy2R+Y5G/A==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1f6drjusg866yscj8029tk4yfpgecklrvezldm02ankm6h8nnwu5s2u6ahy
|
- enc: |
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0UEpja2kxdThZVWZhOGVP
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhbmduOWR1ZloxWjRjTjFp
|
||||||
S0NtSi84MjhnN0RORkh2NjZ4YlYvWS9kZDBNClFzYnVxWnhmQkpCRkRFVUx1RDdX
|
ZFpvUFA2cStzYllUa1BhSmJBYWVUSmNGblZ3Cmw3TnVBSGtwaDV4ZlRRT2h6OWw0
|
||||||
ZHFqYXRqYXM0cWJzcU5EeEtSR1BUVzAKLS0tIDdEY2pnVTJqWlNZVkZldXVYVmFH
|
bGd6dUQ2eE1QVWNTTitSSG80NVhraU0KLS0tIHRVMXFFRGh5cjlwNXpIb0F4TnF3
|
||||||
dVNBRUVodU5sRnpVcG1GZ1RiZzhjTXMKefqBvvD/qZwcSHmFjUnleukVRLueG36Y
|
Ykplcm1DWm04RExHYnRjQjdCOVhLaE0K/VGQ/58QWOAWPToQt22W4iBX7rrh/lxL
|
||||||
Q81KlwQweF2F8kHl7Bqsi+3hH1dZZbVm3vjuGpWFOoti7fowUV55Kw==
|
Via5/T25c64Eh6FXzar+z9zdHjS4s7PLsf6iJIY84xpKCpSAkcaquw==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
- recipient: age1ykcs39e62pz3xu6cedg8ea685kv5d5qsrhgkndygzm8rx30xd5ys5t3qxt
|
recipient: age1f6drjusg866yscj8029tk4yfpgecklrvezldm02ankm6h8nnwu5s2u6ahy
|
||||||
enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqZFZxbDhVUWFEUGhPMlZI
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkdEVYYzR2M1hDSmR6aVZO
|
||||||
SFdBYkpxSnAxTUZXbjVwQnlZQ3l1SWtuZGg0CmVBdnVHbTNUcmwvK01iMnZKZTJh
|
WCtBUTBVUU96SitsTFlBT2IzQjk2Q21LV2tvCkRxVEVESVFsWlczdU5CT2V1a0cw
|
||||||
ajFla3kzYUl4ZWY3czA0WUdNM2lpVFUKLS0tIHo5Uk1pV296MXdnUTZGQ25haWZG
|
MUxXNFJFa1BvRFdGbVpkdDRTYVhROUkKLS0tIHBMaGFTRmgrYnkraGt3YkRCMXhw
|
||||||
QWZDWGRaRDBhY1ZkZk5oTHY0ZVV2RXMKanv+WWRhf5nl+aw/T6QZFVQQmhV1DZfB
|
Rk9GMUhXcWhYL3NXdmRZN0FtQjR2bU0Kql1oAOuJDJ2jcR+WcibBiFiVcMEBbXVS
|
||||||
jkSzOAKOgPx7toYFmpq9E8fAH+zrMzDbxI2z2uyrOFI6v+QE0Ul/iQ==
|
cxydfdl3/la1tqiMd6rnDh/iB5hwjeeULwrgE/5Qjc7w23hMN9AF1g==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
- recipient: age1gvplss0ddmyf6vpjy363wu3n057vhm0j6n7tc94cxd8kadapypws5mtaj0
|
recipient: age1ykcs39e62pz3xu6cedg8ea685kv5d5qsrhgkndygzm8rx30xd5ys5t3qxt
|
||||||
enc: |
|
- enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZcGtMNi9RSG5aTVV5cWdT
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArTnc1ZEorSDlZSW1qY3Zu
|
||||||
NittUXN0Qnpld1YvOU50OUh3Z3ZiSzhHOHdNCnc4TmdYbS9QQnBLbldHSytIdkJl
|
NExrYXgyQjRIQUNRYlFXZCt4bXcxRndzWW40CjNCM3p0VDcwbENoTGxFNGZRR3lM
|
||||||
R0psQWxkZTgyZTRzckkrTGpyNCsvR2sKLS0tIEdLb05aT2I2S3BKcFRrVmtvTGw5
|
R0pnSlluTUpiNk91d0hlci9sOUtBYjQKLS0tIGp2eWpReExSNTdCS0RBQ1F5dDNt
|
||||||
Z1orRCtkTDVXSktuck5pTmV4K05qZHMKZlHHu07q+GnyDDgdwW2Ic3P23PmoSPwn
|
eWhuak00dTFZV0k1WEREQkRPWUFmc00KQ13ormwGmzwPxvId8WXe1PY4FG3g1Juw
|
||||||
WuNLZdlZQleROaRb+zpD+9P1HGGJ3mWAlNlnmjGrRk453k1PbBQ5Og==
|
KnBf20sSRkJ/oj3iEhfd8ZmXeoK1Xc44aeCcVe7NEzVtMhjIdzcNqg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age1gvplss0ddmyf6vpjy363wu3n057vhm0j6n7tc94cxd8kadapypws5mtaj0
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWTHN6TDBHdFU1L1lEQzg4
|
||||||
|
TW1vT08vYnp3bzBzSFlxbGpDSFNycFYycFJRCnYvcjVQOC9rZTFXb0lHQWFUVVhZ
|
||||||
|
ZFVtM09zWW9GZzNMRnBHdHNFNnZHdTgKLS0tIFh1b1pnKzJQUWg4YkRIWVFnRDNz
|
||||||
|
bXRzY1piak43N0dMZFQ1WWdSZjBBT2cKujwWnuf7LFZe1TIu0R+Vc+HGCYqaeRkD
|
||||||
|
jBuPRyN7cqCZ5cK9492BVLg48toU/djCSs1w33aLeTF5Ug/Swduqkg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age1h0prahyukq4l564yqwgcpg3g6gdrjflk0suklussjjrjstxd9uesws8633
|
||||||
lastmodified: "2026-03-15T15:06:29Z"
|
lastmodified: "2026-03-15T15:06:29Z"
|
||||||
mac: ENC[AES256_GCM,data:cF/TJ8VkzrHRUrO5iGdRdlFtqV/5EQ15JwQKIywJvsh0NERK67T21czSP7923MiL0u5QTVPn/rO8R5E/8gBu3r8+fLq+CFl9PDQHEX2JhnYOD5WZR412WMZq3MVR94IMTOrQANMVpS4uhMyvnrqOe4AenxLDyzrYhkwf1KQh4w0=,iv:Qwy8z4uXGMlf+kTMNiE42M9l8LtSJ+O7diknRrsSeYI=,tag:qlCY9r8HnEDmq/jw59C/sg==,type:str]
|
mac: ENC[AES256_GCM,data:cF/TJ8VkzrHRUrO5iGdRdlFtqV/5EQ15JwQKIywJvsh0NERK67T21czSP7923MiL0u5QTVPn/rO8R5E/8gBu3r8+fLq+CFl9PDQHEX2JhnYOD5WZR412WMZq3MVR94IMTOrQANMVpS4uhMyvnrqOe4AenxLDyzrYhkwf1KQh4w0=,iv:Qwy8z4uXGMlf+kTMNiE42M9l8LtSJ+O7diknRrsSeYI=,tag:qlCY9r8HnEDmq/jw59C/sg==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
|
|||||||
@@ -1,29 +1,145 @@
|
|||||||
{ self, inputs, ... }: {
|
{ self, inputs, ... }:
|
||||||
flake.modules.homeManager.step-client = { config, pkgs, lib, ... }: {
|
let
|
||||||
home.file.".step/config/defaults.json".text = builtins.toJSON {
|
defaultCaUrl = "https://janus.john-stream.com/";
|
||||||
ca-url = "https://janus.john-stream.com/";
|
defaultFingerprint = "2036c44f7b5901566ff7611ea6c927291ecc6d2dd00779c0eead70ec77fa10d6";
|
||||||
fingerprint = "2036c44f7b5901566ff7611ea6c927291ecc6d2dd00779c0eead70ec77fa10d6";
|
defaultRoot = ../hosts/janus/root_ca.crt;
|
||||||
root = ../hosts/janus/root_ca.crt;
|
|
||||||
};
|
mkStepBootstrap = { pkgs, caUrl, fingerprint, install ? false }:
|
||||||
home.packages = [
|
(inputs.self.wrappers.stepBootstrap.apply {
|
||||||
inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.step-bootstrap
|
inherit pkgs install;
|
||||||
];
|
ca-url = caUrl;
|
||||||
# sops.secrets."step-ca-defaults" = {
|
inherit fingerprint;
|
||||||
# sopsFile = ../hosts/janus/defaults.json;
|
}).wrapper;
|
||||||
# format = "json";
|
|
||||||
# key = ""; # This causes it to decode the whole file
|
mkDefaultsText = cfg: builtins.toJSON {
|
||||||
# path = "${config.home.homeDirectory}/defaults.json";
|
ca-url = cfg.caUrl;
|
||||||
# mode = "0400";
|
fingerprint = cfg.fingerprint;
|
||||||
# };
|
root = cfg.root;
|
||||||
};
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
flake.modules.nixos.step-client = { config, pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config."step-client";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options."step-client" = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
description = "Enable step-ca client bootstrap";
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
caUrl = lib.mkOption {
|
||||||
|
description = "The step-ca URL used for bootstrap and renewal.";
|
||||||
|
type = lib.types.str;
|
||||||
|
default = defaultCaUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
fingerprint = lib.mkOption {
|
||||||
|
description = "The SHA256 fingerprint of the step-ca root certificate.";
|
||||||
|
type = lib.types.str;
|
||||||
|
default = defaultFingerprint;
|
||||||
|
};
|
||||||
|
|
||||||
|
root = lib.mkOption {
|
||||||
|
description = "The step-ca root certificate used for bootstrap.";
|
||||||
|
type = lib.types.path;
|
||||||
|
default = defaultRoot;
|
||||||
|
};
|
||||||
|
|
||||||
|
certDir = lib.mkOption {
|
||||||
|
description = "Directory used to store root CA material for mTLS and step bootstrap.";
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "/etc/step-ca/certs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [
|
||||||
|
(mkStepBootstrap {
|
||||||
|
inherit pkgs;
|
||||||
|
caUrl = cfg.caUrl;
|
||||||
|
fingerprint = cfg.fingerprint;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.etc."step-ca/defaults.json".text = mkDefaultsText cfg;
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d ${cfg.certDir} 0750 root root -"
|
||||||
|
"d /root/.step 0700 root root -"
|
||||||
|
"d /root/.step/config 0700 root root -"
|
||||||
|
"d /root/.step/certs 0700 root root -"
|
||||||
|
"L+ /root/.step/config/defaults.json - - - - /etc/step-ca/defaults.json"
|
||||||
|
"L+ /root/.step/certs/root_ca.crt - - - - ${cfg.certDir}/root_ca.crt"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
flake.modules.homeManager.step-client = { config, pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config."step-client";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options."step-client" = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
description = "Enable step-ca client bootstrap";
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
caUrl = lib.mkOption {
|
||||||
|
description = "The step-ca URL used for bootstrap and renewal.";
|
||||||
|
type = lib.types.str;
|
||||||
|
default = defaultCaUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
fingerprint = lib.mkOption {
|
||||||
|
description = "The SHA256 fingerprint of the step-ca root certificate.";
|
||||||
|
type = lib.types.str;
|
||||||
|
default = defaultFingerprint;
|
||||||
|
};
|
||||||
|
|
||||||
|
root = lib.mkOption {
|
||||||
|
description = "The step-ca root certificate used for bootstrap.";
|
||||||
|
type = lib.types.path;
|
||||||
|
default = defaultRoot;
|
||||||
|
};
|
||||||
|
|
||||||
|
certDir = lib.mkOption {
|
||||||
|
description = "Directory used to store root CA material for mTLS and step bootstrap.";
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "${config.home.homeDirectory}/.step/certs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable (
|
||||||
|
let
|
||||||
|
certDirPath = lib.removePrefix "${config.home.homeDirectory}/" cfg.certDir;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [
|
||||||
|
(mkStepBootstrap {
|
||||||
|
inherit pkgs;
|
||||||
|
caUrl = cfg.caUrl;
|
||||||
|
fingerprint = cfg.fingerprint;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
home.file.".step/config/defaults.json".text = mkDefaultsText cfg;
|
||||||
|
home.file."${certDirPath}/root_ca.crt".source = cfg.root;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
perSystem = { system, pkgs, lib, ... }: {
|
perSystem = { system, pkgs, lib, ... }: {
|
||||||
packages.step-bootstrap = (inputs.self.wrappers.stepBootstrap.apply {
|
packages.step-bootstrap = mkStepBootstrap {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
ca-url = "https://janus.john-stream.com";
|
caUrl = defaultCaUrl;
|
||||||
fingerprint = "2036c44f7b5901566ff7611ea6c927291ecc6d2dd00779c0eead70ec77fa10d6";
|
fingerprint = defaultFingerprint;
|
||||||
install = true;
|
install = true;
|
||||||
}).wrapper;
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
flake.wrappers.stepBootstrap = inputs.wrappers.lib.wrapModule ({config, lib, wlib, ... }: {
|
flake.wrappers.stepBootstrap = inputs.wrappers.lib.wrapModule ({config, lib, wlib, ... }: {
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Janus
|
||||||
|
|
||||||
|
Generate passwords:
|
||||||
|
```shell
|
||||||
|
mkdir -p /tmp/janus-step-ca-bootstrap && chmod 700 /tmp/janus-step-ca-bootstrap && cd /tmp/janus-step-ca-bootstrap && umask 077 && openssl rand -base64 48 > ca_password.txt && openssl rand -base64 48 > admin_jwk_password.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Bootstrap CA materials with SSH enabled:
|
||||||
|
```shell
|
||||||
|
STEPPATH=/tmp/janus-step-ca-bootstrap/step step ca init --name Janus --dns janus.john-stream.com --dns 192.168.1.244 --address :443 --provisioner admin --password-file /tmp/janus-step-ca-bootstrap/ca_password.txt --provisioner-password-file /tmp/janus-step-ca-bootstrap/admin_jwk_password.txt --ssh --deployment-type standalone --with-ca-url https://janus.john-stream.com
|
||||||
|
```
|
||||||
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
If rotating provisioner password, also set:
|
||||||
|
|
||||||
|
- `/tmp/janus-step-ca-bootstrap/admin_jwk_password.txt` -> `janus.admin_jwk` in `keys/secrets.yaml`
|
||||||
|
|
||||||
|
Secret source-of-truth after this split:
|
||||||
|
|
||||||
|
- `modules/hosts/janus/secrets.yaml`: Janus runtime CA secrets only (`ca_password`, `intermediate_ca_crt`, `intermediate_ca_key`, `ssh_host_ca_key`, `ssh_user_ca_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/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`
|
||||||
@@ -4,55 +4,13 @@ let
|
|||||||
hostname = "janus";
|
hostname = "janus";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
flake.modules.nixos.janus-ca =
|
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.janus-ca;
|
|
||||||
johnHome = lib.attrByPath [ "users" "users" username "home" ] "/home/${username}" config;
|
|
||||||
johnGroup = lib.attrByPath [ "users" "users" username "group" ] username config;
|
|
||||||
cfgInEtc = lib.hasPrefix "/etc/" cfg.certDir;
|
|
||||||
certDirEtcPath =
|
|
||||||
if cfgInEtc then
|
|
||||||
lib.removePrefix "/etc/" cfg.certDir
|
|
||||||
else
|
|
||||||
cfg.certDir;
|
|
||||||
mkStepRules = home: user: group: [
|
|
||||||
"d ${home}/.step 0700 ${user} ${group} -"
|
|
||||||
"d ${home}/.step/config 0700 ${user} ${group} -"
|
|
||||||
"d ${home}/.step/certs 0700 ${user} ${group} -"
|
|
||||||
"L+ ${home}/.step/config/defaults.json - - - - /etc/step-ca/defaults.json"
|
|
||||||
"L+ ${home}/.step/certs/root_ca.crt - - - - ${cfg.certDir}/root_ca.crt"
|
|
||||||
];
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.janus-ca = {
|
|
||||||
certDir = lib.mkOption {
|
|
||||||
description = "String path to where the mtls certs will be stored.";
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/etc/step-ca/certs";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = {
|
|
||||||
environment.etc = lib.mkIf cfgInEtc {
|
|
||||||
"step-ca/defaults.json".text = builtins.toJSON {
|
|
||||||
ca-url = "https://janus.john-stream.com/";
|
|
||||||
fingerprint = "2036c44f7b5901566ff7611ea6c927291ecc6d2dd00779c0eead70ec77fa10d6";
|
|
||||||
root = ./root_ca.crt;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
systemd.tmpfiles.rules =
|
|
||||||
mkStepRules johnHome username johnGroup
|
|
||||||
++ mkStepRules "/root" "root" "root";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
flake.nixosConfigurations."${hostname}" = inputs.nixpkgs.lib.nixosSystem {
|
flake.nixosConfigurations."${hostname}" = inputs.nixpkgs.lib.nixosSystem {
|
||||||
modules = with inputs.self.modules; [
|
modules = with inputs.self.modules; [
|
||||||
nixos.lxc
|
nixos.lxc
|
||||||
nixos.mysops
|
nixos.mysops
|
||||||
nixos.step-ssh-host
|
nixos.step-ssh-host
|
||||||
nixos.janus-ca
|
nixos.step-client
|
||||||
|
nixos.step-ca
|
||||||
inputs.home-manager.nixosModules.home-manager
|
inputs.home-manager.nixosModules.home-manager
|
||||||
nixos."${username}"
|
nixos."${username}"
|
||||||
nixos.docker
|
nixos.docker
|
||||||
@@ -60,7 +18,7 @@ in
|
|||||||
nixos.mtls
|
nixos.mtls
|
||||||
({ lib, pkgs, ... }: {
|
({ lib, pkgs, ... }: {
|
||||||
networking.hostName = hostname;
|
networking.hostName = hostname;
|
||||||
sops.defaultSopsFile = ../../../keys/secrets.yaml;
|
sops.defaultSopsFile = ./secrets.yaml;
|
||||||
step-ssh-host = {
|
step-ssh-host = {
|
||||||
hostname = hostname;
|
hostname = hostname;
|
||||||
extraPrincipals = [
|
extraPrincipals = [
|
||||||
@@ -90,6 +48,7 @@ in
|
|||||||
home-manager.users."${username}" = {
|
home-manager.users."${username}" = {
|
||||||
imports = with inputs.self.modules.homeManager; [
|
imports = with inputs.self.modules.homeManager; [
|
||||||
mysops
|
mysops
|
||||||
|
step-client
|
||||||
];
|
];
|
||||||
docker.enable = true;
|
docker.enable = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
janus:
|
||||||
|
ca_password: ENC[AES256_GCM,data:GmuqoePDJd5Cn7+sWbvXPlGoUf3SVgYnHOoq9mnPWNWj,iv:VY/8olA+yu66wW+RbhD58GtA0YUWuAtm1HUXtNIIuLk=,tag:fCz3x6B4UPw+XpJE0F3t/g==,type:str]
|
||||||
|
intermediate_ca_crt: ENC[AES256_GCM,data:9W6QXGlcPdfas1ea6S3w1OYI/SeF6YDIdF5J7Hv4ype3,iv:H8oVfbMLBRvU0ywovVSB84g0q1wPhHEdzfpIVAY0Bkg=,tag:7/pU0N1SlfC1i8H2IgPGVA==,type:str]
|
||||||
|
intermediate_ca_key: ENC[AES256_GCM,data:wrzE8pgSZrtMA2jyLuVhMFxr47ICDBUkqOFyFJex9h3g,iv:I3Sz07e+cFDOUunCu7ZGcAjckRJDy3NmTXoB0vtA0HI=,tag:inANSVzyAzWlX4J5pheY8A==,type:str]
|
||||||
|
ssh_host_ca_key: ENC[AES256_GCM,data:IT3PcnbrexRDvxoVEyyxYBx7+Brm3SzVP3Yr2UGkFjeH,iv:edfMiRR+EVx9veTH+mEAFtEdC/rlW8uU5jMD8UX2Ylo=,tag:KKS/2GQE8V6obbjfMLspug==,type:str]
|
||||||
|
ssh_user_ca_key: ENC[AES256_GCM,data:w3gc97CYUODNxk0gIyghd9PCksDVvrdvl8j/NQe/tCtw,iv:WbWlVCPV7niVHEJ9sVcO9SAcLSfquE/bvcR5KClxszk=,tag:08uj+lv9MflYOtQh28K6pw==,type:str]
|
||||||
|
sops:
|
||||||
|
age:
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCTEFTSy96QTluaWo0bURH
|
||||||
|
YlpFSWx3VnYvSHpDYU1PNmZrb0FuVHVTcG00CmJnT09OZEJad01OZk8zUzlPT1Ft
|
||||||
|
bVpHeW9UMXZYN1JJQVgrTk9OamhZeXcKLS0tIFhXMVNDQjhVcUp2aHhjenlGVW9z
|
||||||
|
cTNPalJOQVJNQWxzMnVMT1lYQS9SNW8KWapdX8dwxEvcqhKI8RJmCWRrV7sRmS72
|
||||||
|
sUt6HaUGpQfUQ97MtS01DYaSZjbAvj8t//mXhLubZddDTtTuhbpjAg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age1ykcs39e62pz3xu6cedg8ea685kv5d5qsrhgkndygzm8rx30xd5ys5t3qxt
|
||||||
|
- enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWcnVWS2lpMDM5VWxLWDIx
|
||||||
|
R0xWQ3ZOaEVFNTR5bXArNTc4MzFOM2xCQWhjCnBZeUtJQ3RvWDdZeVRpRzBPbTl2
|
||||||
|
M3FOTlRnTDhIaGg2VzM3MFVEc1FVUmcKLS0tIDAzeDlaZGt5Q2dJbzNWRVB4Qmwr
|
||||||
|
SWpxcytNdEFBQ2o0Q3lWSHZSNEdCUUEKgHE0j678WIhcQQsZQ5RcQNkQcP++ibvr
|
||||||
|
ZT3ScL4PAYhH+lxciJK4tit53taevbp5o0jFibaup4ByDvgj7HPclw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
recipient: age1gvplss0ddmyf6vpjy363wu3n057vhm0j6n7tc94cxd8kadapypws5mtaj0
|
||||||
|
lastmodified: "2026-07-04T03:42:39Z"
|
||||||
|
mac: ENC[AES256_GCM,data:qBuVJo9F5IiQGDqji0ZfNH6MYYLgaVuEoHGsvejw1ffFjYeqGI5LrZmez8xTx8dymQADCDYINZNYlKxgXaXdGqrlKaU8GzuWeF7M0Ad43+S/8DbP2OGPXERHAH+IWVjvzlurXs4tWE4ULw4PbsVpWqOBaSk603N7cuy7Ztwfk8M=,iv:lceVJAeZi8FwKo8DAET1hgUi54Bu+0kjWcGEZxs5wCA=,tag:mFkqan9BHtI6NkxqbjkIcQ==,type:str]
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.13.1
|
||||||
@@ -56,6 +56,7 @@
|
|||||||
gnome
|
gnome
|
||||||
desktop
|
desktop
|
||||||
mysops
|
mysops
|
||||||
|
step-client
|
||||||
rebuild
|
rebuild
|
||||||
{
|
{
|
||||||
my-vscode.enable = true;
|
my-vscode.enable = true;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
"${inputs.nixos-hardware}/lenovo/thinkpad/p14s/amd/gen4"
|
"${inputs.nixos-hardware}/lenovo/thinkpad/p14s/amd/gen4"
|
||||||
] ++ (with self.modules.nixos; [
|
] ++ (with self.modules.nixos; [
|
||||||
p14sConfiguration
|
p14sConfiguration
|
||||||
janus-ca
|
|
||||||
rebuild
|
rebuild
|
||||||
sudo
|
sudo
|
||||||
john
|
john
|
||||||
@@ -20,6 +19,7 @@
|
|||||||
steam
|
steam
|
||||||
wireguard
|
wireguard
|
||||||
mtls
|
mtls
|
||||||
|
step-client
|
||||||
# greetd
|
# greetd
|
||||||
# niri
|
# niri
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -8,19 +8,18 @@ in
|
|||||||
flake.nixosConfigurations."${hostname}" = inputs.nixpkgs.lib.nixosSystem {
|
flake.nixosConfigurations."${hostname}" = inputs.nixpkgs.lib.nixosSystem {
|
||||||
modules = with inputs.self.modules; [
|
modules = with inputs.self.modules; [
|
||||||
nixos.lxc
|
nixos.lxc
|
||||||
nixos."${username}"
|
|
||||||
nixos.mysops
|
nixos.mysops
|
||||||
|
nixos."${username}"
|
||||||
nixos.step-ssh-host
|
nixos.step-ssh-host
|
||||||
nixos.login-text
|
nixos.login-text
|
||||||
nixos.docker
|
nixos.docker
|
||||||
nixos.mtls
|
nixos.mtls
|
||||||
nixos.janus-ca
|
nixos.step-client
|
||||||
nixos.forgejo
|
nixos.forgejo
|
||||||
nixos.restic-server
|
nixos.restic-server
|
||||||
# nixos.restic-envoy
|
# nixos.restic-envoy
|
||||||
({ config, pkgs, ... }: {
|
({ config, pkgs, ... }: {
|
||||||
networking.hostName = hostname;
|
networking.hostName = hostname;
|
||||||
time.timeZone = "America/Chicago";
|
|
||||||
|
|
||||||
# Removes password for sudo
|
# Removes password for sudo
|
||||||
security.sudo-rs.extraRules = lib.mkAfter [
|
security.sudo-rs.extraRules = lib.mkAfter [
|
||||||
@@ -38,7 +37,6 @@ in
|
|||||||
users.users."${username}".extraGroups = [ "mtls" ];
|
users.users."${username}".extraGroups = [ "mtls" ];
|
||||||
mtls = {
|
mtls = {
|
||||||
enable = true;
|
enable = true;
|
||||||
certDir = config.janus-ca.certDir;
|
|
||||||
subject = hostname;
|
subject = hostname;
|
||||||
san = [
|
san = [
|
||||||
"${hostname}.john-stream.com"
|
"${hostname}.john-stream.com"
|
||||||
@@ -98,6 +96,7 @@ in
|
|||||||
imports = [
|
imports = [
|
||||||
inputs.self.modules.homeManager.rebuild
|
inputs.self.modules.homeManager.rebuild
|
||||||
inputs.self.modules.homeManager.mysops
|
inputs.self.modules.homeManager.mysops
|
||||||
|
inputs.self.modules.homeManager.step-client
|
||||||
({ config, pkgs, lib, ... }: {
|
({ config, pkgs, lib, ... }: {
|
||||||
homeManagerFlakeDir = "${config.xdg.configHome}/home-manager";
|
homeManagerFlakeDir = "${config.xdg.configHome}/home-manager";
|
||||||
docker.enable = true;
|
docker.enable = true;
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
janus:
|
|
||||||
admin_jwk: ENC[AES256_GCM,data:2XcN5X77wTQ+OUXa4C9xAErGvrwJKseHjCcgoj6jt+c=,iv:9x+M1wM0dYND1JYkJjM4N8pSOok2OF+P9vmm9NCumTI=,tag:dTCfh+KB1iRJBVoNsGqvuw==,type:str]
|
|
||||||
forgejo:
|
forgejo:
|
||||||
#ENC[AES256_GCM,data:/wtm0uXbiWFoGNWtlTzVuNxBR7CPm2FMB98t3AxSj5V5rltLvzF9BjgWoJCiX3ltzmU=,iv:xaZXbUIGJHxPrLRQzEQI7hgRgc0y061jIhoE3zlcMaA=,tag:fQGheCIdBKm6wE+vtj7g6A==,type:comment]
|
#ENC[AES256_GCM,data:/wtm0uXbiWFoGNWtlTzVuNxBR7CPm2FMB98t3AxSj5V5rltLvzF9BjgWoJCiX3ltzmU=,iv:xaZXbUIGJHxPrLRQzEQI7hgRgc0y061jIhoE3zlcMaA=,tag:fQGheCIdBKm6wE+vtj7g6A==,type:comment]
|
||||||
secret_key: ENC[AES256_GCM,data:/jcyeDcsryLqu9Q3VnNaENb71/Tl5JUr0zDzxt8L5UCtnJ/YHA6MKItrQ9ZHFv1XROtnSfZl9D5kKomeM8EVqA==,iv:HxMKAMVQ08gkq6SWENj0/d8i9PhcgPCp5eqbztj9bSg=,tag:nO2dFWT/vfgGc/9JIDZrGw==,type:str]
|
secret_key: ENC[AES256_GCM,data:/jcyeDcsryLqu9Q3VnNaENb71/Tl5JUr0zDzxt8L5UCtnJ/YHA6MKItrQ9ZHFv1XROtnSfZl9D5kKomeM8EVqA==,iv:HxMKAMVQ08gkq6SWENj0/d8i9PhcgPCp5eqbztj9bSg=,tag:nO2dFWT/vfgGc/9JIDZrGw==,type:str]
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
config = {
|
config = {
|
||||||
ssh.certificates.enable = true;
|
ssh.certificates.enable = true;
|
||||||
sops.secrets."janus/admin_jwk" = {
|
sops.secrets."janus/admin_jwk" = {
|
||||||
|
# Shared provisioner credential is intentionally centralized.
|
||||||
|
sopsFile = ../../../keys/secrets.yaml;
|
||||||
owner = "root";
|
owner = "root";
|
||||||
group = "root";
|
group = "root";
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
|
|||||||
@@ -1,22 +1,127 @@
|
|||||||
{ inputs, ... }:
|
{ inputs, ... }:
|
||||||
let
|
|
||||||
ipAddress = "0.0.0.0";
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
flake.modules.nixos.step-ca = { pkgs, ... }: {
|
flake.modules.nixos.step-ca = { config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
# Keep host-specific trust anchor in repo; secret/private keys come from sops.
|
||||||
|
rootCertPath = ../../hosts/janus/root_ca.crt;
|
||||||
|
caPasswordPath = config.sops.secrets."janus/ca_password".path;
|
||||||
|
intermediateCrtPath = config.sops.secrets."janus/intermediate_ca_crt".path;
|
||||||
|
intermediateKeyPath = config.sops.secrets."janus/intermediate_ca_key".path;
|
||||||
|
sshHostCaKeyPath = config.sops.secrets."janus/ssh_host_ca_key".path;
|
||||||
|
sshUserCaKeyPath = config.sops.secrets."janus/ssh_user_ca_key".path;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Placeholders are expected initially until real material is inserted into sops.
|
||||||
|
sops.secrets."janus/ca_password" = {
|
||||||
|
sopsFile = ../../hosts/janus/secrets.yaml;
|
||||||
|
owner = "step-ca";
|
||||||
|
group = "step-ca";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
sops.secrets."janus/intermediate_ca_crt" = {
|
||||||
|
sopsFile = ../../hosts/janus/secrets.yaml;
|
||||||
|
owner = "step-ca";
|
||||||
|
group = "step-ca";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
sops.secrets."janus/intermediate_ca_key" = {
|
||||||
|
sopsFile = ../../hosts/janus/secrets.yaml;
|
||||||
|
owner = "step-ca";
|
||||||
|
group = "step-ca";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
sops.secrets."janus/ssh_host_ca_key" = {
|
||||||
|
sopsFile = ../../hosts/janus/secrets.yaml;
|
||||||
|
owner = "step-ca";
|
||||||
|
group = "step-ca";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
sops.secrets."janus/ssh_user_ca_key" = {
|
||||||
|
sopsFile = ../../hosts/janus/secrets.yaml;
|
||||||
|
owner = "step-ca";
|
||||||
|
group = "step-ca";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
|
||||||
# https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/security/step-ca.nix
|
# https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/security/step-ca.nix
|
||||||
services.step-ca = {
|
services.step-ca = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
address = ipAddress;
|
address = "0.0.0.0";
|
||||||
port = 8443;
|
port = 443;
|
||||||
|
intermediatePasswordFile = caPasswordPath;
|
||||||
|
|
||||||
# https://smallstep.com/docs/step-ca/configuration/#configuration-options
|
# https://smallstep.com/docs/step-ca/configuration/#configuration-options
|
||||||
settings = {
|
settings = {
|
||||||
root = "";
|
root = rootCertPath;
|
||||||
crt = "";
|
crt = intermediateCrtPath;
|
||||||
|
key = intermediateKeyPath;
|
||||||
|
dnsNames = [
|
||||||
|
"janus.john-stream.com"
|
||||||
|
"192.168.1.244"
|
||||||
|
];
|
||||||
|
|
||||||
|
ssh = {
|
||||||
|
hostKey = sshHostCaKeyPath;
|
||||||
|
userKey = sshUserCaKeyPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
db = {
|
||||||
|
type = "badgerv2";
|
||||||
|
dataSource = "/var/lib/step-ca/db";
|
||||||
|
};
|
||||||
|
|
||||||
|
authority = {
|
||||||
|
backdate = "1m0s";
|
||||||
|
provisioners = [
|
||||||
|
{
|
||||||
|
type = "ACME";
|
||||||
|
name = "acme";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
type = "SSHPOP";
|
||||||
|
name = "sshpop";
|
||||||
|
claims.enableSSHCA = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
type = "JWK";
|
||||||
|
name = "admin";
|
||||||
|
key = {
|
||||||
|
use = "sig";
|
||||||
|
kty = "EC";
|
||||||
|
kid = "xoxgOJFbveSLIL2gm1Yu5ZiRb9v8Jxe44F56i3v-Nf8";
|
||||||
|
crv = "P-256";
|
||||||
|
alg = "ES256";
|
||||||
|
x = "zFO8hPx_eH0Iyz7UJI-w8ODMusEKCZ28M76sGWmWYxA";
|
||||||
|
y = "XIWLLyKDzqxV9UH-2KeAkKPDrgLoPrxxW9-PzkXggME";
|
||||||
|
};
|
||||||
|
encryptedKey = "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjYwMDAwMCwicDJzIjoiUVJnTnJVTF9KcmxJYkJMVTlGNVRPZyJ9.DMu7xBNCq5pr-_--YTxNr5Hrcqy6ZmSVHsWurfVXL7Hk0Q3vyYRxiw.h-CnFiYc-DhxThI3.plx3_Qa_0kU-2TwnqFNfAfGnCpfQ2e0iiCMLruNHbLMnHeXQ1BysHBqps45_02zZXIRdHoDgYGtXRSfcdUYYoS0pLoPzC6m301ZFNSAFdRVlSZ3Q6VmWdixPXXnEB4EgSKTT_wxR33L8t9OpFzD85KfY-b_Un1l99ufjCnfg-EYkcICTn_G4-8bcW3eFIvJ6setzu-l0jHMhLQdIweqncn9on9xBXBD-ANhZfP95P2BJt-APqCi8eqiAvn_vClovdg0PxzRwOVDvWREz66FDw-HTU7xDtGO9hACopT5tfZOXDoykgZw1mJsq9NEq9ZzvKG2hvyk1UXtExxrNtFo.5q1OfGU4Amo4Si-vpeI42g";
|
||||||
|
claims = {
|
||||||
|
enableSSHCA = true;
|
||||||
|
disableRenewal = false;
|
||||||
|
allowRenewalAfterExpiry = false;
|
||||||
|
disableSmallstepExtensions = false;
|
||||||
|
};
|
||||||
|
options = {
|
||||||
|
x509 = { };
|
||||||
|
ssh = { };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
tls = {
|
||||||
|
cipherSuites = [
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
||||||
|
];
|
||||||
|
minVersion = 1.2;
|
||||||
|
maxVersion = 1.3;
|
||||||
|
renegotiation = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
step-ca
|
step-ca
|
||||||
step-cli
|
step-cli
|
||||||
|
|||||||
Reference in New Issue
Block a user