diff --git a/agenix/dns/nix.tuxcord.net/nix.tuxcord.net.key.age b/agenix/dns/nix.tuxcord.net/nix.tuxcord.net.key.age new file mode 100644 index 0000000..5e4dd0a --- /dev/null +++ b/agenix/dns/nix.tuxcord.net/nix.tuxcord.net.key.age @@ -0,0 +1,19 @@ +age-encryption.org/v1 +-> ssh-ed25519 Wl2fDA sLlStq5Hzb2JNQubLtMk5/kyIp81aTyjUB/Ysv1gRR0 +lTLWsvT5Oxk8ut/g+o9o0DMOIQVDmi9o4EO0fYeIToo +-> ssh-ed25519 zNC8SA G0XcS2gzF0RopI2DqkWaTYXwjUpkVtdrxSQ+p8bfE0w +pZVIg/1P8BbnpRfV5F0FG3xgLSiA8M+nosQ8iNeYmcU +-> ssh-ed25519 EiAAKw qWmO0IjKoUFVxbxFUx36JIhME2PU7lkD+3agKO7+6nA +yEIw8IzQmM8C9dZoPajtvdUOF5kJ/C+rtgLczcmP1bs +-> ssh-rsa eFi+Zw +O5XRvS+Y/1mm9nQ7IZmxEp7RmFjAH0OTKPkRTME7BybnePPZLL0l6wMP26hx88Nv +dOqdaS07Xb26EIgCS/4xCY4sPWZNEfAfnDVoF4/SNbmfbN0XpNpR981AWcxiTL35 +Fngk0lPa1NtuUH4S4zTda21kXHE0zv2mYLNMuek8dTrUd2piC+Z0WJJdrG1LK0hN +dDuLzX/mNibNXDvYxyD6mtkO2S1wO9QL88ucNZptT29vcaD48EZM/SsAwgf3OoqH +kd7jSTTdZ/yk8ccTMiT5eskQ3ZZcqc7JaF+M2d88DP6LcSaJnNzyVSEMAHHfpoY1 +/kHxZ88/ehwPDXrp0bL448jdPuWqPSerzCWyyZFbc8Jj6zRUtC5joL0Vq2Rqs+EH +rmKMfi1l2+utleGYfCyHI5/czsMhJ2jXLGPguWQQdixNtb/RWFw6DeRP9xdO9QJR +LkoAFgv0ykP+L+C6sA7bpJqIGNftl4x8OUQxrKtf3YQ8K2LhUZb23JPn4Ob/QXo/ + +--- W7eUDhB/RBUYV1gaM4ktPEOVU6l5IRgOoRDpKKpvAnM +O\MOJ !HpK:g[6MVbY;F'#7&s1 ر65_n’m.q'q6f-Ww#56r#Ā=4El[ \ No newline at end of file diff --git a/agenix/secrets.nix b/agenix/secrets.nix index 3101494..eafb482 100644 --- a/agenix/secrets.nix +++ b/agenix/secrets.nix @@ -12,4 +12,6 @@ in "dns/tuxcord.test/tuxcord.test.key.age".publicKeys = [ tuxcord-ca ] ++ builtins.attrValues users; "dns/tuxcord.test/sub.tuxcord.test.key.age".publicKeys = [ tuxcord-ca ] ++ builtins.attrValues users; + + "dns/nix.tuxcord.net/nix.tuxcord.net.key.age".publicKeys = [ tuxcord-ca ] ++ builtins.attrValues users; } diff --git a/nixos/common.nix b/nixos/common.nix index a6a0487..5291f89 100644 --- a/nixos/common.nix +++ b/nixos/common.nix @@ -28,6 +28,8 @@ in ./vm.nix ]; + age.secrets.ntfy.file = "${self}/agenix/ntfy.age"; + nix = { package = inputs'.nix-super.packages.default; diff --git a/nixos/default.nix b/nixos/default.nix index ed32421..e2448ee 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -33,5 +33,6 @@ in tuxcord-ca = mkSystem "tuxcord-ca" "x86_64-linux"; tuxcord-test = mkSystem "tuxcord-test" "x86_64-linux"; + tuxcord-acmetest = mkSystem "tuxcord-acmetest" "x86_64-linux"; }; } diff --git a/nixos/hosts/tuxcord-acmetest/default.nix b/nixos/hosts/tuxcord-acmetest/default.nix new file mode 100644 index 0000000..11d4f90 --- /dev/null +++ b/nixos/hosts/tuxcord-acmetest/default.nix @@ -0,0 +1,11 @@ +{ + acme = { + enable = true; + rfc2136.nameserver = "tuxcord.net"; + }; + + dns.enable = true; + networking.fqdn = "nix.tuxcord.net"; + + time.timeZone = "Europe/Madrid"; +} diff --git a/nixos/hosts/tuxcord-ca/default.nix b/nixos/hosts/tuxcord-ca/default.nix index a3eeb69..a25a2db 100644 --- a/nixos/hosts/tuxcord-ca/default.nix +++ b/nixos/hosts/tuxcord-ca/default.nix @@ -4,6 +4,11 @@ ./storage.nix ]; + acme = { + enable = true; + useSelfDns = true; + }; + dns.enable = true; networking.fqdn = "tuxcord.net"; time.timeZone = "Canada/Eastern"; diff --git a/nixos/hosts/tuxcord-test/default.nix b/nixos/hosts/tuxcord-test/default.nix index ad811a1..41b1be4 100644 --- a/nixos/hosts/tuxcord-test/default.nix +++ b/nixos/hosts/tuxcord-test/default.nix @@ -1,4 +1,5 @@ { + acme.enable = false; dns.enable = true; networking.fqdn = "tuxcord.test"; } diff --git a/nixos/modules/acme.nix b/nixos/modules/acme.nix new file mode 100644 index 0000000..20c2b05 --- /dev/null +++ b/nixos/modules/acme.nix @@ -0,0 +1,89 @@ +{ + config, + pkgs, + lib, + ... +}: +let + cfg = config.acme; + + inherit (lib) + mkIf + mkEnableOption + mkOption + types + ; + + inherit (config.networking) fqdn; +in +{ + # we'll only support rfc2136 based challenges + options.acme = { + enable = mkEnableOption "" // { + default = true; + }; + + useSelfDns = mkOption { + default = false; + description = "Sets values of the self DNS if enabled, otherwise requires manual `rfc2136` nameserver and key values."; + }; + + rfc2136 = { + key = mkOption { + type = types.path; + default = config.age.secrets."dns/${fqdn}.key.age".path; + }; + + nameserver = mkOption { + type = types.str; + default = if cfg.useSelfDns then fqdn else null; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = with cfg.rfc2136; nameserver != null && key != null; + message = "ACME needs rfc2136 parameters to work, consider using `useSelfDns` option."; + } + ]; + + environment.persistence."/persist".directories = [ + { + directory = "/var/lib/acme"; + group = "acme"; + user = "acme"; + } + ]; + + security.acme = { + acceptTerms = true; + + defaults = { + email = "error@tuxcord.net"; + reloadServices = [ "nginx" ]; + postRun = '' + source ${config.age.secrets.ntfy.path} + ${pkgs.ntfy-sh}/bin/ntfy publish -T recycle -t "${config.host.name}" "HTTPS certificate has been renewed" + ''; + }; + + certs."${fqdn}" = { + dnsProvider = "rfc2136"; + environmentFile = + with cfg.rfc2136; + builtins.toFile "dns-01-challenge.cfg" '' + RFC2136_NAMESERVER=${nameserver} + RFC2136_TSIG_FILE="${key}" + ''; + extraDomainNames = [ + "*.${fqdn}" + "${fqdn}" + ]; + + inherit (config.services.nginx) group; + }; + }; + }; +} diff --git a/nixos/modules/default.nix b/nixos/modules/default.nix index 01c80d9..2593ae5 100644 --- a/nixos/modules/default.nix +++ b/nixos/modules/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./acme.nix ./dns.nix ./fail2ban.nix ./gitea.nix diff --git a/nixos/modules/dns.nix b/nixos/modules/dns.nix index ffed8c7..8ed8c63 100644 --- a/nixos/modules/dns.nix +++ b/nixos/modules/dns.nix @@ -1,6 +1,16 @@ { config, lib, ... }: let - agenixDnsDir = ../../agenix/dns + "/${config.dns.domain}"; + cfg = config.dns; + + inherit (lib) + mkEnableOption + mkIf + strings + ; + + inherit (config.networking) fqdn; + + agenixDnsDir = "${self}/agenix/dns/${fqdn}"; agenixKeys = builtins.attrNames (builtins.readDir agenixDnsDir); keys = map ( @@ -18,7 +28,7 @@ let { name = zoneDomain; path = config.age.secrets."dns/${filename}".path; - type = if zoneDomain == config.dns.domain then zonesub else subdomain; + type = if zoneDomain == fqdn then zonesub else subdomain; } ) agenixKeys; @@ -34,11 +44,6 @@ in enable = mkEnableOption "" // { default = true; }; - - domain = mkOption { - type = with lib.types; str; - default = config.networking.fqdn; - }; }; config = mkIf cfg.enable { @@ -53,7 +58,8 @@ in value = { file = path; group = "named"; - owner = "named"; + owner = if config.acme.enable then "acme" else "named"; + mode = "440"; }; } ) agenixKeys @@ -65,7 +71,7 @@ in extraConfig = builtins.concatStringsSep "\n" (map (key: "include \"${key.path}\";") keys); zones = { - "${config.dns.domain}" = { + "${fqdn}" = { # grant "tuxcord.net" zonesub ANY; extraConfig = '' update-policy { @@ -74,7 +80,7 @@ in )} }; ''; - file = "/var/dns/${config.dns.domain}.zone"; # need to put default stuff + file = "/var/dns/${fqdn}.zone"; # need to put default stuff master = true; }; }; diff --git a/nixos/modules/gitea.nix b/nixos/modules/gitea.nix index 7d33da8..e1b0452 100644 --- a/nixos/modules/gitea.nix +++ b/nixos/modules/gitea.nix @@ -1,4 +1,9 @@ { config, lib, ... }: +let + inherit (config.networking) fqdn; + + acmeEnabled = config.acme.enable; +in { services.gitea = { enable = true; @@ -8,8 +13,8 @@ lfs.enable = true; - settings.server.DOMAIN = config.networking.fqdn; - # settings.server.ROOT_URL = "https://git.tuxcord.net/"; ? would also depend on ssl status + settings.server.DOMAIN = fqdn; + settings.server.ROOT_URL = "${if isHTTPS then "https" else "http"}://${fqdn}/"; settings.server.HTTP_PORT = 3000; settings.service.DISABLE_REGISTRATION = true; diff --git a/nixos/modules/nginx.nix b/nixos/modules/nginx.nix index c9cbfec..3883f31 100644 --- a/nixos/modules/nginx.nix +++ b/nixos/modules/nginx.nix @@ -4,8 +4,12 @@ let mkVhost = attrs: + let + acmeEnabled = config.acme.enable; + in { - forceSSL = false; # TODO: tweak per host + forceSSL = acmeEnabled; + useACMEHost = if acmeEnabled then fqdn else null; } // attrs;