feat: add private ca for all internal web services

This commit is contained in:
Ryan Yin
2024-04-03 11:32:29 +08:00
parent 468480b4e7
commit f831061889
12 changed files with 118 additions and 22 deletions

2
certs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.key
*.csr

7
certs/README.md Normal file
View File

@@ -0,0 +1,7 @@
# My Private PKI / CA
This is my private Private Key Infrastructure (PKI) / Certificate Authority (CA) for my personal
use. It is used to issue certificates for my own servers and services.
All the private keys are ignored by git, and will be stored in my private secrets repo
[../secrets](../secrets/)

10
certs/ecc-ca.crt Normal file
View File

@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBajCB8QIJAIwL98is2nQPMAoGCCqGSM49BAMEMB8xHTAbBgNVBAMMFFJ5YW40
WWluJ3MgUm9vdCBDQSAxMB4XDTI0MDQwMzA4NDgzM1oXDTM0MDQwMTA4NDgzM1ow
HzEdMBsGA1UEAwwUUnlhbjRZaW4ncyBSb290IENBIDEwdjAQBgcqhkjOPQIBBgUr
gQQAIgNiAAQ6ixMbsGZ/u/ZnwzOZ49naVL7rQxm9C74SboGytKcYBH03JjC7tgZ3
DylirxSLcTYHHtCz9ajdamP6+sgiGVpUODtfGSO+WmS+gAbLjCS37T41bkUhkx88
JU4NsGhjPXcwCgYIKoZIzj0EAwQDaAAwZQIwDrGLSdO+p/1uywkzqzdM/OnZs8bp
n60uBhUI7EZzDmrouOFeGx+dXYI5yy5AD/qDAjEA7fTQx+jccyOj4dimq1iU9+71
e/gWYg0rexfy/+9dQY6kvwMzv8Lnm6URaRMbE1Q/
-----END CERTIFICATE-----

1
certs/ecc-ca.srl Normal file
View File

@@ -0,0 +1 @@
C050420A8E5A3C1E

22
certs/ecc-csr.conf Normal file
View File

@@ -0,0 +1,22 @@
[ req ]
prompt = no
req_extensions = v3_ext
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
countryName = US
stateOrProvinceName = NYK
localityName = NYK
organizationName = Ryan4Yin
organizationalUnitName = Ryan4Yin
commonName = writefor.fun # deprecated, use subjectAltName(SAN) instead
emailAddress = rayn4yin@linux.com
[ alt_names ]
DNS.1 = writefor.fun
DNS.2 = *.writefor.fun
[ v3_ext ]
subjectAltName=@alt_names
basicConstraints = CA:false
extendedKeyUsage = serverAuth

14
certs/ecc-server.crt Normal file
View File

@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICKTCCAa6gAwIBAgIJAMBQQgqOWjweMAoGCCqGSM49BAMEMB8xHTAbBgNVBAMM
FFJ5YW40WWluJ3MgUm9vdCBDQSAxMB4XDTI0MDQwMzA4NDgzM1oXDTM0MDQwMTA4
NDgzM1owgYkxCzAJBgNVBAYTAlVTMQwwCgYDVQQIDANOWUsxDDAKBgNVBAcMA05Z
SzERMA8GA1UECgwIUnlhbjRZaW4xETAPBgNVBAsMCFJ5YW40WWluMRUwEwYDVQQD
DAx3cml0ZWZvci5mdW4xITAfBgkqhkiG9w0BCQEWEnJheW40eWluQGxpbnV4LmNv
bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABCNTYKDq/I99NltQR5eKrrovQXp9BbLV
iuUdYmzFrAh+NC9ikiIqTfDwP+c+7QvDyI3KXu3KI2qPSPdxktZKDUPHK4p2Y2kZ
xKOI2IFTgTqV3uBciyx7ayWPTwBYxsTDmqNLMEkwJwYDVR0RBCAwHoIMd3JpdGVm
b3IuZnVugg4qLndyaXRlZm9yLmZ1bjAJBgNVHRMEAjAAMBMGA1UdJQQMMAoGCCsG
AQUFBwMBMAoGCCqGSM49BAMEA2kAMGYCMQCHw9YkDo15P9mqEObvxSUak8tQmhBB
9wB81Qg4c+JsMCZA1rMUB7GkNJj1Dr9rWLoCMQDSituLzmo/yPLEOrbNV83bj3/I
ikKgobSie3pMXm5ZG7krOXaunyFRR/bIkih2V2Q=
-----END CERTIFICATE-----

19
certs/gen-certs.sh Normal file
View File

@@ -0,0 +1,19 @@
# 1. generate the private key for the CA root certificate
openssl ecparam -genkey -name secp384r1 -out ecc-ca.key
# 2. generate the CA root certificate with the private key
# with the validity period of 10 years
openssl req -x509 -new -SHA512 -key ecc-ca.key -subj "/CN=Ryan4Yin's Root CA 1" -days 3650 -out ecc-ca.crt
# 3. generate the private key for the server certificate
openssl ecparam -genkey -name secp384r1 -out ecc-server.key
# 4. generate the certificate signing request (CSR) for the server certificate
# using the private key and the configuration file ecc-csr.conf
openssl req -new -SHA512 -key ecc-server.key -out ecc-server.csr -config ecc-csr.conf
# 5. sign the server certificate with the CA root certificate
openssl x509 -req -SHA512 -in ecc-server.csr -CA ecc-ca.crt -CAkey ecc-ca.key \
-CAcreateserial -out ecc-server.crt -days 3650 \
-extensions v3_ext -extfile ecc-csr.conf
openssl x509 -noout -text -in ecc-ca.crt
openssl x509 -noout -text -in ecc-server.crt

6
flake.lock generated
View File

@@ -892,10 +892,10 @@
"mysecrets": { "mysecrets": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1711871709, "lastModified": 1712114794,
"narHash": "sha256-Pj667YJdXbJPhQVUutpKoqH6e66eF8my5q8RQyl0BXI=", "narHash": "sha256-qWSnhqYo7o9+ThiH5TV5yPOWSKXCKpwSP+7HjnjBZvY=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "c0239ed183c43c18f6bdf2f9045602e1bb9ca310", "rev": "066524c12e11687110642005d5d51fec88306573",
"shallow": true, "shallow": true,
"type": "git", "type": "git",
"url": "ssh://git@github.com/ryan4yin/nix-secrets.git" "url": "ssh://git@github.com/ryan4yin/nix-secrets.git"

View File

@@ -1,4 +1,12 @@
{myvars, ...}: { {config, ...}: let
hostCommonConfig = ''
encode zstd gzip
tls ${../../certs/ecc-server.crt} ${config.age.secrets."certs/ecc-server.key".path} {
protocols tls1.3 tls1.3
curves x25519 secp384r1 secp521r1
}
'';
in {
services.caddy = { services.caddy = {
enable = true; enable = true;
# Reload Caddy instead of restarting it when configuration file changes. # Reload Caddy instead of restarting it when configuration file changes.
@@ -12,23 +20,19 @@
globalConfig = '' globalConfig = ''
http_port 80 http_port 80
https_port 443 https_port 443
auto_https off auto_https disable_certs
''; '';
# ACME related settings.
# email = myvars.useremail;
# acmeCA = "https://acme-v02.api.letsencrypt.org/directory";
# Dashboard # Dashboard
virtualHosts."http://home.writefor.fun".extraConfig = '' virtualHosts."home.writefor.fun".extraConfig = ''
encode zstd gzip ${hostCommonConfig}
reverse_proxy http://localhost:4401 reverse_proxy http://localhost:4401
''; '';
# https://caddyserver.com/docs/caddyfile/directives/file_server # https://caddyserver.com/docs/caddyfile/directives/file_server
virtualHosts."http://file.writefor.fun".extraConfig = '' virtualHosts."file.writefor.fun".extraConfig = ''
root * /var/lib/caddy/fileserver/ root * /var/lib/caddy/fileserver/
encode zstd gzip ${hostCommonConfig}
file_server browse { file_server browse {
hide .git hide .git
precompressed zstd br gzip precompressed zstd br gzip
@@ -36,42 +40,42 @@
''; '';
# Datastore # Datastore
virtualHosts."http://attic.writefor.fun".extraConfig = '' virtualHosts."attic.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:3300 reverse_proxy http://localhost:3300
''; '';
virtualHosts."http://git.writefor.fun".extraConfig = '' virtualHosts."git.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:3301 reverse_proxy http://localhost:3301
''; '';
virtualHosts."http://sftpgo.writefor.fun".extraConfig = '' virtualHosts."sftpgo.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:3302 reverse_proxy http://localhost:3302
''; '';
virtualHosts."http://webdav.writefor.fun".extraConfig = '' virtualHosts."webdav.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:3303 reverse_proxy http://localhost:3303
''; '';
virtualHosts."http://transmission.writefor.fun".extraConfig = '' virtualHosts."transmission.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:9091 reverse_proxy http://localhost:9091
''; '';
# Monitoring # Monitoring
virtualHosts."http://uptime-kuma.writefor.fun".extraConfig = '' virtualHosts."uptime-kuma.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:3350 reverse_proxy http://localhost:3350
''; '';
virtualHosts."http://grafana.writefor.fun".extraConfig = '' virtualHosts."grafana.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:3351 reverse_proxy http://localhost:3351
''; '';
virtualHosts."http://prometheus.writefor.fun".extraConfig = '' virtualHosts."prometheus.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:9090 reverse_proxy http://localhost:9090
''; '';
virtualHosts."http://alertmanager.writefor.fun".extraConfig = '' virtualHosts."alertmanager.writefor.fun".extraConfig = ''
encode zstd gzip encode zstd gzip
reverse_proxy http://localhost:9093 reverse_proxy http://localhost:9093
''; '';

View File

@@ -10,6 +10,11 @@
] ]
++ (import ../overlays args); ++ (import ../overlays args);
# Add my private PKI's CA certificate to the system-wide trust store.
security.pki.certificateFiles = [
../certs/ecc-ca.crt
];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git # used by nix flakes git # used by nix flakes
git-lfs # used by huggingface models git-lfs # used by huggingface models

View File

@@ -26,6 +26,7 @@
++ [ ++ [
{modules.secrets.server.application.enable = true;} {modules.secrets.server.application.enable = true;}
{modules.secrets.server.operation.enable = true;} {modules.secrets.server.operation.enable = true;}
{modules.secrets.server.webserver.enable = true;}
]; ];
home-modules = map mylib.relativeToRoot [ home-modules = map mylib.relativeToRoot [
"home/linux/tui.nix" "home/linux/tui.nix"

View File

@@ -34,6 +34,7 @@ in {
server.application.enable = mkEnableOption "NixOS Secrets for Application Servers"; server.application.enable = mkEnableOption "NixOS Secrets for Application Servers";
server.operation.enable = mkEnableOption "NixOS Secrets for Operation Servers(Backup, Monitoring, etc)"; server.operation.enable = mkEnableOption "NixOS Secrets for Operation Servers(Backup, Monitoring, etc)";
server.kubernetes.enable = mkEnableOption "NixOS Secrets for Kubernetes"; server.kubernetes.enable = mkEnableOption "NixOS Secrets for Kubernetes";
server.webserver.enable = mkEnableOption "NixOS Secrets for Web Servers(contains tls cert keys)";
impermanence.enable = mkEnableOption "whether use impermanence and ephemeral root file system"; impermanence.enable = mkEnableOption "whether use impermanence and ephemeral root file system";
}; };
@@ -244,5 +245,15 @@ in {
// high_security; // high_security;
}; };
}) })
(mkIf cfg.server.webserver.enable {
age.secrets = {
"certs/ecc-server.key" = {
file = "${mysecrets}/certs/ecc-server.key.age";
mode = "0400";
owner = "caddy"; # used by caddy only
};
};
})
]); ]);
} }