Refactored how SSL certs are configured for nginx
Made a separate ACME module to handle requesting certs from multiple machines. Right now, the module only supports exactly one wildcard cert. It might make sense to have cache.kilonull.com use a cert specific to its subdomain rather than also requesting a wildcard cert (or maybe the nginx on its host shouldn't care about TLS and it should be node's responsibility).
This commit is contained in:
parent
60917107b1
commit
d5969ca923
|
@ -7,7 +7,7 @@
|
||||||
}:
|
}:
|
||||||
with lib; let
|
with lib; let
|
||||||
cfg = config.aa.nix;
|
cfg = config.aa.nix;
|
||||||
selfHostedCacheHost = "http://192.168.113.69/";
|
selfHostedCacheHost = "https://cache.kilonull.com/";
|
||||||
in {
|
in {
|
||||||
options.aa.nix = with types; {
|
options.aa.nix = with types; {
|
||||||
enable = mkEnableOption "manage nix configuration.";
|
enable = mkEnableOption "manage nix configuration.";
|
||||||
|
|
56
modules/security/acme/default.nix
Normal file
56
modules/security/acme/default.nix
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
options,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
format,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.aa.security.acme;
|
||||||
|
in {
|
||||||
|
options.aa.security.acme = with types; {
|
||||||
|
enable = mkEnableOption "Automatic Certificate Management Environment (ACME)";
|
||||||
|
useStaging = mkOption {
|
||||||
|
type = bool;
|
||||||
|
description = ''
|
||||||
|
Use the staging environment (use when configuring for the first time to
|
||||||
|
avoid being locked out).
|
||||||
|
'';
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
domainName = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = "The domain to request a wildcard cert for.";
|
||||||
|
};
|
||||||
|
dnsCredentialsFile = mkOption {
|
||||||
|
type = path;
|
||||||
|
description = "The path to the credentials file for the DNS provider.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Only supports exactly one wildcard cert using Cloudflare (only use case I have)
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
security.acme = {
|
||||||
|
acceptTerms = true;
|
||||||
|
defaults = {
|
||||||
|
email = config.aa.user.email;
|
||||||
|
group = "nginx";
|
||||||
|
server = mkIf cfg.useStaging "https://acme-staging-v02.api.letsencrypt.org/directory";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Wildcard cert
|
||||||
|
certs."${cfg.domainName}" = {
|
||||||
|
group = "nginx";
|
||||||
|
dnsProvider = "cloudflare";
|
||||||
|
# Private network resolves *.kilonull.com to private servers but `lego`
|
||||||
|
# (acme client under the hood) needs to find the cloudflare nameservers
|
||||||
|
# to determine the correct zone to apply changes in. Use cloudflare's
|
||||||
|
# own DNS to make `lego` happy (will resolve names to a public IP).
|
||||||
|
dnsResolver = "1.1.1.1:53";
|
||||||
|
credentialsFile = cfg.dnsCredentialsFile;
|
||||||
|
extraDomainNames = [("*." + cfg.domainName)];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -11,6 +11,14 @@ with lib; let
|
||||||
in {
|
in {
|
||||||
options.aa.services.adguardhome = with types; {
|
options.aa.services.adguardhome = with types; {
|
||||||
enable = mkEnableOption "adguardhome";
|
enable = mkEnableOption "adguardhome";
|
||||||
|
acmeCertName = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
If set to a non-empty string, forces SSL with the supplied acme
|
||||||
|
certificate.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -26,37 +34,16 @@ in {
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
virtualHosts."adguardhome.kilonull.com" = {
|
virtualHosts."adguardhome.kilonull.com" =
|
||||||
forceSSL = true;
|
{
|
||||||
useACMEHost = "kilonull.com";
|
locations."/" = {
|
||||||
locations."/" = {
|
proxyPass = "http://127.0.0.1:3000";
|
||||||
proxyPass = "http://127.0.0.1:3000";
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (cfg.acmeCertName != "") {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = cfg.acmeCertName;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# So that nginx has access to the ACME certs
|
|
||||||
users.users.nginx.extraGroups = ["acme"];
|
|
||||||
|
|
||||||
age.secrets.cf_dns_kilonull.file = ../../../secrets/cf_dns_kilonull.age;
|
|
||||||
|
|
||||||
security.acme = {
|
|
||||||
# NOTE: Uncomment line below when testing changes
|
|
||||||
# defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory";
|
|
||||||
acceptTerms = true;
|
|
||||||
defaults.email = "iam@alejandr0angul0.dev";
|
|
||||||
|
|
||||||
# Wildcard cert
|
|
||||||
certs."kilonull.com" = {
|
|
||||||
dnsProvider = "cloudflare";
|
|
||||||
# Private network resolves *.kilonull.com to private servers but `lego`
|
|
||||||
# (acme client under the hood) needs to find the cloudflare nameservers
|
|
||||||
# to determine the correct zone to apply changes in. Use cloudflare's
|
|
||||||
# own DNS to make `lego` happy (will resolve names to a public IP).
|
|
||||||
dnsResolver = "1.1.1.1:53";
|
|
||||||
credentialsFile = config.age.secrets.cf_dns_kilonull.path;
|
|
||||||
extraDomainNames = ["*.kilonull.com"];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall = {
|
networking.firewall = {
|
||||||
|
|
|
@ -11,6 +11,14 @@ with lib; let
|
||||||
in {
|
in {
|
||||||
options.aa.services.nextcloud = with types; {
|
options.aa.services.nextcloud = with types; {
|
||||||
enable = mkEnableOption "nextcloud";
|
enable = mkEnableOption "nextcloud";
|
||||||
|
acmeCertName = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
If set to a non-empty string, forces SSL with the supplied acme
|
||||||
|
certificate.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -47,9 +55,9 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
# nextcloud module configures nginx, just need to specify SSL stuffs here
|
# nextcloud module configures nginx, just need to specify SSL stuffs here
|
||||||
services.nginx.virtualHosts.${config.services.nextcloud.hostName} = {
|
services.nginx.virtualHosts.${config.services.nextcloud.hostName} = mkIf (cfg.acmeCertName != "") {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
useACMEHost = "kilonull.com";
|
useACMEHost = cfg.acmeCertName;
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [80 443];
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
|
|
@ -19,6 +19,14 @@ in {
|
||||||
type = str;
|
type = str;
|
||||||
description = "The subdomain to use.";
|
description = "The subdomain to use.";
|
||||||
};
|
};
|
||||||
|
acmeCertName = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
If set to a non-empty string, forces SSL with the supplied acme
|
||||||
|
certificate.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -38,8 +46,8 @@ in {
|
||||||
|
|
||||||
nginx = {
|
nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
virtualHosts = {
|
virtualHosts."${cfg.subdomain_name}.${cfg.domain_name}" =
|
||||||
"${cfg.subdomain_name}.${cfg.domain_name}" = {
|
{
|
||||||
serverAliases = ["${cfg.subdomain_name}"];
|
serverAliases = ["${cfg.subdomain_name}"];
|
||||||
locations."/".extraConfig = ''
|
locations."/".extraConfig = ''
|
||||||
proxy_pass http://localhost:${toString config.services.nix-serve.port};
|
proxy_pass http://localhost:${toString config.services.nix-serve.port};
|
||||||
|
@ -47,13 +55,16 @@ in {
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
'';
|
'';
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (cfg.acmeCertName != "") {
|
||||||
|
forceSSL = true;
|
||||||
|
useACMEHost = cfg.acmeCertName;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall = {
|
networking.firewall = {
|
||||||
allowedTCPPorts = [80];
|
allowedTCPPorts = [80 443];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -2,8 +2,9 @@ let
|
||||||
# Remember to pass '--identity identities/me.txt` when using this key
|
# Remember to pass '--identity identities/me.txt` when using this key
|
||||||
users.me = "age1yubikey1qdwgvfqrcqmyw56ux7azuvqr6f8nanszu27nztvxmn4utmplgxctzt90g25";
|
users.me = "age1yubikey1qdwgvfqrcqmyw56ux7azuvqr6f8nanszu27nztvxmn4utmplgxctzt90g25";
|
||||||
|
|
||||||
|
machines.gospel = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGDzjXVoQEfO9JIcFbp56EvQ0oBdr9Cmhxp4z0ih+ZEZ";
|
||||||
machines.node = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIETLBnc8kJokmFiA28BaSYpeE7flY1W0SM5C1pWv/tOv";
|
machines.node = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIETLBnc8kJokmFiA28BaSYpeE7flY1W0SM5C1pWv/tOv";
|
||||||
in {
|
in {
|
||||||
"cf_dns_kilonull.age".publicKeys = [users.me machines.node];
|
"cf_dns_kilonull.age".publicKeys = [users.me machines.node machines.gospel];
|
||||||
"nextcloud_admin.age".publicKeys = [users.me machines.node];
|
"nextcloud_admin.age".publicKeys = [users.me machines.node];
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
./zfs.nix
|
./zfs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
age.secrets.cf_dns_kilonull.file = ../../../secrets/cf_dns_kilonull.age;
|
||||||
|
|
||||||
aa = {
|
aa = {
|
||||||
nix.enable = true;
|
nix.enable = true;
|
||||||
|
|
||||||
|
@ -19,11 +21,19 @@
|
||||||
|
|
||||||
apps.yubikey.enable = true;
|
apps.yubikey.enable = true;
|
||||||
|
|
||||||
|
security.acme = {
|
||||||
|
enable = true;
|
||||||
|
# useStaging = true;
|
||||||
|
domainName = "kilonull.com";
|
||||||
|
dnsCredentialsFile = config.age.secrets.cf_dns_kilonull.path;
|
||||||
|
};
|
||||||
|
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
services.nix-serve = {
|
services.nix-serve = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain_name = "kilonull.com";
|
domain_name = "kilonull.com";
|
||||||
subdomain_name = "gospel";
|
subdomain_name = "cache";
|
||||||
|
acmeCertName = "kilonull.com";
|
||||||
};
|
};
|
||||||
services.printing.enable = true;
|
services.printing.enable = true;
|
||||||
services.tailscale = {
|
services.tailscale = {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
./zfs.nix
|
./zfs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
age.secrets.cf_dns_kilonull.file = ../../../secrets/cf_dns_kilonull.age;
|
||||||
|
|
||||||
aa = {
|
aa = {
|
||||||
nix.enable = true;
|
nix.enable = true;
|
||||||
nix.useSelfhostedCache = true;
|
nix.useSelfhostedCache = true;
|
||||||
|
@ -18,8 +20,20 @@
|
||||||
configureServerRouting = true;
|
configureServerRouting = true;
|
||||||
};
|
};
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
services.adguardhome.enable = true;
|
services.adguardhome = {
|
||||||
services.nextcloud.enable = true;
|
enable = true;
|
||||||
|
acmeCertName = "kilonull.com";
|
||||||
|
};
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
acmeCertName = "kilonull.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
security.acme = {
|
||||||
|
enable = true;
|
||||||
|
domainName = "kilonull.com";
|
||||||
|
dnsCredentialsFile = config.age.secrets.cf_dns_kilonull.path;
|
||||||
|
};
|
||||||
|
|
||||||
system.zfs.enable = true;
|
system.zfs.enable = true;
|
||||||
system.monitoring.enable = true;
|
system.monitoring.enable = true;
|
||||||
|
|
Loading…
Reference in a new issue