From 76d6a094dceb83cb89fa50e5e95847e62a6a71c7 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 9 Apr 2024 20:38:40 +0200 Subject: [PATCH] fix: need to split wildcard definitions because the nginx module would cause infinite recursion otherwise --- README.md | 2 +- hosts/envoy/acme.nix | 2 +- hosts/envoy/default.nix | 1 - hosts/envoy/secrets/local.nix.age | Bin 805 -> 786 bytes hosts/sentinel/acme.nix | 2 +- hosts/sentinel/secrets/local.nix.age | Bin 828 -> 781 bytes modules/acme-wildcard.nix | 28 +++++++++++++-------------- users/myuser/secrets/user.nix.age | Bin 4774 -> 4847 bytes 8 files changed, 16 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 81f7666..fa9bac9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ including my homelab, external servers and my development machines. 🖥️ | Server | sire | Threadripper 1950X | Home media server and data storage. Runs all services as microvms. 🥔 | Server | zackbiene | ODROID N2+ | ARM SBC for home automation, isolating the sketchy stuff from my main network ☁️ | VPS | sentinel | Hetzner Cloud server | Proxies and protects my local services -☁️ | VPS | envoy | Hetzner Cloud server | Mailserver (WIP, still on gentoo) +☁️ | VPS | envoy | Hetzner Cloud server | Mailserver ## Overview diff --git a/hosts/envoy/acme.nix b/hosts/envoy/acme.nix index 200c858..f818396 100644 --- a/hosts/envoy/acme.nix +++ b/hosts/envoy/acme.nix @@ -24,6 +24,6 @@ in { dnsPropagationCheck = true; reloadServices = ["nginx"]; }; - inherit (acme) certs; + inherit (acme) certs wildcardDomains; }; } diff --git a/hosts/envoy/default.nix b/hosts/envoy/default.nix index 9fd8d9f..7aab654 100644 --- a/hosts/envoy/default.nix +++ b/hosts/envoy/default.nix @@ -14,7 +14,6 @@ boot.mode = "bios"; users.groups.acme.members = ["nginx"]; - wireguard.proxy-sentinel.firewallRuleForAll.allowedTCPPorts = [80 443]; services.nginx.enable = true; services.nginx.recommendedSetup = true; diff --git a/hosts/envoy/secrets/local.nix.age b/hosts/envoy/secrets/local.nix.age index e2152cb16ebfa2025b48667aaf8059d71edc83b9..bf125b78bc74e29fd72f35723e4ab8bc4db40f80 100644 GIT binary patch delta 766 zcmVK%DX*O?qOJzxHGes+EcV|pXM|gEcMM!5a&uL7NoZC=N>x=< zMR+hxS9)T3T3QNWO=wp$PHks1dTC>6VnlOLLoYONZ&!3lFl$qGMPX8KG-_pHZgy*P zVo3@uJ|JpxJzp(na%Ew2WeRUED^@~6bZ&P}IBqaDX>nyvb#QBSMo2|eT0(6#XLMt1 zHfc4&TO>9p}M^-Xfa!+J7GlN9osZTjb(1DYL+oU@<4NJR25^*Lx03JoD?Sl#~omP7e?c%NHYFX zafnRa{R^NO9w@Q9!3nvs)6}_2rqF{j>z`$wi)wLLtwY&gCe!~};@_gnbVU!#tfvVa zasu{Z``?qOVG@A75A>Rj}D*`W?kwDa%5 zvL2%gcF$LzL>>Jo7DLVfcmC-%pN#K>mVjD9a(6Q!1(YViSR5l>Ytk11b>J*fsp4pv w11hw>!X*VC$OJ3%S5%eD$?6v`Kjw|iFUo(?p6?up2Yuy_VbPFF>hL4_s_bJu^#A|> delta 786 zcmV+t1MU2h2Bij&Ab&AOG&pZ!ZB|ZhGDk{bZZ&FXcy~@XT2DrLYe7ygXF)bmZbWA| zaA;#`cM4-RNNP)EGg(AIHg-ZxL1bliH(6*kX;?H#a4=1BLt|8GZ%t2Ccq>^)Gzu*~ zAaH4REpRe5HXwL$Q)M_&AVE1zSb2CzSW;4IIZRe}HgIHbb$>81aZY1uV>wV^Fk@6N zGjTaIcXvT$W@HLacV}}!SyyXXYiB}dK`}3KaaSurLN91AdSPogczRAwN?3GyPHt{g zZ8QokJ|ILbXL4m>b7dfTeK22TBOq5}IxA9YZ6H}xQGIAN3PDsuSx`A~SvXcQNMU+c zIeABOYc^?gXn$8QW^F=NcWz-xR!lN4WpFi5D>iO0c6T;1WJF_SQC4X-HA*W@LN^L= zd3G^nX-h#!Mm1G#RcCE8PB?8$P*hQHR8@KkEiEk|RaQ27cWY2INN{vWT3KOwGe$vE zL^w=wG)6*scywiDHb--6Id(ZvLux?^ky)81DQo4Ulz)_8#XTJKY0hf%WD~^y__R5J zCi^c=Dwq}?a0xs|rzP?WHLdtd+sd_iwNFiIeHQZCkpcCkEh`NVXL=1~PBxglCq!yza{;)T&9 zx%|tt(tmYDy7<|Yaqu&O*hyO&L8|<5gxk}$_^ungFII%xqynjy7~CN1?7Nebq&j#l ztjW5l7F=mz7ea_{hl7fej19%8p_AEWCvy&~z#KUl0 z88?&bv~(=a0_`9L;;K9@72#U`=-BbA3gcks{+fm|TmcVzxW2-L+O!nItMT@Bt((%s zt&9kbEjAp>uw4{A<^o_mp_?PY>aa*T4myq?M`gF7lLoGvUJ4Dc+QVZVx#?nz(5i4t Q^$W7;*<6(I?+Re;a>|`dqW}N^ diff --git a/hosts/sentinel/acme.nix b/hosts/sentinel/acme.nix index 200c858..f818396 100644 --- a/hosts/sentinel/acme.nix +++ b/hosts/sentinel/acme.nix @@ -24,6 +24,6 @@ in { dnsPropagationCheck = true; reloadServices = ["nginx"]; }; - inherit (acme) certs; + inherit (acme) certs wildcardDomains; }; } diff --git a/hosts/sentinel/secrets/local.nix.age b/hosts/sentinel/secrets/local.nix.age index b7a16d16f44066400a0bafa95ce7f492e0f1027a..711dec8f4a3a23518c1680d5e0655778944af657 100644 GIT binary patch delta 761 zcmVb7de=NiIe>Mj&w@G;KNxSvO2kS#WblNiVc@9b zO)+@wFMSYT+rXI{N5F^?r5(`gGU0i5-q<8a_UH$%dJgb|PA%;7V~n1WVpnQsTA@>` zK&TtC1rIlT9!1-`*PFxo^lmel7b>CMeUSELG6tJ#s)A`X=h^AX#p z@8VI7ntvqU30v{1dIXLY)nFaMI{lW`Dp7Awr!3cMN(HdyrBKtD;~N3kpD*S(E3bj< z{KC?|5q>}XTn}0e$=>Kvws*_`&h!q7WYoEH*q=lv)Bu~u35kR${a{@w4r6_)c4csbN@i7j_=>6WkVRGWAZ}IUQC3-^lS?Af^$mk6=+aP^e zyuM88WE$RJ^G?8Bjj$ZoP`p9O)eXn36xMHUa+z56rZcx~Ri9x~u`4=s{4h^=SXcpx rbkMU@l*7wTl%EVjoXp-QVnR7sS4C@ZV^~&1aYj{iPFQVXGfz2d zYkG7uSqe#YV@5P|b6RJ3H&%06F=|6~QesC>ZZA1)HD+{na!NUMLRWJuMlo1SMG7rG zAaH4REpRe5HXwL$Q)M_&AVDy4Xe(7UMKEJdH%m8fQaDsoX@77|FF|=oLU>MZZ)i+% zM@U6UX;Cn0S8obYXlXKJV^e5DLTztkVoxhkaCk{~YHDgtY;R>WPDVLJQF2&JWn)To zFLw$pJ|K5yL|8&iQY~k4Wnpt=ASNJjc}-^uRY+%YMrB5MWolY*Pi%K{Nl`Ixc4pOn+urV>wJhHA!hsMK?`HZZuH}EiEk|Pj*W-b9XOSV`OhaMNDi?HdS^? zZF*BIXW^pw*YW!s1c8CHk=F0VXi9iYfc~0oVu}= z-PK=_9I>B%=XldS#rOF7_B;yP0%d)>XW8{GnTp%4G>_6bbo}%yjL&ti#A(r#NE;^6ujVO3xF_ALvQq zt}2IbOI{ffjbdwYqD5OUo=IgvvxesObONmwK(<^z3k}birFB)lvEOW%Fo+;ZY0Qt2 z3*?QaiGPgOj?Kv*$j^n{H#ExfC&#y3d8lho*785(*GXD}8fS+ngn|B`C??c|kfemY zbZyD6&|M~R*jX>Fk562B!xavDliA@Ntb|{`y_nX=u?27ep2?9uDsn%eK8m78XLfaY zHki_Ewuj-|1jcpX{*r9w8o%N~Au$AMkUB(W0)G|KjhM0V_~e{f%&1V_eqg7&pPKKR-CZ}aoxi>{kTCe?u4rFj diff --git a/modules/acme-wildcard.nix b/modules/acme-wildcard.nix index 0aefecb..9652470 100644 --- a/modules/acme-wildcard.nix +++ b/modules/acme-wildcard.nix @@ -6,9 +6,8 @@ inherit (lib) assertMsg - attrNames filter - filterAttrs + genAttrs hasInfix head mkIf @@ -16,19 +15,14 @@ removeSuffix types ; - - wildcardDomains = attrNames (filterAttrs (_: v: v.wildcard) config.security.acme.certs); in { - options.security.acme.certs = mkOption { - type = types.attrsOf (types.submodule (submod: { - options.wildcard = mkOption { - default = false; - type = types.bool; - description = "If set to true, this will automatically append `*.` to `extraDomainNames`."; - }; - - config.extraDomainNames = mkIf submod.config.wildcard ["*.${submod.config._module.args.name}"]; - })); + options.security.acme.wildcardDomains = mkOption { + type = types.listOf types.str; + default = []; + description = '' + List of domains to which a wilcard certificate exists under the same name in `certs`. + All of these certs will automatically have `*.` appended to `extraDomainNames`. + ''; }; options.services.nginx.virtualHosts = mkOption { @@ -45,7 +39,7 @@ in { matchingCerts = filter (x: !hasInfix "." (removeSuffix ".${x}" domain)) - wildcardDomains; + config.security.acme.wildcardDomains; in mkIf submod.config.useACMEWildcardHost { useACMEHost = assert assertMsg (matchingCerts != []) "No wildcard certificate was defined that matches ${domain}"; @@ -53,4 +47,8 @@ in { }; })); }; + + config.security.acme.certs = genAttrs config.security.acme.wildcardDomains (domain: { + extraDomainNames = ["*.${domain}"]; + }); } diff --git a/users/myuser/secrets/user.nix.age b/users/myuser/secrets/user.nix.age index 7c82412b6183e0148ad24f9e465989823f52952b..52232d87b5c4f7c18bb7bf442c072db1d4fa0c0e 100644 GIT binary patch literal 4847 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 V4}yIAwiu9#0758>B{!sngPlK1Ap-ya literal 4774 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