ctucx.git: nixfiles

ctucx' nixfiles

commit e96e036c4d3eaf9c4bd4081572ac2aca5a5e1620
parent e95601ec61ffa0ffc6f8713313057b9e1092fe88
Author: Katja (ctucx) <git@ctu.cx>
Date: Sun, 9 Mar 2025 10:36:05 +0100

configurations/nixos/services: add CA
10 files changed, 139 insertions(+), 0 deletions(-)
diff --git a/configurations/nixos/configure/router/ruleset.nft b/configurations/nixos/configure/router/ruleset.nft
@@ -30,6 +30,7 @@ table inet firewall {
 		tcp dport ssh    accept
 		tcp dport http   accept
 		tcp dport https  accept
+		tcp dport 8443   accept comment "step-ca"
 		tcp dport 22000  accept comment "syncthing"
 		udp dport 21027  accept comment "syncthing"
 	}
diff --git a/configurations/nixos/services/ca/default.nix b/configurations/nixos/services/ca/default.nix
@@ -0,0 +1,68 @@
+{ config, ctucxLib, ... }:
+
+{
+
+  dns.zones."ctu.cx".subdomains."ca".AAAA = [ config.networking.primaryIP ];
+
+  age.secrets.caPassword.file = ./. + "/../../../../secrets/${config.networking.hostName}/caPassword.age";
+
+  services.pcscd.enable = true;
+
+  services.nginx.enable = true;
+  services.nginx.virtualHosts."ca.ctu.cx" = {
+    useACMEHost = "${config.networking.fqdn}";
+    forceSSL    = true;
+    kTLS        = true;
+    locations."/1.0/crl".proxyPass = "http://${toString config.services.step-ca.settings.insecureAddress}/1.0/crl";
+  };
+
+  services.step-ca = {
+    enable  = true;
+    address = "[2a03:4000:4d:5e:acab::1]";
+    port    = 8443;
+    intermediatePasswordFile = config.age.secrets.caPassword.path;
+    settings = {
+      insecureAddress   = "[::1]:9001";
+      logger.format     = "text";
+      root              = ../../../../secrets/certs/root_ca.crt;
+      crt               = ../../../../secrets/certs/intermediate_ca.crt;
+      key               = "yubikey:slot-id=83";
+      kms.type          = "yubikey";
+      kms.pin           = "123456";
+      dnsNames          = [ "ca.ctu.cx" ];
+      crl.enabled       = true;
+      crl.idpURL        = "http://ca.ctu.cx/1.0/crl";
+      db.type           = "badgerv2";
+      db.dataSource     = "/var/lib/step-ca/db";
+      tls.cipherSuites  = [ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" ];
+      tls.minVersion    = 1.2;
+      tls.maxVersion    = 1.3;
+      tls.renegotiation = false;
+      authority         = {
+        provisioners = let
+          adminCA = ctucxLib.toBase64 (builtins.readFile ../../../../secrets/certs/admin_ca.crt);
+        in [
+          {
+            type  = "X5C";
+            name  = "server-auth";
+            roots = adminCA;
+            options.x509.templateFile = ./templates/server-auth.tpl;
+            policy.x509.allow = {
+              dns   = [ "*.ctu.cx" "*.katja.wtf" ];
+              email = [ "@ctu.cx"  "@katja.wtf" ];
+            };
+          }
+          {
+            type  = "X5C";
+            name  = "client-auth";
+            roots = adminCA;
+            options.x509.templateFile = ./templates/client-auth.tpl;
+          }
+        ];
+        claims.maxTLSCertDuration     = "${toString (365*24)}h";
+        claims.defaultTLSCertDuration = "${toString (365*24)}h";
+      };
+    };
+  };
+
+}
diff --git a/configurations/nixos/services/ca/templates/client-auth.tpl b/configurations/nixos/services/ca/templates/client-auth.tpl
@@ -0,0 +1,11 @@
+{
+	"subject": {{ toJson .Subject }},
+	"sans": {{ toJson .SANs }},
+	{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
+	"keyUsage": ["keyEncipherment", "digitalSignature"],
+	{{- else }}
+	"keyUsage": ["digitalSignature"],
+	{{- end }}
+	"extKeyUsage": ["clientAuth"],
+	"crlDistributionPoints": ["http://ca.ctu.cx/1.0/crl"]
+}
diff --git a/configurations/nixos/services/ca/templates/server-auth.tpl b/configurations/nixos/services/ca/templates/server-auth.tpl
@@ -0,0 +1,11 @@
+{
+	"subject": {{ toJson .Subject }},
+	"sans": {{ toJson .SANs }},
+	{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
+	"keyUsage": ["keyEncipherment", "digitalSignature"],
+	{{- else }}
+	"keyUsage": ["digitalSignature"],
+	{{- end }}
+	"extKeyUsage": ["clientAuth", "serverAuth"],
+	"crlDistributionPoints": ["http://ca.ctu.cx/1.0/crl"]
+}
diff --git a/machines/briefkasten/default.nix b/machines/briefkasten/default.nix
@@ -13,6 +13,7 @@
       ctucxConfig.services.prometheus-exporters
       ctucxConfig.services.restic-server
 
+      ctucxConfig.services.ca
 
       ctucxConfig.websites."music.home.ctu.cx"
       ctucxConfig.websites."audiobooks.home.ctu.cx"
diff --git a/secrets/briefkasten/caPassword.age b/secrets/briefkasten/caPassword.age
@@ -0,0 +1,12 @@
+-----BEGIN AGE ENCRYPTED FILE-----
+YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6QklaQS9CMHFZRmh5cmFU
+b2hPNit5ODJkSkdGZHZML0R1SjVydys4ZXdrCngwNVdDU2txUDdoMXdYOW8rTnJV
+OFdvK0lNdlhEUG5NcWtMdjhCSTg1bFEKLT4gc3NoLWVkMjU1MTkgNGhLQ013IFN0
+TmxLSEN2K1A4aXNkZGpGMVBFMnI5cnhYM0RRNld5SGIwQ0Y2Um1zbncKMndJTEFm
+b2R3VnpnRENxVEFWc3lhK3JHVFQrbDBEdTc5a29zVjRmZkJ4WQotPiAuND54Pj4n
+Pi1ncmVhc2UgRzsjIHFZJ2VMSi99ClNYa1V3VHM2UTJzWEcyV0VoczhiK29wT2Ri
+L0psa29tZ0VielJuY2NISHpoUlgwWTFwcmhRWWwrcFZsNGl2c04KclZTK2hwNHJn
+SnR5cGhvRnZUMGFYY25HYkNoblpQZEpvN0kKLS0tIDgyWFordldjRlpMNUdrSzZU
+RWgxNU1Ca0RRR0hGbms1a1lPVDg1Z1Q0SkUK2G660T/07q8JgXOo9nlOhpdgSLKA
+HkLwRYY1zE9uFk5PLR0bhgeC
+-----END AGE ENCRYPTED FILE-----
diff --git a/secrets/certs/admin_ca.crt b/secrets/certs/admin_ca.crt
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBpzCCAUygAwIBAgIRAKKLvEljdpVO6JNYqflWWncwCgYIKoZIzj0EAwIwKDEO
+MAwGA1UEChMFY3R1Y3gxFjAUBgNVBAMTDWN0dWN4IFJvb3QgQ0EwHhcNMjUwMzA5
+MDgzMzM1WhcNMzUwMzA5MjAzMzI4WjAZMRcwFQYDVQQDEw5jdHVjeCBBZG1pbiBD
+QTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNoP42cEYZAa/aIq/Jzb+LIMT7aQ
+H34ROfIpFqFP4S68gx/hqvjx2GOrhYQYIfKe5jsMg/KeExvTXL+xkUYsOFWjZjBk
+MA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQ8
+nn+RmWgvvSKZmsp7aMaBvG19xzAfBgNVHSMEGDAWgBSqhrhQedsdpiYGJVAfVHht
+4wr6VDAKBggqhkjOPQQDAgNJADBGAiEAn6s7l1x326EgcJ5tYDlyh+kMYS6f8xP/
+8JcmbQcib9wCIQD56V/koqIQrGUi1m/Lfd0L0fHbZxz/l7KNLJshW7iv1A==
+-----END CERTIFICATE-----
diff --git a/secrets/certs/intermediate_ca.crt b/secrets/certs/intermediate_ca.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIB2jCCAX+gAwIBAgIQEAfq2YT/7Jfzx4cpsQvmvjAKBggqhkjOPQQDAjAoMQ4w
+DAYDVQQKEwVjdHVjeDEWMBQGA1UEAxMNY3R1Y3ggUm9vdCBDQTAeFw0yNTAzMDkw
+ODMxMDNaFw0zNTAzMDkyMDMwNTVaMCAxHjAcBgNVBAMTFWN0dWN4IEludGVybWVk
+aWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCUWnWAaFbaj+fDqJ+6Y
+KQnaX0tLhJyLUU+UBP4AvuCKGZCWasog5THaI0EB8aAONac3Qz/Y9Jza4uWo6Wxm
+5zijgZIwgY8wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD
+VR0OBBYEFHzxUGaL7gI5MvCJjkCDbJ9gIUNJMB8GA1UdIwQYMBaAFKqGuFB52x2m
+JgYlUB9UeG3jCvpUMCkGA1UdHwQiMCAwHqAcoBqGGGh0dHA6Ly9jYS5jdHUuY3gv
+MS4wL2NybDAKBggqhkjOPQQDAgNJADBGAiEArFAxS4ZmcksBIfx7dabtlSWsVM6y
+uJfIEfcOwgWNdxICIQDIOylbFiLnqkHVYCiQKBSOttJvBVl4kMrgwzhhHiPZ2g==
+-----END CERTIFICATE-----
diff --git a/secrets/certs/root_ca.crt b/secrets/certs/root_ca.crt
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBkjCCATmgAwIBAgIQHcFZjp65wx2iQWzi8TZ4QDAKBggqhkjOPQQDAjAoMQ4w
+DAYDVQQKEwVjdHVjeDEWMBQGA1UEAxMNY3R1Y3ggUm9vdCBDQTAeFw0yNTAzMDkw
+ODI2NDJaFw0zNTAzMDcwODI2NDJaMCgxDjAMBgNVBAoTBWN0dWN4MRYwFAYDVQQD
+Ew1jdHVjeCBSb290IENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEs9Q/rCru
+O1gqNosldxZluPX4UGBwtxjEAHN53axv1IeGzvzBXHzVggbGxnyCza4Dfe21jVTw
+OPMsH7E1nhVw26NFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C
+AQEwHQYDVR0OBBYEFKqGuFB52x2mJgYlUB9UeG3jCvpUMAoGCCqGSM49BAMCA0cA
+MEQCIGfh/cdpuZ4+mdmAwtKH+s8XPy/OoBJBbdI45jDkqJCpAiBhQy4n+2jR9tJo
+7bdNaN1dvCvhqgP8OFETk6g3ir8THQ==
+-----END CERTIFICATE-----
diff --git a/secrets/secrets.nix b/secrets/secrets.nix
@@ -41,6 +41,7 @@ let
       "wireguard-privkey.age"
       "restic-server-htpasswd.age"
       "pppd-env.age"
+      "caPassword.age"
 
       "restic/gotosocial.age"
       "restic/influxdb.age"