ops/nixos: migrate everything to vault-agent-acme
This commit is contained in:
parent
0c7f785107
commit
daccfa5717
14 changed files with 126 additions and 123 deletions
|
@ -69,7 +69,6 @@ in {
|
||||||
recommendedTlsSettings = true;
|
recommendedTlsSettings = true;
|
||||||
recommendedGzipSettings = true;
|
recommendedGzipSettings = true;
|
||||||
virtualHosts."objdump.zxcvbnm.ninja" = {
|
virtualHosts."objdump.zxcvbnm.ninja" = {
|
||||||
useACMEHost = "objdump.zxcvbnm.ninja";
|
|
||||||
default = true;
|
default = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
|
@ -82,11 +81,9 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
security.acme.certs."objdump.zxcvbnm.ninja" = {
|
my.vault.acmeCertificates."objdump.zxcvbnm.ninja" = {
|
||||||
group = config.services.nginx.group;
|
extraNames = [ "*.objdump.zxcvbnm.ninja" ];
|
||||||
extraDomainNames = [
|
nginxVirtualHosts = [ "objdump.zxcvbnm.ninja" ];
|
||||||
"*.objdump.zxcvbnm.ninja"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
my.fup.listen = [
|
my.fup.listen = [
|
||||||
"0.0.0.0" "[::]"
|
"0.0.0.0" "[::]"
|
||||||
|
|
|
@ -58,8 +58,8 @@ in {
|
||||||
use-auth-secret = true;
|
use-auth-secret = true;
|
||||||
realm = "matrix.zxcvbnm.ninja";
|
realm = "matrix.zxcvbnm.ninja";
|
||||||
static-auth-secret = machineSecrets.turnSecret;
|
static-auth-secret = machineSecrets.turnSecret;
|
||||||
cert = "${config.security.acme.certs."matrix.zxcvbnm.ninja".directory}/fullchain.pem";
|
cert = "/var/lib/acme/matrix.zxcvbnm.ninja/fullchain.pem";
|
||||||
pkey = "${config.security.acme.certs."matrix.zxcvbnm.ninja".directory}/key.pem";
|
pkey = "/var/lib/acme/matrix.zxcvbnm.ninja/privkey.pem";
|
||||||
};
|
};
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -71,7 +71,6 @@ in {
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
"zxcvbnm.ninja" = {
|
"zxcvbnm.ninja" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
useACMEHost = "matrix.zxcvbnm.ninja";
|
|
||||||
locations = let
|
locations = let
|
||||||
inherit (lib) mapAttrs' nameValuePair;
|
inherit (lib) mapAttrs' nameValuePair;
|
||||||
wellKnown = {
|
wellKnown = {
|
||||||
|
@ -90,13 +89,11 @@ in {
|
||||||
};
|
};
|
||||||
"matrix.zxcvbnm.ninja" = {
|
"matrix.zxcvbnm.ninja" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
useACMEHost = "matrix.zxcvbnm.ninja";
|
|
||||||
locations."/".return = "301 https://element.zxcvbnm.ninja$request_uri";
|
locations."/".return = "301 https://element.zxcvbnm.ninja$request_uri";
|
||||||
locations."/_matrix".proxyPass = "http://[::1]:8008";
|
locations."/_matrix".proxyPass = "http://[::1]:8008";
|
||||||
};
|
};
|
||||||
"element.zxcvbnm.ninja" = {
|
"element.zxcvbnm.ninja" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
useACMEHost = "matrix.zxcvbnm.ninja";
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
add_header X-Frame-Options SAMEORIGIN;
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
add_header X-Content-Type-Options nosniff;
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
@ -168,9 +165,10 @@ in {
|
||||||
members = [ "turnserver" "nginx" ];
|
members = [ "turnserver" "nginx" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.certs."matrix.zxcvbnm.ninja" = {
|
my.vault.acmeCertificates."matrix.zxcvbnm.ninja" = {
|
||||||
group = "matrixcert";
|
group = "matrixcert";
|
||||||
extraDomainNames = [ "element.zxcvbnm.ninja" "zxcvbnm.ninja" ];
|
extraNames = [ "element.zxcvbnm.ninja" "zxcvbnm.ninja" ];
|
||||||
|
nginxVirtualHosts = [ "zxcvbnm.ninja" "element.zxcvbnm.ninja" "matrix.zxcvbnm.ninja" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "21.05";
|
system.stateVersion = "21.05";
|
||||||
|
|
|
@ -36,8 +36,8 @@ in {
|
||||||
use-auth-secret = true;
|
use-auth-secret = true;
|
||||||
realm = "turn.lukegb.com";
|
realm = "turn.lukegb.com";
|
||||||
static-auth-secret = machineSecrets.turnSecret;
|
static-auth-secret = machineSecrets.turnSecret;
|
||||||
cert = "${config.security.acme.certs."turn.lukegb.com".directory}/fullchain.pem";
|
cert = "/var/lib/acme/turn.lukegb.com/fullchain.pem";
|
||||||
pkey = "${config.security.acme.certs."turn.lukegb.com".directory}/key.pem";
|
pkey = "/var/lib/acme/turn.lukegb.com/privkey.pem";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.prosody = {
|
services.prosody = {
|
||||||
|
@ -50,8 +50,8 @@ in {
|
||||||
virtualHosts."lukegb.com" = {
|
virtualHosts."lukegb.com" = {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
domain = "lukegb.com";
|
domain = "lukegb.com";
|
||||||
ssl.cert = "${config.security.acme.certs."xmpp.lukegb.com".directory}/fullchain.pem";
|
ssl.cert = "/var/lib/acme/xmpp.lukegb.com/fullchain.pem";
|
||||||
ssl.key = "${config.security.acme.certs."xmpp.lukegb.com".directory}/key.pem";
|
ssl.key = "/var/lib/acme/xmpp.lukegb.com/privkey.pem";
|
||||||
};
|
};
|
||||||
muc = [{
|
muc = [{
|
||||||
domain = "muc.xmpp.lukegb.com";
|
domain = "muc.xmpp.lukegb.com";
|
||||||
|
@ -86,12 +86,12 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme = {
|
my.vault.acmeCertificates = {
|
||||||
certs."xmpp.lukegb.com" = {
|
"xmpp.lukegb.com" = {
|
||||||
group = "prosody";
|
group = "prosody";
|
||||||
extraDomainNames = [ "*.xmpp.lukegb.com" "lukegb.com" ];
|
extraNames = [ "*.xmpp.lukegb.com" "lukegb.com" ];
|
||||||
};
|
};
|
||||||
certs."turn.lukegb.com" = {
|
"turn.lukegb.com" = {
|
||||||
group = "turnserver";
|
group = "turnserver";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,14 +54,9 @@ in {
|
||||||
};
|
};
|
||||||
my.ip.tailscale = "100.120.98.116";
|
my.ip.tailscale = "100.120.98.116";
|
||||||
|
|
||||||
security.acme.certs."as205479.net" = {
|
my.vault.acmeCertificates."as205479.net" = {
|
||||||
extraDomainNames = [ "www.as205479.net" ];
|
group = "acme";
|
||||||
dnsProvider = "gcloud";
|
reloadOrRestartUnits = [ "freeradius.service" ];
|
||||||
credentialsFile = secrets.gcpDNSCredentials;
|
|
||||||
dnsPropagationCheck = false;
|
|
||||||
postRun = ''
|
|
||||||
systemctl restart freeradius
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
users.users.nginx.extraGroups = lib.mkAfter [ "acme" ];
|
users.users.nginx.extraGroups = lib.mkAfter [ "acme" ];
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ eap {
|
||||||
#
|
#
|
||||||
tls-config tls-common {
|
tls-config tls-common {
|
||||||
#private_key_password = whatever
|
#private_key_password = whatever
|
||||||
private_key_file = /var/lib/acme/as205479.net/key.pem
|
private_key_file = /var/lib/acme/as205479.net/privkey.pem
|
||||||
|
|
||||||
# If Private key & Certificate are located in
|
# If Private key & Certificate are located in
|
||||||
# the same file, then private_key_file &
|
# the same file, then private_key_file &
|
||||||
|
|
|
@ -192,11 +192,9 @@ in {
|
||||||
dataDir = "/persist/etc/znc";
|
dataDir = "/persist/etc/znc";
|
||||||
useLegacyConfig = false;
|
useLegacyConfig = false;
|
||||||
};
|
};
|
||||||
security.acme.certs."znc.lukegb.com" = {
|
my.vault.acmeCertificates."znc.lukegb.com" = {
|
||||||
dnsProvider = null;
|
extraNames = [ "akiichiro.lukegb.com" ];
|
||||||
webroot = "/var/lib/acme/.challenges";
|
|
||||||
group = "znc-acme";
|
group = "znc-acme";
|
||||||
extraDomainNames = ["akiichiro.lukegb.com"];
|
|
||||||
};
|
};
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -251,7 +251,6 @@ in {
|
||||||
services.pomerium = {
|
services.pomerium = {
|
||||||
enable = true;
|
enable = true;
|
||||||
secretsFile = machineSecrets.pomeriumSecrets;
|
secretsFile = machineSecrets.pomeriumSecrets;
|
||||||
useACMEHost = "int.lukegb.com";
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
address = ":443";
|
address = ":443";
|
||||||
|
@ -280,6 +279,10 @@ in {
|
||||||
authenticate_service_url = "https://auth.int.lukegb.com";
|
authenticate_service_url = "https://auth.int.lukegb.com";
|
||||||
signout_redirect_url = "https://logged-out.int.lukegb.com";
|
signout_redirect_url = "https://logged-out.int.lukegb.com";
|
||||||
|
|
||||||
|
certificates = [
|
||||||
|
{ cert = "/var/lib/acme/lukegb.com/fullchain.pem"; key = "/var/lib/acme/lukegb.com/privkey.pem"; }
|
||||||
|
];
|
||||||
|
|
||||||
policy = let
|
policy = let
|
||||||
baseConfig = {
|
baseConfig = {
|
||||||
allowed_domains = [ "lukegb.com" ];
|
allowed_domains = [ "lukegb.com" ];
|
||||||
|
@ -344,18 +347,18 @@ in {
|
||||||
systemd.services.pomerium = {
|
systemd.services.pomerium = {
|
||||||
wants = lib.mkAfter [ "redis.service" ];
|
wants = lib.mkAfter [ "redis.service" ];
|
||||||
after = lib.mkAfter [ "redis.service" ];
|
after = lib.mkAfter [ "redis.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
SupplementaryGroups = [ "acme" ];
|
||||||
|
ReadOnlyPaths = [ "/var/lib/acme" ];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
security.acme.certs."int.lukegb.com" = {
|
my.vault.acmeCertificates."lukegb.com" = {
|
||||||
domain = "*.int.lukegb.com";
|
extraNames = [
|
||||||
extraDomainNames = [
|
|
||||||
# "int.lukegb.com" # redundant with *.lukegb.com
|
|
||||||
"lukegb.com"
|
"lukegb.com"
|
||||||
"*.lukegb.com"
|
"*.lukegb.com"
|
||||||
"objdump.zxcvbnm.ninja"
|
"objdump.zxcvbnm.ninja"
|
||||||
];
|
];
|
||||||
postRun = ''
|
reloadOrRestartUnits = [ "pomerium.service" ];
|
||||||
systemctl restart pomerium
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "20.09";
|
system.stateVersion = "20.09";
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
{ config, depot, lib, ... }:
|
{ config, depot, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
security.acme.certs."as205479.net" = {
|
|
||||||
dnsProvider = "gcloud";
|
|
||||||
credentialsFile = depot.ops.secrets.gcpDNSCredentials;
|
|
||||||
dnsPropagationCheck = false;
|
|
||||||
};
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
virtualHosts."as205479.net" = {
|
virtualHosts."as205479.net" = {
|
||||||
useACMEHost = "as205479.net";
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/".root = depot.web.as205479 config.networking.hostName;
|
locations."/".root = depot.web.as205479 config.networking.hostName;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
my.vault.acmeCertificates."as205479.net" = {
|
||||||
|
role = "letsencrypt-gcloud-as205479";
|
||||||
|
extraNames = [ "www.as205479.net" ];
|
||||||
|
nginxVirtualHosts = [ "as205479.net" ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,6 @@ in
|
||||||
services.nginx.recommendedTlsSettings = true;
|
services.nginx.recommendedTlsSettings = true;
|
||||||
services.nginx.virtualHosts = {
|
services.nginx.virtualHosts = {
|
||||||
"baserow.lukegb.com" = {
|
"baserow.lukegb.com" = {
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
proxy_read_timeout 1800s;
|
proxy_read_timeout 1800s;
|
||||||
|
@ -160,7 +159,6 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
"api.baserow.lukegb.com" = {
|
"api.baserow.lukegb.com" = {
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
proxy_read_timeout 1800s;
|
proxy_read_timeout 1800s;
|
||||||
|
@ -173,9 +171,7 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
"baserow-media.zxcvbnm.ninja" = {
|
"baserow-media.zxcvbnm.ninja" = {
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
|
|
||||||
root = "/var/lib/baserow/media";
|
root = "/var/lib/baserow/media";
|
||||||
locations."/user_files" = {
|
locations."/user_files" = {
|
||||||
root = "/var/lib/baserow/media";
|
root = "/var/lib/baserow/media";
|
||||||
|
@ -191,6 +187,12 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
my.vault.acmeCertificates = {
|
||||||
|
"baserow.lukegb.com" = {
|
||||||
|
extraNames = [ "api.baserow.lukegb.com" "baserow-media.zxcvbnm.ninja" ];
|
||||||
|
nginxVirtualHosts = [ "baserow.lukegb.com" "api.baserow.lukegb.com" "baserow-media.zxcvbnm.ninja" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services.postfix = {
|
services.postfix = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -27,14 +27,13 @@ in
|
||||||
ssl = true;
|
ssl = true;
|
||||||
}) config.my.fup.listen);
|
}) config.my.fup.listen);
|
||||||
in {
|
in {
|
||||||
security.acme.certs."p.lukegb.com" = {
|
my.vault.acmeCertificates."p.lukegb.com" = {
|
||||||
group = config.services.nginx.group;
|
nginxVirtualHosts = [ "p.lukegb.com" ];
|
||||||
};
|
};
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
virtualHosts."p.lukegb.com" = {
|
virtualHosts."p.lukegb.com" = {
|
||||||
listen = nginxListen;
|
listen = nginxListen;
|
||||||
useACMEHost = "p.lukegb.com";
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://unix:${sock}";
|
proxyPass = "http://unix:${sock}";
|
||||||
|
|
|
@ -25,21 +25,19 @@ in
|
||||||
ssl = true;
|
ssl = true;
|
||||||
}) config.my.quotesdb.listen);
|
}) config.my.quotesdb.listen);
|
||||||
in {
|
in {
|
||||||
security.acme.certs."bfob.gg" = {
|
my.vault.acmeCertificates."bfob.gg" = {
|
||||||
group = config.services.nginx.group;
|
extraNames = [ "*.bfob.gg" ];
|
||||||
extraDomainNames = ["*.bfob.gg"];
|
nginxVirtualHosts = [ "qdb.bfob.gg" "quotes.bfob.gg" "dev-quotes.bfob.gg" ];
|
||||||
};
|
};
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
virtualHosts."qdb.bfob.gg" = {
|
virtualHosts."qdb.bfob.gg" = {
|
||||||
listen = nginxListen;
|
listen = nginxListen;
|
||||||
useACMEHost = "bfob.gg";
|
|
||||||
globalRedirect = "quotes.bfob.gg";
|
globalRedirect = "quotes.bfob.gg";
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
};
|
};
|
||||||
virtualHosts."quotes.bfob.gg" = {
|
virtualHosts."quotes.bfob.gg" = {
|
||||||
listen = nginxListen;
|
listen = nginxListen;
|
||||||
useACMEHost = "bfob.gg";
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/static" = {
|
locations."/static" = {
|
||||||
root = "${pkg}/share";
|
root = "${pkg}/share";
|
||||||
|
@ -50,7 +48,6 @@ in
|
||||||
};
|
};
|
||||||
virtualHosts."dev-quotes.bfob.gg" = {
|
virtualHosts."dev-quotes.bfob.gg" = {
|
||||||
listen = nginxListen;
|
listen = nginxListen;
|
||||||
useACMEHost = "bfob.gg";
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://127.0.0.1:8000";
|
proxyPass = "http://127.0.0.1:8000";
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
{ pkgs, config, depot, lib, ... }:
|
{ pkgs, config, depot, lib, ... }:
|
||||||
let
|
let
|
||||||
inherit (lib) mkOption types mkBefore optionalAttrs;
|
inherit (lib) mkOption types mkBefore optionalAttrs mkDefault;
|
||||||
|
|
||||||
|
acmeCertificates = lib.mapAttrsToList (name: cOrig: cOrig // { inherit name; }) config.my.vault.acmeCertificates;
|
||||||
|
|
||||||
# Work out where we're being asked to write things, and which groups, so we can correctly get permissions.
|
# Work out where we're being asked to write things, and which groups, so we can correctly get permissions.
|
||||||
fullchainPath = c: pathFor c.fullchain c "fullchain.pem";
|
fullchainPath = c: pathFor c.fullchain c "fullchain.pem";
|
||||||
|
@ -12,7 +14,17 @@ let
|
||||||
keyPath = c: pathFor c.key c "privkey.pem";
|
keyPath = c: pathFor c.key c "privkey.pem";
|
||||||
pathFor = p: c: suffix: if isNull p.path then "/var/lib/acme/${c.name}/${suffix}" else p.path;
|
pathFor = p: c: suffix: if isNull p.path then "/var/lib/acme/${c.name}/${suffix}" else p.path;
|
||||||
|
|
||||||
acmeCertificatesGroups = lib.unique (lib.filter (x: x != "") (builtins.concatMap (c: [ c.fullchain.group c.chain.group c.key.group ]) config.my.vault.acmeCertificates));
|
isNginx = c: builtins.length c.nginxVirtualHosts > 0;
|
||||||
|
defaultGroup = c: if isNull c.group then if isNginx c then "nginx" else "acme" else c.group;
|
||||||
|
groupOrDefault = p: c: if isNull p then defaultGroup c else p;
|
||||||
|
|
||||||
|
reloadOrRestartUnits = c: (lib.optional (isNginx c) "nginx.service") ++ c.reloadOrRestartUnits;
|
||||||
|
|
||||||
|
acmeCertificatesGroups = lib.unique (lib.filter (x: x != "") (builtins.concatMap (c: [
|
||||||
|
(groupOrDefault c.fullchain.group c)
|
||||||
|
(groupOrDefault c.chain.group c)
|
||||||
|
(groupOrDefault c.key.group c)
|
||||||
|
]) acmeCertificates));
|
||||||
|
|
||||||
acmeCertificatesTemplate = builtins.concatMap (c: let
|
acmeCertificatesTemplate = builtins.concatMap (c: let
|
||||||
secretStanza = ''
|
secretStanza = ''
|
||||||
|
@ -27,14 +39,16 @@ let
|
||||||
'';
|
'';
|
||||||
destination = fullchainPath c;
|
destination = fullchainPath c;
|
||||||
perms = c.fullchain.mode;
|
perms = c.fullchain.mode;
|
||||||
command = pkgs.writeShellScript "post-${c.name}-crt" ''
|
command = let
|
||||||
|
grp = groupOrDefault c.fullchain.group c;
|
||||||
|
in pkgs.writeShellScript "post-${c.name}-crt" ''
|
||||||
sleep 1s # Cheap hack...
|
sleep 1s # Cheap hack...
|
||||||
${lib.optionalString (c.fullchain.group != "") ''
|
${lib.optionalString (grp != "") ''
|
||||||
chgrp "${c.fullchain.group}" "${fullchainPath c}"
|
chgrp "${grp}" "${fullchainPath c}"
|
||||||
''}
|
''}
|
||||||
${lib.concatMapStringsSep "\n" (x: ''
|
${lib.concatMapStringsSep "\n" (x: ''
|
||||||
/run/current-system/sw/bin/systemctl reload-or-restart ${x}
|
/run/current-system/sw/bin/systemctl reload-or-restart ${x}
|
||||||
'') c.reloadOrRestartUnits}
|
'') (reloadOrRestartUnits c)}
|
||||||
${lib.concatMapStringsSep "\n" (x: ''
|
${lib.concatMapStringsSep "\n" (x: ''
|
||||||
/run/current-system/sw/bin/systemctl restart ${x}
|
/run/current-system/sw/bin/systemctl restart ${x}
|
||||||
'') c.restartUnits}
|
'') c.restartUnits}
|
||||||
|
@ -48,9 +62,11 @@ let
|
||||||
'';
|
'';
|
||||||
destination = chainPath c;
|
destination = chainPath c;
|
||||||
perms = c.chain.mode;
|
perms = c.chain.mode;
|
||||||
command = pkgs.writeShellScript "post-${c.name}-chain" ''
|
command = let
|
||||||
${lib.optionalString (c.chain.group != "") ''
|
grp = groupOrDefault c.chain.group c;
|
||||||
chgrp "${c.chain.group}" "${chainPath c}"
|
in pkgs.writeShellScript "post-${c.name}-chain" ''
|
||||||
|
${lib.optionalString (grp != "") ''
|
||||||
|
chgrp "${grp}" "${chainPath c}"
|
||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
} {
|
} {
|
||||||
|
@ -61,13 +77,15 @@ let
|
||||||
'';
|
'';
|
||||||
destination = keyPath c;
|
destination = keyPath c;
|
||||||
perms = c.key.mode;
|
perms = c.key.mode;
|
||||||
command = pkgs.writeShellScript "post-${c.name}-key" ''
|
command = let
|
||||||
${lib.optionalString (c.key.group != "") ''
|
grp = groupOrDefault c.key.group c;
|
||||||
chgrp "${c.key.group}" "${keyPath c}"
|
in pkgs.writeShellScript "post-${c.name}-key" ''
|
||||||
|
${lib.optionalString (grp != "") ''
|
||||||
|
chgrp "${grp}" "${keyPath c}"
|
||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
]) config.my.vault.acmeCertificates;
|
]) acmeCertificates;
|
||||||
|
|
||||||
acmeCertificatesTmpdirs = lib.unique (builtins.concatMap (c:
|
acmeCertificatesTmpdirs = lib.unique (builtins.concatMap (c:
|
||||||
let
|
let
|
||||||
|
@ -75,21 +93,25 @@ let
|
||||||
chainDir = dirOf (chainPath c);
|
chainDir = dirOf (chainPath c);
|
||||||
keyDir = dirOf (keyPath c);
|
keyDir = dirOf (keyPath c);
|
||||||
|
|
||||||
dirGroup = if fullchainDir == keyDir && chainDir == keyDir && c.fullchain.makeDir && c.chain.makeDir && c.key.makeDir then if c.fullchain.group == c.key.group && c.fullchain.group == c.chain.group then c.fullchain.group else "-" else null;
|
fullchainGroup = groupOrDefault c.fullchain.group c;
|
||||||
|
chainGroup = groupOrDefault c.chain.group c;
|
||||||
|
keyGroup = groupOrDefault c.key.group c;
|
||||||
|
|
||||||
fullchainDirGroup = if isNull dirGroup then c.fullchain.group else dirGroup;
|
dirGroup = if fullchainDir == keyDir && chainDir == keyDir && c.fullchain.makeDir && c.chain.makeDir && c.key.makeDir then if fullchainGroup == keyGroup && fullchainGroup == chainGroup then fullchainGroup else "-" else null;
|
||||||
chainDirGroup = if isNull dirGroup then c.chain.group else dirGroup;
|
|
||||||
keyDirGroup = if isNull dirGroup then c.key.group else dirGroup;
|
fullchainDirGroup = if isNull dirGroup then fullchainGroup else dirGroup;
|
||||||
|
chainDirGroup = if isNull dirGroup then chainGroup else dirGroup;
|
||||||
|
keyDirGroup = if isNull dirGroup then keyGroup else dirGroup;
|
||||||
in lib.optional c.fullchain.makeDir "d ${fullchainDir} 0750 vault-agent ${fullchainDirGroup} - -"
|
in lib.optional c.fullchain.makeDir "d ${fullchainDir} 0750 vault-agent ${fullchainDirGroup} - -"
|
||||||
++ lib.optional c.chain.makeDir "d ${chainDir} 0750 vault-agent ${chainDirGroup} - -"
|
++ lib.optional c.chain.makeDir "d ${chainDir} 0750 vault-agent ${chainDirGroup} - -"
|
||||||
++ lib.optional c.key.makeDir "d ${keyDir} 0750 vault-agent ${keyDirGroup} - -"
|
++ lib.optional c.key.makeDir "d ${keyDir} 0750 vault-agent ${keyDirGroup} - -"
|
||||||
) config.my.vault.acmeCertificates);
|
) acmeCertificates);
|
||||||
|
|
||||||
allRestartableUnits = lib.unique (builtins.concatMap (c: c.reloadOrRestartUnits ++ c.restartUnits) config.my.vault.acmeCertificates);
|
allRestartableUnits = lib.unique (builtins.concatMap (c: (reloadOrRestartUnits c) ++ c.restartUnits) acmeCertificates);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.my.vault.acmeCertificates = mkOption {
|
options.my.vault.acmeCertificates = mkOption {
|
||||||
type = with types; listOf (submodule {
|
type = with types; attrsOf (submodule {
|
||||||
options = let
|
options = let
|
||||||
fileType = what: defaultMode: submodule {
|
fileType = what: defaultMode: submodule {
|
||||||
options = {
|
options = {
|
||||||
|
@ -105,9 +127,9 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = str;
|
type = nullOr str;
|
||||||
default = "acme";
|
default = null;
|
||||||
description = "Owner group to set for the ${what}.";
|
description = "Owner group to set for the ${what}. If null, taken from parent.";
|
||||||
};
|
};
|
||||||
|
|
||||||
makeDir = mkOption {
|
makeDir = mkOption {
|
||||||
|
@ -123,10 +145,6 @@ in
|
||||||
default = "letsencrypt-cloudflare";
|
default = "letsencrypt-cloudflare";
|
||||||
description = "Which role to use for certificate issuance.";
|
description = "Which role to use for certificate issuance.";
|
||||||
};
|
};
|
||||||
name = mkOption {
|
|
||||||
type = str;
|
|
||||||
description = "First hostname for the certificate.";
|
|
||||||
};
|
|
||||||
extraNames = mkOption {
|
extraNames = mkOption {
|
||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
|
@ -149,6 +167,18 @@ in
|
||||||
description = "List of systemd units to restart after obtaining a new certificate.";
|
description = "List of systemd units to restart after obtaining a new certificate.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nginxVirtualHosts = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [];
|
||||||
|
description = "List of nginx virtual hosts to apply SSL to.";
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = "Owner group to set for the generated files. Defaults to 'acme' unless nginxVirtualHosts is set, in which case it defaults to 'nginx'.";
|
||||||
|
};
|
||||||
|
|
||||||
fullchain = mkOption {
|
fullchain = mkOption {
|
||||||
type = fileType "certificate's full chain" "0644";
|
type = fileType "certificate's full chain" "0644";
|
||||||
default = {};
|
default = {};
|
||||||
|
@ -163,7 +193,7 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = [];
|
default = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
@ -181,6 +211,18 @@ in
|
||||||
tmpfiles.rules = acmeCertificatesTmpdirs;
|
tmpfiles.rules = acmeCertificatesTmpdirs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.nginx = optionalAttrs config.my.vault.enable {
|
||||||
|
virtualHosts = builtins.listToAttrs (builtins.concatMap (certData: let
|
||||||
|
fullchain = fullchainPath certData;
|
||||||
|
chain = chainPath certData;
|
||||||
|
key = keyPath certData;
|
||||||
|
in map (hostName: lib.nameValuePair hostName {
|
||||||
|
sslCertificate = mkDefault (fullchainPath certData);
|
||||||
|
sslCertificateKey = mkDefault (keyPath certData);
|
||||||
|
sslTrustedCertificate = mkDefault (chainPath certData);
|
||||||
|
}) certData.nginxVirtualHosts) acmeCertificates);
|
||||||
|
};
|
||||||
|
|
||||||
security.polkit.extraConfig = lib.mkAfter ''
|
security.polkit.extraConfig = lib.mkAfter ''
|
||||||
// NixOS module: depot/lib/vault-agent-acme.nix
|
// NixOS module: depot/lib/vault-agent-acme.nix
|
||||||
polkit.addRule(function(action, subject) {
|
polkit.addRule(function(action, subject) {
|
||||||
|
|
|
@ -186,7 +186,6 @@ in {
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
root = "/srv/pancake/public_html";
|
root = "/srv/pancake/public_html";
|
||||||
useACMEHost = "invoices.lukegb.com";
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
tryFiles = "$uri $uri/ @router";
|
tryFiles = "$uri $uri/ @router";
|
||||||
|
@ -201,7 +200,6 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
"plex-totoro.lukegb.com" = {
|
"plex-totoro.lukegb.com" = {
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://localhost:32400/";
|
proxyPass = "http://localhost:32400/";
|
||||||
|
@ -241,18 +239,6 @@ in {
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme = {
|
|
||||||
certs."invoices.lukegb.com" = {
|
|
||||||
domain = "invoices.lukegb.com";
|
|
||||||
postRun = ''
|
|
||||||
systemctl reload nginx
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
certs."trains.lukegb.com" = {
|
|
||||||
domain = "trains.lukegb.com";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.prometheus = {
|
services.prometheus = {
|
||||||
enable = true;
|
enable = true;
|
||||||
stateDir = "export/monitoring/prometheus";
|
stateDir = "export/monitoring/prometheus";
|
||||||
|
@ -557,17 +543,10 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
my.vault.acmeCertificates = [
|
my.vault.acmeCertificates = {
|
||||||
{
|
"plex-totoro.lukegb.com" = { nginxVirtualHosts = [ "plex-totoro.lukegb.com" ]; };
|
||||||
name = "lukegb.com";
|
"invoices.lukegb.com" = { nginxVirtualHosts = [ "invoices.lukegb.com" ]; };
|
||||||
role = "lukegb.com-staging";
|
};
|
||||||
extraNames = [ "*.lukegb.com" "*.int.lukegb.com" ];
|
|
||||||
restartUnits = [ "nginx.service" ];
|
|
||||||
#certificate.path = "/tmp/lukegb.com.crt";
|
|
||||||
#key.path = "/tmp/lukegb.com.key";
|
|
||||||
key.group = "acme";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "20.03";
|
system.stateVersion = "20.03";
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,20 +133,14 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.certs."ha.lukegb.com" = {
|
|
||||||
dnsProvider = "cloudflare";
|
|
||||||
credentialsFile = secrets.cloudflareCredentials;
|
|
||||||
domain = "ha.lukegb.com";
|
|
||||||
postRun = ''
|
|
||||||
systemctl reload nginx
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
services.nginx.virtualHosts."ha.lukegb.com" = {
|
services.nginx.virtualHosts."ha.lukegb.com" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
useACMEHost = "ha.lukegb.com";
|
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://localhost:8123/";
|
proxyPass = "http://localhost:8123/";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
my.vault.acmeCertificates."ha.lukegb.com" = {
|
||||||
|
nginxVirtualHosts = [ "ha.lukegb.com" ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue