From 0fa3e1ec0ef186f7d714a53b3e18312d99a3f251 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:58:08 -0600 Subject: [PATCH 01/75] fix (crowdsec): Scope of Journalctl access --- services/crowdsec.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index f7e2e5a..d53f84e 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -18,9 +18,9 @@ in { services = { crowdsec = { enable = true; + allowLocalJournalAccess = true; settings = { api.server = { listen_uri = crowdsec-url; }; - allowLocalJournalAccess = true; crowdsec_service.acquisition_path = pkgs.writeText "acquisitions.yaml" (toMultiYAML [ { From 2ea0b6822143fddb4bdd918eea3b65aabe2662c6 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:00:16 -0600 Subject: [PATCH 02/75] fix (crowdsec): API url --- services/crowdsec.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index d53f84e..99c53b8 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -42,7 +42,7 @@ in { crowdsec-firewall-bouncer = { enable = true; settings = { - api_url = firewall-bouncer-name; + api_url = crowdsec-url; api_key = firewall-bouncer-key; }; }; From 4ca995f75a1933bab49f505314d727b204469174 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 10 Nov 2025 21:41:27 -0600 Subject: [PATCH 03/75] fix (crowdsec): Add hub update steps --- services/crowdsec.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 99c53b8..76c5024 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -80,6 +80,14 @@ in { set -eu set -o pipefail + # I had to run these commands in order to manually install collections + # using cscli. + # Not sure how often they should actually be run, but I would rather + # include this here. + # https://discourse.crowdsec.net/t/solved-cant-find-collections-appsec/1830 + cscli capi register + cscli hub update + ${pkgs.lib.concatMapStrings collection-check collections} ''; in [ From b2928eb81f660d617862766444f67753ce125b38 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 10 Nov 2025 21:47:29 -0600 Subject: [PATCH 04/75] fix (crowdsec): Proper URI syntax for API --- services/crowdsec.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 76c5024..378b2b4 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -1,6 +1,6 @@ { pkgs, config, ... }: let - crowdsec-url = "127.0.0.1:2763"; + crowdsec-port = "2763"; firewall-bouncer-name = "fw-bouncer"; # Although this key can be reproduced by anyone who actually cares to, the # Crowdsec API will not be exposed to the outside world, so keeping this key @@ -20,7 +20,7 @@ in { enable = true; allowLocalJournalAccess = true; settings = { - api.server = { listen_uri = crowdsec-url; }; + api.server = { listen_uri = "127.0.0.1:${crowdsec-port}"; }; crowdsec_service.acquisition_path = pkgs.writeText "acquisitions.yaml" (toMultiYAML [ { @@ -42,7 +42,7 @@ in { crowdsec-firewall-bouncer = { enable = true; settings = { - api_url = crowdsec-url; + api_url = "http://localhost:${crowdsec-port}"; api_key = firewall-bouncer-key; }; }; From 1fba4037317e7e9985c3bcae8ba71df6b7075cd0 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 10 Nov 2025 22:17:28 -0600 Subject: [PATCH 05/75] fix (crowdsec): Add sleep to avoid rate limits --- services/crowdsec.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 378b2b4..93627cb 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -63,6 +63,7 @@ in { if ! cscli collections list | grep -q "${collection}"; then cscli collections install "${collection}" + sleep 1 fi ''; @@ -86,7 +87,9 @@ in { # include this here. # https://discourse.crowdsec.net/t/solved-cant-find-collections-appsec/1830 cscli capi register + sleep 1 cscli hub update + sleep 1 ${pkgs.lib.concatMapStrings collection-check collections} ''; From f982232c99a38d3bc6a89946cb163b615b494adf Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Tue, 11 Nov 2025 21:39:34 -0600 Subject: [PATCH 06/75] fix (crowdsec): hub permissions issues --- services/crowdsec.nix | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 93627cb..6c33fce 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -86,10 +86,13 @@ in { # Not sure how often they should actually be run, but I would rather # include this here. # https://discourse.crowdsec.net/t/solved-cant-find-collections-appsec/1830 - cscli capi register - sleep 1 - cscli hub update - sleep 1 + # Unfortunately, this section is now causing permissions issues. I'm + # leaving the code here for reference, but commenting it out to allow + # Crowdsec to run + # cscli capi register + # sleep 1 + # cscli hub update + # sleep 1 ${pkgs.lib.concatMapStrings collection-check collections} ''; From 2c4e7097046bcf3b61adbab77009b8c8d04e88c5 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Tue, 11 Nov 2025 21:42:25 -0600 Subject: [PATCH 07/75] debug (crowdsec): Add verbose logging to Crowdsec collection install step --- services/crowdsec.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 6c33fce..8504da4 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -62,7 +62,7 @@ in { collection-check = collection: '' if ! cscli collections list | grep -q "${collection}"; then - cscli collections install "${collection}" + cscli collections --trace install "${collection}" sleep 1 fi From 3b9b7f684d10b61086ba7eb971b6943d0a0f297c Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Tue, 11 Nov 2025 21:59:28 -0600 Subject: [PATCH 08/75] Revert "fix (crowdsec): hub permissions issues" This reverts commit f982232c99a38d3bc6a89946cb163b615b494adf. --- services/crowdsec.nix | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 8504da4..6a54584 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -86,13 +86,10 @@ in { # Not sure how often they should actually be run, but I would rather # include this here. # https://discourse.crowdsec.net/t/solved-cant-find-collections-appsec/1830 - # Unfortunately, this section is now causing permissions issues. I'm - # leaving the code here for reference, but commenting it out to allow - # Crowdsec to run - # cscli capi register - # sleep 1 - # cscli hub update - # sleep 1 + cscli capi register + sleep 1 + cscli hub update + sleep 1 ${pkgs.lib.concatMapStrings collection-check collections} ''; From 4d563444468308476220868d202a39904aa45f4a Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:36:19 -0600 Subject: [PATCH 09/75] secrets: Rekey secrets for secret purposes --- secrets.nix | 5 ++++- secrets/ansible-vault-password.age | 24 ++++++++++++------------ secrets/darwin-policies-json.age | Bin 834 -> 1214 bytes secrets/network-information.age | Bin 907 -> 907 bytes secrets/pihole.age | 28 ++++++++++++++-------------- secrets_file.enc | 16 +++++++--------- secrets_odyssey.enc | 13 ++++++++----- systems/darwin/corianne.nix | 7 +++++++ 8 files changed, 52 insertions(+), 41 deletions(-) diff --git a/secrets.nix b/secrets.nix index 3b3ede4..c0d5047 100644 --- a/secrets.nix +++ b/secrets.nix @@ -8,6 +8,8 @@ let "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaDPqRJHoqgY2pseh/mnhjaGWXprHk2s5I52LhHpHcF millironx@bosephus"; odyssey-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; + corianne-host = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHKKkucebeb1GcerOZAAs5GQsgTS8kXw5W41b9Fy9+hp root@corianne.local"; corianne-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOgL2lO9RJBdQYANoxGyWXcNKi5/NZkRHHo/rNqaYMc/ millironx@corianne"; harmony-millironx = @@ -26,5 +28,6 @@ in { ++ [ bosephus-host ]; "secrets/pihole.age".publicKeys = system-administrators ++ [ bosephus-host ]; "secrets/ansible-vault-password.age".publicKeys = system-administrators; - "secrets/darwin-policies-json.age".publicKeys = system-administrators; + "secrets/darwin-policies-json.age".publicKeys = system-administrators + ++ [ corianne-host ]; } diff --git a/secrets/ansible-vault-password.age b/secrets/ansible-vault-password.age index 99a96bc..d833716 100644 --- a/secrets/ansible-vault-password.age +++ b/secrets/ansible-vault-password.age @@ -1,13 +1,13 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ Ni2CHjeijXHfF62cUqVTm8MAOn6rRg8UrhqN6xvdkyk -DsT0Ysx88FlCLeRzoOGctX7KqatX9/UCr5WdtdLJAf4 --> ssh-ed25519 1g/xww jRn91F29sISMyi41anAlzVCzt1t1DnUqxtryqkTQPlM -cysgZLQR0YhiJYXBl59DjKbm+N8FnjA46wkQtnAzBFA --> ssh-ed25519 +kBihw t6wlSnDKGgSzGhNJnryXVbDR40DATaV3fHovtI/u7zo -zOyCZtzfLKeer9K6SMpfTxn6El4HB7gQFQqLOxIYB5U --> ssh-ed25519 dbKeHw cn+8WTwis58bYm2pfEra6LeLvzEZ8GhZrOEeN+kkhCM -fnlUAj8JtG8+r7Cj8xYUgF+JM6Pwqawn4sGI1LOeN78 --> ssh-ed25519 Svnssw zmDBR8TdRZ9NzNhwPYRN6c8naTxAkULyUZpKgk7Gshk -0XCwpegEIlGXhnzLLUtmciKQiYiZRgnSOSvCcYeXXk8 ---- D/lZ36n5sVste2NWfdOx8/klPh0CTmMjVQN74KIqDRY -]%C}NO"v#˱t_Q;^*!+<+dB/K` \ No newline at end of file +-> ssh-ed25519 il3lzQ 8BY+QUEGqILKLs6ROw7llEOhx0GgrfFeKDcEgHePUFw +SPiG48tkp5ewFc6/uNj+541B6YJODGmDFEbET2BfoZ0 +-> ssh-ed25519 1g/xww HyUG/jNJgHCceV/9vaaoSHc681x6Gg/uY+RIfQxIBxU +6XVufQ4A9r8HPU9QLZ/idx3NjDf+UeKVMhtk9+Awy4E +-> ssh-ed25519 +kBihw XjhEk6TF6M5OalqVQNpAemlmgMIJnfuH6M600DnJql0 +3zQPJZcsfnbUqRf5XWTJNbyqMb/rsSBIkS7YlYsyMcs +-> ssh-ed25519 dbKeHw nIG5Z+XdJ3dyMxFOxyFMHw5sUkRJ2dsooJbIScNwlxM +brJoiOSQcwgs3vNSk8eK6dzH3zfQGFNdEWj3jjMM5e0 +-> ssh-ed25519 Svnssw +VFbKj457mYT3GXQSacQ13J8MSkYe6A26ssNbqh8LAQ +rJzIG170BcRlsLERhnfaqgRFeAL4Yw7zvtb1gGvUkCU +--- ebIxmIBuNqNgfVWvOJc/0OpFBf3Q7pmApGgHYjrtJI8 +AeO:(7_x0׷ jfV /D.8⿀1ߠ[qf!7ht0Y \ No newline at end of file diff --git a/secrets/darwin-policies-json.age b/secrets/darwin-policies-json.age index 9fa2d2bb8cc42f93a14b737c82f652ccaa1914d0..eabc269965926dde0005b303d3d4c30974d04056 100644 GIT binary patch delta 1127 zcmZ9}`)?Bk003YZ1lb`mVqgLj8!(%!lwPmx+9mSn`fji9yX$%wq1Wrky0V0|*!~ju;5XO)Q#^3$^h40v;FKf3fC^v%$ zNvcbtsIW$Jc9)<|1Z8gqB9O4d zrlFiL3Hb?U?J0axsf+T`kl=76+ zY}QxQMAEO{slx;$8O6kKJ{7e%gP6UQMSV~XOXLv*4f|v-t=Cv-8Hd4?l>=J%Hb%?R z6h=WwCtjfQR58;c;&il_cJVQ_Iw>2R<`fxeZrl3O_@~3!v?El|6|xM+M%;c-5G@&+ zklMfiBGD;t7G5^tl*S#>c|zG{#IL9G5u!Dg#QZsL3Zo66R-grC24dUXC~4N30Lbj)iVjQ6 zkx7%yVUx%Tu6QD6X)UG6QW!U)TsCF5M+Bq675jgHoOCK-lfs(BIVDMxti{69gjr?wI;Gt$i~vBHVd*O{GIPSy|b& zY1xfObE^HP@S{U1;D@TK>TD0}0=JJ1Uf(TjyJ|nk=uh4nSUBqfFtxL~{6Vm1JF~ug3_5?YZp!MRd+l`}9qyRX)l%BbTmyT@ z$~yMLn>AA!8}|+L-FL8O?tOl)Gxh7+^2VP{nc-hrn(~9xr;c5{)w=eMNt^2T)*qQB zE$+);Lma}t7SnXv{uE~)IfDR^(?^%wd`^O2Ua@M~$iVH#Do?3u`|ehlk)b7DPea$7 zD{mOQ?wi}KzVRwKrugI5gvR-|PK>Ty*~=26Cuh}ubB#$nF`pdw%09=9@4H+;-bhqG z0rW4-+Z{jKpV*&Sfw>md*Id5PbA9BiP;uvz_a!)ZYw47O3s-gOzFYro-`|I{ix=r1 zjoW|r%I%@mZ`_^TKS&)a%$Ypg+O7Ne_-~VIr!ODgdfKKUsEi_h8VFaM(6c6ESK5 z!r~8-2tek!WC_e=eA$=@D9r)^!#*r2IPy-r8TM$p>C*`ijb{v`r6eimK}*7VWergn zOKxJMTjK@R;o8@&>qVDX=!Ib*&<)6Lv(@T`R8+6hU_B_99G)zr1R>He?o>^8J(vOv z(_*(g~s zfSML77lZL4?1u_fR4?a2zee~pG$!^3qG>KxQ5k?jWQX9C0UY3vh%YYUxmF{Kp%}y3 zEEb8DDnh9ha+VPkO_yWTXy4Ke89^h%v0xcwz_jfH(uBYvty(@2ZGak~seDqR-I`uZ z!4gV2q?Alry%{sENf6_S<|v*p;<^yVp^EMnsRpH+Mibzb011swE?qyEQTkO;@z;#3 zyN;_Rg~((gC@)~WaFd3#3TXN`w4dS=lFc~6d^MhrxJxA_3oD)q&B0c~E7#Oq&CABB zUWux)X-wweK!9_&T&`{sEcyYq5si>Cl#3R;plCHwqmm@yg43@?sB#DyY)H8@8)B-C zMEc^$*CT6g-`%=u>sTA}eD3^F_V}SoKNd-LS^nytnO0@sy)G&bMq z69N-AAAg>I^Z@P}yLP`}9eaFd|BHc7XN>W}o!K3o!>5-hl<=i}@2xKT`oHt{@IRYZ z9hkF=Pv<^NO`luX*fntC@b@hp+j)G5yl|Od!PSRmmt=N*6Suu%u56rYJM9k+Z4g zKoba&MgVv$9Wz9|ZsHD2$-Xk6*;U*De7;6g7_AS-m57vM*UM0rj*<0Rl3Hyvib+^s zwFr4ByS7g21K!tc2L(e7^Es-2P|I30Fd?F`#IR8+rRGwQvyG4wAjl8Gp;u754ymsw z%#dxv>Um+;%b)|Z-^2|*Di>UJVCl7BxJ=v$J`1_!!kJWL&UMY8Uk>L_wM{i%Z$N~O z4b4ZrQMT-iWrk`z#bTV6b zEW_9=j3~2XCM%#-lo@rft-Ex?5F&{mD^;Z+a)4qfnOw$Q0eEH8lLt;b6T_-nPtBIV ztAUASPzndcn1NCxcy4cAfHSqscYsk|^qZXLC?kuIY@aR!oOMu}YgnZvArs9_=Zi`^ z#AawU1U1yxt1%Y~+$>hxe6zXIrYKbs>k2-~0LkH!x+uk_8U(flRBGUj?{A-Sex&yvoH_sfpBMD+etvuZ&5etX+8=1g z+8du9y{CS1a_jW=%}0M9`S$ahuU>ny|NBUC50!uU`j5}$*mQU<wd2S%Ut05(o~u z9E5TOL#YqU!J6)2=Y#NSD#8kK4I+Rx`=XNQ>Bnny6|95j{lFOH17v*D$qieLy>xu3J z&=AHE7#`rraO^L85}W&o8%>ZpLii3W|CndwIe3ta8f>$c7O-8zvIa0E+Nr_q=BLVIUthcbUnj!o$sZ|nNz}eOS_8bx8y9BN< zaMz^xHe+*GyYl@0sOu;-o}*DpxSS_jTyj*K&ze+E1(&iz;l1&k8+lB*rA5yr$|*^0 zD7qCGZIg9bJf($x!D~%Gh0HwNE6^0}SUi-X>&|R!leljbEYlh`vm`bmbTqa-yA3oN z4Um@*L?euu+Klwg+)Jya*c;QS3tNJSNz!JE5fNm~3ISn&M>p?XetADX{?g9fQ!f_Z zJpXq7XSHAx_FR#)k zy;GOeiyh)Qlsc0<_BH*PaN@@shX+FZ>QmpEAK!ey`z1arvnSKzZ ssh-ed25519 il3lzQ Q+/uqZhUWs5pb5T1ocD+/qTSo4DJbd/W1exruQ34zAE -8HFRvEblGVrkoVaqAl/Af6wrDn6A+3unZIMBipEkwgA --> ssh-ed25519 1g/xww PqXxTvLaF6ZlcVov81VrVH130jFh2iGmHPRtBYV4ME4 -1VBknQzaNZyoz2wvgKX+IZGaOEnJ1xGvxPYxq10ar/U --> ssh-ed25519 +kBihw QXNxY9OQeIM98OqmHoa/S2kMZqSX+ndgxGyCJpHJ+gg -b3DmfUswyPQ09sp57v3QMNEF/Ka3w9Qj2s1kGUSinmQ --> ssh-ed25519 dbKeHw 5GzjKgjUX5e6Net7voWBykC17zRcdSFDFbDsSwp5FAU -GwTEg3YR9HdcQHPg+XjP2Lg1BpcWA4VunbZSBdxVaYU --> ssh-ed25519 Svnssw imRjD5CJu/jOac3t/APHbYBnsyJVQdebR6K52A6GdwM -n+Q9kEEkYRBuEzWlSwbjJNsjF8uKloeUEWYxHa29B4U --> ssh-ed25519 jb0ALQ 4qbGIofHcyhJVfL24peGqqzg0tFdxbWBHJFenwehIAI -Ta3ye4quyHvvE+2CGZwYvQMwWfdrLIdqADLvJYhllPY ---- 3hbht7PYqFafVmcQWQwv3q2gUXM8HXajtmAaMnrh59s - +X984R2,􈱨(#42#*, b禽H_z }߅x7A!))vʞ¨W-eX-G<@~Ek?kGlQK4c&*J9V_0 µz+ɰ¯C ўQGXkg* -jl31JMOE[=S \ No newline at end of file +-> ssh-ed25519 il3lzQ QKUv2QtA6XAVZMc/RET+iJp/IgChWjPnttkT00YNkgo +8wS1EJ6+H+1++dyzEGoq7B7JT7G4wg/NDSNRxDPoRdQ +-> ssh-ed25519 1g/xww I/jn9oDI27fOq7Pf4aMIe10IJUiLz45KQfxbwoV2Yl8 +guK9G+fDLoVxO21YvDeZa14H0gOpm5ma3s+1r7VF77U +-> ssh-ed25519 +kBihw 6uyyp7Jg70FDmlC8Sos+GY/PKPS3QQKR0p1ofODQmC4 +aQDzLv9H54Ucsa3tiVHWhxkV1F83fwNTXIt8k4V5ngs +-> ssh-ed25519 dbKeHw CPQh63MLby86GqOiZv8sxD6qMezQj17fCPLjigCMG0A +OgcvqThhfSUelRy2WZ5eALyJ8uQft8gYdbMuySUi+Ko +-> ssh-ed25519 Svnssw VAK1KKUe7aMf/Rj5r5KnjeobG1JZQXKzNWXjuXpgRyc +Udegl2sZBsVUhN+XwlfSbC1HrKu05uZolm8dsQberuU +-> ssh-ed25519 jb0ALQ M6bx55Kzp4VtQUTq6vkg31JXfew8E+QqHAuXVjFLrxw +wmoYs4tGa56+GuY4r0RtTfXpxW9XTqC2YJlmGsVEHIY +--- wzjCBOS1iGnQe8ZPgaKTs7PZvI0TnRZd11eL7yoaWL0 +$rzGM}(^M؏*lQ̢*U-f7Cc/9~:$ZSR@]htC7y1gaCM !*1B{> oBN& îW_s7&:LK鯵Of׭N1!Vt;QBgRy1j(hv \ No newline at end of file diff --git a/secrets_file.enc b/secrets_file.enc index 20df784..33fcb27 100644 --- a/secrets_file.enc +++ b/secrets_file.enc @@ -1,10 +1,8 @@ $ANSIBLE_VAULT;1.1;AES256 -65366137313461383534313965646333656565353061336361363661613033393264353661346337 -3838653162383134393463323631613439373663396363380a633339396236363962313333343465 -31623961393532666136616438633734366261353866383264323730383432326635626637343739 -3235313062623637380a386235316437396534353261383832643165316565386263396664363962 -62393364333335373631356161373263313930343565626433383539373030363662353630633933 -63336333613965653635313637336437653139616564313861336332323739653865383531356233 -31373530343766343131346663656566363038643230343462336332323135323337353539303763 -33366638393064323431323636346161343936643062323861313766613264336465326132333631 -33306666383561653965303539313366653030663330393363363565333439383133 +33613635643765623937663135313833396162343134383466343966333964386364356134663264 +3137633339396462633431316634623834646437646162360a626564313831373761636161656232 +35316566336232666336646231356665366633303530623961666465366163306166623336656364 +3835353035333031620a633332376237336530343134623832363534383761616564616138363766 +30306361383462353361636161636335313461313835663362393839623735313738316465656537 +66396635323432376530346532353238346139376261366237343763373535623364633731323830 +333730373965613131336166626230333263 diff --git a/secrets_odyssey.enc b/secrets_odyssey.enc index fba7129..a7a96da 100644 --- a/secrets_odyssey.enc +++ b/secrets_odyssey.enc @@ -1,6 +1,9 @@ $ANSIBLE_VAULT;1.1;AES256 -30343638643335363463653231623566623961613534323261393639623865633964653634333562 -3838613035393661656362383736313561366466396439390a383162366362643364636335613664 -39646137666437353762363764373562393736626530333336626261366232383063633732623238 -6531633638366335640a363461383535646663316533386137323966326237373836363561323462 -66646635383137333834363165666365366235333734646364616637383363666239 +61363033383536303833366237323662663236313163663033306138383162383062643830616466 +6531636430613462646161343939343363663533373737340a613433363666353432383463356439 +33656266633131336565613433653062656563656637656464346232656238646339303961373265 +6639643637303433380a393163366331373964353261383662656664643031626432366231346332 +34303964346137616233343930333331306363326332383465653163386539306430303965316437 +30343333373565623431653436653832356366343937653136346535316166383262623730343831 +62376532346237323465653261316339353034323633623632313630666531373839633665333637 +34356162356565396564 diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index db34258..66a74b8 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -15,6 +15,8 @@ in { rig-install ]; + age.secrets.firefox-policy.file = ./../../secrets/darwin-policies-json.age; + # Use a custom configuration.nix location. # $ darwin-rebuild switch -I darwin-config=$HOME/.config/nixpkgs/darwin/configuration.nix environment.darwinConfig = "$HOME/.config/home-manager/configuration.nix"; @@ -130,6 +132,11 @@ in { --user=${config.system.primaryUser} \ --set-home \ _rig-install ${r-version} + + echo "Applying custom defaults..." + /usr/bin/defaults import \ + /Library/Preferences/org.mozilla.firefox \ + ${config.age.secrets.firefox-policy.path} ''; nix.settings.experimental-features = [ "nix-command" "flakes" ]; From 71a086d07e3372078a739ed80cba6cb5b4ac6e15 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:36:53 -0600 Subject: [PATCH 10/75] dock (corianne): Remove unavailable Chromium PWAs --- systems/darwin/corianne.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index 66a74b8..582ffdf 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -76,8 +76,6 @@ in { (sysApp "Logseq") (sysApp "Zed") (sysApp "Steam") - (chromeApp "Instinct Dashboard") - (chromeApp "Carestream") ]; show-process-indicators = true; show-recents = false; From be4ce6fe1fbef35c5ac12a63a6967da8cd8fe365 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 18:07:44 -0600 Subject: [PATCH 11/75] pkgs (common): Install agenix cli via overlay --- flake.nix | 2 +- homes/common.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index a5b90d9..3841859 100644 --- a/flake.nix +++ b/flake.nix @@ -61,7 +61,7 @@ pkgs = import nixpkgs { inherit system; config.allowUnfree = true; - overlays = [ nur.overlays.default ]; + overlays = [ nur.overlays.default agenix.overlays.default ]; }; pkgs-unstable = import nixpkgs-unstable { inherit system; diff --git a/homes/common.nix b/homes/common.nix index 2b452dd..a83cb2b 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -31,6 +31,7 @@ in { }; }; packages = with pkgs; [ + agenix btop cowsay figlet From e094a8ac6a87ea197a04377d350e21c0388dab87 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 18:24:23 -0600 Subject: [PATCH 12/75] config (harmony): Remove Harmony/Asahi configs --- flake.nix | 6 -- homes/harmony.nix | 95 ----------------------------- inventory.yaml | 7 --- playbooks/packages.yaml | 69 ++++++--------------- playbooks/repos.yaml | 31 +--------- secrets.nix | 4 -- secrets/ansible-vault-password.age | 22 +++---- secrets/darwin-policies-json.age | Bin 1214 -> 1104 bytes secrets/network-information.age | 28 ++++----- secrets/pihole.age | Bin 926 -> 816 bytes secrets_harmony.enc | 6 -- 11 files changed, 46 insertions(+), 222 deletions(-) delete mode 100644 homes/harmony.nix delete mode 100644 secrets_harmony.enc diff --git a/flake.nix b/flake.nix index 3841859..680c30b 100644 --- a/flake.nix +++ b/flake.nix @@ -105,12 +105,6 @@ "tchristensen@beocat" = mkHomeConfiguration { hostname = "beocat"; }; - "millironx@harmony" = mkHomeConfiguration { - hostname = "harmony"; - arch = "aarch64"; - desktop = true; - }; - "millironx@odyssey" = mkHomeConfiguration { hostname = "odyssey"; desktop = true; diff --git a/homes/harmony.nix b/homes/harmony.nix deleted file mode 100644 index 2e48431..0000000 --- a/homes/harmony.nix +++ /dev/null @@ -1,95 +0,0 @@ -{ config, lib, pkgs, pkgs-unstable, ... }: { - # harmony is an Asahi Fedora box - # I don't use NixOS, so there are some programs that don't interact well with - # the base system (or won't even install) when installed from Nix. - # There is no uniform way to trigger dnf package installs from Nix, so I'm - # just going to list my packages here. I hope to create a custom script that - # mimics the ideas of a Brewfile someday - # TODO: Create a Brewfile equivalent for dnf - - # dnf repos: - # https://github.com/terrapkg/packages?tab=readme-ov-file - # https://pkgs.tailscale.com/stable/fedora/tailscale.repo - # https://packagecloud.io/filips/FirefoxPWA - - # copr repos: - # iucar/rstudio - - # dnf packages: - # apptainer - # chromium - # firefoxpwa - The nix version installs an "immutable" runtime, which simply launches extra browser windows on non-NixOS - # inkscape - # kate - # kdiff3 - # krita - # lutris - # musescore - # nextcloud-client - # nextcloud-client-dolphin - # obs-studio - # podman-compose - # podman-docker - # qownnotes - # qt - # rssguard - # rstudio-desktop - # steam - # supertuxkart - # tailscale - # thunderbird - # vlc - # vorta - The vorta package is aarch64 compatible, but you cannot see any icons, and it cannot access local ssh keys, so we have to use the dnf package instead - # yakuake - # zed - # zsh - # R - # https://downloads.sourceforge.net/project/mscorefonts2/rpms/msttcore-fonts-installer-2.6-1.noarch.rpm - home = { - username = "millironx"; - homeDirectory = "/home/millironx"; - # Signal desktop is not available in any other package repository for aarch64 linux - # Similarly, Bitwarden is non-functional in all other forms using a 16k page size - packages = with pkgs; [ - trayscale - veracrypt - pkgs-unstable.signal-desktop - pkgs.bitwarden-desktop - ]; - }; - programs = { - git = { - signing = { - key = "0x37A3041D1C8C4524!"; - signByDefault = true; - }; - }; - }; - services = { - gpg-agent = { sshKeys = [ "207D13371E19752A67AA2686C16354D9963821DB" ]; }; - }; - xdg = { - configFile = { - "nextflow.config".text = '' - params { - config_profile_description = 'harmony Asahi Linux local profile' - config_profile_contact = 'Thomas A. Christensen II <25492070+MillironX@users.noreply.github.com>' - config_profile_url = null - - max_memory = 12.GB - max_cpus = 12 - max_time = 7.d - } - - apptainer { - enabled = true - autoMounts = true - } - - process { - executor = 'local' - } - ''; - }; - }; -} diff --git a/inventory.yaml b/inventory.yaml index ba53698..63f1f3c 100644 --- a/inventory.yaml +++ b/inventory.yaml @@ -3,20 +3,13 @@ ungrouped: hosts: localhost: ansible_connection: local - harmony: - ansible_connection: local odyssey: ansible_connection: local -asahi: - hosts: - harmony: - amd64: hosts: odyssey: fedora: hosts: - harmony: odyssey: diff --git a/playbooks/packages.yaml b/playbooks/packages.yaml index 612acde..b3d0947 100644 --- a/playbooks/packages.yaml +++ b/playbooks/packages.yaml @@ -1,55 +1,9 @@ --- -# These are repos and packages that are useless or unavailable on Asahi Linux, -# or have completely separate install procedures. -- name: Configure amd64-specific dnf packages - hosts: amd64 - become: true - tasks: - - name: Install x86-specific dnf packages - ansible.builtin.dnf: - name: - - libdvdcss - - mkvtoolnix - - mpv - - protontricks - - x264 - - x264-libs - state: present - - name: Install VeraCrypt - ansible.builtin.dnf: - name: https://launchpad.net/veracrypt/trunk/1.26.20/+download/veracrypt-1.26.20-Fedora-40-x86_64.rpm - state: present - disable_gpg_check: true - -- name: Configure amd64-specific Flatpaks - hosts: amd64 - become: false - tasks: - - name: Install x86-specific Flatpaks - community.general.flatpak: - name: - - com.bitwarden.desktop - - com.slack.Slack - - dev.deedles.Trayscale - - org.signal.Signal - state: latest - method: user - remote: flathub - -- name: Configure Asahi Linux-specific dnf packages - hosts: asahi - become: true - tasks: - - name: Install aarch64-specific dnf packages - ansible.builtin.dnf: - name: - - veracrypt - -- name: Configure common (all arch) dnf packages +- name: Configure dnf packages hosts: fedora become: true tasks: - - name: Install common (all arch) dnf packages + - name: Install dnf packages ansible.builtin.dnf: name: - chromium @@ -64,15 +18,19 @@ - kdenlive - kdiff3 - krita + - libdvdcss - libjpeg-devel - libpng-devel - libtiff-devel - libwebp-devel + - mkvtoolnix + - mpv - musescore - nextcloud-client - nextcloud-client-dolphin - obs-studio - onedrive + - protontricks - qownnotes - qt - rssguard @@ -82,6 +40,8 @@ - thunderbird - vlc - vorta + - x264 + - x264-libs - yakuake - zed - zsh @@ -92,6 +52,11 @@ name: https://downloads.sourceforge.net/project/mscorefonts2/rpms/msttcore-fonts-installer-2.6-1.noarch.rpm state: present disable_gpg_check: true + - name: Install VeraCrypt + ansible.builtin.dnf: + name: https://launchpad.net/veracrypt/trunk/1.26.20/+download/veracrypt-1.26.20-Fedora-40-x86_64.rpm + state: present + disable_gpg_check: true - name: Install rig (R installation manager) ansible.builtin.dnf: name: https://github.com/r-lib/rig/releases/download/latest/r-rig-latest-1.{{ ansible_architecture }}.rpm @@ -109,19 +74,23 @@ name: "*" state: latest # noqa: package-latest -- name: Configure common (all arch) Flatpaks +- name: Configure Flatpaks hosts: fedora become: false tasks: - - name: Install common (all arch) Flatpaks + - name: Install Flatpaks community.general.flatpak: name: + - com.bitwarden.desktop - com.github.tchx84.Flatseal - com.logseq.Logseq + - com.slack.Slack + - dev.deedles.Trayscale - io.freetubeapp.FreeTube - io.github.alainm23.planify - io.github.dweymouth.supersonic - io.openrct2.OpenRCT2 + - org.signal.Signal - org.zulip.Zulip - net.ankiweb.Anki state: latest diff --git a/playbooks/repos.yaml b/playbooks/repos.yaml index b771518..36b2eb0 100644 --- a/playbooks/repos.yaml +++ b/playbooks/repos.yaml @@ -1,6 +1,6 @@ --- -- name: Configure amd64-specific package repositories - hosts: amd64 +- name: Configure dnf package repositories + hosts: fedora become: true tasks: - name: Install RPM Fusion free repository @@ -20,31 +20,6 @@ - name: Install Zotero COPR repository community.general.copr: name: "mozes/zotero7" - -# Asahi Linux comes with its own strange version of RPMFusion installed, so -# RPMFusion is installed only on amd64 systems. In addition, VeraCrypt and -# Zotero *are* available via COPR, but from different repos than their amd64 -# counterparts. -# Also, Asahi has its own version string, so we have to manually specify the -# chroot for COPR repos added via Ansible. This is handled automatically when -# using `dnf copr enable ...`, but not via Ansible. -- name: Configure Asahi Linux-specific package repositories - hosts: asahi - become: true - tasks: - - name: Install Zotero COPR repository - community.general.copr: - name: "isaksamsten/Zotero" - chroot: "fedora-{{ ansible_distribution_major_version }}-aarch64" - - name: Install VeraCrypt COPR repository - community.general.copr: - name: "architektapx/veracrypt" - chroot: "fedora-{{ ansible_distribution_major_version }}-aarch64" - -- name: Configure common (all arch) package repositories - hosts: fedora - become: true - tasks: - name: Install Tailscale repo ansible.builtin.yum_repository: name: tailscale-stable @@ -110,7 +85,7 @@ register: terra_priority changed_when: terra_priority.rc != 0 -- name: Configure Flathub remote +- name: Configure Flatpack remotes hosts: fedora become: false tasks: diff --git a/secrets.nix b/secrets.nix index c0d5047..1b118dd 100644 --- a/secrets.nix +++ b/secrets.nix @@ -12,15 +12,11 @@ let "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHKKkucebeb1GcerOZAAs5GQsgTS8kXw5W41b9Fy9+hp root@corianne.local"; corianne-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOgL2lO9RJBdQYANoxGyWXcNKi5/NZkRHHo/rNqaYMc/ millironx@corianne"; - harmony-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFBYxsCkw+ObDzIvU8z/rSlYcQx0JIt1bCVxKcDxeNNZ millironx@harmony"; - system-administrators = [ anderson-millironx bosephus-millironx odyssey-millironx corianne-millironx - harmony-millironx ]; in { diff --git a/secrets/ansible-vault-password.age b/secrets/ansible-vault-password.age index d833716..9234dd3 100644 --- a/secrets/ansible-vault-password.age +++ b/secrets/ansible-vault-password.age @@ -1,13 +1,11 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ 8BY+QUEGqILKLs6ROw7llEOhx0GgrfFeKDcEgHePUFw -SPiG48tkp5ewFc6/uNj+541B6YJODGmDFEbET2BfoZ0 --> ssh-ed25519 1g/xww HyUG/jNJgHCceV/9vaaoSHc681x6Gg/uY+RIfQxIBxU -6XVufQ4A9r8HPU9QLZ/idx3NjDf+UeKVMhtk9+Awy4E --> ssh-ed25519 +kBihw XjhEk6TF6M5OalqVQNpAemlmgMIJnfuH6M600DnJql0 -3zQPJZcsfnbUqRf5XWTJNbyqMb/rsSBIkS7YlYsyMcs --> ssh-ed25519 dbKeHw nIG5Z+XdJ3dyMxFOxyFMHw5sUkRJ2dsooJbIScNwlxM -brJoiOSQcwgs3vNSk8eK6dzH3zfQGFNdEWj3jjMM5e0 --> ssh-ed25519 Svnssw +VFbKj457mYT3GXQSacQ13J8MSkYe6A26ssNbqh8LAQ -rJzIG170BcRlsLERhnfaqgRFeAL4Yw7zvtb1gGvUkCU ---- ebIxmIBuNqNgfVWvOJc/0OpFBf3Q7pmApGgHYjrtJI8 -AeO:(7_x0׷ jfV /D.8⿀1ߠ[qf!7ht0Y \ No newline at end of file +-> ssh-ed25519 il3lzQ WthM+rK9ntTt0GkP6Z7kuFeOCMkYdY5OkoxtIY8xnk8 +howoRiqpwVW+K4ybhHngRfqobGOqSlye6da6+QJg2xU +-> ssh-ed25519 1g/xww 7iNs/T1MXDvZTtbz3s9Dx8CERfL4TBpn4fwhSv8j+yQ +cHXWpo3FEmkD2867IhdCpG4Pkq+LRkvi54OvTeSQA8s +-> ssh-ed25519 +kBihw HXgixNdqoB102vJDQ74UhC2wUIpYNv21ZvfFRgPmyX4 +09wYp8mUSl0ixLbtbK3E+u/7KVx8bYXTAwbzWN9TX/k +-> ssh-ed25519 dbKeHw PhePJgvp9fRMEJdtYwq3MV+CfNbEs1xJrQefJPQtl3Y +muMZYzYC8aHJBq96Z12pvxA32Cs4KFcG/0YHVT6tX8o +--- lunvYfBDg4+g00hMQJc6ZHQiBQ9k/qubJBYQ+p6aXhc +Ϛ:VnߛTFW=r TvM_=!՟Ǧ~N0 IPem̮.3/T[ \ No newline at end of file diff --git a/secrets/darwin-policies-json.age b/secrets/darwin-policies-json.age index eabc269965926dde0005b303d3d4c30974d04056..258d0b23b1fc8689c6a140a4b33da33f087ce132 100644 GIT binary patch delta 1035 zcmV+m1oZp93D5|TEPrW4Q$jIkY+++^H#1l_acWjeGH-ZyOKop5Y;8ZwgXsNK{aHZew&yGFDMiS2k~TL^DrnG)YloRdz~3Yc^?GR6}=cYHw#qNeV4K zAaiqQEoEdfH8n9gATehzcz1UoWMVZ^F;Fp8HaAXhYDi&ectuGg zR!>1sQ&m<)SwnAFH&$*`R#!4+HCi%uFl}r#Qgc~Pb8uF8WHxA6FjR!}ieS$btvIBRTkZFzrGc|m7uW?C|CHAi?ac5qitWiV({XJS%UMG9|6a8pY! zc{oZiG)7utW;9V#Pj`4mIYnW0IaGRbLpgJ6OKVe2XfZHCK?*G`Eg)2GbV*T2cy2>c zNl!>oT6Zx-Z8Jn!VM|J9Z8>FiLt;i|NK0sKQgAa*K?>CFSFm+bYg2!8>+`^%+YHD_ z;y$vi85eeh+r2o6Li02-7F#8P{JU~ZLsk}ZAb7{7Z?pQC{SQgy4LspddwK;HWbQ4s zfCL`>4eHQ_A3iOTft7F`EcUU}5qpl`q2_n;wI!8JmG&;s%vntWhrT$aC|bdEm!VujJ04X#r1w?;c~q~yv?)|@wzBM zMkq*4+hl8?X4!p!oK&x?OSDPVqI+=G&tROteJJE7of3l|JdOdZA~l({^T<8o=3S6_ zrBA??!eH1GWPL$7F*rE=@^C85^)PTr>{kZ1=MI{KJ5fE?pf7)BN7Z4P<5($4l{hF# zC6N^WM8uJ~Li#aKz8XKxT3XNvB? zyO@=`5L}c*a!X%?UP+v}(cLe+MibLbPU|fN1@kjNml}3}u~z@S9C@}-V*ehz{U{Bz zN|ge(hrBed7?1VI9VX)Gxz92Y&O6cHp}-=Uyr5y%8`l;e)QI~xs21f*{N9B0otHZR F;l8Nys2l(Q delta 1127 zcmZ9|`)?Bk0Kjn^M7Kj?#J~h5Hefc{D7{|WwM*pD^>ux}?yl=$0=-__yX)h6y}MrT zkPI9HhC)zS1Y-z_GXf5k4IP3~(J=u*aDa%W3^72|A%-y|f{~y72foSYd#3t}n$7du zn?Z#32IB#$kdu_G-D7TwCA`Ln)7@$d$L)y_mJa1H8{yBCY=FgOHN-7OK@@N#i71RY zX8~o-Zuh_-13I)m3>PwxPallYETCSb;(1D)AR&W6+oIB@G$lz=*wQf931T2!5(4kq}jzrz=q?j{^vIOc- z+FR0aS$|O*eeKrM5fMqnFe#F!VpeAebF^}(AIf3LJc6JRzv5#IS{tL_9+0x}K#S1E z>NtkRXei~x3rwCaW?Ceii51f>A+FJ+6raI)V62SaJZl^WLchzx&xpn zSu+eFw}C-KW+-0-cgjx5%kVlJVFBI<=LIf-#*4DqZBB(~h}MU&unZQw9O+1DlyEGV z^Mn%to%#Qh!o?iVODan14(q+)Y%>xtF!?CaYLBO|K+Z>Dj1km{jM$WcxHdORS{^1K zi=QvT);OF=lg$yc#EGs%GG}cqrO8qRH=%r%ayX)*$>@r2IrWfYOW}MI$&j4YDlmja zV(q>(sbP4#-lyb^K>~F`4k>9;Xp{#OJ)951o(Qk^mZYMX&M6wjB;rCzMw`qA0nsB( z1zF&{K2#5=)oK+Tu#^IX?13@bu1Q+snXu#z`hxBx=3p5wXks91J4BO&j?L(SswtiG z*Up*l-n`>p^ZxFd8Sw10ZIQ^cRAYrt*B@_OX#>YM-QPataYpw>a8&&3oz>+|@kDt= z_r|5yAIz={oWzd|Q^5BXSH;;8+zDFD6C_Q%RkscZUgm)X(b#a~TD zSD#%!bj?3!kLLO-)&;|fV_#Q zd<+;~n7b=+W+1sQvmA3RtgE_ozW3Vbm*L`$C-2Ih(9I>24=h;OrT=!_H~oJf)GbY}x<*-20x3!i=}ISJuxMn7DUI z^RfNY*dIR~^w&J|{G<(iRlW0>(L?n;J$3azpocy32sw6X_tAzywSrYUx`rn=b diff --git a/secrets/network-information.age b/secrets/network-information.age index bccc467..a1394fe 100644 --- a/secrets/network-information.age +++ b/secrets/network-information.age @@ -1,15 +1,15 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ X/F7G7EJbo6QTCGBSp2irApe2qkFUmj2OytrpOVVQ2w -yjitkwkxhNJLxSK4zF25o2lhZO6drBkjwHYykcPnoIw --> ssh-ed25519 1g/xww HriK0yZF3EEh2mB8RpVWBGzuPiK1DB80BeXZAt5Runo -8ke05EDxykN/tu5wEzL3RvRnleBeWKpblm/iXb0pJ8U --> ssh-ed25519 +kBihw bG3XH77yhvMR+HsJMwi1WsXo4aSm5ez80gRlgkTosSo -/WhUI2gKt94naWkeDrXvxnc2fsJvqmcARJnnhrU9sjw --> ssh-ed25519 dbKeHw Bugbp/ovWaODwR6msKnGB3D/dT/ZMmFyr6Za0VAJqBQ -+FfFa1w5/Ok8rIhp+NOBxfqoGFFlGwt8hPhxzibAVf8 --> ssh-ed25519 Svnssw xpuVCV4OJi8G8R5vuSMio9hoRWmufOsCaEyhLMKarh0 -/82i3ZFwQtMonTj4wfa9KPig9qUIJomVYk3QlpB4rJk --> ssh-ed25519 jb0ALQ cbnyjqANs0f/CsiD/peCuJuMJfuaNKIIzbd/87OEV2Y -iQmJxEOQuharrlkiaOdQXnTSUcsq+b7BzSo+G35QJIw ---- eDJuMw4WC33Ihy5OBr2gkeewAFBpCa3gO3CYehr5bOo -VR@X[6gȣl ʑm.P4MiYt̾~ x\Y㒊UMGd܏{'mB,@[e]{NbN] a!*ͬ`YQn95 'q5]-6:FYL$} \ No newline at end of file +-> ssh-ed25519 il3lzQ DhOVslXJ/kZmHvfCLw3rPiRrR1NxTC6zV6Di9WOUY1o +i+OTfk7LWc3rT+T8yFGlPabsgVkddPAr3D6oc5hpe/Y +-> ssh-ed25519 1g/xww xiWVbXWJXtgPLnPWC5bRCvdgceKuY/7wrAbWGlBmZWA +C7rwIOD0xGzTpGRgAycHlspsGaLLwFG6j+6/vPkVtkI +-> ssh-ed25519 +kBihw E2rOacH/0J3YWuplB01z51r/MW3jF36l1C+QeqY6zls +162dh2KpWV71727zPZ2fpS7btQsQ/IL43kuViypZwWc +-> ssh-ed25519 dbKeHw k4ZekrotAzMlC6+RifphXj108iEra0AH4DrCxOSI/gg ++9eibvHzF88lm9Qi/FCfW87D9BW25+zkzQbnhe/F3Rw +-> ssh-ed25519 jb0ALQ Z8WYL7/D990/IWBHGKZInn3Rffol0jnraGQyQbqCdWE +LQa3mmMrA6Qx8wChzlWmB3M2OAtjVep5ryOZH3oZOMA +--- avI87pf1OwXk3BW8w9jW95NK4U/vfUg0pJoqjQ6eCS4 +75l7gϹNU%*-^$z1,4G԰@:~,Se@7p += >H0㭅m7mUW +W-y EÎ8+gM/- z 펈5%l0l صΙ|JEz y=a1jpIQfܝ3 \ No newline at end of file diff --git a/secrets/pihole.age b/secrets/pihole.age index dfe146e15d5f9d48bbcaed9310e1d30094e418cb..3e0bcc96880e77514de21d77a18bf0a24bef5682 100644 GIT binary patch delta 746 zcmZ9|OKZ~r007{6nKLR3L8hQs4_>UbP15usDyE5T(;^XX3_`WmCuM8aDHmMmIzSv~y2(IH= z8RXDhwpE6jNOCV{GKAxHq*x$&I4QK#fMn4f8N^~q1*c616TlP;3ZzWtnSR|SP)Oi- zKg(f0RWX3*?yzNP(S`yc2$%_jYRq%pu!00Wt9ml;St+pI*6O)7W+ip3iu+xKP1<^* zOWCrJOHly|pnklEx0zT=+|NpFpF6MnjWOt2#m+;IwPSImfO+0IRl6g9?}yaJTtL3$isAnkVpp!m@dV} z&0@Z$_uXRI9T8huAw4&~Y70ZmuX|UI-R1h#*Zut(%M<^=+dIb-3TP03~1VnNFU)nFlQK}Md!fH3uY`UY0 zqw!tJ0w?L1QbjbS$`vs!+oA*!_~+nZr)OABENGI=nrUQM85Lo)kj~-BJSvJbaDCfi z;gdMlpX5(8{%m}C@$1%E${s6~F!MD<-Ec(fwzu~!DG3O9zs s@TsBg%a`tL+IM$u|7sfvhf&c&j literal 926 zcmZY5-;3LH008g@QAfca5Bi`Un86t1LT$cn(xelHZF-lsN!ot%t7$+bZIf@3rcK-Y zYAVXX)IEsYgM-_Hdl?7%;^c&Z=tSiZ*%Z_lJq3M`>6khN6%>EJpMSvzJ|?pA)^xbY zW|13A9|{(zkbqqN6c&a~-WnAt3RE!HFZnBoL0(OYFshdIs%D78g0!LFZfjO(BG&17 z-Dwn!6@uuu$0*1#sSGw+WxRm{93N$?4KA3|HM*tH9GRj*yDqn-WxX3nBY0Q?sIW{^ ztXc4;m7v}%(spM~cWu%Xn-(CNE!7oPB*jB}IYXEvcGW+}wMg4Q-^T0N}c{WDS&KCPE zf5L^@Mx)u!<@0$gU3qM+BLkP4LW?oF$mErf?ixvxP^OYG0>BdJEHHZlk$d;WWA7i_ zdi&N7ik`F(;uzpV6%HL)0>^=X^0eyx&vNJ5a zPvPyBQ96!yl&=YqGtK3i*FzWew~Tc@{ovELuKynk`8_xO$5Li+e0NA^yBBJkhd wc=b}pzV_8OKYjK}`%iFmO^Y6e_ujexc?~`I%=u?eOW%Ezf$QGCC!A#eKLx)^)&Kwi diff --git a/secrets_harmony.enc b/secrets_harmony.enc deleted file mode 100644 index e91177d..0000000 --- a/secrets_harmony.enc +++ /dev/null @@ -1,6 +0,0 @@ -$ANSIBLE_VAULT;1.1;AES256 -38383539613238613864336630316433666436623334313334393762396536663530336264306661 -3338616565316138616666343862366638643134343931320a633366363539326461346636373738 -66393138653463663536313065623332383166386332303564323939336630333163623637386434 -6538393966633731660a616437356233643234363562366433663437383439326161353330356331 -63346432663036353332303266343361346266396437396131376531303265356233 From 160c8e82735da607de469cfd10fe4503e61516c7 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 18:24:52 -0600 Subject: [PATCH 13/75] lint (ansible): Fix line length --- playbooks/nix.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/playbooks/nix.yaml b/playbooks/nix.yaml index 672725f..50d9952 100644 --- a/playbooks/nix.yaml +++ b/playbooks/nix.yaml @@ -45,7 +45,8 @@ register: home_manager_exists - name: Init home-manager ansible.builtin.shell: | - /nix/var/nix/profiles/default/bin/nix run home-manager -- switch --flake git+https://code.millironx.com/millironx/nix-dotfiles#{{ ansible_user_id }}@{{ ansible_hostname }} + /nix/var/nix/profiles/default/bin/nix run home-manager -- switch \ + --flake git+https://code.millironx.com/millironx/nix-dotfiles#{{ ansible_user_id }}@{{ ansible_hostname }} when: not home_manager_exists.stat.exists register: home_manager_init changed_when: home_manager_init.rc == 0 From d080b9d480456adbdc33955b6a04c36505c66f33 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 18:25:13 -0600 Subject: [PATCH 14/75] lint (ansible): Fix template reference/location --- playbooks/config.yaml | 2 +- {templates => playbooks/templates}/policies.json | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {templates => playbooks/templates}/policies.json (100%) diff --git a/playbooks/config.yaml b/playbooks/config.yaml index 4aa2dd4..156dc63 100644 --- a/playbooks/config.yaml +++ b/playbooks/config.yaml @@ -11,7 +11,7 @@ mode: "755" - name: Create Firefox DNS policy ansible.builtin.template: - src: "{{ playbook_dir }}/../templates/policies.json" + src: "policies.json" dest: /etc/firefox/policies/policies.json mode: "644" diff --git a/templates/policies.json b/playbooks/templates/policies.json similarity index 100% rename from templates/policies.json rename to playbooks/templates/policies.json From 65ee23cc363cee37be4ef035c1db8cbecc2e304b Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 18:27:25 -0600 Subject: [PATCH 15/75] activation (common): remove git hash recorder I used to try to control Ansible's bootstrapping of home-manager by recording the current git hash of the home-manager repo, but I haven't allowed ansible to touch home-manager after initial setup for a while now, so remove the hash code. --- homes/common.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/homes/common.nix b/homes/common.nix index a83cb2b..61ba3f1 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -87,14 +87,6 @@ in { }; sessionPath = [ "$HOME/.local/bin" ]; activation = { - recordHmGitHash = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - cd "$HOME/.config/home-manager" || exit 1 - if [ -z "$(${pkgs.git}/bin/git status --porcelain --untracked-files=no)" ]; then - run echo "$(${pkgs.git}/bin/git rev-parse HEAD)" | tee $HOME/.cache/hm-git-hash - else - run echo '*' | tee $HOME/.cache/hm-git-hash - fi - ''; installRunic = lib.hm.dag.entryAfter [ "writeBoundary" ] '' run ${pkgs.julia-bin}/bin/julia --project=@runic --startup-file=no -e 'using Pkg; Pkg.add(name="Runic", version="${runic_version}")' ''; From 9fc8c9a8901e97aee77bddf803794f42f0cd4f54 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 19:29:26 -0600 Subject: [PATCH 16/75] services (borgmatic): Add borgmatic service --- secrets.nix | 16 +++++++++----- secrets/borgmatic-passphrase.age | 15 +++++++++++++ secrets/borgmatic-ssh-config.age | 15 +++++++++++++ services/borgmatic.nix | 37 ++++++++++++++++++++++++++++++++ systems/linux/mcentire.nix | 1 + 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 secrets/borgmatic-passphrase.age create mode 100644 secrets/borgmatic-ssh-config.age create mode 100644 services/borgmatic.nix diff --git a/secrets.nix b/secrets.nix index 1b118dd..15c2329 100644 --- a/secrets.nix +++ b/secrets.nix @@ -6,12 +6,14 @@ let "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxTfeg+GZsfmG8TuEV1xW1gXknAIKzZ3UjZ3guRY+EW root@nixos"; bosephus-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaDPqRJHoqgY2pseh/mnhjaGWXprHk2s5I52LhHpHcF millironx@bosephus"; - odyssey-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; corianne-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHKKkucebeb1GcerOZAAs5GQsgTS8kXw5W41b9Fy9+hp root@corianne.local"; corianne-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOgL2lO9RJBdQYANoxGyWXcNKi5/NZkRHHo/rNqaYMc/ millironx@corianne"; + mcentire-host = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINT51tQgsKzTIQc9WSQj01h/gPRvAD3k9jRhXppY7xmd root@nixos"; + odyssey-millironx = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; system-administrators = [ anderson-millironx bosephus-millironx @@ -20,10 +22,14 @@ let ]; in { + "secrets/ansible-vault-password.age".publicKeys = system-administrators; + "secrets/borgmatic-passphrase.age".publicKeys = system-administrators + ++ [ mcentire-host ]; + "secrets/borgmatic-ssh-config.age".publicKeys = system-administrators + ++ [ mcentire-host ]; + "secrets/darwin-policies-json.age".publicKeys = system-administrators + ++ [ corianne-host ]; "secrets/network-information.age".publicKeys = system-administrators ++ [ bosephus-host ]; "secrets/pihole.age".publicKeys = system-administrators ++ [ bosephus-host ]; - "secrets/ansible-vault-password.age".publicKeys = system-administrators; - "secrets/darwin-policies-json.age".publicKeys = system-administrators - ++ [ corianne-host ]; } diff --git a/secrets/borgmatic-passphrase.age b/secrets/borgmatic-passphrase.age new file mode 100644 index 0000000..31b7e97 --- /dev/null +++ b/secrets/borgmatic-passphrase.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 il3lzQ NZt+Qn166/k1xA8H+0i40Nf0QUcNoo/mPB4xEsbc52g +WDnvHlN0EAM3kcH4P0w9Fl6LaPYFLK9uhbL2C/asXkQ +-> ssh-ed25519 1g/xww 607VONmCuvQWVfbXOwtW36OrLDSmC1b3FJfcXG8coVk +aKmWBrjrk3cUfGJuEwmuzgiMfeqaDM4sFA9lSEyXb2A +-> ssh-ed25519 +kBihw mUCQloe1iMe4TupQmQRV/SsvDl7GYAy9qNgd/9QuRVs +pl5NvOjZpOmslTm34qhyIY8ihbGfvi5TUMNIN+KftQA +-> ssh-ed25519 dbKeHw mDRPmYMHU/U39xGm+cPt/DDX1VFwJR9q7Ej393eygjc +sneArlOp/HU1N9aXQjGunmcL2lSJ+uUfnLUKJrfuwWY +-> ssh-ed25519 +C0WRg +swZ49g3n/MdCXcaVVN+oJppbhVOeYyVhJBA/0O+zFI +PleOEzaPcOWCQKSULfZ1V8MIcuzS7W0J6KoqSQWuM44 +--- RtNvvt/RSfurXkC29xKp02PWD5+8Ikrdh3JJHzcUECM +r +ǔj &(F-WlEϮ3~K@BO,hJ-^ ,#yڦBn#qִr39PjsgdiÆв?o><^+E4< )K7;/xߎؔ +bh \ No newline at end of file diff --git a/secrets/borgmatic-ssh-config.age b/secrets/borgmatic-ssh-config.age new file mode 100644 index 0000000..cae035c --- /dev/null +++ b/secrets/borgmatic-ssh-config.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 il3lzQ +g4/yAloij23EO70Lwv3NHdzUlI3yM17V+GZVet+DB4 +KoJqTEeF5ol4q+ZwcO+bWsP+hKszCMAUrok0yU+L6WU +-> ssh-ed25519 1g/xww aGc6VKpwoGQyjsPxc4hFPqc5sTzpOx/p7AJL2otF3QE +u5gZXqSUKLMxKsekgixy5h57GZVmIXChnxOTq5iFv9o +-> ssh-ed25519 +kBihw FESLL/bEja1rrQm4V2VIFM9pEuP8ydNSiHgatiEqWDk +Y5D1RoMCKuX3HxUpebwNUgJFQJnJR0GILNeg2DOPaDs +-> ssh-ed25519 dbKeHw EiccNUjhFewzAI+OWDrZnGNZbY1uoP99EJhvDn3AKyw +QQohrq0jZJIwXGkycvn7Q4JFJmkhUwxXZEB5HN217Tg +-> ssh-ed25519 +C0WRg rbfEQSHbKDIvm6p2o9CiJIMNRFWlKaQE7TALCdgauzs +6NWlDEKfWnYHFwleqOF6fSOzjxNkjdBFeFRl1Cj1L9A +--- E6T4y6crIEiWxE3G9OOQDrRky4919i7FM0zDnPiqUH4 +d bt=p(Wwx9r }&l +g`ep~kP$vUH"-,4&Nh#%8]@(I BJY 4eQs"wNr-Cmqx +!q \ No newline at end of file diff --git a/services/borgmatic.nix b/services/borgmatic.nix new file mode 100644 index 0000000..28b1b45 --- /dev/null +++ b/services/borgmatic.nix @@ -0,0 +1,37 @@ +{ pkgs, config, ... }: { + + # We don't want to expose the location where borg backups are going, so we + # will setup an encrypted ssh config that references the host/username + # combo as simply 'borgserver' + age.secrets = { + borgmatic-ssh-config = { file = ./../secrets/borgmatic-ssh-config.age; }; + borgmatic-passphrase = { file = ./../secrets/borgmatic-passphrase.age; }; + }; + + services.borgmatic = { + enable = true; + + # This is the bare-bones way to get Borgmatic up and running. Other services + # are expected to declare their stateful directories by adding to + # `services.borgmatic.configurations."${config.networking.hostName}".source_directories` + # and to add their databases to + # `services.borgmatic.configurations."${config.networking.hostName}".[mariadb|postgresql|etc]_databases` + + configurations."${config.networking.hostName}" = { + source_directories = [ "/home" "/root" ]; + repositories = [{ + label = "${config.networking.hostName}-default"; + path = "ssh://borgserver/./repo"; + }]; + ssh_command = + "${pkgs.openssh}/bin/ssh -F ${config.age.secrets.borgmatic-ssh-config.path}"; + encryption_passcommand = + "${pkgs.coreutils}/bin/cat ${config.age.secrets.borgmatic-passphrase.path}"; + retention = { + keep_daily = 7; + keep_weekly = 4; + keep_monthly = 6; + }; + }; + }; +} diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 07135d1..60fd158 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -4,6 +4,7 @@ imports = [ # Include the results of the hardware scan. ./hardware-configuration/mcentire.nix ./../../services/nixos-update.nix + ./../../services/borgmatic.nix ./../../services/crowdsec.nix ]; From ac57a31f06f41f67eb990d655f009e0e3277ee60 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 16 Nov 2025 19:39:29 -0600 Subject: [PATCH 17/75] lint (borgmatic): Move retention to global scope --- services/borgmatic.nix | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/services/borgmatic.nix b/services/borgmatic.nix index 28b1b45..c028df2 100644 --- a/services/borgmatic.nix +++ b/services/borgmatic.nix @@ -27,11 +27,9 @@ "${pkgs.openssh}/bin/ssh -F ${config.age.secrets.borgmatic-ssh-config.path}"; encryption_passcommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.borgmatic-passphrase.path}"; - retention = { - keep_daily = 7; - keep_weekly = 4; - keep_monthly = 6; - }; + keep_daily = 7; + keep_weekly = 4; + keep_monthly = 6; }; }; } From 4a8ddb0784e7242f9aa21cd3f27d0016d17d8c6e Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 19 Nov 2025 09:05:53 -0600 Subject: [PATCH 18/75] pkg (desktop): Remove ghostty --- homes/desktop.nix | 1 - playbooks/packages.yaml | 1 - programs/ghostty.nix | 19 ------------------- systems/darwin/corianne.nix | 1 - 4 files changed, 22 deletions(-) delete mode 100644 programs/ghostty.nix diff --git a/homes/desktop.nix b/homes/desktop.nix index 2a0790c..03229ed 100644 --- a/homes/desktop.nix +++ b/homes/desktop.nix @@ -2,7 +2,6 @@ imports = [ ./../programs/firefox.nix - ./../programs/ghostty.nix ./../programs/zed.nix ./../services/gpg-agent.nix ]; diff --git a/playbooks/packages.yaml b/playbooks/packages.yaml index b3d0947..d7a60d7 100644 --- a/playbooks/packages.yaml +++ b/playbooks/packages.yaml @@ -11,7 +11,6 @@ - fontconfig-devel - freetype-devel - fribidi-devel - - ghostty - inkscape - jq - kate diff --git a/programs/ghostty.nix b/programs/ghostty.nix deleted file mode 100644 index bd91415..0000000 --- a/programs/ghostty.nix +++ /dev/null @@ -1,19 +0,0 @@ -{ pkgs, ... }: { - programs.ghostty = - let modifierKey = if pkgs.stdenv.isDarwin then "cmd" else "ctrl"; - in { - enable = true; - package = null; - enableBashIntegration = true; - enableZshIntegration = true; - settings = { - quick-terminal-position = "top"; - quick-terminal-screen = "main"; - quick-terminal-autohide = true; - quick-terminal-size = "50%,50%"; - keybind = "global:${modifierKey}+backquote=toggle_quick_terminal"; - macos-hidden = "always"; - linux-cgroup = "always"; - }; - }; -} diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index 582ffdf..e8292b7 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -192,7 +192,6 @@ in { "dolphin" "firefox" "freetube" - "ghostty" "inkscape" "iterm2" "logi-options+" From c8a1aa969263181c4483ea4b7e41e6f149e0d8cb Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 19 Nov 2025 09:12:53 -0600 Subject: [PATCH 19/75] addons (firefox): Install plasma-integration only on Linux --- programs/firefox.nix | 91 +++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/programs/firefox.nix b/programs/firefox.nix index 520a4ef..d5925d8 100644 --- a/programs/firefox.nix +++ b/programs/firefox.nix @@ -1,4 +1,4 @@ -{ firefox-addons, buildFirefoxXpiAddon, lib, ... }: { +{ pkgs, firefox-addons, buildFirefoxXpiAddon, lib, ... }: { programs.firefox = { enable = true; package = @@ -31,49 +31,52 @@ }; }; containersForce = true; - extensions.packages = with firefox-addons; [ - bitwarden - multi-account-containers - floccus - libredirect - old-reddit-redirect - plasma-integration - pwas-for-firefox - ublock-origin - user-agent-string-switcher - web-archives - zotero-connector - (buildFirefoxXpiAddon rec { - pname = "always_in_container"; - version = "1.0.7"; - addonId = "{a1e9543e-5f73-4763-b376-04e53fd12cbd}"; - url = - "https://addons.mozilla.org/firefox/downloads/file/4032840/${pname}-${version}.xpi"; - sha256 = "sha256-bLxjL2P6Sd06q98MSHYRTNigtcjGwn/C2r4ANWCqKrw="; - meta = with lib; { - homepage = "https://github.com/tiansh/always-in-container"; - description = - "Chose a container every time you try to open a page out of a container"; - license = licenses.mpl20; - platforms = platforms.all; - }; - }) - (buildFirefoxXpiAddon rec { - pname = "open_with"; - version = "7.2.6"; - addonId = "openwith@darktrojan.net"; - url = - "https://addons.mozilla.org/firefox/downloads/file/3831723/${pname}-${version}.xpi"; - sha256 = "sha256-f9eGhLxg4UyVn4o5e4DRkraLWzj11SGto/GOwsJa9kg="; - meta = with lib; { - homepage = "https://darktrojan.github.io/openwith/"; - description = - "Quickly test out your web pages in Chrome, Edge, Safari, or Opera. Open With opens the current page in your other browsers with just two clicks."; - license = licenses.mpl20; - platforms = platforms.all; - }; - }) - ]; + extensions.packages = with firefox-addons; + [ + bitwarden + multi-account-containers + floccus + libredirect + old-reddit-redirect + pwas-for-firefox + ublock-origin + user-agent-string-switcher + web-archives + zotero-connector + (buildFirefoxXpiAddon rec { + pname = "always_in_container"; + version = "1.0.7"; + addonId = "{a1e9543e-5f73-4763-b376-04e53fd12cbd}"; + url = + "https://addons.mozilla.org/firefox/downloads/file/4032840/${pname}-${version}.xpi"; + sha256 = "sha256-bLxjL2P6Sd06q98MSHYRTNigtcjGwn/C2r4ANWCqKrw="; + meta = with lib; { + homepage = "https://github.com/tiansh/always-in-container"; + description = + "Chose a container every time you try to open a page out of a container"; + license = licenses.mpl20; + platforms = platforms.all; + }; + }) + (buildFirefoxXpiAddon rec { + pname = "open_with"; + version = "7.2.6"; + addonId = "openwith@darktrojan.net"; + url = + "https://addons.mozilla.org/firefox/downloads/file/3831723/${pname}-${version}.xpi"; + sha256 = "sha256-f9eGhLxg4UyVn4o5e4DRkraLWzj11SGto/GOwsJa9kg="; + meta = with lib; { + homepage = "https://darktrojan.github.io/openwith/"; + description = + "Quickly test out your web pages in Chrome, Edge, Safari, or Opera. Open With opens the current page in your other browsers with just two clicks."; + license = licenses.mpl20; + platforms = platforms.all; + }; + }) + ] ++ (if pkgs.stdenv.hostPlatform.isDarwin then + [ ] + else + [ plasma-integration ]); search = { default = "Kagi"; privateDefault = "Milliron X Search"; From f9672236f53cc3f551740a23c5182378f02f5077 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 19 Nov 2025 09:13:25 -0600 Subject: [PATCH 20/75] addons (firefox): Remove Floccus addon --- programs/firefox.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/firefox.nix b/programs/firefox.nix index d5925d8..974f27c 100644 --- a/programs/firefox.nix +++ b/programs/firefox.nix @@ -35,7 +35,6 @@ [ bitwarden multi-account-containers - floccus libredirect old-reddit-redirect pwas-for-firefox From ac6c552339c12c358fe0a07298226f28226c9049 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 19 Nov 2025 09:15:18 -0600 Subject: [PATCH 21/75] pkgs (firefoxpwa): Remove Firefox PWAs --- playbooks/packages.yaml | 1 - playbooks/repos.yaml | 8 -------- programs/firefox.nix | 3 --- systems/darwin/corianne.nix | 1 - 4 files changed, 13 deletions(-) diff --git a/playbooks/packages.yaml b/playbooks/packages.yaml index d7a60d7..58e7263 100644 --- a/playbooks/packages.yaml +++ b/playbooks/packages.yaml @@ -7,7 +7,6 @@ ansible.builtin.dnf: name: - chromium - - firefoxpwa - fontconfig-devel - freetype-devel - fribidi-devel diff --git a/playbooks/repos.yaml b/playbooks/repos.yaml index 36b2eb0..476dfdb 100644 --- a/playbooks/repos.yaml +++ b/playbooks/repos.yaml @@ -28,14 +28,6 @@ enabled: true gpgcheck: true gpgkey: https://pkgs.tailscale.com/stable/fedora/repo.gpg - - name: Install FirefoxPWA repository - ansible.builtin.yum_repository: - name: firefoxpwa - description: FirefoxPWA repository - baseurl: https://packagecloud.io/filips/FirefoxPWA/fedora/$releasever/$basearch - gpgcheck: true - gpgkey: https://packagecloud.io/filips/FirefoxPWA/gpgkey - enabled: true # Note that I still have to specify the chroot for COPR repos b/c of Asahi - name: Install RStudio copr repository community.general.copr: diff --git a/programs/firefox.nix b/programs/firefox.nix index 974f27c..d4b98e5 100644 --- a/programs/firefox.nix +++ b/programs/firefox.nix @@ -37,7 +37,6 @@ multi-account-containers libredirect old-reddit-redirect - pwas-for-firefox ublock-origin user-agent-string-switcher web-archives @@ -248,7 +247,6 @@ "floccus_handmadeideas_org-browser-action" "7esoorv3_alefvanoon_anonaddy_me-browser-action" "plasma-browser-integration_kde_org-browser-action" - "firefoxpwa_filips_si-browser-action" "_d07ccf11-c0cd-4938-a265-2a4d6ad01189_-browser-action" # Web Archives "openwith_darktrojan_net-browser-action" "zotero_chnm_gmu_edu-browser-action" @@ -284,7 +282,6 @@ "floccus_handmadeideas_org-browser-action" "7esoorv3_alefvanoon_anonaddy_me-browser-action" "plasma-browser-integration_kde_org-browser-action" - "firefoxpwa_filips_si-browser-action" "ublock0_raymondhill_net-browser-action" "_d07ccf11-c0cd-4938-a265-2a4d6ad01189_-browser-action" "zotero_chnm_gmu_edu-browser-action" diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index e8292b7..e4d4447 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -182,7 +182,6 @@ in { "docker" "docker-buildx" "docker-credential-helper" - "firefoxpwa" "mpv" ]; casks = [ From 8d188dea43d8e0d3fe3d203e91906b261330f4ae Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 19 Nov 2025 09:27:19 -0600 Subject: [PATCH 22/75] addons (firefox): Remove web archives addon --- programs/firefox.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/firefox.nix b/programs/firefox.nix index d4b98e5..ed6705f 100644 --- a/programs/firefox.nix +++ b/programs/firefox.nix @@ -39,7 +39,6 @@ old-reddit-redirect ublock-origin user-agent-string-switcher - web-archives zotero-connector (buildFirefoxXpiAddon rec { pname = "always_in_container"; From 4a9eed6ecb2b9a122be0ddc4495e028e0918750a Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:34:08 -0600 Subject: [PATCH 23/75] brew (corianne): Remove LogiOptions app --- systems/darwin/corianne.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index e4d4447..d294dcf 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -193,7 +193,6 @@ in { "freetube" "inkscape" "iterm2" - "logi-options+" "logseq" "macfuse" "musescore" From b6b514278ecf22d61780e8ace9935252ee8c2598 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 24 Nov 2025 11:02:47 -0600 Subject: [PATCH 24/75] defaults (Dock/Taskbar): Make taskbar and dock have the same Apps Except for Steam, because Steam is weird and will spawn extra windows that don't play well with Taskbar. --- programs/taskbar.nix | 6 ++++++ systems/darwin/corianne.nix | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/programs/taskbar.nix b/programs/taskbar.nix index 757d42d..cff7787 100644 --- a/programs/taskbar.nix +++ b/programs/taskbar.nix @@ -25,6 +25,10 @@ bundleIdentifier = "org.mozilla.thunderbird"; action = "launchOrActivateApp"; } + { + bundleIdentifier = "com.microsoft.Outlook"; + action = "launchOrActivateApp"; + } { bundleIdentifier = "dev.zed.Zed"; action = "launchOrActivateApp"; @@ -34,11 +38,13 @@ action = "launchOrActivateApp"; } { + # Instinct dashboard bundleIdentifier = "com.apple.Safari.WebApp.2F51A6D0-087A-438F-92D3-A73FE09CB4CC"; action = "launchOrActivateApp"; } { + # Carestream bundleIdentifier = "com.apple.Safari.WebApp.5EC6478E-03A6-4147-8A4D-6EF3DE3F06D3"; action = "launchOrActivateApp"; diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index d294dcf..dea0f34 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -73,9 +73,12 @@ in { in [ (sysApp "Firefox") (sysApp "Thunderbird") - (sysApp "Logseq") + (sysApp "Microsoft Outlook") (sysApp "Zed") + (sysApp "Logseq") (sysApp "Steam") + (localApp "Instinct Dashboard") + (localApp "Carestream") ]; show-process-indicators = true; show-recents = false; From f2069cacb9d3d5687da98ee9df494e9362b780b1 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:40:10 -0600 Subject: [PATCH 25/75] secrets: Add mcentire-millironx ssh key --- secrets.nix | 5 ++++- secrets/ansible-vault-password.age | Bin 575 -> 685 bytes secrets/borgmatic-passphrase.age | Bin 781 -> 891 bytes secrets/borgmatic-ssh-config.age | 28 +++++++++++++-------------- secrets/darwin-policies-json.age | Bin 1104 -> 1214 bytes secrets/network-information.age | 30 +++++++++++++++-------------- secrets/pihole.age | Bin 816 -> 926 bytes 7 files changed, 34 insertions(+), 29 deletions(-) diff --git a/secrets.nix b/secrets.nix index 15c2329..1de9bc8 100644 --- a/secrets.nix +++ b/secrets.nix @@ -12,13 +12,16 @@ let "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOgL2lO9RJBdQYANoxGyWXcNKi5/NZkRHHo/rNqaYMc/ millironx@corianne"; mcentire-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINT51tQgsKzTIQc9WSQj01h/gPRvAD3k9jRhXppY7xmd root@nixos"; + mcentire-millironx = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOdC6eNx2nBi3PWK/n4GJMbVf+NlQJv13aUqxse/h1kL millironx@mcentire"; odyssey-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; system-administrators = [ anderson-millironx bosephus-millironx - odyssey-millironx corianne-millironx + mcentire-millironx + odyssey-millironx ]; in { diff --git a/secrets/ansible-vault-password.age b/secrets/ansible-vault-password.age index 9234dd3799ef7952f74be2fc64c5ee3c7388333d..c5b657899971cdff5c4f51077d04eee9528417c7 100644 GIT binary patch literal 685 zcmZY5JFk;q0LF0#Czi81Xe3T5sRc?~a4>1}(leD5`F<&a$dAa=IFw1@WdJEx1l~QD6}gmSh?2ZMj@e2wt19P}5{h%#^}o z*Bb~H5@kMH!&%Sa!yy;b(h!qHjTMG|_xRl9Zm{DlqM#ak13tsGA!S zg0GfjwRgwau*RA;iZiQG`0(P_Bz zcf52Fqlu(eqJ01 zGdL}Eq}S`AY_vayfxLCK!Ydj8j48&=EvXWOd7sL-PDF*62Pz=FS(=@9WRL HhJU+%Y*pp< delta 503 zcmV~$yN{D_007_^&xNS#O(u25%Ci(q&ZN*%N(%)_3qKr8DNkv66biJ%UG6{7nmFiS zTue;#mKz)#92{;r&&k=*#7zfX{k{)3J|8^2cVZNQ1h0ooT<8Vbj}*#kM;qQ9b5aBx z&>BZcT?_zS#}N$$NtI|}mR2(Z9+F!-5Mp2Rvc&F>v&nMnQqG)$Rnf=mDb#$}$n&7- zI(VyvF%8T|>Z)qALpeuuOftKrr5E;&;B%&1(_ByUMx@TBG3iyoq@gT#Cu)bzpMSk}Xb7es*0Pf&EQaEx*j3x)G~n=R zI!J+B;+R!>yyh#btw};CQ-PFTO(#n`7&k_C2vqvwLiW(;Lvcv{vS z0_Spa$S?W`3WS+X6(*fP&1SQ)+{7jD*sf2)K8gmCDlRBXP(xN_A|%_`A`3(nPN}&W zETEs?ULHJ{-FY8h{djey^Vf}|7k}25H!t*3`uq6k?)mrE`-`{xWBL5{DSB)0NqOh4 TKAv5ky}AEuPki}@=#Tyb(ao?* diff --git a/secrets/borgmatic-passphrase.age b/secrets/borgmatic-passphrase.age index 31b7e9786d18fa414940ff9583e1c5a3e362d7bb..ba13eb39250c07f4450f6815c5c08ecb87d3ddba 100644 GIT binary patch literal 891 zcmZY6&&%6%0LO6$gF!*WgD5H(+3BIw{A$vKxo5OZ)1>LIG)cd0Rj_HAZ+$HIcx@FyG{sAmT_ldJ%F-Yx3TF}9BfUaKHofW0!zMFo+Z}cjVLj;TM%^5wKtwri zsmzm3+mzLoJr1U&iO2YDC2atQf*sJsT#e=YEkBo4uA?{W%rp-Iw6+>#aduS0A-c^n zgjZb1FJiadFVbE(as4eZWyTgYb?T@RxelHam}_f31F+I)G#QuOM!UHYb-9{=FiNeF z#h0gcSIlu^h6@nTb?e0mK3F+cT%cvkbUKF;RrHrz7R5QH-;&b>Tu=D5%+ zMYR}ISFj2#s1I#`3#`-HNM(*EsAY3$thup0UV}D$_|X5fCI&_jS;LK#ND774jEHL# z10xqyk)#)O%M@wHiA|mqU~4Rsd{*j=Ib~{wMgvS0QpfqtVPXv@V>Zxc%ocaDjEuvG zP{r!uwn_yFHlvnC8QMg2>;_|{*Pljznp)!edpL$ z)ZU9f@BVu2!I^(Pesq2RyKfJ6pS((Z_VktKzI?f}bG+nY(dWi*f6?NFA6^%@(_dhp KoUL9s@zj6RnmmXA literal 781 zcmZY4OKZ~r003Zo3^WP@L2zCy3`B`FNs~T;Lv7RakuqEUg20Sxtwb`3;4#Za?XeJJ=lY=FBB>PAL5A5(34|>SW_4H)Ro3$$htFX{GEmfH z!T{vFJ1E&KOlBFhqn0opj_`t=sxurDUvmgVK?{_w){7a{lR7|?cI2Gj_B*I5>P0FfBPSdi7NcvuW}d-< zLKe4cB%=7R z=zuEUhw}M4A{8R4iuclF8^uv=WVBTvaJ8&&b6uz;A}rpl3+-a)I%*|h*C;R)b+;nY zl&^=8+}Ly@V7Y3+;Hz(ZfGy)^2^coxAtwsXP7S{m0&cclUkt zGtRezea60TE$i9Y`PJ9=zV3f@;==8V-tqG@r{03wN$mXoEi-@r>^e-Rk6nlE+<3e) dJh!s;>B_aKrG@#4$@QxXmjUJbyg9YB>mLnZ6Da@y diff --git a/secrets/borgmatic-ssh-config.age b/secrets/borgmatic-ssh-config.age index cae035c..ba01275 100644 --- a/secrets/borgmatic-ssh-config.age +++ b/secrets/borgmatic-ssh-config.age @@ -1,15 +1,15 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ +g4/yAloij23EO70Lwv3NHdzUlI3yM17V+GZVet+DB4 -KoJqTEeF5ol4q+ZwcO+bWsP+hKszCMAUrok0yU+L6WU --> ssh-ed25519 1g/xww aGc6VKpwoGQyjsPxc4hFPqc5sTzpOx/p7AJL2otF3QE -u5gZXqSUKLMxKsekgixy5h57GZVmIXChnxOTq5iFv9o --> ssh-ed25519 +kBihw FESLL/bEja1rrQm4V2VIFM9pEuP8ydNSiHgatiEqWDk -Y5D1RoMCKuX3HxUpebwNUgJFQJnJR0GILNeg2DOPaDs --> ssh-ed25519 dbKeHw EiccNUjhFewzAI+OWDrZnGNZbY1uoP99EJhvDn3AKyw -QQohrq0jZJIwXGkycvn7Q4JFJmkhUwxXZEB5HN217Tg --> ssh-ed25519 +C0WRg rbfEQSHbKDIvm6p2o9CiJIMNRFWlKaQE7TALCdgauzs -6NWlDEKfWnYHFwleqOF6fSOzjxNkjdBFeFRl1Cj1L9A ---- E6T4y6crIEiWxE3G9OOQDrRky4919i7FM0zDnPiqUH4 -d bt=p(Wwx9r }&l -g`ep~kP$vUH"-,4&Nh#%8]@(I BJY 4eQs"wNr-Cmqx -!q \ No newline at end of file +-> ssh-ed25519 il3lzQ 9QYGvIhYSyGcFmNdjK6qo2PnX+/t4LnU7eO3+TilFk8 +/6TLFd43tAdI5JKOPVk5YgBLzqdoc++CHtpYqBVMus8 +-> ssh-ed25519 1g/xww RV80BUKnJCyP2CsExGXqnEmXk1XAPkSyVEN+hByUcDo +IpbyT1t33/DCt8iP3Jy64FC88SqQTeTLB1bur3g5qzk +-> ssh-ed25519 dbKeHw CjnqCn7n/6pLpSaF7Q1u2vFBoLOswOaYSoQYwEu0yik +CSykNB4CmGuLWURDJWSAhtAhLcJ4iaeaYNKVsG9w/S4 +-> ssh-ed25519 3qPtug yNNOpEPutJhoRfkXQVnyUJ28Rtyh0oSClXLBVT77mWQ +Yr5TcwBZZbskLUmudPYnyIFvtcxbe+xKnde/5fAW4Dg +-> ssh-ed25519 +kBihw wf+3MXdvYBGBXUci/SiBfL+VPbVkuM1kl9jOHOxr9x8 +3Cgmhh7uI/Hrv3474FrkqspOx0kooNZcG5untJguvYI +-> ssh-ed25519 +C0WRg XJILB7Fa+o5NQPy+sQTt5z5S/WcxzEKTqR4dadFnphU +sdrs/Yf2lf14Dy22hFpzaTgCwvaDaWaXWMlERS58izk +--- 8zj6q3V/OQPbTiHOfin0sXT9gbVNYMCRSWoXMKxYFDo +PVzRbc1Q1T:rU kbXTk䑡ɧ釣ךUG XRl~ҷ8B:.:z?ɐıxED OמQ} `uPI3p|W!3U{mG2F7T)2 \ No newline at end of file diff --git a/secrets/darwin-policies-json.age b/secrets/darwin-policies-json.age index 258d0b23b1fc8689c6a140a4b33da33f087ce132..77d73854bd711eab398e705e736311d2fd8e19b0 100644 GIT binary patch delta 1128 zcmZ9|`*YI-003a&P_S|cjK|Rsg-LkOc z_q$R`hDkuQ-UlK9KT;Jl8YN325vss*xCw_aN7`8L0mD{a1*X%kSRq%(X8}6uF-sCt z&ADkpZtzNavZfxh;CfPYn#@|ts?sf0%d(&ghai&)tWbkdeLj~{Hv~g?PAfa|F`mf* zT-Jx9R@m)}b6}APhhQK;GjSK3#6+hJQ4uto5=1PND9%p*YvD@s_{PDKTe z%8o%|m7|KUNK+IKrG*NwJxufZIzv*>BA##-$+%+(kYfc1JVem#a6rzWb=-si~K-*YEaUInuj)WYOt8s~63i z{O`72=J51p^=Ge^9*nho56*2q z`7(Q<@6qJ)-JAA8-*VbDB2fA0^!Bd5cdfb~r!?mLl|uht4_dCRU9#cUq?IF!*@08ZwgXsNK{aHZew&yGFDMiS2k~TL^DrnG)YloRdz~3Yc^?GR6}=cYHw#qNeV4K zAaiqQEoEdfH8n9gATehzcz1UoWMVZ^F;Fp8HaAXhYDi&ect%M=V|s6AdRcX4b4WLM zc{ep!X=F-dGgVbM3Suy0H)%LHFh^l!Xm4gTayDjUMpZ#KW^XcTFEUa~Mp1G{Q!!U{ zIZjGzlg$AaS9(x0H%(JZOj>JjR&i-KaCJ08PDxX8Zgg0Bb1^V-NLoT{H)l6;Idg3| z3VK#gK~GavRz+DuZ&){0Zd6uRGG;YeGIlU+Y&BAISx<9tR(NDKXjm{=k?|LQM>$$- zQBp~2VP$hiSwm+;WlTs|Zc0LFb7*N$T4-)-OGM5VrDc^Q%`qzMma@cbvaaeazi9fSgpXt4p*=)uMZF*3V#^zkMj=C!G?5A3Tl$tRgj;we!e5;^tkD zdZkammcn4z6l8rtIWagm{qk@s%=IvEN$gh!w&xC-gF8_@*Pt(dW=GXwn&Vh0NtHM# zNhOgK|3t)*xkCCqx7E6~(YFVzonXt!LP|mp!Y5ProF?(;a$-swts#8Gr=7jcki6|> zDg^la9rgs)86Du~gQcAS?&c)(J>lT)1Q?QgnS@u8*jmFQbe`*Nk?O92>}PKf9A}E| zz`K~0yAWKIL~=`CgkDLUxzXJ(yhan#O-}1A1qJgnK$jYJfU#Epz8rbBP-6ccy!|K* zv`Uo%wuihlt{9K?$sH!*>ABA`5zaf&-=V-FnY^H3*BjRsAJmBZH>einOZ?u1^qrSG G0O7t}|ETr= diff --git a/secrets/network-information.age b/secrets/network-information.age index a1394fe..c35cd60 100644 --- a/secrets/network-information.age +++ b/secrets/network-information.age @@ -1,15 +1,17 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ DhOVslXJ/kZmHvfCLw3rPiRrR1NxTC6zV6Di9WOUY1o -i+OTfk7LWc3rT+T8yFGlPabsgVkddPAr3D6oc5hpe/Y --> ssh-ed25519 1g/xww xiWVbXWJXtgPLnPWC5bRCvdgceKuY/7wrAbWGlBmZWA -C7rwIOD0xGzTpGRgAycHlspsGaLLwFG6j+6/vPkVtkI --> ssh-ed25519 +kBihw E2rOacH/0J3YWuplB01z51r/MW3jF36l1C+QeqY6zls -162dh2KpWV71727zPZ2fpS7btQsQ/IL43kuViypZwWc --> ssh-ed25519 dbKeHw k4ZekrotAzMlC6+RifphXj108iEra0AH4DrCxOSI/gg -+9eibvHzF88lm9Qi/FCfW87D9BW25+zkzQbnhe/F3Rw --> ssh-ed25519 jb0ALQ Z8WYL7/D990/IWBHGKZInn3Rffol0jnraGQyQbqCdWE -LQa3mmMrA6Qx8wChzlWmB3M2OAtjVep5ryOZH3oZOMA ---- avI87pf1OwXk3BW8w9jW95NK4U/vfUg0pJoqjQ6eCS4 -75l7gϹNU%*-^$z1,4G԰@:~,Se@7p -= >H0㭅m7mUW -W-y EÎ8+gM/- z 펈5%l0l صΙ|JEz y=a1jpIQfܝ3 \ No newline at end of file +-> ssh-ed25519 il3lzQ YxgllrvBeqfXMCWKq2JF9aqyoq5CUTHXW5Y/DhxEDzE +55NxukxXnmQ27WqW/yjkvTLd/3QmcO8uxCxsGu95rHM +-> ssh-ed25519 1g/xww yIGdDpxlTv5I1LyueRLGY4LxpKHIYDVEN/fkcMlNvD4 +0vvuzTeqH59Kw+JFzmITJI8bgEevwJdPtqknuTx0QAU +-> ssh-ed25519 dbKeHw ZZEDohW79lqKjT4TTQSGvjav+n6mESo1RALb+Xbbcw8 +gwj6rEy0G95IYBAgB1F8W5wXhRP1n+1SUTIp6/XWCHU +-> ssh-ed25519 3qPtug 9kX4TyecOvRgb+KCk3FAC3QbhhxU55VRiQGNOytGFSM +LpBauBXhI4vfBHEfw/d1l4ao7qkEe/Daaow4CyDtpJM +-> ssh-ed25519 +kBihw Qiyi1AaxGLyXdsNFu+TcNQ/xxOLEkYUbTIWYClVw+Qg +ocPR0AsEh3OPRWa1kWTlXcoit/yv/iywHfcgJZh/iFA +-> ssh-ed25519 jb0ALQ 7OFB68omi4iWdrKdywc+f6f69mGThijWPTktuAbA2ws +XzZnyv3qsGFM/25KapNdM4n/poisk2sTzgy1ECqWODk +--- RCAULQI2W/aA4Smb0LaA0xrT1GiH+bOGrMRLVY8O41E +Y~2mEA)L+ b oX5Cѕ^Hvq]N $n)X¬xlVgT)%M6aT2YM5Y ~ +HpS n&x(̞i? +K C̔KpMbCq*v ಽMl$ \ No newline at end of file diff --git a/secrets/pihole.age b/secrets/pihole.age index 3e0bcc96880e77514de21d77a18bf0a24bef5682..1b2bc2533d7d7de5063e15de08cacfa0e5dd6df6 100644 GIT binary patch literal 926 zcmZ9~ON-nD003YWtr$u@C<-EMEXr2Hn8#!?31T6WWL}x)wHiu+u2=O+39LsdRK+FNAr|z)>7yg5R_Y5XYpTwKC@i|0 zm>2{Jbij0gVmR{R$;MKx8y=gND(0nem`}D~8mAS7bV!j+JYSbvD!!_rHk@Y}NT%gR zOET+xPfU=sn&Jr5@3mQaG%gV_o;75@KmwYe)DZ_jnrT~^fv~fd7(`U*aHY??lB*y- z7fG_0W0P^jNDMlZRyEV$t#$?msJa|8@kGvL&K^u6NNfhI-W7UXVkD5c&?hw8@1>~5 zMSwA(>3HcYbr&(Z2s(os94^o%PY(K##3-8?O2(eUY_=F~RjV$LTP6lee#1(c{c zbvDlXP>h>Q(ZHJ`yy#a`KB#*gAi%Q0R^rQ1b%j+97Ue9&K$chfAp+!&jp*G#cf}q}16hYLhPef5f1s@lc;p6O2_`WksuM8aDI;j~MzSv~y2(IH= z8RXDhwpE6jNOCu4GKAxHq*x$&I4QK#fMn4f8N^~q1*c616TlP;3ZzWtnSR|SP)Oi- zKg(f0RWX3*uCQfk(S`yc2$%_jYRq%pu!00Wt9ml;St+pI*6O)7W+ip3iu+xKP1<^* zOWCrJOHly|pnklEx0zT=+{;RBp3|fbh)3?jR4-6+$8%Bw)G} z8#jyjn%;MdWp_kuWrg(g*P%%UQ;}j?DLQVkpxQ#g#aT-h=^9;X3l_)Z^Nit^Q!>oU z0OC`wSY}jCgS}Rzf`Hj_%Xd&dLRksWD|n#WDsd_#Ad35c(q1W!Qk8HMR=b&I(;ZbD zjqg$xNKeL;DxxV>u83*b7A=@U8KMK!G%Uc4m2kpFh=K_fblXXR5k4b!2pQJ{DKScx zYLN(swD1 zK8s_0e)44F&xThQzipYO?6Fb_GY?g77um(fU*^e~^7#7u3l%6dL4;Pl3vOzSXR{|3 z24`RYjvpKk!RJSQjjcO!Xeuv;_A|>r-7qsBHsxM?9GK^x9!bBQ+s-@(_B|LLKYjVq zxvP!KFFQN@gw)&lBlPplg?-Cz-B~0D$7ZQxJJ^A#+LQDNX-#L@(TX%|uLxEaZmbQ% sbE~&4UAVV#&)u1k@6}fu4jg{;`ShL9H$zL_pE|tx?6uXe-wyQu0z0%0f&c&j From 1730970935d170d806fc82eebd1ab68b8db40dd3 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:41:09 -0600 Subject: [PATCH 26/75] homes (mcentire): Add home-manager config for mcentire --- flake.nix | 2 ++ homes/mcentire.nix | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 homes/mcentire.nix diff --git a/flake.nix b/flake.nix index 680c30b..a703651 100644 --- a/flake.nix +++ b/flake.nix @@ -101,6 +101,8 @@ "millironx@anderson" = mkHomeConfiguration { hostname = "anderson"; }; + "millironx@mcentire" = mkHomeConfiguration { hostname = "mcentire"; }; + "millironx@bosephus" = mkHomeConfiguration { hostname = "bosephus"; }; "tchristensen@beocat" = mkHomeConfiguration { hostname = "beocat"; }; diff --git a/homes/mcentire.nix b/homes/mcentire.nix new file mode 100644 index 0000000..82adbbc --- /dev/null +++ b/homes/mcentire.nix @@ -0,0 +1,8 @@ +{ ... }: { + home = { + username = "millironx"; + homeDirectory = "/home/millironx"; + }; + programs = { }; + services = { }; +} From 3fd32ffa45c984a6eb09c6dfcf44d2fe0cd58406 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:19:28 -0600 Subject: [PATCH 27/75] feat: Add podman-secrets module --- bin/secret-translator.jl | 30 ++++++++ modules/podman-secrets.nix | 154 +++++++++++++++++++++++++++++++++++++ systems/linux/mcentire.nix | 1 + 3 files changed, 185 insertions(+) create mode 100644 bin/secret-translator.jl create mode 100644 modules/podman-secrets.nix diff --git a/bin/secret-translator.jl b/bin/secret-translator.jl new file mode 100644 index 0000000..ce50af8 --- /dev/null +++ b/bin/secret-translator.jl @@ -0,0 +1,30 @@ +#!/usr/bin/env julia +using TOML: TOML + +function remove_podman_secrets() + run(`podman secret rm --all`) + return nothing +end #function + +function create_podman_secret(name, secret) + run( + Cmd( + `podman secret create --env=true --replace $name SECRET`; + env = Dict("SECRET" => secret), + ), + ) + return nothing +end #function + +function parse_toml_secrets(file) + foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) + return nothing +end #function + +function main() + remove_podman_secrets() + foreach(parse_toml_secrets, ARGS) + return 0 +end #function + +main() diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix new file mode 100644 index 0000000..41a01c5 --- /dev/null +++ b/modules/podman-secrets.nix @@ -0,0 +1,154 @@ +# Warning to my future self: This module was "vibe coded" by Claude Sonnet 4.5. +# I originally had a hand-written module in here that did the secrets +# translation as the root user. I knew that I would want to support multiple +# secrets files and multiple users, and thought I should be able to create an +# arbitrary number of them, similar to how you can have an arbitrary number +# of `programs.firefox.profiles`. Unfortunately, even after looking at lots of +# example modules, I could not figure out the syntax (Nix has a serious lack +# of minimum working examples), so I broke down and asked Claude to rewrite it +# for me. Based on everything that I read, this seems to be exactly what I asked +# for. +# +# Here is the prompt I used to get here: +# [@Per service isolation on NixOS with Traefik](zed:///agent/thread/94cb8a22-ff0c-4772-a1a1-018b0107f334?name=Per+service+isolation+on+NixOS+with+Traefik) +# +# [@podman-secrets.nix](file:///home/millironx/.config/home-manager/modules/podman-secrets.nix) +# +# I originally wrote this module assuming that I would use Podman as root for +# all containers. I would like to fix the module to have as many secrets files +# processed as needed with services setup for each secret that is run as the +# appropriate user. Ideally, the syntax for working with secrets to be +# translated would be +# +# ```nix +# { config, ... }: { +# age.secrets = { +# "caddy.toml" = { +# file = ./../secrets/caddy.toml.age; +# owner = "caddy"; +# group = "caddy"; +# }; +# +# "authentik.toml" = { +# file = ./../secrets/authentik.toml.age; +# owner = "authentik"; +# group = "authentik"; +# }; +# +# "freshrss.toml" = { +# file = ./../secrets/freshrss.toml.age; +# owner = "freshrss"; +# group = "freshrss"; +# }; +# }; +# +# millironx.podman-secrets = with config; { +# caddy = { +# user = "caddy"; +# secrets-files = [ +# ./../not-really-secret.toml +# age.secrets."caddy.toml".path +# ]; +# }; +# authentik = { +# user = "authentik"; +# secrets-files = [ +# age.secrets."authentik.toml".path +# ]; +# }; +# freshrss = { +# user = "freshrss"; +# secrets-files = [ +# age.secrets."freshrss.toml".path +# ]; +# }; +# }; +# } +# ``` +# +# Can you help me rewrite the module to accomplish this? +# +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.millironx.podman-secrets; + + secret-translator = pkgs.writeScriptBin "secret-translator" + (builtins.readFile ./../bin/secret-translator.jl); + + # Submodule type for each service's secrets configuration + serviceSecretsType = types.submodule { + options = { + user = mkOption { + type = types.str; + description = "User account to run the secrets translation service as"; + example = "caddy"; + }; + + secrets-files = mkOption { + type = types.listOf (types.either types.path types.string); + description = + "List of TOML files containing secrets to translate to Podman secrets"; + example = literalExpression '' + [ + "/run/agenix/caddy.toml" + ./../not-really-secret.toml + ] + ''; + default = [ ]; + }; + }; + }; + + # Generate a systemd service for each configured service + mkSecretsService = name: serviceCfg: + nameValuePair "podman-secrets-${name}" { + description = "Podman secrets converter service for ${name}"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + Type = "oneshot"; + User = serviceCfg.user; + ExecStart = "${secret-translator}/bin/secret-translator ${ + lib.concatStringsSep " " serviceCfg.secrets-files + }"; + Path = [ "${pkgs.podman}/bin" "${pkgs.julia-lts-bin}/bin" ]; + }; + }; + + # Filter out services with no secrets-files + enabledServices = + lib.filterAttrs (name: serviceCfg: serviceCfg.secrets-files != [ ]) cfg; + +in { + options.millironx.podman-secrets = mkOption { + type = types.attrsOf serviceSecretsType; + description = '' + Per-service Podman secrets configuration. + Each attribute creates a separate systemd service that translates TOML secrets + files into Podman secrets for the specified user. + ''; + example = literalExpression '' + { + caddy = { + user = "caddy"; + secrets-files = [ + ./../not-really-secret.toml + config.age.secrets."caddy.toml".path + ]; + }; + authentik = { + user = "authentik"; + secrets-files = [ + config.age.secrets."authentik.toml".path + ]; + }; + } + ''; + default = { }; + }; + + config = mkIf (enabledServices != { }) { + systemd.services = lib.mapAttrs' mkSecretsService enabledServices; + }; +} diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 60fd158..7c0634a 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -3,6 +3,7 @@ { imports = [ # Include the results of the hardware scan. ./hardware-configuration/mcentire.nix + ./../../modules/podman-secrets.nix ./../../services/nixos-update.nix ./../../services/borgmatic.nix ./../../services/crowdsec.nix From 2b0684863245e19fff61f3f9790ff69ec2852e56 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:12:50 -0600 Subject: [PATCH 28/75] service (mcentire): Add authentik service --- flake.nix | 4 ++ secrets.nix | 2 + secrets/authentik.toml.age | Bin 0 -> 1222 bytes services/authentik.nix | 128 +++++++++++++++++++++++++++++++++++++ systems/linux/mcentire.nix | 5 ++ 5 files changed, 139 insertions(+) create mode 100644 secrets/authentik.toml.age create mode 100644 services/authentik.nix diff --git a/flake.nix b/flake.nix index a703651..204941e 100644 --- a/flake.nix +++ b/flake.nix @@ -138,9 +138,13 @@ "mcentire" = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { + home-manager-quadlet-nix = quadlet-nix.homeManagerModules.quadlet; + }; modules = [ ./systems/linux/mcentire.nix agenix.nixosModules.default + home-manager.nixosModules.home-manager quadlet-nix.nixosModules.quadlet crowdsec.nixosModules.crowdsec crowdsec.nixosModules.crowdsec-firewall-bouncer diff --git a/secrets.nix b/secrets.nix index 1de9bc8..8042bf6 100644 --- a/secrets.nix +++ b/secrets.nix @@ -26,6 +26,8 @@ let in { "secrets/ansible-vault-password.age".publicKeys = system-administrators; + "secrets/authentik.toml.age".publicKeys = system-administrators + ++ [ mcentire-host ]; "secrets/borgmatic-passphrase.age".publicKeys = system-administrators ++ [ mcentire-host ]; "secrets/borgmatic-ssh-config.age".publicKeys = system-administrators diff --git a/secrets/authentik.toml.age b/secrets/authentik.toml.age new file mode 100644 index 0000000000000000000000000000000000000000..1ef8f6e277acf7a7b989bfa87f553f5f1d1d0ac8 GIT binary patch literal 1222 zcmZY4>u(bU003~zNPtQJGXe}9)UhD$GJ0+AXm33Gyz66qTzh>DNUpu>_1f!o?e*?@ zhs%KBruZPTY>o(sKsF;j!ec-NI6t5P1p=6W43LPB03w6ML;_|Qzs|qlmmkT{jWnMs zDXnF;z%MP77@efoG_KMLLZ*?X3^1%mv@B=j)S%X+Qyo~v>MND-v>Hu#Q;5L?O5w7> z73Z2=B3@*&32z`mazs!=mLzXBg^CK1T}Gt6Qa<7aqXB`;M4eE~nr|g5E{POv8AqXc zqNZnb6IRS6bL!?<_j?{&PLLmh3V$^LSEl{#Z|95L_)KcC8=6A}x!71b6m_KZhz`T=l z`Qf0sxsXqZVW&C7ILa)Xb!a;7-?tA{bz_~-o`vtdFb~hEIkJEITMc`r9~@+xc0L+= zspZeZdBeyi&6$JacV0e(u0Co~77wm&Upr;20a;zc&YC=@2637veS$6+?5Yba;x9Zs zwe8n|@Y3q4f}FWd^%It?XYTFKuJ`L3>VeJ=HtxE5ZPn&(_(jck;PLt}d2Y0K^SuxE z%(~IHb?>4lwGSV>{xs43)2j1b>XOj|-We^`$IgB<^6bWgTlzkcJU!(?!u8G%l|QI? zEv}~9na9%1sprZYzQ1zMzVnN5vcB`EZsE`ncXeIgordSzB0G1lNRiIRTX#P^eAx7U zsrOx>|D=UFxsSWKa`+H@v8C>ERMiTaSC0SU9-qAUY3Yy|J$w2MY1{g{Z|>@rR=jp9 zf4cY9`oYi7cMeRFo}C>2XZx33;fwye$CmUVJ=-^=91bXXbabG4?nAk1?QhDJX&p!O zYij*Vt<$?+eRk>je0oP{9`n_SGvM3KsR!qsBS(g>W#sgwj>#K79$aqtbj|E7?FZi3 zdpYJ?vGMWp9^?Ftwfl}WAk{NRcGUfR;?Xzq!j{^WzXu+)&7L7{s&Bf#u3c%X3r_R& zT->rAnxoJ4OdT2@oqID$2ET1<;<0{pezZ4S9vcaUYq=`Jg0_|I9bY@IpZR@klKsh# J`)~X;@-Hw|+A;tD literal 0 HcmV?d00001 diff --git a/services/authentik.nix b/services/authentik.nix new file mode 100644 index 0000000..30ee781 --- /dev/null +++ b/services/authentik.nix @@ -0,0 +1,128 @@ +{ config, home-manager-quadlet-nix, ... }: +let + user = "authentik"; + state-directory = "/var/lib/authentik"; + port = "9000"; + +in { + # Secrets are translated in the system scope, but performed by the user, + # so are available in the user's Podman secrets + age.secrets = { + "authentik.toml" = { + file = ./../secrets/authentik.toml.age; + owner = "${user}"; + }; + }; + + millironx.podman-secrets.authentik = { + user = "${user}"; + secrets-files = [ config.age.secrets."authentik.toml".path ]; + }; + + systemd.tmpfiles.rules = [ "d ${state-directory} 1775 ${user} ${user} -" ]; + + services.caddy.virtualHosts."auth.millironx.com".extraConfig = '' + reverse_proxy http://127.0.0.1:${port} + ''; + + # Create a dedicated user for this service + users.users."${user}" = { + group = "${user}"; + isSystemUser = true; + linger = true; + autoSubUidGidRange = true; + }; + users.groups."${user}" = {}; + + home-manager.users."${user}" = { config, ... }: { + imports = [ home-manager-quadlet-nix ]; + + home.stateVersion = "25.05"; + + virtualisation.quadlet.containers = { + authentik-db = { + autoStart = true; + containerConfig = { + image = "docker.io/library/postgres:16"; + environments = { + POSTGRES_DB = "${user}"; + POSTGRES_USER = "${user}"; + }; + secrets = [ + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=POSTGRES_PASSWORD" + ]; + healthCmd = "pg_isready -d \${POSTGRES_DB} -U \${POSTGRES_USER}"; + healthInterval = "30s"; + healthRetries = 5; + healthStartPeriod = "20s"; + volumes = [ "${state-directory}/database:/var/lib/postgresql/data" ]; + }; + }; + + authentik-worker = { + autoStart = true; + containerConfig = { + image = "ghcr.io/goauthentik/server:2025.10.2"; + environments = { + AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; + AUTHENTIK_POSTGRESQL__NAME = "${user}"; + AUTHENTIK_POSTGRESQL__USER = "${user}"; + }; + exec = "worker"; + secrets = [ + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" + "AUTHENTIK_SECRET_KEY,type=env" + ]; + volumes = [ + "${state-directory}/media:/media" + "${state-directory}/custom-templates:/templates" + "${state-directory}/certs:/certs" + ]; + }; + unitConfig.Requires = [ + config.virtualisation.quadlet.containers.authentik-db.ref + "network-online.target" + ]; + unitConfig.After = [ + config.virtualisation.quadlet.containers.authentik-db.ref + "network-online.target" + ]; + }; + + authentik = { + autoStart = true; + containerConfig = { + image = "ghcr.io/goauthentik/server:2025.10.2"; + environments = { + AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; + AUTHENTIK_POSTGRESQL__NAME = "${user}"; + AUTHENTIK_POSTGRESQL__USER = "${user}"; + }; + secrets = [ + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" + "AUTHENTIK_SECRET_KEY,type=env" + "AUTHENTIK_EMAIL__HOST,type=env" + "AUTHENTIK_EMAIL__PORT,type=env" + "AUTHENTIK_EMAIL__USERNAME,type=env" + "AUTHENTIK_EMAIL__PASSWORD,type=env" + "AUTHENTIK_EMAIL__USE_SSL,type=env" + "AUTHENTIK_EMAIL__FROM,type=env" + ]; + publishPorts = [ "127.0.0.1:${port}:${port}" ]; + volumes = [ + "${state-directory}/media:/media" + "${state-directory}/custom-templates:/templates" + ]; + }; + unitConfig.Requires = [ + config.virtualisation.quadlet.containers.authentik-db.ref + "network-online.target" + ]; + unitConfig.After = [ + config.virtualisation.quadlet.containers.authentik-db.ref + "network-online.target" + ]; + }; + }; + }; +} diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 7c0634a..4a1b09a 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -7,6 +7,7 @@ ./../../services/nixos-update.nix ./../../services/borgmatic.nix ./../../services/crowdsec.nix + ./../../services/authentik.nix ]; # Use the GRUB 2 boot loader. @@ -17,6 +18,7 @@ useDHCP = false; interfaces.eth0.useDHCP = true; hostName = "mcentire"; # Define your hostname. + firewall.allowedTCPPorts = [ 80 443 ]; }; # Set your time zone. @@ -56,8 +58,11 @@ services = { openssh.enable = true; tailscale.enable = true; + caddy.enable = true; }; + virtualisation.quadlet.enable = true; + system.stateVersion = "25.05"; # Did you read the comment? nix = { extraOptions = "experimental-features = nix-command flakes"; }; } From 72e4f04b317c7d9fdf553266c475e8d684d6b55e Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:51:53 -0600 Subject: [PATCH 29/75] fix (podman-secrets): Use explicit Julia call --- modules/podman-secrets.nix | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix index 41a01c5..9e7028a 100644 --- a/modules/podman-secrets.nix +++ b/modules/podman-secrets.nix @@ -73,7 +73,7 @@ with lib; let cfg = config.millironx.podman-secrets; - secret-translator = pkgs.writeScriptBin "secret-translator" + secret-translator-script = pkgs.writeText "secret-translator.jl" (builtins.readFile ./../bin/secret-translator.jl); # Submodule type for each service's secrets configuration @@ -109,10 +109,11 @@ let serviceConfig = { Type = "oneshot"; User = serviceCfg.user; - ExecStart = "${secret-translator}/bin/secret-translator ${ + ExecStart = + "${pkgs.julia-lts-bin}/bin/julia --startup-file=no ${secret-translator-script} ${ lib.concatStringsSep " " serviceCfg.secrets-files }"; - Path = [ "${pkgs.podman}/bin" "${pkgs.julia-lts-bin}/bin" ]; + Path = [ "${pkgs.podman}/bin" ]; }; }; From 1f322921bdb7fd1638eff149a4370e99a6035a8a Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:02:49 -0600 Subject: [PATCH 30/75] fix (podman-secrets): Use explicit pkg references in script --- bin/secret-translator.jl | 30 ------------------------------ modules/podman-secrets.nix | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 35 deletions(-) delete mode 100644 bin/secret-translator.jl diff --git a/bin/secret-translator.jl b/bin/secret-translator.jl deleted file mode 100644 index ce50af8..0000000 --- a/bin/secret-translator.jl +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env julia -using TOML: TOML - -function remove_podman_secrets() - run(`podman secret rm --all`) - return nothing -end #function - -function create_podman_secret(name, secret) - run( - Cmd( - `podman secret create --env=true --replace $name SECRET`; - env = Dict("SECRET" => secret), - ), - ) - return nothing -end #function - -function parse_toml_secrets(file) - foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) - return nothing -end #function - -function main() - remove_podman_secrets() - foreach(parse_toml_secrets, ARGS) - return 0 -end #function - -main() diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix index 9e7028a..c6a3eaa 100644 --- a/modules/podman-secrets.nix +++ b/modules/podman-secrets.nix @@ -73,8 +73,38 @@ with lib; let cfg = config.millironx.podman-secrets; - secret-translator-script = pkgs.writeText "secret-translator.jl" - (builtins.readFile ./../bin/secret-translator.jl); + secret-translator = pkgs.writeScriptBin "secret-translator" '' + #!${pkgs.julia-lts-bin}/bin/julia + using TOML: TOML + + function remove_podman_secrets() + run(`${pkgs.podman}/bin/podman secret rm --all`) + return nothing + end #function + + function create_podman_secret(name, secret) + run( + Cmd( + `${pkgs.podman}/bin/podman secret create --env=true --replace $name SECRET`; + env = Dict("SECRET" => secret), + ), + ) + return nothing + end #function + + function parse_toml_secrets(file) + foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) + return nothing + end #function + + function main() + remove_podman_secrets() + foreach(parse_toml_secrets, ARGS) + return 0 + end #function + + main() + ''; # Submodule type for each service's secrets configuration serviceSecretsType = types.submodule { @@ -109,11 +139,9 @@ let serviceConfig = { Type = "oneshot"; User = serviceCfg.user; - ExecStart = - "${pkgs.julia-lts-bin}/bin/julia --startup-file=no ${secret-translator-script} ${ + ExecStart = "${secret-translator}/bin/secret-translator ${ lib.concatStringsSep " " serviceCfg.secrets-files }"; - Path = [ "${pkgs.podman}/bin" ]; }; }; From 49a2f7cd3566a4e5f079012b956b48af3a564235 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:12:20 -0600 Subject: [PATCH 31/75] fix (podman-secrets): Create home directory for authentik user --- services/authentik.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/authentik.nix b/services/authentik.nix index 30ee781..ce924b6 100644 --- a/services/authentik.nix +++ b/services/authentik.nix @@ -29,10 +29,12 @@ in { users.users."${user}" = { group = "${user}"; isSystemUser = true; + home = "${state-directory}"; + createHome = true; linger = true; autoSubUidGidRange = true; }; - users.groups."${user}" = {}; + users.groups."${user}" = { }; home-manager.users."${user}" = { config, ... }: { imports = [ home-manager-quadlet-nix ]; From 8e5734469c044381fc36748da1ff0c6d53cea1d1 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 28 Nov 2025 17:46:17 -0600 Subject: [PATCH 32/75] fix (podman-secrets): setuid path NixOS does some weird stuff with setting security bits in wrappers, rather than in packages themselves, and this was breaking podman. Add the wrappers directory to the PATH of the secrets service. --- bin/secret-translator.jl | 32 ++++++++++++++++++++++++++++++++ modules/podman-secrets.nix | 38 ++++++-------------------------------- 2 files changed, 38 insertions(+), 32 deletions(-) create mode 100644 bin/secret-translator.jl diff --git a/bin/secret-translator.jl b/bin/secret-translator.jl new file mode 100644 index 0000000..c5dee39 --- /dev/null +++ b/bin/secret-translator.jl @@ -0,0 +1,32 @@ +#!/usr/bin/env julia +using TOML: TOML + +@show ENV["PATH"] + +function remove_podman_secrets() + run(`podman secret rm --all`) + return nothing +end #function + +function create_podman_secret(name, secret) + run( + addenv( + `podman secret create --env=true --replace $name SECRET`, + Dict("SECRET" => secret), + ), + ) + return nothing +end #function + +function parse_toml_secrets(file) + foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) + return nothing +end #function + +function main() + remove_podman_secrets() + foreach(parse_toml_secrets, ARGS) + return 0 +end #function + +main() diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix index c6a3eaa..83073b3 100644 --- a/modules/podman-secrets.nix +++ b/modules/podman-secrets.nix @@ -73,38 +73,8 @@ with lib; let cfg = config.millironx.podman-secrets; - secret-translator = pkgs.writeScriptBin "secret-translator" '' - #!${pkgs.julia-lts-bin}/bin/julia - using TOML: TOML - - function remove_podman_secrets() - run(`${pkgs.podman}/bin/podman secret rm --all`) - return nothing - end #function - - function create_podman_secret(name, secret) - run( - Cmd( - `${pkgs.podman}/bin/podman secret create --env=true --replace $name SECRET`; - env = Dict("SECRET" => secret), - ), - ) - return nothing - end #function - - function parse_toml_secrets(file) - foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) - return nothing - end #function - - function main() - remove_podman_secrets() - foreach(parse_toml_secrets, ARGS) - return 0 - end #function - - main() - ''; + secret-translator = pkgs.writeScriptBin "secret-translator" + (builtins.readFile ./../bin/secret-translator.jl); # Submodule type for each service's secrets configuration serviceSecretsType = types.submodule { @@ -139,9 +109,13 @@ let serviceConfig = { Type = "oneshot"; User = serviceCfg.user; + ProtectProc = "invisible"; ExecStart = "${secret-translator}/bin/secret-translator ${ lib.concatStringsSep " " serviceCfg.secrets-files }"; + Environment = "PATH=/run/wrappers/bin:${ + lib.makeBinPath (with pkgs; [ shadow podman julia-lts-bin ]) + }"; }; }; From ce174b61fd21266da3fd8fab9d0f204432facc6f Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 08:36:00 -0600 Subject: [PATCH 33/75] meta: Add gitignore --- .gitignore | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd099b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,74 @@ +### Linux gitignore ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# Metadata left by Dolphin file manager, which comes with KDE Plasma +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# Log files created by default by the nohup command +nohup.out + +### MacOS gitignore ### +# General +.DS_Store +__MACOSX/ +.AppleDouble +.LSOverride +Icon[] + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Nix gitignore ### +# Ignore build outputs from performing a nix-build or `nix build` command +result +result-* + +# Ignore automatically generated direnv output +.direnv + +### Vim gitignore ### +# Swap +[._]*.s[a-v][a-z] +# comment out the next line if you don't need vector files +!*.svg +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ From 70f98a6200c09f281884d8dbf48c0082ad4a09b4 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 08:57:54 -0600 Subject: [PATCH 34/75] meta: Add README --- README.md | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..58c9d60 --- /dev/null +++ b/README.md @@ -0,0 +1,166 @@ +# nix-dotfiles + +System and home configurations for my machines. + ++----------+-----------------+--------+---------+--------------------------------+ +| Machine | Role | OS | Arch | Configuration tool | +| | | | |-----------------+--------------+ +| | | | | System | Home | ++==========+=================+--------+---------+=================+==============+ +| anderson | server | linux | x86_64 | dpkg/Docker | home-manager | +| | | | | (not this repo) | | ++----------+-----------------+--------+---------+-----------------+--------------+ +| bosephus | server | linux | x86_64 | NixOS | home-manager | ++----------+-----------------+--------+---------+-----------------+--------------+ +| corianne | MacBook | darwin | aarch64 | nix-darwin | home-manager | ++----------+-----------------+--------+---------+-----------------+--------------+ +| harmony | MacBook (Asahi) | linux | aarch64 | Ansible | home-manager | ++----------+-----------------+--------+---------+-----------------+--------------+ +| odyssey | workstation | linux | x86_64 | Ansible | home-manager | ++----------+-----------------+--------+---------+-----------------+--------------+ + +## Quickstart + +### Home dotfiles + +> ![WARNING] +> Fedora systems will set this up automagically via Ansible. Follow the +[Fedora quickstart] instructions. + +Ensure Nix is installed, with the `nix` command and flakes enabled. I try to use +the [Determinate Nix installer] (with upstream Nix) to install Nix with these +options turned on by default. + +```bash +curl -fsSL https://install.determinate.systems/nix | sh -s -- install +``` + +Once Nix is installed, clone the repository to `~/.config/home-manager` and +initiate home-manager. + +```bash +git clone https://code.millironx.com/millironx/nix-dotfiles.git ~/.config/home-manager +nix run home-manager -- switch --flake ~/.config/home-manager#$USER@$(hostname -s) +``` + +In the case that the host has not been assigned a configuration within this repo +yet, pick a hostname with the same system OS, arch, and role as the target +system to get temporary dotfiles up and running. + +```bash +nix run home-manager -- switch --flake ~/.config/home-manager#millironx@anderson +``` + +Once an SSH (with or without GPG) key has been setup and added to the authorized +keys of the git server, switch the upstream to track an authorized (i.e. +read/write) version of the repo. + +```bash +cd ~/.config/home-manager +git remote set-url origin git@code.millironx.com:millironx/nix-dotfiles.git +cd - +``` + +### NixOS + +Switching to a flake-based config requires running as root. All of the following +commands are assumed to be running as root. + +Ensure that the `nix` command and flakes are enabled. + +```bash +sed -i '/^}/i nix.settings.experimental-features = [ "nix-command" "flakes" ];' /etc/nixos/configuration.nix +nixos-rebuild switch +``` + +> ![NOTE] +> To allow secret decryption in the system, the *machine*-specific SSH key must +> be added to the publicKeys attribute of all applicable secrets, and the +> `hardware-configuration.nix` file must be added to git. Copying arbitrary +> strings like SSH keys or disk UUIDs between systems can be painful, so it might +> be worth setting up the [home dotfiles] immediately after enabling flakes, +> then running these steps on the same machine to avoid typos. Alternatively, I +> might someday be smart enough to create an installer CD that automagically +> sets this up for me. + +Get the machine-specific public SSH key. + +```bash +cat /etc/ssh/ssh_host_ed25519_key.pub +``` + +On a separate machine, add the machine's SSH key to `./secrets.nix` and assign +it to any secrets it would need. + +```nix +let + bosephus-host = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxTfeg+GZsfmG8TuEV1xW1gXknAIKzZ3UjZ3guRY+EW root@nixos"; + bosephus-millironx = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaDPqRJHoqgY2pseh/mnhjaGWXprHk2s5I52LhHpHcF millironx@bosephus"; + odyssey-millironx = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; + + system-administrators = [ + bosephus-millironx + odyssey-millironx + ]; +in { + "secrets/network-information.age".publicKeys = system-administrators + ++ [ bosephus-host ]; +} +``` + +Rekey the secrets, and push the updated secrets to the upstream repo. + +```bash +nix run github:ryantm/agenix -- --rekey +git add secrets.nix secrets/* +git commit -m "added $NEW_HOST to secrets" +git push +``` + +Copy the target machine's `hardware-configuration.nix` file to this repo's +`./systems/linux/hardware-configuration/$NEW_HOST.nix`, and be sure to update +the configuration to import its own `hardware-configuration`. + +```bash +cp /etc/nixos/hardware-configuration.nix ./systems/linux/hardware-configuration/$NEW_HOST.nix +``` + +```nix +{ config, pkgs, ... }: { + imports = [ + ./hardware-configuration/bosephus.nix + ]; +} +``` + +Commit and push the hardware configuration to the upstream repo. + +```bash +git add systems/linux/* +git commit -m "added $NEW_HOST hardware configuration" +git push +``` + +Now switch to the flake by pulling and switching in one step. + + +```bash +nixos-rebuild switch --flake git+https://code.millironx.com/millironx/nix-dotfiles#$(hostname -s) +``` + +### Fedora + +Fedora systems are managed using Ansible. + +TODO + +## Home settings + +TODO + +[determinate nix installer]: https://github.com/DeterminateSystems/nix-installer +[fedora quickstart]: #fedora +[home dotfiles]: #home-dotfiles From 4e84e57e3b5cc0590a4d8073e25460c47b6c9383 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:06:23 -0600 Subject: [PATCH 35/75] docs: Convert README table to pipe format --- README.md | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 58c9d60..c6c80bd 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,13 @@ System and home configurations for my machines. -+----------+-----------------+--------+---------+--------------------------------+ -| Machine | Role | OS | Arch | Configuration tool | -| | | | |-----------------+--------------+ -| | | | | System | Home | -+==========+=================+--------+---------+=================+==============+ -| anderson | server | linux | x86_64 | dpkg/Docker | home-manager | -| | | | | (not this repo) | | -+----------+-----------------+--------+---------+-----------------+--------------+ -| bosephus | server | linux | x86_64 | NixOS | home-manager | -+----------+-----------------+--------+---------+-----------------+--------------+ -| corianne | MacBook | darwin | aarch64 | nix-darwin | home-manager | -+----------+-----------------+--------+---------+-----------------+--------------+ -| harmony | MacBook (Asahi) | linux | aarch64 | Ansible | home-manager | -+----------+-----------------+--------+---------+-----------------+--------------+ -| odyssey | workstation | linux | x86_64 | Ansible | home-manager | -+----------+-----------------+--------+---------+-----------------+--------------+ +| Machine | Role | OS | Arch | System config tool | Home config tool | +| -------- | --------------- | ------ | ------- | --------------------------- | ---------------- | +| anderson | server | linux | x86_64 | dpkg/Docker (not this repo) | home-manager | +| bosephus | server | linux | x86_64 | NixOS | home-manager | +| corianne | MacBook | darwin | aarch64 | nix-darwin | home-manager | +| harmony | MacBook (Asahi) | linux | aarch64 | Ansible | home-manager | +| odyssey | workstation | linux | x86_64 | Ansible | home-manager | ## Quickstart From e9b1841f7b438851933c88e7850a19b921821577 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:07:15 -0600 Subject: [PATCH 36/75] docs: Remove harmony reference --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c6c80bd..4f810a9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ System and home configurations for my machines. | anderson | server | linux | x86_64 | dpkg/Docker (not this repo) | home-manager | | bosephus | server | linux | x86_64 | NixOS | home-manager | | corianne | MacBook | darwin | aarch64 | nix-darwin | home-manager | -| harmony | MacBook (Asahi) | linux | aarch64 | Ansible | home-manager | | odyssey | workstation | linux | x86_64 | Ansible | home-manager | ## Quickstart From fa6b537a3c828ca5a90668fa6eb9797e9bec24fb Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:17:07 -0600 Subject: [PATCH 37/75] docs: Add mcentire to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4f810a9..d650f9b 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ System and home configurations for my machines. | -------- | --------------- | ------ | ------- | --------------------------- | ---------------- | | anderson | server | linux | x86_64 | dpkg/Docker (not this repo) | home-manager | | bosephus | server | linux | x86_64 | NixOS | home-manager | +| mcentire | server | linux | x86_64 | NixOS | home-manager | | corianne | MacBook | darwin | aarch64 | nix-darwin | home-manager | | odyssey | workstation | linux | x86_64 | Ansible | home-manager | From 8d96ef7684bac912cd5508e1e73288279b33d0ea Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:01:45 -0600 Subject: [PATCH 38/75] fix (podman-secrets): Use user systemd unit User systemd units cannot wait for system units. Fix race condition bugs in user Quadlet services by using a user service that the Quadlet services can use as a `After=` or `Requires=` directive. --- modules/podman-secrets.nix | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix index 83073b3..fb99285 100644 --- a/modules/podman-secrets.nix +++ b/modules/podman-secrets.nix @@ -77,7 +77,7 @@ let (builtins.readFile ./../bin/secret-translator.jl); # Submodule type for each service's secrets configuration - serviceSecretsType = types.submodule { + serviceSecretsType = types.submodule ({ config, name, ... }: { options = { user = mkOption { type = types.str; @@ -97,18 +97,28 @@ let ''; default = [ ]; }; - }; - }; - # Generate a systemd service for each configured service + ref = mkOption { + type = types.str; + description = + "Reference to the systemd service name for declaring dependencies"; + readOnly = true; + default = "podman-secrets-${name}.service"; + example = "podman-secrets-caddy.service"; + }; + }; + }); + + # Generate a systemd user service for each configured service mkSecretsService = name: serviceCfg: nameValuePair "podman-secrets-${name}" { description = "Podman secrets converter service for ${name}"; - wantedBy = [ "multi-user.target" ]; + wantedBy = [ "default.target" ]; + + unitConfig.ConditionUser = "${serviceCfg.user}"; serviceConfig = { Type = "oneshot"; - User = serviceCfg.user; ProtectProc = "invisible"; ExecStart = "${secret-translator}/bin/secret-translator ${ lib.concatStringsSep " " serviceCfg.secrets-files @@ -128,8 +138,8 @@ in { type = types.attrsOf serviceSecretsType; description = '' Per-service Podman secrets configuration. - Each attribute creates a separate systemd service that translates TOML secrets - files into Podman secrets for the specified user. + Each attribute creates a separate systemd user service that translates TOML secrets + files into Podman secrets. ''; example = literalExpression '' { @@ -152,6 +162,6 @@ in { }; config = mkIf (enabledServices != { }) { - systemd.services = lib.mapAttrs' mkSecretsService enabledServices; + systemd.user.services = lib.mapAttrs' mkSecretsService enabledServices; }; } From b2477b9f24d650cc13cda7abd0523234e4d54c9f Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:03:20 -0600 Subject: [PATCH 39/75] fix (authentik): Too many fixes to list Bad on me, but I have spent way too long making edits that are all required on mcentire to get Authentik semi-working. There are lots of notes in here on reasoning of why stuff is the way it is. Backup still needs to be configured, and potentially Crowdsec. --- services/authentik.nix | 225 ++++++++++++++++++++++++++--------------- 1 file changed, 141 insertions(+), 84 deletions(-) diff --git a/services/authentik.nix b/services/authentik.nix index ce924b6..ee57695 100644 --- a/services/authentik.nix +++ b/services/authentik.nix @@ -5,8 +5,8 @@ let port = "9000"; in { - # Secrets are translated in the system scope, but performed by the user, - # so are available in the user's Podman secrets + # Secrets are translated in the system NixOS scope, but performed by the user, + # via a user systemd unit, so are available in the user's Podman secrets age.secrets = { "authentik.toml" = { file = ./../secrets/authentik.toml.age; @@ -19,7 +19,15 @@ in { secrets-files = [ config.age.secrets."authentik.toml".path ]; }; - systemd.tmpfiles.rules = [ "d ${state-directory} 1775 ${user} ${user} -" ]; + # Podman, unlike Docker apparently, does not automatically create mount points + # within folders, so every mounted folder needs to be specified here. + systemd.tmpfiles.rules = [ + "d ${state-directory} 1775 ${user} ${user} -" + "d ${state-directory}/database 1775 ${user} ${user} -" + "d ${state-directory}/media 1775 ${user} ${user} -" + "d ${state-directory}/certs 1775 ${user} ${user} -" + "d ${state-directory}/custom-templates 1775 ${user} ${user} -" + ]; services.caddy.virtualHosts."auth.millironx.com".extraConfig = '' reverse_proxy http://127.0.0.1:${port} @@ -27,104 +35,153 @@ in { # Create a dedicated user for this service users.users."${user}" = { + # Group is technically not mandatory, but NixOS complains that an unset + # group is "unsafe." The group has to be declared below group = "${user}"; - isSystemUser = true; + + # System users don't have a shell. For security purposes, that *would* be + # superior, but that means that, e.g. borgmatic can't `sudo` into the + # account to access Podman commands + isNormalUser = true; + + # A home directory is mandatory in order to allow systemd user units to be + # created and run home = "${state-directory}"; createHome = true; + + # Settings for running containers while a login shell is not active linger = true; autoSubUidGidRange = true; }; users.groups."${user}" = { }; - home-manager.users."${user}" = { config, ... }: { + home-manager.users."${user}" = { config, osConfig, ... }: { imports = [ home-manager-quadlet-nix ]; home.stateVersion = "25.05"; - virtualisation.quadlet.containers = { - authentik-db = { - autoStart = true; - containerConfig = { - image = "docker.io/library/postgres:16"; - environments = { - POSTGRES_DB = "${user}"; - POSTGRES_USER = "${user}"; + virtualisation.quadlet = { + containers = { + authentik-db = { + autoStart = true; + containerConfig = { + image = "docker.io/library/postgres:16"; + environments = { + POSTGRES_DB = "${user}"; + POSTGRES_USER = "${user}"; + }; + secrets = [ + # POSTGRES_PASSWORD is used by the container to setup the + # database, PGPASSWORD is used by pg_dump to authenticate for + # backup purposes + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=POSTGRES_PASSWORD" + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=PGPASSWORD" + ]; + + # Double dollarsigns are required for use of *container* environment + # variables, Nix escaping creates the weird $\${} syntax + healthCmd = "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"; + healthInterval = "30s"; + healthRetries = 5; + healthStartPeriod = "20s"; + + # Volumes have to be bound with the :U label to allow for username + # remapping in rootless containers. :Z/:z is not needed b/c NixOS + # does not support SELinux + volumes = + [ "${state-directory}/database:/var/lib/postgresql/data:U" ]; + + # A network is actually required for these containers to talk to one + # another. I suppose the more idiomatic way would be for these + # related containers to be in a "pod," but I'm still struggling + # learning the idiosyncrasies of quadlet/rootless/podman, so we'll + # stick with this for now + networks = + [ config.virtualisation.quadlet.networks.authentik-net.ref ]; + }; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=POSTGRES_PASSWORD" - ]; - healthCmd = "pg_isready -d \${POSTGRES_DB} -U \${POSTGRES_USER}"; - healthInterval = "30s"; - healthRetries = 5; - healthStartPeriod = "20s"; - volumes = [ "${state-directory}/database:/var/lib/postgresql/data" ]; + + # Allowing this container to start before the secrets are translated + # will lead to errors. Use osConfig b/c secrets are declared in the + # system NixOS scope, even though it is a user process. + unitConfig.Requires = + [ osConfig.millironx.podman-secrets.authentik.ref ]; + unitConfig.After = + [ osConfig.millironx.podman-secrets.authentik.ref ]; + }; + + authentik-worker = { + autoStart = true; + containerConfig = { + image = "ghcr.io/goauthentik/server:2025.10.2"; + environments = { + AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; + AUTHENTIK_POSTGRESQL__NAME = "${user}"; + AUTHENTIK_POSTGRESQL__USER = "${user}"; + }; + exec = "worker"; + secrets = [ + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" + "AUTHENTIK_SECRET_KEY,type=env" + ]; + volumes = [ + "${state-directory}/media:/media:U" + "${state-directory}/custom-templates:/templates:U" + "${state-directory}/certs:/certs:U" + ]; + networks = + [ config.virtualisation.quadlet.networks.authentik-net.ref ]; + }; + unitConfig.Requires = + [ config.virtualisation.quadlet.containers.authentik-db.ref ]; + unitConfig.After = + [ config.virtualisation.quadlet.containers.authentik-db.ref ]; + }; + + authentik = { + autoStart = true; + containerConfig = { + image = "ghcr.io/goauthentik/server:2025.10.2"; + environments = { + AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; + AUTHENTIK_POSTGRESQL__NAME = "${user}"; + AUTHENTIK_POSTGRESQL__USER = "${user}"; + }; + exec = "server"; + secrets = [ + "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" + "AUTHENTIK_SECRET_KEY,type=env" + "AUTHENTIK_EMAIL__HOST,type=env" + "AUTHENTIK_EMAIL__PORT,type=env" + "AUTHENTIK_EMAIL__USERNAME,type=env" + "AUTHENTIK_EMAIL__PASSWORD,type=env" + "AUTHENTIK_EMAIL__USE_SSL,type=env" + "AUTHENTIK_EMAIL__FROM,type=env" + ]; + + # Change from Traefik: publish ports to localhost only via 127.0.0.1 + # and then reverse proxy to that port. Authentik does not appear to + # have a way to configure the port, so we will use the default of + # 9000 for non-secured traffic. + publishPorts = [ "127.0.0.1:${port}:${port}" ]; + volumes = [ + "${state-directory}/media:/media:U" + "${state-directory}/custom-templates:/templates:U" + ]; + networks = + [ config.virtualisation.quadlet.networks.authentik-net.ref ]; + }; + unitConfig.Requires = + [ config.virtualisation.quadlet.containers.authentik-db.ref ]; + unitConfig.After = + [ config.virtualisation.quadlet.containers.authentik-db.ref ]; }; }; - authentik-worker = { - autoStart = true; - containerConfig = { - image = "ghcr.io/goauthentik/server:2025.10.2"; - environments = { - AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; - AUTHENTIK_POSTGRESQL__NAME = "${user}"; - AUTHENTIK_POSTGRESQL__USER = "${user}"; - }; - exec = "worker"; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" - "AUTHENTIK_SECRET_KEY,type=env" - ]; - volumes = [ - "${state-directory}/media:/media" - "${state-directory}/custom-templates:/templates" - "${state-directory}/certs:/certs" - ]; - }; - unitConfig.Requires = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - unitConfig.After = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - }; + networks.authentik-net = { }; - authentik = { - autoStart = true; - containerConfig = { - image = "ghcr.io/goauthentik/server:2025.10.2"; - environments = { - AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; - AUTHENTIK_POSTGRESQL__NAME = "${user}"; - AUTHENTIK_POSTGRESQL__USER = "${user}"; - }; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" - "AUTHENTIK_SECRET_KEY,type=env" - "AUTHENTIK_EMAIL__HOST,type=env" - "AUTHENTIK_EMAIL__PORT,type=env" - "AUTHENTIK_EMAIL__USERNAME,type=env" - "AUTHENTIK_EMAIL__PASSWORD,type=env" - "AUTHENTIK_EMAIL__USE_SSL,type=env" - "AUTHENTIK_EMAIL__FROM,type=env" - ]; - publishPorts = [ "127.0.0.1:${port}:${port}" ]; - volumes = [ - "${state-directory}/media:/media" - "${state-directory}/custom-templates:/templates" - ]; - }; - unitConfig.Requires = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - unitConfig.After = [ - config.virtualisation.quadlet.containers.authentik-db.ref - "network-online.target" - ]; - }; + # One of the main advantages of using Quadlet + autoUpdate.enable = true; }; }; } From 6a1cc7877ce1e59dd199776e893c8f91d338225e Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:52:06 -0600 Subject: [PATCH 40/75] users (mcentire): Add millironx to adm group --- systems/linux/mcentire.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 4a1b09a..9171e5a 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -44,7 +44,7 @@ millironx = { isNormalUser = true; description = "Thomas A. Christensen II"; - extraGroups = [ "wheel" ]; + extraGroups = [ "adm" "wheel" ]; }; }; From a3a8ea9a34e8d4772445fbcebce9d9f1d53285e8 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 14:03:20 -0600 Subject: [PATCH 41/75] services (linux): Remove nixos-update service --- services/nixos-update.nix | 50 -------------------------------------- systems/linux/bosephus.nix | 1 - systems/linux/mcentire.nix | 1 - 3 files changed, 52 deletions(-) delete mode 100644 services/nixos-update.nix diff --git a/services/nixos-update.nix b/services/nixos-update.nix deleted file mode 100644 index f0678ec..0000000 --- a/services/nixos-update.nix +++ /dev/null @@ -1,50 +0,0 @@ -# This file is designed to be used in the imports -{ pkgs, config, ... }: - -{ - environment.systemPackages = [ - (pkgs.writeScriptBin "update-nixos" '' - #!${pkgs.bash}/bin/bash - echo "Requesting system update..." - ${pkgs.systemd}/bin/systemctl start nixos-update.service - '') - ]; - - # Service to update NixOS configuration from git repo - systemd.services."nixos-update" = { - description = "Update NixOS configuration from git repository"; - path = with pkgs; [ coreutils ]; - script = '' - # Rebuild the system directly from the remote flake - ${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --flake git+https://code.millironx.com/millironx/nix-dotfiles.git#${config.networking.hostName} - ''; - serviceConfig = { - Type = "oneshot"; - User = "root"; - }; - }; - - # Timer to run the update service daily at 3am - systemd.timers."nixos-update" = { - wantedBy = [ "timers.target" ]; - description = "Run NixOS update daily at 3am"; - timerConfig = { - OnCalendar = "3:00"; - Persistent = true; - Unit = "nixos-update.service"; - }; - }; - - # Polkit rule to allow non-root users to trigger the update - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if (action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "nixos-update.service" && - action.lookup("verb") == "start" && - subject.isInGroup("wheel")) { - return polkit.Result.YES; - } - }); - ''; - -} diff --git a/systems/linux/bosephus.nix b/systems/linux/bosephus.nix index 3a0a271..98cf0e7 100644 --- a/systems/linux/bosephus.nix +++ b/systems/linux/bosephus.nix @@ -8,7 +8,6 @@ imports = [ ./hardware-configuration/bosephus.nix ./hardware-configuration/bosephus-external-drives.nix - ./../../services/nixos-update.nix ./../../services/samba.nix ./../../services/pihole.nix ]; diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 9171e5a..81be915 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -4,7 +4,6 @@ imports = [ # Include the results of the hardware scan. ./hardware-configuration/mcentire.nix ./../../modules/podman-secrets.nix - ./../../services/nixos-update.nix ./../../services/borgmatic.nix ./../../services/crowdsec.nix ./../../services/authentik.nix From 8b5fa1dfe9d3858b5804264c7226199ab46e223f Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:01:45 -0600 Subject: [PATCH 42/75] service (authentik): Add Borgmatic config --- services/authentik.nix | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/services/authentik.nix b/services/authentik.nix index ee57695..85d7ea1 100644 --- a/services/authentik.nix +++ b/services/authentik.nix @@ -1,4 +1,4 @@ -{ config, home-manager-quadlet-nix, ... }: +{ config, pkgs, home-manager-quadlet-nix, ... }: let user = "authentik"; state-directory = "/var/lib/authentik"; @@ -33,6 +33,22 @@ in { reverse_proxy http://127.0.0.1:${port} ''; + services.borgmatic.configurations."${config.networking.hostName}" = { + source_directories = [ + "${state-directory}/media" + "${state-directory}/certs" + "${state-directory}/custom-templates" + ]; + + postgresql_databases = [{ + name = "authentik"; + pg_dump_command = + "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db pg_dump --username=${user}"; + pg_restore_command = + "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db pg_restore --username=${user}"; + }]; + }; + # Create a dedicated user for this service users.users."${user}" = { # Group is technically not mandatory, but NixOS complains that an unset From 1301fd94b33ce55017a36790dbbacfba6a46e61e Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:09:48 -0600 Subject: [PATCH 43/75] fix (borgmatic): Add postgresql config --- systems/linux/mcentire.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index 81be915..4bd52f3 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -58,6 +58,10 @@ openssh.enable = true; tailscale.enable = true; caddy.enable = true; + + # Do not "enable" database services, but include the package configuration + # so that borgmatic does not freak out about unset variables + postgresql.package = pkgs.postgresql_17; }; virtualisation.quadlet.enable = true; From 086cae0a56e4203822e9005d25581c6a5d639d24 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:14:01 -0600 Subject: [PATCH 44/75] fix (borgmatic): Add psql command --- services/authentik.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/authentik.nix b/services/authentik.nix index 85d7ea1..f507dac 100644 --- a/services/authentik.nix +++ b/services/authentik.nix @@ -42,6 +42,8 @@ in { postgresql_databases = [{ name = "authentik"; + psql_command = + "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db psql --username=${user}"; pg_dump_command = "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db pg_dump --username=${user}"; pg_restore_command = From c49474d8ce7b0612523d6bde593bc843e7fe2687 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Tue, 2 Dec 2025 09:56:36 -0600 Subject: [PATCH 45/75] flake: Upgrade nixpkgs to nixos-25.11 family This commit upgrades nixpkgs to nixos-25.11, and all other management systems (home-manager, nix-darwin, etc.) to the equivalent tag, and also upgrades any syntax within the modules to follow new syntax. 1. Upgrades nixpkgs to nixos-25.11 2. Upgrades nixpkgs-darwin to nixpkgs-25.11-darwin 3. Upgrades home-manger to release-25.11 4. Upgrades nix-darwin to 25.11 5. Implements conditional to use nixpkgs on Linux and nixpkgs-darwin on Darwin 6. Replace micromamba with mamba-cpp and set alias, see 7. Replace asitop with its new name: macpm 8. Remove ollama package and launchd service. ollama was removed from Linux in 275270cef7, but remained in Darwin. The build process technically did not fail, but it did extend build time and is unused, so it was removed. 9. Switch git program module to use new syntax 10. Switch to NixOS-provided Crowdsec module 11. Switch logind lidSwitch settings to use new syntax 12. Switch sabma module to use new syntax --- flake.lock | 122 ++++++++++------------------------- flake.nix | 22 +++---- homes/common.nix | 3 +- homes/darwin.nix | 18 +----- homes/desktop.nix | 1 - programs/git.nix | 8 ++- programs/shells.nix | 2 +- services/crowdsec.nix | 128 +++++++++++-------------------------- services/samba.nix | 1 - systems/linux/bosephus.nix | 4 +- 10 files changed, 91 insertions(+), 218 deletions(-) diff --git a/flake.lock b/flake.lock index a1cd1d3..982ba78 100644 --- a/flake.lock +++ b/flake.lock @@ -14,11 +14,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1754433428, - "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=", + "lastModified": 1762618334, + "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", "owner": "ryantm", "repo": "agenix", - "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d", + "rev": "fcdea223397448d35d9b31f798479227e80183f6", "type": "github" }, "original": { @@ -27,27 +27,6 @@ "type": "github" } }, - "crowdsec": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1752497357, - "narHash": "sha256-9epXn1+T6U4Kfyw8B9zMzbERxDB3VfaPXhVebtai6CE=", - "ref": "refs/heads/main", - "rev": "84db7dcea77f7f477d79e69e35fb0bb560232667", - "revCount": 42, - "type": "git", - "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" - }, - "original": { - "type": "git", - "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" - } - }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -69,23 +48,6 @@ "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "id": "flake-utils", - "type": "indirect" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -93,16 +55,16 @@ ] }, "locked": { - "lastModified": 1756679287, - "narHash": "sha256-Xd1vOeY9ccDf5VtVK12yM0FS6qqvfUop8UQlxEB+gTQ=", + "lastModified": 1764613336, + "narHash": "sha256-L979az28t/+SXvYw9qhOno5HLlDwkZOpz6LzCLnjmRM=", "owner": "nix-community", "repo": "home-manager", - "rev": "07fc025fe10487dd80f2ec694f1cd790e752d0e8", + "rev": "f3902b5d8767985680875ad86d028371100faeb3", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-25.05", + "ref": "release-25.11", "repo": "home-manager", "type": "github" } @@ -114,59 +76,59 @@ ] }, "locked": { - "lastModified": 1757432263, - "narHash": "sha256-qHn+/0+IOz5cG68BZUwL9BV3EO/e9eNKCjH3+N7wMdI=", + "lastModified": 1764161084, + "narHash": "sha256-HN84sByg9FhJnojkGGDSrcjcbeioFWoNXfuyYfJ1kBE=", "owner": "LnL7", "repo": "nix-darwin", - "rev": "1fef4404de4d1596aa5ab2bd68078370e1b9dcdb", + "rev": "e95de00a471d07435e0527ff4db092c84998698e", "type": "github" }, "original": { "owner": "LnL7", - "ref": "nix-darwin-25.05", + "ref": "nix-darwin-25.11", "repo": "nix-darwin", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1757545623, - "narHash": "sha256-mCxPABZ6jRjUQx3bPP4vjA68ETbPLNz9V2pk9tO7pRQ=", + "lastModified": 1764522689, + "narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "8cd5ce828d5d1d16feff37340171a98fc3bf6526", + "rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-25.05", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-darwin": { "locked": { - "lastModified": 1757590060, - "narHash": "sha256-EWwwdKLMZALkgHFyKW7rmyhxECO74+N+ZO5xTDnY/5c=", + "lastModified": 1764572236, + "narHash": "sha256-hLp6T/vKdrBQolpbN3EhJOKTXZYxJZPzpnoZz+fEGlE=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0ef228213045d2cdb5a169a95d63ded38670b293", + "rev": "b0924ea1889b366de6bb0018a9db70b2c43a15f8", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-25.05-darwin", + "ref": "nixpkgs-25.11-darwin", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-unstable": { "locked": { - "lastModified": 1757034884, - "narHash": "sha256-PgLSZDBEWUHpfTRfFyklmiiLBE1i1aGCtz4eRA3POao=", + "lastModified": 1764642553, + "narHash": "sha256-mvbFFzVBhVK1FjyPHZGMAKpNiqkr7k++xIwy+p/NQvA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ca77296380960cd497a765102eeb1356eb80fed0", + "rev": "f720de59066162ee879adcc8c79e15c51fe6bfb4", "type": "github" }, "original": { @@ -184,11 +146,11 @@ ] }, "locked": { - "lastModified": 1757647720, - "narHash": "sha256-qf/utP3d1qBDl5R4yWUCt7E7CHTkw2NY8BEsS7lJ0dc=", + "lastModified": 1764683664, + "narHash": "sha256-Mr5HKf/bjAJ8H7/H0qJSk2BEV/OILkDIFKrGK0dUVUk=", "owner": "nix-community", "repo": "NUR", - "rev": "ef767aa25f9f917fe25d3848051f0e54ae42349f", + "rev": "b8b40e258cf4c959b06b7322648c87674633629b", "type": "github" }, "original": { @@ -207,11 +169,11 @@ ] }, "locked": { - "lastModified": 1756632588, - "narHash": "sha256-ydam6eggXf3ZwRutyCABwSbMAlX+5lW6w1SVZQ+kfSo=", + "lastModified": 1763909441, + "narHash": "sha256-56LwV51TX/FhgX+5LCG6akQ5KrOWuKgcJa+eUsRMxsc=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "d47428e5390d6a5a8f764808a4db15929347cd77", + "rev": "b24ed4b272256dfc1cc2291f89a9821d5f9e14b4", "type": "github" }, "original": { @@ -222,11 +184,11 @@ }, "quadlet-nix": { "locked": { - "lastModified": 1754008153, - "narHash": "sha256-MYT1mDtSkiVg343agxgBFsnuNU3xS8vRy399JXX1Vw0=", + "lastModified": 1763141753, + "narHash": "sha256-XAHkOkLEWbRQZ6t/SowwOukrUfIneNQOC/UEQlTaPBU=", "owner": "SEIAROTg", "repo": "quadlet-nix", - "rev": "1b2d27d460d8c7e4da5ba44ede463b427160b5c4", + "rev": "211b5c626cf9ea91403b510e2ac5ca03a7194566", "type": "github" }, "original": { @@ -238,7 +200,6 @@ "root": { "inputs": { "agenix": "agenix", - "crowdsec": "crowdsec", "home-manager": "home-manager", "nix-darwin": "nix-darwin", "nixpkgs": "nixpkgs", @@ -258,11 +219,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1757591399, - "narHash": "sha256-OlvNzfsqDok0y5PDY+2dK5T53GsxAdm1YGdYHjxAiHM=", + "lastModified": 1764648280, + "narHash": "sha256-xniOnxIx/qhm+maO4mb9BZ7FytcUhNeTm1Y/QBjNf8o=", "owner": "rycee", "repo": "nur-expressions", - "rev": "b7d4f61ce9db44ba82859e15f6e1c175959948e3", + "rev": "119826bd51ad1a8012e0585f3a073571a35a812e", "type": "gitlab" }, "original": { @@ -286,21 +247,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 204941e..bbd1632 100644 --- a/flake.nix +++ b/flake.nix @@ -3,8 +3,8 @@ inputs = { # Specify the source of Home Manager and Nixpkgs. - nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; - nixpkgs-darwin.url = "github:nixos/nixpkgs/nixpkgs-25.05-darwin"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; + nixpkgs-darwin.url = "github:nixos/nixpkgs/nixpkgs-25.11-darwin"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable"; # Inputs for both darwin and linux systems @@ -17,7 +17,7 @@ }; }; home-manager = { - url = "github:nix-community/home-manager/release-25.05"; + url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; }; nur = { @@ -30,10 +30,6 @@ }; # Linux-specific inputs - crowdsec = { - url = "git+https://codeberg.org/kampka/nix-flake-crowdsec.git"; - inputs.nixpkgs.follows = "nixpkgs"; - }; plasma-manager = { url = "github:nix-community/plasma-manager"; inputs = { @@ -45,20 +41,21 @@ # Darwin-specific inputs nix-darwin = { - url = "github:LnL7/nix-darwin/nix-darwin-25.05"; + url = "github:LnL7/nix-darwin/nix-darwin-25.11"; inputs.nixpkgs.follows = "nixpkgs-darwin"; }; }; outputs = { self, nix-darwin, nixpkgs, nixpkgs-darwin, nixpkgs-unstable - , home-manager, agenix, rycee-nurpkgs, nur, crowdsec, plasma-manager - , quadlet-nix, ... }: + , home-manager, agenix, rycee-nurpkgs, nur, plasma-manager, quadlet-nix, ... + }: let mkHomeConfiguration = { hostname, arch ? "x86_64", os ? "linux" , desktop ? false, extraModules ? [ ] }: let system = "${arch}-${os}"; - pkgs = import nixpkgs { + syspkg = if os == "darwin" then nixpkgs-darwin else nixpkgs; + pkgs = import syspkg { inherit system; config.allowUnfree = true; overlays = [ nur.overlays.default agenix.overlays.default ]; @@ -146,9 +143,6 @@ agenix.nixosModules.default home-manager.nixosModules.home-manager quadlet-nix.nixosModules.quadlet - crowdsec.nixosModules.crowdsec - crowdsec.nixosModules.crowdsec-firewall-bouncer - { nixpkgs.overlays = [ crowdsec.overlays.default ]; } ]; }; }; diff --git a/homes/common.nix b/homes/common.nix index 61ba3f1..078bdd5 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -45,7 +45,7 @@ in { jq julia-bin lynx - micromamba + mamba-cpp most nextflow p7zip @@ -84,6 +84,7 @@ in { "tailscale set --exit-node=$(tailscale exit-node suggest | awk '{print $4}' | head -n1)"; # tsed - TailScale Exit node Disconnect tsed = "tailscale set --exit-node="; + micromamba = "mamba"; }; sessionPath = [ "$HOME/.local/bin" ]; activation = { diff --git a/homes/darwin.nix b/homes/darwin.nix index d3c2982..9cabb63 100644 --- a/homes/darwin.nix +++ b/homes/darwin.nix @@ -7,7 +7,7 @@ ]; home = { packages = with pkgs; [ - asitop + macpm pinentry_mac (pkgs.writeShellScriptBin "uq" '' xattr -rdv com.apple.quarantine "/Applications/$1.app" @@ -34,22 +34,6 @@ launchd = { enable = true; agents = { - ollama = { - enable = true; - config = { - Label = "local.home-manager.ollama"; - ProgramArguments = [ "${pkgs.ollama}/bin/ollama" "serve" ]; - RunAtLoad = true; - KeepAlive = true; - StandardOutPath = - "${config.home.homeDirectory}/Library/Logs/ollama.log"; - StandardErrorPath = - "${config.home.homeDirectory}/Library/Logs/ollama-error.log"; - EnvironmentVariables = { - PATH = "${lib.makeBinPath [ pkgs.ollama ]}:$PATH"; - }; - }; - }; freetube-sync = { enable = true; diff --git a/homes/desktop.nix b/homes/desktop.nix index 03229ed..7b1b2ad 100644 --- a/homes/desktop.nix +++ b/homes/desktop.nix @@ -22,7 +22,6 @@ nil nixd nixfmt-classic - ollama quarto roboto-slab shellcheck diff --git a/programs/git.nix b/programs/git.nix index b4d790d..173e5f1 100644 --- a/programs/git.nix +++ b/programs/git.nix @@ -1,9 +1,11 @@ { ... }: { programs.git = { enable = true; - userName = "Thomas A. Christensen II"; - userEmail = "25492070+MillironX@users.noreply.github.com"; - extraConfig = { + settings = { + user = { + name = "Thomas A. Christensen II"; + email = "25492070+MillironX@users.noreply.github.com"; + }; core = { editor = "nvim"; }; credential = { helper = "store"; }; color = { ui = "auto"; }; diff --git a/programs/shells.nix b/programs/shells.nix index 93b2d9d..6745cf4 100644 --- a/programs/shells.nix +++ b/programs/shells.nix @@ -1,7 +1,7 @@ { pkgs, ... }: let conda_init = shell: '' - eval "$(${pkgs.micromamba}/bin/micromamba shell hook --shell ${shell})" + eval "$(${pkgs.mamba-cpp}/bin/mamba shell hook --shell ${shell})" ''; nd_bash_function = '' diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 6a54584..5c3e279 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -1,101 +1,49 @@ -{ pkgs, config, ... }: -let - crowdsec-port = "2763"; - firewall-bouncer-name = "fw-bouncer"; - # Although this key can be reproduced by anyone who actually cares to, the - # Crowdsec API will not be exposed to the outside world, so keeping this key - # super secret really isn't that important to me. Still make it look random - # so that hungry botnets can't just slurp up the password in plaintext. - firewall-bouncer-key = builtins.hashString "sha256" - "${config.networking.hostName}-crowdsec-bouncer-salt"; - toMultiYAML = items: - pkgs.lib.concatMapStrings (item: - '' - - --- - '' + (pkgs.lib.generators.toYAML { } item) + "\n") items; -in { +{ pkgs, config, ... }: { services = { crowdsec = { enable = true; - allowLocalJournalAccess = true; - settings = { - api.server = { listen_uri = "127.0.0.1:${crowdsec-port}"; }; - crowdsec_service.acquisition_path = pkgs.writeText "acquisitions.yaml" - (toMultiYAML [ - { - source = "journalctl"; - journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ]; - labels.type = "syslog"; - } - { - filenames = [ "/var/log/auth.log" ]; - labels.type = "syslog"; - } - { - filenames = [ "/var/log/syslog" "/var/log/kern.log" ]; - labels.type = "syslog"; - } - ]); + localConfig = { + acquisitions = [ + { + source = "journalctl"; + journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ]; + labels.type = "syslog"; + } + { + filenames = [ "/var/log/auth.log" ]; + labels.type = "syslog"; + } + { + filenames = [ "/var/log/syslog" "/var/log/kern.log" ]; + labels.type = "syslog"; + } + ]; }; + hub = { + collections = [ + "crowdsecurity/base-http-scenarios" + "crowdsecurity/http-cve" + "crowdsecurity/http-dos" + "crowdsecurity/iptables" + "crowdsecurity/linux" + "crowdsecurity/sshd" + "crowdsecurity/whitelist-good-actors" + ]; + }; + settings = { + general = { api.server.enable = true; }; + # See https://github.com/NixOS/nixpkgs/issues/445342 + lapi.credentialsFile = "/var/lib/crowdsec/lapi-credentials.yaml"; + }; + autoUpdateService = true; }; + crowdsec-firewall-bouncer = { enable = true; - settings = { - api_url = "http://localhost:${crowdsec-port}"; - api_key = firewall-bouncer-key; - }; + registerBouncer.enable = true; }; }; - systemd.services.crowdsec.serviceConfig = { - ExecStartPre = let - bouncer-script = pkgs.writeScriptBin "register-bouncer" '' - #!${pkgs.runtimeShell} - set -eu - set -o pipefail - - if ! cscli bouncers list | grep -q "${firewall-bouncer-name}"; then - cscli bouncers add "${firewall-bouncer-name}" --key "${firewall-bouncer-key}" - fi - ''; - collection-check = collection: '' - - if ! cscli collections list | grep -q "${collection}"; then - cscli collections --trace install "${collection}" - sleep 1 - fi - - ''; - collections = [ - "crowdsecurity/base-http-scenarios" - "crowdsecurity/http-cve" - "crowdsecurity/http-dos" - "crowdsecurity/iptables" - "crowdsecurity/linux" - "crowdsecurity/sshd" - "crowdsecurity/whitelist-good-actors" - ]; - collection-script = pkgs.writeScriptBin "install-collections" '' - #!${pkgs.runtimeShell} - set -eu - set -o pipefail - - # I had to run these commands in order to manually install collections - # using cscli. - # Not sure how often they should actually be run, but I would rather - # include this here. - # https://discourse.crowdsec.net/t/solved-cant-find-collections-appsec/1830 - cscli capi register - sleep 1 - cscli hub update - sleep 1 - - ${pkgs.lib.concatMapStrings collection-check collections} - ''; - in [ - "${bouncer-script}/bin/register-bouncer" - "${collection-script}/bin/install-collections" - ]; - }; + systemd.tmpfiles.rules = let cfg = config.services.crowdsec; + in [ "d /var/lib/crowdsec 0755 ${cfg.user} ${cfg.group}" ]; } diff --git a/services/samba.nix b/services/samba.nix index e6fa607..b248d33 100644 --- a/services/samba.nix +++ b/services/samba.nix @@ -2,7 +2,6 @@ services.samba = { enable = true; package = pkgs.sambaFull; - securityType = "user"; openFirewall = true; settings = { global = { diff --git a/systems/linux/bosephus.nix b/systems/linux/bosephus.nix index 98cf0e7..79dcf54 100644 --- a/systems/linux/bosephus.nix +++ b/systems/linux/bosephus.nix @@ -17,8 +17,8 @@ boot.loader.efi.canTouchEfiVariables = true; # Ignore lid - so I can close without having the system go into sleep mode - services.logind.lidSwitch = "ignore"; - services.logind.lidSwitchDocked = "ignore"; + services.logind.settings.Login.HandleLidSwitch = "ignore"; + services.logind.settings.Login.HandleLidSwitchDocked = "ignore"; # Secrets age.secrets = { From 24d7b7d533c875f9bb47a1062352268dcebb5147 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 4 Dec 2025 08:59:53 -0600 Subject: [PATCH 46/75] programs (zed): Add build+preview on demand support for LaTeX --- programs/zed.nix | 25 ++++++++++++++++++++++++- systems/darwin/corianne.nix | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/programs/zed.nix b/programs/zed.nix index 19beb45..b3f7fd6 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -1,4 +1,4 @@ -{ ... }: { +{ pkgs, ... }: { programs.zed-editor = { enable = true; extensions = [ @@ -58,6 +58,22 @@ initialization_options.formatting.command = [ "nixfmt" ]; settings.nix.flake.autoArchive = true; }; + texlab = { + settings = { + build = { + onSave = false; + forwardSearchAfter = true; + }; + forwardSearch = if pkgs.stdenv.hostPlatform.isDarwin then { + executable = + "/Applications/Skim.app/Contents/SharedSupport/displayline"; + args = [ "-r" "%l" "%p" "%f" "-g" ]; + } else { + executable = "/usr/bin/okular"; + args = [ "--unique" "file:%p#src:%l%f" ]; + }; + }; + }; tinymist = { settings = { exportPdf = "onSave"; @@ -81,5 +97,12 @@ ui_font_size = 16; wrap_guides = [ 80 92 120 ]; }; + userTasks = [{ + label = "latexmk (project)"; + command = "latexmk"; + args = [ "-synctex=1" "-pdf" "-recorder" ]; + cwd = "$ZED_DIRNAME"; + tags = [ "latex-build" ]; + }]; }; } diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index dea0f34..df713b7 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -206,6 +206,7 @@ in { "rig" "rstudio" "signal" + "skim" "slack" "stats" "steam" From ac837750c9aeafa1d29e85ec89dcbd8b7e981e14 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:00:37 -0600 Subject: [PATCH 47/75] nix-builder (corianne): Add rosetta builder --- flake.lock | 59 +++++++++++++++++++++++++++++++++++++ flake.nix | 15 +++++++--- systems/darwin/corianne.nix | 24 +++++++++++++-- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index 982ba78..6141529 100644 --- a/flake.lock +++ b/flake.lock @@ -90,6 +90,64 @@ "type": "github" } }, + "nix-rosetta-builder": { + "inputs": { + "nixos-generators": "nixos-generators", + "nixpkgs": [ + "nixpkgs-darwin" + ] + }, + "locked": { + "lastModified": 1756177999, + "narHash": "sha256-aSbB7/jrt7ujiJ55f2uGhOo+usGxVSkqbAMVgg2jDls=", + "owner": "cpick", + "repo": "nix-rosetta-builder", + "rev": "ebb7162a975074fb570a2c3ac02bc543ff2e9df4", + "type": "github" + }, + "original": { + "owner": "cpick", + "repo": "nix-rosetta-builder", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1736643958, + "narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": [ + "nix-rosetta-builder", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1737057290, + "narHash": "sha256-3Pe0yKlCc7EOeq1X/aJVDH0CtNL+tIBm49vpepwL1MQ=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "d002ce9b6e7eb467cd1c6bb9aef9c35d191b5453", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1764522689, @@ -202,6 +260,7 @@ "agenix": "agenix", "home-manager": "home-manager", "nix-darwin": "nix-darwin", + "nix-rosetta-builder": "nix-rosetta-builder", "nixpkgs": "nixpkgs", "nixpkgs-darwin": "nixpkgs-darwin", "nixpkgs-unstable": "nixpkgs-unstable", diff --git a/flake.nix b/flake.nix index bbd1632..59c9ce0 100644 --- a/flake.nix +++ b/flake.nix @@ -44,11 +44,15 @@ url = "github:LnL7/nix-darwin/nix-darwin-25.11"; inputs.nixpkgs.follows = "nixpkgs-darwin"; }; + nix-rosetta-builder = { + url = "github:cpick/nix-rosetta-builder"; + inputs.nixpkgs.follows = "nixpkgs-darwin"; + }; }; outputs = { self, nix-darwin, nixpkgs, nixpkgs-darwin, nixpkgs-unstable - , home-manager, agenix, rycee-nurpkgs, nur, plasma-manager, quadlet-nix, ... - }: + , home-manager, agenix, rycee-nurpkgs, nur, plasma-manager, quadlet-nix + , nix-rosetta-builder, ... }: let mkHomeConfiguration = { hostname, arch ? "x86_64", os ? "linux" , desktop ? false, extraModules ? [ ] }: @@ -119,8 +123,11 @@ }; agenix = agenix; }; - modules = - [ ./systems/darwin/corianne.nix agenix.darwinModules.default ]; + modules = [ + ./systems/darwin/corianne.nix + agenix.darwinModules.default + nix-rosetta-builder.darwinModules.default + ]; }; nixosConfigurations = { diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index df713b7..f1c1eb2 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -26,9 +26,27 @@ in { }; # Auto upgrade nix package and the daemon service. - nix.enable = true; - #services.nix-daemon.tempDir = "/nix/tmp"; - nix.package = pkgs.nix; + nix = { + enable = true; + gc = { + automatic = true; + interval = { Weekday = 1; }; + options = '' + --delete-older-than 14d + ''; + }; + # Needed for rosetta-builder, see + # + # + linux-builder = { + enable = true; + ephemeral = true; + }; + extraOptions = '' + extra-platforms = x86_64-darwin + ''; + }; + nix-rosetta-builder.onDemand = true; # Create /etc/zshrc that loads the nix-darwin environment. programs.zsh.enable = true; # default shell on catalina From 91083619640f3f1df55a554bc453c9ca601bc5ba Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:00:54 -0600 Subject: [PATCH 48/75] pkgs (desktop): add nixos-rebuild package --- homes/desktop.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/homes/desktop.nix b/homes/desktop.nix index 7b1b2ad..255db78 100644 --- a/homes/desktop.nix +++ b/homes/desktop.nix @@ -22,6 +22,7 @@ nil nixd nixfmt-classic + nixos-rebuild quarto roboto-slab shellcheck From 0571d801edfe6009b430207bed9ba06682de736a Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:07:16 -0600 Subject: [PATCH 49/75] services (bosephus): Remove pihole service --- services/pihole.nix | 27 --------------------------- systems/linux/bosephus.nix | 1 - 2 files changed, 28 deletions(-) delete mode 100644 services/pihole.nix diff --git a/services/pihole.nix b/services/pihole.nix deleted file mode 100644 index ed4cd19..0000000 --- a/services/pihole.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ config, ... }: - -{ - age.secrets = { - pihole-credentials = { - file = ./../secrets/pihole.age; - owner = "root"; - group = "root"; - }; - }; - virtualisation = { - quadlet = { - containers = { - pihole = { - containerConfig = { - image = "docker.io/pihole/pihole:2025.06.2"; - publishPorts = - [ "53:53/tcp" "53:53/udp" "80:80/tcp" "443:443/tcp" ]; - environmentFiles = [ config.age.secrets.pihole-credentials.path ]; - networks = [ "bridge" ]; - dns = [ "127.0.0.1" "194.242.2.9" "9.9.9.9" ]; - }; - }; - }; - }; - }; -} diff --git a/systems/linux/bosephus.nix b/systems/linux/bosephus.nix index 79dcf54..6c8d181 100644 --- a/systems/linux/bosephus.nix +++ b/systems/linux/bosephus.nix @@ -9,7 +9,6 @@ ./hardware-configuration/bosephus.nix ./hardware-configuration/bosephus-external-drives.nix ./../../services/samba.nix - ./../../services/pihole.nix ]; # Bootloader. From a0175f565bd07dcade50fc431660c0d37152efc3 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 8 Dec 2025 08:11:43 -0600 Subject: [PATCH 50/75] secrets! (pihole): Remove pihole secrets --- secrets.nix | 1 - secrets/pihole.age | Bin 926 -> 0 bytes 2 files changed, 1 deletion(-) delete mode 100644 secrets/pihole.age diff --git a/secrets.nix b/secrets.nix index 8042bf6..1e0ec3d 100644 --- a/secrets.nix +++ b/secrets.nix @@ -36,5 +36,4 @@ in { ++ [ corianne-host ]; "secrets/network-information.age".publicKeys = system-administrators ++ [ bosephus-host ]; - "secrets/pihole.age".publicKeys = system-administrators ++ [ bosephus-host ]; } diff --git a/secrets/pihole.age b/secrets/pihole.age deleted file mode 100644 index 1b2bc2533d7d7de5063e15de08cacfa0e5dd6df6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 926 zcmZ9~ON-nD003YWtr$u@C<-EMEXr2Hn8#!?31T6WWL}x)wHiu+u2=O+39LsdRK+FNAr|z)>7yg5R_Y5XYpTwKC@i|0 zm>2{Jbij0gVmR{R$;MKx8y=gND(0nem`}D~8mAS7bV!j+JYSbvD!!_rHk@Y}NT%gR zOET+xPfU=sn&Jr5@3mQaG%gV_o;75@KmwYe)DZ_jnrT~^fv~fd7(`U*aHY??lB*y- z7fG_0W0P^jNDMlZRyEV$t#$?msJa|8@kGvL&K^u6NNfhI-W7UXVkD5c&?hw8@1>~5 zMSwA(>3HcYbr&(Z2s(os94^o%PY(K##3-8?O2(eUY_=F~RjV$LTP6lee#1(c{c zbvDlXP>h>Q(ZHJ`yy#a`KB#*gAi%Q0R^rQ1b%j+97Ue9&K$chfAp+!&jp* Date: Mon, 8 Dec 2025 14:44:22 -0600 Subject: [PATCH 51/75] service (freshrss): Add freshrss service --- secrets.nix | 2 + secrets/freshrss.toml.age | Bin 0 -> 1285 bytes services/freshrss.nix | 124 +++++++++++++++++++++++++++++++++++++ systems/linux/mcentire.nix | 1 + 4 files changed, 127 insertions(+) create mode 100644 secrets/freshrss.toml.age create mode 100644 services/freshrss.nix diff --git a/secrets.nix b/secrets.nix index 1e0ec3d..45783ee 100644 --- a/secrets.nix +++ b/secrets.nix @@ -34,6 +34,8 @@ in { ++ [ mcentire-host ]; "secrets/darwin-policies-json.age".publicKeys = system-administrators ++ [ corianne-host ]; + "secrets/freshrss.toml.age".publicKeys = system-administrators + ++ [ mcentire-host ]; "secrets/network-information.age".publicKeys = system-administrators ++ [ bosephus-host ]; } diff --git a/secrets/freshrss.toml.age b/secrets/freshrss.toml.age new file mode 100644 index 0000000000000000000000000000000000000000..9bfa06c148bbaa685ffb520116db0ee1f6964663 GIT binary patch literal 1285 zcmZY2`)?Bk003YE1h+0LkPQeLvQlLul+s<>>w~~d*Vnb(wY^@i*DEB@_O93V+Fl>m z_O1}ZcuaJX06N$phz`ic28huOofE?VB`{FKQwL)Rh%BNI351z|zt8U<_<}Sgr&8gp zkmh1+YAKtg6$L;fZ;<42Q8`5_K@iYOVhL5Egh+5ZWR{V>dV?1=nMnc9vj!~;CyPF7AcE;&1>nuFkTpm|DK(6zQjkfb#bYsb#AhaC8YeP& z184GiQkn}1IM&1!g z(s`$hnY^hoZZ1ztQZa)kX15@KTL|d+JVXSnc8$ZU5Fp-)+9^C+G5}FK0t()u$l{H8 zG0usg@w7HU>5^_ISO}|1O)hHyRbiNqF*t(OFbC)hhRK_ZX^cgSlAswQ^C}Sb+qsm+ zqq8WIE~}fisC{G(H1nWK=wmdNhYWox0aaao1QpEx?TaAfU*<@-xp zryUvWyDoivC)Kos+jmiPue-NXc-8UA=5s?2?q3)^<*Vr)t6kGvR&`6%I<$8721RGb zgY8xC{C(o=)xU23AdYW&Ffn!JiMmbAvtGRAxqa~clM%XX&Unq6W5S_@<#Q@$x1oF6 z;kS3xZDTIANc;NEzoKR#=K74Iy*tzx3Wz(J?95txP z*H=tH^FzH=ElLA19T;9w=W5HooNwI!FwwIP*0=v#`Au4~NlARP5c^f~^}XD;$yI@^ z8%OR|HY@gYtlz19a`W1THBY;O15(>}AUI0y>FkQOFOrR2s>Jp&ORML~-S&-VD#q!> zTgJ8rrkovqI*~b=71e-Di}X-gZ|~-nktJ<|Aw>MSY{u}48T}tb$_K9Y3?T2mH@Bhr zy0$vK$hoMZ0%s*>_`|(#M5T|92bcXOJ{+3zu=~leN4t-Yw@e>CG0_;~X4Xmf+O+LM zP4TV+8l&yJXZO){*uaxJ>ve-XzT=C^2`hQ!M(zAQ)9MCl+5)(?A!}{j1rD@7 YLKB}BFMJ%nQT5@0^545&+b Date: Mon, 8 Dec 2025 17:22:33 -0600 Subject: [PATCH 52/75] fix (freshrss): Set OIDC variables --- secrets/freshrss.toml.age | Bin 1285 -> 1652 bytes services/freshrss.nix | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/secrets/freshrss.toml.age b/secrets/freshrss.toml.age index 9bfa06c148bbaa685ffb520116db0ee1f6964663..9fc2f10451f6ba0748e727945e1c5e1e0668054f 100644 GIT binary patch delta 1569 zcmV++2HyFF3iJ$+EPpq8Nl!&)MQ&|jMNeT#GHEn5O)^qcSx!lAcSdq;V^3yhL25@+ zVMtV0X9_h-Ic!vTbV*ilL`-8vWO!#%Rdz^KP*hhnGBkNFbb3!sGi73VMlnxkRSGRW zAaiqQEoEdfH8n9gATehzcz1UoRCz&RVt8#yNo#3RLuhGDI7V_&XJvIZOlEIGGgmla zNlj@~Q*lBtT6I!u3TjkDGizBkQg}!(V>32WNkVp0NNZMdO>8eYT61euaW8CaR&Qu> zF-}c1k?|K-cvfp=cvm@dVsuPSR&POCI5jYGSTHzYH8C%6bwzA4Y(`{od2VkwcR^N|ZDC|EH!*rjcrS8tQ8Q9cZ&+knP*_)RIdW)hQCc@RdTC>mUjY|aR&PNy zR!L?`Lu6D}SZzmjW@l4!a6)=aFL^I{O;2KNFLG^cGFoO)aWZcTaaUP%VK+BdF=j6{ zN^3|}aZyKaM^IKlIY&%pNn~nsVK7Z-XJspHS8sEZ%>fvHLQP0@W<+&KFi=cROhY+K zK}bbKT32!}ZB9~8NN`n2Suj#;F;;nXML`N{ZBKVXVMSCpI5=@ZbSp)7GdD6xGEFou zI9G5oFHB`ZQ*uycNpeF=XE+KiJ|J^*Xf0)AGBq_ZIUp-TFjrD%Aa!OhVR1)MXmD0W zIZIS+czQ2?c}{OKRVz1eM{`$jLNskJXJ{{1b4xN)X9{6SdSOv)LUB@YOm1#@QZ_Yh zaY<5YP%=eUSZh&aH$zrxNm+13F;_)&Zwf6fEg)7mGg2}`M0a8`M^0`wNNPrSLT7Jb zdR9keN?J=$PjPp3XI58wZEkZ}FbcW1l)wDe@Wl#$Gq4W$K|7M?WR~j263nSlO( zmtM~sX)J_?T)aw{0@QyN&|5kOHGyO@8&F{OxbaF#G+*PoiSd!Y(eutUqLgFJ!9ZBe z!H){7-g;K_4IA2DoMW*&DR&Pv0gz{a2AeE)Qh=}%!Qlmbg>7!B_hw+|xX8W28oW~h z0OhZL#xItLH@ze_HavoHHu*pPn{OLvrd}O|u;EvgMZw`lC7F54CEG?q39(UMvJ9zl zvz=<)x?7# z)F0(l_BFG+DWT-m8_sMS?!mWRu{-t7%>LP(fJEWK zDwLUd9T&jubm&?+D#v7usMKgb*kAt(8YZMJz+{vSbHt>`+#|hZLWMAP@Ld8R&bZY? zV9}9pS^9+yKiV`Xb&RplSMBRzKPWIGh;Adpor|jAJ8$G?7Sjp?w`N!in%x~)CX*e1 zt3D}I22~bW^N_m6OvuqD62FngU1E;YAMAujEElS~KuNMyaA+pKhNj5PzK6R92sIlq zoRaeA7jlszyVm{H4u=v<6RU3DHdwq28}&4KB#^0VfdqYaL6$7@QJMhkGz+dL4(w&e ztwhh5=wUj!$<>1Cbk^QH(GljOrj9G}rdx@}w+aNxQ_|Ii?FHz!jdgV;bzBGGJixvh+I(IxQBHWNAd z`6GkJ^NLIael`mwbr}_sMvlsSkc46)Eua>II|SAV=-oGYeo4_9S=q9OzVGpW8Dq5s z-IV#f#N}-d%F(H|{_59Jx^X2^Wc{jm&CFU;K6OM>tS9=JnM;B+f@Ymot-c2lXA`JN zq|}?IpfFuHWuGf9V`+0>Q7@q*K@4@SbG_o>wEA3>suwixEKVy<69^@ukDS9ovJ8eo zV^jPX)6uqz54IA(wRy(CfRVs|ifEZ?1SsXuzF3yxXONJBx8|V>D4F_xyM?Cfy;fPJ zJ(OONxG9v;Xa^#?D6N}6DyCenC7}@^q_`LXSsBZw1Sr*R$wPXoNo~Y>PH76F(rW;9 z04u>ER$=8|_jcw@oArL`RX1=ELPJgkTkW!NDm5s6V~MmGTTyn>SBhL1#)TO^>eMj7 TQp=5l-tjk9811F4Ea9H#b} zbcU3IP9{S^iz6Y6)g&@pSZIl+(lVC>0U$&djxla;Mo;G(l8hLXC!H#~KI4ibVk~U0 zGek8w9rSqhYPfB(f{^DiNgTrL@t{zjU~KM$0R!!_2oz4#q>MUoIcx#={z#4%8muBbUY(humP5fI;0vcYY9Z@tX0VDT05VvniUp@n1fg&X7&@QyhainPyuoKce4#ji zT7`a;RBK_}uea4n=(>C+ud}%21kL0mq$=ml_+gzZ?hU(C{|^vqYY3F)$6W>l$`X`a zn57t!V_fEf)rn|HUDlvZxJZOHiEZYP)SQw><$wXRdL>~gh`AYpQEiQ%G^26^Gh-QoNTYgl0!J|$ zMFXp;`*7u}p|-JtQ8@6=tK^T>JCF-&%Zta`e`Z7iUQ=MtnWFX3_=K>8_pB4sO||E5 z4>ewT34A%dr#Zjn3ip|Iz{v~FXgIol(aHn)Z8MJ!_1_RYxf`ormf3#^xZl&)#l7nM zWb66ihYv1}opx6Cj90B|EGoMVv<$DGw@KX9`LMO@y}wVMyH@z?)(^aJ)5ED5b52%o zX`K7w9rVtj4^IW?qWKe*Z;x|_7Z=Yjo!5@->ww>FtKPv}ZWi?SUwBb+79Bm`x~8M5 z`q_ekt$olRU-gb|NF2Go+-KeP=Zcxn4~=Q$)a$FJpoQMPvSz7!|0akbXTl!6cU)UlgKU$3c%K!R)`rGIl_qNTW_evYZdpkGoR8HQyzG>alZqJ~= z^c@I}QG2_(gB?qR($kVChu@q1VGR=a+MSXo+ zR|l504|x&Z=fc?|t7Z>u4-^kx>m5Yi|Dd9_@rJTIvBbKhq)B_p?KGnVF`tNU+|1@yt z@yg?8deI1Ai8QvHTlrvk=fS|eUqrh{7qn1aOHUEE%deh3RI;5nH*f7ZwgDfUyt`2~ z#1d^^luj9`t2e8v7WV7b*7|2If~#s%#+KdSV8>%D@@ekk$G)3oyABrr-u>DE-q3&D C6W@&h diff --git a/services/freshrss.nix b/services/freshrss.nix index e1da1ef..93272aa 100644 --- a/services/freshrss.nix +++ b/services/freshrss.nix @@ -101,8 +101,19 @@ in { CRON_MIN = "2,32"; LISTEN = "0.0.0.0:${port}"; OIDC_ENABLED = "1"; + OIDC_PROVIDER_METADATA_URL = + "https://auth.millironx.com/application/o/freshrss/.well-known/openid-configuration"; + OIDC_REMOTE_USER_CLAIM = "preferred_username"; + # OIDC_SCOPES = "openid profile"; + # OIDC_X_FORWARDED_HEADERS = "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; }; - secrets = [ "FRESHRSS_INSTALL,type=env" "FRESHRSS_USER,type=env" ]; + secrets = [ + "FRESHRSS_INSTALL,type=env" + "FRESHRSS_USER,type=env" + "OIDC_CLIENT_ID,type=env" + "OIDC_CLIENT_SECRET,type=env" + "OIDC_CLIENT_CRYPTO_KEY,type=env" + ]; healthCmd = "cli/health.php"; healthTimeout = "10s"; healthStartPeriod = "60s"; @@ -111,14 +122,15 @@ in { healthRetries = 3; networks = [ networks."${serviceContainer}".ref ]; }; - unitConfig.Requires = [ containers."${serviceContainer}-db".ref ]; - unitConfig.After = [ containers."${serviceContainer}-db".ref ]; + unitConfig.Requires = [ secrets.ref containers."${serviceContainer}-db".ref ]; + unitConfig.After = [ secrets.ref containers."${serviceContainer}-db".ref ]; }; }; networks."${serviceContainer}" = { }; autoUpdate.enable = true; + autoEscape = true; }; }; } From 1eebebdeb0848b48a7db2f157e8cf6454c2e2895 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 8 Dec 2025 17:25:48 -0600 Subject: [PATCH 53/75] fix (freshrss): Bind port --- services/freshrss.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/services/freshrss.nix b/services/freshrss.nix index 93272aa..8f4d193 100644 --- a/services/freshrss.nix +++ b/services/freshrss.nix @@ -121,6 +121,7 @@ in { healthInterval = "75s"; healthRetries = 3; networks = [ networks."${serviceContainer}".ref ]; + publishPorts = [ "127.0.0.1:${port}:${port}" ]; }; unitConfig.Requires = [ secrets.ref containers."${serviceContainer}-db".ref ]; unitConfig.After = [ secrets.ref containers."${serviceContainer}-db".ref ]; From 3f35901fd31c5862fa6791f6e7588d1150369712 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 8 Dec 2025 17:29:00 -0600 Subject: [PATCH 54/75] fix (freshrss): Uncomment required variables --- services/freshrss.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/freshrss.nix b/services/freshrss.nix index 8f4d193..b2985db 100644 --- a/services/freshrss.nix +++ b/services/freshrss.nix @@ -104,8 +104,8 @@ in { OIDC_PROVIDER_METADATA_URL = "https://auth.millironx.com/application/o/freshrss/.well-known/openid-configuration"; OIDC_REMOTE_USER_CLAIM = "preferred_username"; - # OIDC_SCOPES = "openid profile"; - # OIDC_X_FORWARDED_HEADERS = "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; + OIDC_SCOPES = "openid profile"; + OIDC_X_FORWARDED_HEADERS = "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; }; secrets = [ "FRESHRSS_INSTALL,type=env" From 1fc358b482ce80a3e0ba8528a2be9eed9f84362d Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:40:27 -0600 Subject: [PATCH 55/75] fix (freshrss): Networking stack fixes --- services/freshrss.nix | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/services/freshrss.nix b/services/freshrss.nix index b2985db..aa1210b 100644 --- a/services/freshrss.nix +++ b/services/freshrss.nix @@ -25,7 +25,9 @@ in { }; services.caddy.virtualHosts."feeds.millironx.com".extraConfig = '' - reverse_proxy http://127.0.0.1:${port} + reverse_proxy http://127.0.0.1:${port} { + header_up X-Forwarded-Port 443 + } ''; systemd.tmpfiles.rules = builtins.map createTmpfilesRule @@ -96,16 +98,21 @@ in { autoStart = true; containerConfig = { image = "docker.io/freshrss/freshrss:1"; + # Required to allow the container to talk to the host ports, in + # other words, to resolve Authentik correctly + addHosts = [ "auth.millironx.com:host-gateway" ]; environments = { TZ = osConfig.time.timeZone; CRON_MIN = "2,32"; LISTEN = "0.0.0.0:${port}"; + TRUSTED_PROXY = "172.16.0.1/12 192.168.0.1/16"; OIDC_ENABLED = "1"; OIDC_PROVIDER_METADATA_URL = "https://auth.millironx.com/application/o/freshrss/.well-known/openid-configuration"; OIDC_REMOTE_USER_CLAIM = "preferred_username"; - OIDC_SCOPES = "openid profile"; - OIDC_X_FORWARDED_HEADERS = "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; + OIDC_SCOPES = "openid email profile"; + OIDC_X_FORWARDED_HEADERS = + "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; }; secrets = [ "FRESHRSS_INSTALL,type=env" @@ -123,8 +130,10 @@ in { networks = [ networks."${serviceContainer}".ref ]; publishPorts = [ "127.0.0.1:${port}:${port}" ]; }; - unitConfig.Requires = [ secrets.ref containers."${serviceContainer}-db".ref ]; - unitConfig.After = [ secrets.ref containers."${serviceContainer}-db".ref ]; + unitConfig.Requires = + [ secrets.ref containers."${serviceContainer}-db".ref ]; + unitConfig.After = + [ secrets.ref containers."${serviceContainer}-db".ref ]; }; }; From 6fbf0f2b7d209ad5bd60c1cc2d7f05bfe3125115 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Tue, 9 Dec 2025 08:47:04 -0600 Subject: [PATCH 56/75] fix (freshrss): OIDC config mounting After much troubleshooting, I figured out that FreshRSS does not actually support OIDC with the use of the environment variables for configuration. Instead, the config files actually have to be set with the web wizard and persisted with a volume mount. Do that. --- secrets/freshrss.toml.age | Bin 1652 -> 1185 bytes services/freshrss.nix | 14 +++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/secrets/freshrss.toml.age b/secrets/freshrss.toml.age index 9fc2f10451f6ba0748e727945e1c5e1e0668054f..e253b881a3ab7741cedfcd65baaf390014ecedea 100644 GIT binary patch delta 1099 zcmZ9}>u(bU003}7B3eMjOa=t7VwS-&0ly|&kONL}x)*RJdPx_dBE z4DbPDB7rO#AIl=T3^v6DV$dLv@YrT1%xp0*6eB@JKpBJKkgDJP{R_Xl3wxe;yRkwV zT`=Hs(-8-6@R2z0PoR2)@MR0F6dVdUXsg$%fW|E2lX;aVizxzWNA(1pC}v&yc$v0= zpr6xaas+@&e!ClWx{_%Z2L@Hzm(`_GQp>TB!JxCKbvz)6qB=qg?h+ia;^jbz1Sz9v z_v`eW#hf5;)Jtht!9qb$u&qq_Y@~|gm0}Bu#;sB`V`8vu8uZ$A0E7fRN}Rw_P=GX0 zSw&+ITupnYYUxD4m5fN}@tf`8B$_r@t;RG3DGJ2<*(MyYp+ObiE|fJS zD`*P-6q1IBq%nsS`7o|&$pKPp0;Wx9Ims2%oJ-snn^Q}NfdXnM!hwvH#A&L%-2`%^ z3~0g_YA!|dCcm5mQW>ORNjO|8o{3n(h!o6%vKPzdNspTk$U+uG87o2(PLC7Aynd&F z5ToM0(K)ph#)zUVb`Fs7h%HWO^6de$E@@+pZrNuNO(h~6@;M7EE959xWy@wV8Yin@ zrW9vu;~Ys;iicWwEE(`5K-8t!y+tBvH6cZY`Tu|h0ck(4&H`kJY0b5;Kb1L!UF)NZ_KV$BTmHHsd@wwJLC>QN(U1QLJ@Q3O{e%9Y zz4^~s$%Bq>yXJgmviH`O*UhBd7+c1!pZ;W-P$>*5!wa@mmQU{)&Q~t4K(ELH-);C_ zf4g&X)_kXWBhgoPdGaauxvKPTqRsZJcA&Z+Y9M}+R8Z`+dHU>*pyY$V!)N^? zq55NTH)!l);;MMUC+I_@;`Ldwif^Z delta 1570 zcmV+-2Hp9g3G@t*EPpq8Nl!&)MQ&|jMNeT#GHEn5O)^qcSx!lAcSdq;V^3yhL25@+ zVMtV0X9_h-Ic!vTbV*ilL`-8vWO!#%Rdz^KP*hhnGBkNFbb3!sGi73VMlnxkRSGRW zAaiqQEoEdfH8n9gATehzcz1UoRCz&RVt8#yNo#3RLuhGDI7V_&XJvIZOlEIGGgmla zNlj@~Q*lBtT6I!u3TjkDGizBkQg}!(V>32WNkVp0NNZMdO>8eYT61euaW8CaR&Qu> zF-}c1k?|K-cvfp=cvm@dVsuPSR&POCI5jYGSTHzYH8C%6bwzA4Y(`{od2VkwcR^N|ZDC|EH!*rjcrS8tQ8Q9cZ&+knP*_)RIdW)hQCc@RdTC>mUjY|aR&PNy zR!L?`Lu6D}SZzmjW@l4!a6)=aFL^I{O;2KNFLG^cGFoO)aWZcTaaUP%VK+BdF=j6{ zN^3|}aZyKaM^IKlIY&%pNn~nsVK7Z-XJspHS8sEZ%>fsGVM0wvb!J3$Nia}MPE12N zOF>9QMOs&KFKtdzPe^c8Nm(#bY%x}Obwxo6Yi&<=LSaQzI5;?QL3ArccQZFKNit0| zFF03lGA~SJLQ`^3Wl3^FOJ_I=Ej}P~b7(DPWHL21F*zVBLoioTXCQTEFJW;cO zd6!<#8)+Cn2$j!J&J=iDX56ND{|JM3@$q*^A9w@?R_|?RN zA=Dq`RrWQryD6dM)#Uw!tW%gf2~tVxh?(Di6HYp;Ya7mN8}7lkU9mg$&dmPVoq$B) z!YY)Rc^wzP?R4l`IV#6wjHuLTKiFUY3mPV*F2H1z4Rge#$lN2nWkQ88cJN&SAkMhe zL}1a8Z&~_<4L{m6D0Pgn&{ys2VLvD^BZzJz!<~z&;5%>RXBN{61Gi>a3!2>>StgTz z9jiVmR0dTRS@V#(#!Sf3CKA7q#$95L(;w`FM=TeryFf{@Rd8q~zlNsB&Ax}b2M9GA zF`Sa}=NEF3BD>c8)eeUeOcSea-!@ph3>)<{c_fgjYk>rPc0rab^HG`r>@*9mCl2go z$E`%qnCM|TxyjXn>2%iKJkb&6qoQ>-WYnVCz1G=gTGR;|7V5oZ&q zNu<=9r=T!hIAxzJE@NqPU{NojBS8#xu5-QO;k5c(l&Tjr?<`I$P7??vqK}-zLb42o zLSs|>7}L?Vix0LEz_oeCz<`l|z=~*@Y6K|d(7srf;%AVMg16?O3n-cTe!GRH>%CT4 zr9G5hk+><8(P#%Ex+txiKPskNt|g%nA*8q%0a+Q#rUWR}ZplM>s!46cdQNEyqS9*s zbpR{DAy#4KU-x$AO`G+8>Qy&z5kf;w1zYX1a4Iz@eq)KW8Cy|y(pQQZT*ieNKI+sk U!BdvvGu&uI%oixil6p9*qiI{35C8xG diff --git a/services/freshrss.nix b/services/freshrss.nix index aa1210b..2f142ff 100644 --- a/services/freshrss.nix +++ b/services/freshrss.nix @@ -7,10 +7,9 @@ let serviceContainer = "freshrss"; stateSubDir = subDir: "${stateDirectory}/${subDir}"; createTmpfilesRule = subDir: "d ${stateSubDir subDir} 1755 ${user} ${user}"; - volumeMount = subDir: bindDir: "${stateDirectory}/${subDir}:${bindDir}:U"; dbDirectories = [ "database" ]; - serviceDirectories = [ ]; + serviceDirectories = [ "data" "extensions" ]; in { age.secrets = { "freshrss.toml" = { @@ -85,9 +84,8 @@ in { healthInterval = "30s"; healthRetries = 5; healthStartPeriod = "20s"; - volumes = pkgs.lib.imap0 (i: sub: - volumeMount sub - (builtins.elemAt [ "/var/lib/postgresql/data" ] i)) dbDirectories; + volumes = + [ "${stateDirectory}/database:/var/lib/postgresql/data:U" ]; networks = [ networks."${serviceContainer}".ref ]; }; unitConfig.Requires = [ secrets.ref ]; @@ -115,8 +113,6 @@ in { "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; }; secrets = [ - "FRESHRSS_INSTALL,type=env" - "FRESHRSS_USER,type=env" "OIDC_CLIENT_ID,type=env" "OIDC_CLIENT_SECRET,type=env" "OIDC_CLIENT_CRYPTO_KEY,type=env" @@ -129,6 +125,10 @@ in { healthRetries = 3; networks = [ networks."${serviceContainer}".ref ]; publishPorts = [ "127.0.0.1:${port}:${port}" ]; + volumes = [ + "${stateDirectory}/data:/var/www/FreshRSS/data:U" + "${stateDirectory}/extensions:/var/www/FreshRSS/extensions:U" + ]; }; unitConfig.Requires = [ secrets.ref containers."${serviceContainer}-db".ref ]; From 9fcc736104c91155d321c5efd20578f0247e8404 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:40:41 -0600 Subject: [PATCH 57/75] config (zed): Switch to external Nix formatter --- programs/zed.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/zed.nix b/programs/zed.nix index b3f7fd6..9477d87 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -52,12 +52,12 @@ }; }; }; + Nix = { + formatter.external.command = "${pkgs.nixfmt-classic}/bin/nixfmt"; + }; }; lsp = { - nil = { - initialization_options.formatting.command = [ "nixfmt" ]; - settings.nix.flake.autoArchive = true; - }; + nil = { settings.nix.flake.autoArchive = true; }; texlab = { settings = { build = { From d40b20d8cc0b2af586ee3e3f3f9436fea285c024 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:44:14 -0600 Subject: [PATCH 58/75] config (zed): Switch default model to Claude Sonnet 4.5 --- programs/zed.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zed.nix b/programs/zed.nix index 9477d87..4b97b71 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -23,7 +23,7 @@ use_modifier_to_send = true; default_model = { provider = "zed.dev"; - model = "claude-3-7-sonnet"; + model = "claude-sonnet-4-5"; }; default_profile = "minimal"; }; From c7f76d5c1c921d95b8a62540f6ef253c6bd97ed8 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:46:29 -0600 Subject: [PATCH 59/75] config (zed): Add new git_hosting_providers key --- programs/zed.nix | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/programs/zed.nix b/programs/zed.nix index 4b97b71..30f2bcb 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -30,6 +30,18 @@ buffer_font_family = "FiraCode Nerd Font"; buffer_font_size = 11; features = { edit_prediction_provider = "zed"; }; + git_hosting_providers = [ + { + provider = "forgejo"; + base_url = "https://code.millironx.com"; + name = "Milliron X Code"; + } + { + provider = "forgejo"; + base_url = "https://codeberg.org"; + name = "Codeberg"; + } + ]; languages = { Julia = { formatter = { From 20465843e45d377581a65b25bda7505b54558830 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:50:14 -0600 Subject: [PATCH 60/75] config (git): Add ssh rewrites --- programs/git.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/programs/git.nix b/programs/git.nix index 173e5f1..244e916 100644 --- a/programs/git.nix +++ b/programs/git.nix @@ -42,6 +42,11 @@ }; merge = { conflictstyle = "zdiff3"; }; pull = { rebase = true; }; + "url \"ssh://git@github.com/\"".insteadOf = "https://github.com/"; + "url \"ssh://git@gitlab.com/\"".insteadOf = "https://gitlab.com/"; + "url \"ssh://git@codeberg.com/\"".insteadOf = "https://codeberg.com/"; + "url \"ssh://git@code.millironx.com/\"".insteadOf = + "https://code.millironx.com/"; }; }; } From 69205e695fc529a0e4fc90d067172aa9ae9732a2 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:50:44 -0600 Subject: [PATCH 61/75] shell: Add git clone shortcut function --- programs/shells.nix | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/programs/shells.nix b/programs/shells.nix index 6745cf4..6d226b9 100644 --- a/programs/shells.nix +++ b/programs/shells.nix @@ -10,13 +10,32 @@ let } ''; + sourceCodeDirectory = + if pkgs.stdenv.hostPlatform.isDarwin then "~/Developer" else "~/src"; + clone_bash_function = '' + unalias gc + function gc() { + REPO_ID="$(echo "''${1}" | \ + awk '{ + sub(/^git@/, ""); + sub(/^https:\/\//, ""); + sub (/:/, "/"); + sub(/\.git$/, ""); + print + }')" + git clone "https://''${REPO_ID}.git" ${sourceCodeDirectory}/''${REPO_ID} + cd ${sourceCodeDirectory}/''${REPO_ID} + } + + ''; in { programs = { bash = { enable = true; - initExtra = conda_init "bash" + nd_bash_function + '' - export PS1="[\[\e[32m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\] \[\e[34m\]\W\[\e[m\]] \\$ " - ''; + initExtra = conda_init "bash" + nd_bash_function + clone_bash_function + + '' + export PS1="[\[\e[32m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\] \[\e[34m\]\W\[\e[m\]] \\$ " + ''; }; zsh = { enable = true; @@ -37,7 +56,7 @@ in { "zsh-users/zsh-completions" ]; }; - initContent = conda_init "zsh" + nd_bash_function; + initContent = conda_init "zsh" + nd_bash_function + clone_bash_function; }; }; } From 8e283c2288e46a25b73ef31118b594de6bbdcc6b Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:16:57 -0600 Subject: [PATCH 62/75] config (zed): Enable Typst previews --- programs/zed.nix | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/programs/zed.nix b/programs/zed.nix index 30f2bcb..dba9b38 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -87,6 +87,7 @@ }; }; tinymist = { + initialization_options = { preview.background.enabled = true; }; settings = { exportPdf = "onSave"; outputPath = "$root/$name"; @@ -109,12 +110,28 @@ ui_font_size = 16; wrap_guides = [ 80 92 120 ]; }; - userTasks = [{ - label = "latexmk (project)"; - command = "latexmk"; - args = [ "-synctex=1" "-pdf" "-recorder" ]; - cwd = "$ZED_DIRNAME"; - tags = [ "latex-build" ]; - }]; + userTasks = [ + { + label = "latexmk (project)"; + command = "latexmk"; + args = [ "-synctex=1" "-pdf" "-recorder" ]; + cwd = "$ZED_DIRNAME"; + tags = [ "latex-build" ]; + } + { + label = "Open Typst preview"; + command = "${ + if pkgs.stdenv.hostPlatform.isDarwin then "open" else "xdg-open" + } http://127.0.0.1:23635/"; + use_new_terminal = true; + allow_concurrent_runs = false; + reveal = "never"; + reveal_target = "dock"; + hide = "always"; + shell = "system"; + show_summary = true; + show_command = true; + } + ]; }; } From b6a67cfa987bf959ab7425305c05c875c8716fc6 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:18:00 -0600 Subject: [PATCH 63/75] shell: Add repo_init function --- programs/shells.nix | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/programs/shells.nix b/programs/shells.nix index 6d226b9..edb0f18 100644 --- a/programs/shells.nix +++ b/programs/shells.nix @@ -28,14 +28,37 @@ let } ''; + repo_init_function = '' + function rinit() { + REPO_ID="$(echo "''${1}" | \ + awk '{ + sub(/^git@/, ""); + sub(/^https:\/\//, ""); + sub (/:/, "/"); + sub(/\.git$/, ""); + print + }')" + + mkdir -p ${sourceCodeDirectory}/''${REPO_ID} + cd ${sourceCodeDirectory}/''${REPO_ID} + + git init + + git remote add origin git@''${REPO_ID/\//:}.git + } + + ''; + + shell_functions = shell: + (conda_init shell) + nd_bash_function + clone_bash_function + + repo_init_function; in { programs = { bash = { enable = true; - initExtra = conda_init "bash" + nd_bash_function + clone_bash_function - + '' - export PS1="[\[\e[32m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\] \[\e[34m\]\W\[\e[m\]] \\$ " - ''; + initExtra = shell_functions "bash" + '' + export PS1="[\[\e[32m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\] \[\e[34m\]\W\[\e[m\]] \\$ " + ''; }; zsh = { enable = true; @@ -56,7 +79,7 @@ in { "zsh-users/zsh-completions" ]; }; - initContent = conda_init "zsh" + nd_bash_function + clone_bash_function; + initContent = shell_functions "zsh"; }; }; } From 01cf1735738d562f7375706a59f82381e4a0ea13 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:19:35 -0600 Subject: [PATCH 64/75] brew (corianne): Install Vienna --- systems/darwin/corianne.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index f1c1eb2..b4755c9 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -234,6 +234,7 @@ in { "ungoogled-chromium" "veracrypt" "vlc" + "vienna" "vorta" "zed" "zotero" From 117cf076970c939852e43091b1e32da783003f87 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:19:52 -0600 Subject: [PATCH 65/75] brew (corianne): Remove Musescore --- systems/darwin/corianne.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index b4755c9..d4787fe 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -216,7 +216,6 @@ in { "iterm2" "logseq" "macfuse" - "musescore" "nextcloud" "openrct2" "qownnotes" From 7e65bc03b38bd3a35b51509982247f0402c40043 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:20:07 -0600 Subject: [PATCH 66/75] brew (corianne): Remove Anki --- systems/darwin/corianne.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index d4787fe..c83a9a1 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -207,7 +207,6 @@ in { ]; casks = [ "alt-tab" - "anki" "db-browser-for-sqlite" "dolphin" "firefox" From 8c313aae3766137a709f7e1f3dd6dc7dcf6d4cb2 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:20:58 -0600 Subject: [PATCH 67/75] dnf (fedora): Remove musescore --- playbooks/packages.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/playbooks/packages.yaml b/playbooks/packages.yaml index 58e7263..34f40c8 100644 --- a/playbooks/packages.yaml +++ b/playbooks/packages.yaml @@ -23,7 +23,6 @@ - libwebp-devel - mkvtoolnix - mpv - - musescore - nextcloud-client - nextcloud-client-dolphin - obs-studio From 7d8843c399f9e4fa17005953fc40c6b7451e12c9 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:21:10 -0600 Subject: [PATCH 68/75] flatpak (fedora): Remove Anki --- playbooks/packages.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/playbooks/packages.yaml b/playbooks/packages.yaml index 34f40c8..f13c01b 100644 --- a/playbooks/packages.yaml +++ b/playbooks/packages.yaml @@ -89,7 +89,6 @@ - io.openrct2.OpenRCT2 - org.signal.Signal - org.zulip.Zulip - - net.ankiweb.Anki state: latest method: user remote: flathub From 8336b25291c679848f1ce0a5216432c980917d22 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 26 Dec 2025 20:47:15 -0600 Subject: [PATCH 69/75] fix (zed): Make LaTeX preview open in background The order of the arguments matters to make Skip.app open in the background for LaTeX documents, so fix the order. --- programs/zed.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/zed.nix b/programs/zed.nix index dba9b38..dfbbef0 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -79,7 +79,7 @@ forwardSearch = if pkgs.stdenv.hostPlatform.isDarwin then { executable = "/Applications/Skim.app/Contents/SharedSupport/displayline"; - args = [ "-r" "%l" "%p" "%f" "-g" ]; + args = [ "-r" "-g" "%l" "%p" "%f" ]; } else { executable = "/usr/bin/okular"; args = [ "--unique" "file:%p#src:%l%f" ]; From 05ad4dc62f2b89a3e0a7998c9a32db5b88cc41bd Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sat, 20 Dec 2025 20:18:12 -0600 Subject: [PATCH 70/75] feat (linux-desktop): Convert Plasma settings into plasma-manager --- dotfiles/dolphinrc | 24 ------ dotfiles/konsolerc | 9 --- flake.nix | 2 +- homes/linux-desktop.nix | 8 -- programs/konsole.nix | 23 ++++++ programs/plasma.nix | 170 ++++++++++++++++++++++++++++++++++++++++ programs/yakuake.nix | 19 +++++ 7 files changed, 213 insertions(+), 42 deletions(-) delete mode 100644 dotfiles/dolphinrc delete mode 100644 dotfiles/konsolerc create mode 100644 programs/konsole.nix create mode 100644 programs/yakuake.nix diff --git a/dotfiles/dolphinrc b/dotfiles/dolphinrc deleted file mode 100644 index 2f11ee4..0000000 --- a/dotfiles/dolphinrc +++ /dev/null @@ -1,24 +0,0 @@ -MenuBar=Disabled - -[DetailsMode] -PreviewSize=16 - -[General] -BrowseThroughArchives=true -EditableUrl=true -GlobalViewProps=false -ShowFullPath=true -ShowStatusBar=FullWidth -ShowZoomSlider=true -Version=202 - - -[KFileDialog Settings] -Places Icons Auto-resize=false -Places Icons Static Size=22 - -[MainWindow] -MenuBar=Disabled - -[PreviewSettings] -Plugins=audiothumbnail,avif,blenderthumbnail,comicbookthumbnail,cursorthumbnail,djvuthumbnail,ebookthumbnail,exrthumbnail,directorythumbnail,fontthumbnail,imagethumbnail,jpegthumbnail,jxl,kraorathumbnail,windowsexethumbnail,windowsimagethumbnail,mobithumbnail,opendocumentthumbnail,gsthumbnail,rawthumbnail,svgthumbnail,gdk-pixbuf-thumbnailer,ffmpegthumbs,gsf-office diff --git a/dotfiles/konsolerc b/dotfiles/konsolerc deleted file mode 100644 index 7f417e8..0000000 --- a/dotfiles/konsolerc +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -DefaultProfile=My Default.profile - -[MainWindow] -StatusBar=Disabled -ToolBarsMovable=Disabled - -[UiSettings] -ColorScheme=Default diff --git a/flake.nix b/flake.nix index 59c9ce0..3b4f7b7 100644 --- a/flake.nix +++ b/flake.nix @@ -81,7 +81,7 @@ ] ++ (if desktop then [ ./homes/desktop.nix ] else [ ]) ++ (if (desktop && os == "linux") then [ ./homes/linux-desktop.nix - plasma-manager.homeManagerModules.plasma-manager + plasma-manager.homeModules.plasma-manager ] else [ ]) ++ extraModules; extraSpecialArgs = { diff --git a/homes/linux-desktop.nix b/homes/linux-desktop.nix index 6d78716..2516d48 100644 --- a/homes/linux-desktop.nix +++ b/homes/linux-desktop.nix @@ -113,20 +113,12 @@ in { configFile = { "plasma-workspace/env/ZED_WINDOW_DECORATIONS.sh".text = "export ZED_WINDOW_DECORATIONS=server"; - "dolphinrc".source = - mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/dolphinrc"; - "konsolerc".source = - mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/konsolerc"; "onedrive/config".text = '' force_session_upload = "true" delay_inotify_processing = "true" ''; - "yakuakerc".source = - mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/yakuakerc"; }; dataFile = { - "konsole/My Default.profile".source = - mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/MyDefault.profile"; "kio/servicemenus/kate.desktop".source = ./../dotfiles/kate.desktop; "kio/servicemenus/vlc.desktop".source = ./../dotfiles/vlc.desktop; "kio/servicemenus/word-to-pdf.desktop".source = diff --git a/programs/konsole.nix b/programs/konsole.nix new file mode 100644 index 0000000..66043de --- /dev/null +++ b/programs/konsole.nix @@ -0,0 +1,23 @@ +{ ... }: { + programs.konsole = { + enable = true; + defaultProfile = "millironx"; + profiles.millironx = { + colorScheme = "Breeze"; + font = { + name = "MesloLGS NF"; + size = 10; + }; + extraConfig = { + "Cursor Options".CursorShape = 1; + General.RemoteTabTitleFormat = "[SSH] %H"; + "Interaction Options" = { + CopyTextAsHTML = false; + MouseWheelZoomEnabled = false; + UnderlineFilesEnabled = true; + }; + "Terminal Features".BlinkingCursorEnabled = true; + }; + }; + }; +} diff --git a/programs/plasma.nix b/programs/plasma.nix index ea0b6e7..2fdd769 100644 --- a/programs/plasma.nix +++ b/programs/plasma.nix @@ -1,7 +1,177 @@ { config, ... }: { + + imports = [ ./konsole.nix ./yakuake.nix ]; + programs.plasma = { enable = true; + overrideConfig = true; + shortcuts = { yakuake.toggle-window-state = "Ctrl+`"; }; + configFile = { + dolphinrc = { + DetailsMode.PreviewSize = 16; + General = { + BrowseThroughArchives = true; + EditableUrl = true; + GlobalViewProps = false; + ShowFullPath = true; + ShowStatusBar = "FullWidth"; + ShowZoomSlider = true; + }; + "KFileDialog Settings" = { + "Places Icons Auto-resize" = false; + "Places Icons Static Size" = 22; + }; + PreviewSettings.Plugins = + "audiothumbnail,avif,blenderthumbnail,comicbookthumbnail,cursorthumbnail,djvuthumbnail,ebookthumbnail,exrthumbnail,directorythumbnail,fontthumbnail,imagethumbnail,jpegthumbnail,jxl,kraorathumbnail,windowsexethumbnail,windowsimagethumbnail,mobithumbnail,opendocumentthumbnail,gsthumbnail,rawthumbnail,svgthumbnail,gdk-pixbuf-thumbnailer,ffmpegthumbs,gsf-office"; + }; + }; + input.mice = [{ + enable = true; + name = "Logitech M705"; + vendorId = "046d"; + productId = "406d"; + naturalScroll = true; + }]; + kwin = { + cornerBarrier = false; + titlebarButtons = { + left = [ "close" "minimize" "maximize" ]; + right = [ "help" ]; + }; + virtualDesktops = { + number = 2; + rows = 1; + }; + }; + panels = [ + ### Screen 0 panels ### + ##### Top: Fedora menu | App switcher | Menu bar | CPU monitor | Memory monitor | Network monitor | System tray | clock ##### + { + location = "top"; + floating = true; + height = 27; + lengthMode = "fill"; + opacity = "adaptive"; + hiding = "normalpanel"; + screen = 0; + widgets = [ + { kickoff = { icon = "fedora-logo-icon"; }; } + "org.kde.plasma.marginsseparator" + "org.kde.plasma.windowlist" + "org.kde.plasma.appmenu" + "org.kde.plasma.panelspacer" + { + name = "org.kde.plasma.systemmonitor.cpu"; + config = { + Appearance.chartFace = "org.kde.ksysguard.barchart"; + Sensors.highPrioritySensorIds = "[${ + builtins.concatStringsSep "," (builtins.genList + (i: ''"cpu/cpu${builtins.toString i}/usage"'') 12) + }]"; + }; + } + { + name = "org.kde.plasma.systemmonitor.memory"; + config.Appearance.chartFace = "org.kde.ksysguard.horizontalbars"; + } + { + name = "org.kde.plasma.systemmonitor.net"; + config = { + Appearance.chartFace = "org.kde.ksysguard.horizontalbars"; + Sensors.highPrioritySensorIds = + ''[ "network/all/download","network/all/upload" ]''; + # These are the values needed to make the network indicator + # actually useful, but it appears that plasma-manager doesn't + # support nesting this deep yet. Disable for now. + # "org.kde.ksysguard.horizontalbars".General = { + # rangeAuto = false; + # rangeFromMultiplier = 1048576; + # rangeFromUnit = 202; + # rangeToMultiplier = 1048576; + # rangeToUnit = 202; + # }; + }; + } + { systemTray = { }; } + { digitalClock = { }; } + ]; + } + ##### Bottom: Virtual desktop pager | Full-name taskbar w/ pins | Downloads folder | Trash folder + { + location = "bottom"; + floating = true; + height = 44; + lengthMode = "fill"; + opacity = "adaptive"; + hiding = "normalpanel"; + screen = 0; + widgets = [ + "org.kde.plasma.pager" + { + iconTasks = { + iconsOnly = false; + behavior.showTasks.onlyInCurrentScreen = true; + launchers = [ + "applications:systemsettings.desktop" + "applications:org.kde.discover.desktop" + "preferred://filemanager" + "preferred://browser" + "applications:net.thunderbird.Thunderbird.desktop" + "applications:io.github.alainm23.planify.desktop" + "applications:dev.zed.Zed.desktop" + "applications:com.logseq.Logseq.desktop" + "applications:net.lutris.Lutris.desktop" + ]; + }; + } + "org.kde.plasma.panelspacer" + "org.kde.plasma.marginsseparator" + { + name = "org.kde.plasma.folder"; + config = { + General.url = "file://${config.home.homeDirectory}/Downloads"; + }; + } + "org.kde.plasma.trash" + ]; + } + + ### Screen 1 panels ### + ##### Top: App switcher | Menu bar ##### + { + location = "top"; + floating = true; + height = 27; + lengthMode = "fill"; + opacity = "adaptive"; + hiding = "normalpanel"; + screen = 1; + widgets = [ "org.kde.plasma.windowlist" "org.kde.plasma.appmenu" ]; + } + ##### Bottom: Virtual desktop pager | Full-name taskbar w/o pins ##### + { + location = "bottom"; + floating = true; + height = 44; + lengthMode = "fill"; + opacity = "adaptive"; + hiding = "normalpanel"; + screen = 1; + widgets = [ + "org.kde.plasma.pager" + { + iconTasks = { + iconsOnly = false; + behavior.showTasks.onlyInCurrentScreen = true; + launchers = [ ]; + }; + } + ]; + } + ]; + powerdevil.AC.autoSuspend.action = "nothing"; workspace = { + lookAndFeel = "org.kde.breezedark.desktop"; wallpaperFillMode = "preserveAspectCrop"; wallpaperSlideShow = { interval = 86400; diff --git a/programs/yakuake.nix b/programs/yakuake.nix new file mode 100644 index 0000000..f8b86a7 --- /dev/null +++ b/programs/yakuake.nix @@ -0,0 +1,19 @@ +# Note: this file uses the lower-level `programs.plasma.configFile` syntax +# since plasma-manager does not yet support a high-level module for Yakuake +{ ... }: { + programs.plasma.configFile.yakuakerc = { + "Desktop Entry".DefaultProfile = "millironx.profile"; + Shortcuts = { + next-session = "Shift+Right; Ctrl+Shift+Tab"; + previous-terminal = "none"; + }; + Window = { + DynamicTabTitles = true; + Height = 60; + Screen = 1; + ShowSystrayIcon = false; + Width = 60; + }; + Dialogs.FirstRun = false; + }; +} From 9628c7b433e295eb8b7e94c8335a7888dc86b7b5 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sat, 20 Dec 2025 21:33:58 -0600 Subject: [PATCH 71/75] pkgs (common): Add Runic.jl cli --- homes/common.nix | 25 ++----------------------- pkgs/default.nix | 1 + pkgs/runic.nix | 12 ++++++++++++ 3 files changed, 15 insertions(+), 23 deletions(-) create mode 100644 pkgs/runic.nix diff --git a/homes/common.nix b/homes/common.nix index 078bdd5..50a33e0 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -1,13 +1,4 @@ -{ config, lib, pkgs, pkgs-unstable, ... }: -let - runic_version = "1.5.0"; - runic = pkgs.fetchFromGitHub { - owner = "fredrikekre"; - repo = "Runic.jl"; - rev = "v${runic_version}"; - hash = "sha256-y+kiBA94vUMHH0fEEBg7+c9PEgzjGqh6nCuSRnawhQI="; - }; -in { +{ config, lib, pkgs, pkgs-unstable, custom-pkgs, ... }: { imports = [ ./../programs/shells.nix ./../programs/bat.nix @@ -20,16 +11,6 @@ in { ]; home = { stateVersion = "23.11"; - file = { - ".local/bin/runic" = { - source = runic + "/bin/runic"; - executable = true; - }; - ".local/bin/git-runic" = { - source = runic + "/bin/git-runic"; - executable = true; - }; - }; packages = with pkgs; [ agenix btop @@ -53,6 +34,7 @@ in { pipx python3 zulu17 + custom-pkgs.runic ]; sessionVariables = { PAGER = "most"; @@ -88,9 +70,6 @@ in { }; sessionPath = [ "$HOME/.local/bin" ]; activation = { - installRunic = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - run ${pkgs.julia-bin}/bin/julia --project=@runic --startup-file=no -e 'using Pkg; Pkg.add(name="Runic", version="${runic_version}")' - ''; installJuliaFormatter = lib.hm.dag.entryAfter [ "writeBoundary" ] '' run ${pkgs.julia-bin}/bin/julia --project=@JuliaFormatter --startup-file=no -e 'using Pkg; Pkg.add(name="JuliaFormatter", version="2.1.6")' ''; diff --git a/pkgs/default.nix b/pkgs/default.nix index 2e0c11e..80d0fad 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -2,5 +2,6 @@ { ark = pkgs.callPackage ./ark.nix { }; + runic = pkgs.callPackage ./runic.nix {}; sc4pac = pkgs.callPackage ./sc4pac.nix { }; } diff --git a/pkgs/runic.nix b/pkgs/runic.nix new file mode 100644 index 0000000..b91b550 --- /dev/null +++ b/pkgs/runic.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: +with pkgs; +let + juliaWithRunic = + julia-bin.withPackages.override { setDefaultDepot = false; } [ "Runic" ]; + depotWithRunic = runCommand "getRunicDepot" { } '' + ${juliaWithRunic}/bin/julia -e 'println(first(DEPOT_PATH))' | tee $out + ''; +in writeShellScriptBin "runic" '' + export JULIA_DEPOT_PATH=$(< ${depotWithRunic}) + exec ${juliaWithRunic}/bin/julia --startup-file=no -e 'using Runic; exit(Runic.main(ARGS))' -- "$@" +'' From 55ea13d49b7943be338bb36739b6f7cd810fea7f Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Sat, 20 Dec 2025 22:56:02 -0600 Subject: [PATCH 72/75] pkgs (common): Add JuliaFormatter.jl cli --- homes/common.nix | 1 + pkgs/default.nix | 10 +++++----- pkgs/jlfmt.nix | 12 ++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 pkgs/jlfmt.nix diff --git a/homes/common.nix b/homes/common.nix index 50a33e0..a7566a9 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -34,6 +34,7 @@ pipx python3 zulu17 + custom-pkgs.jlfmt custom-pkgs.runic ]; sessionVariables = { diff --git a/pkgs/default.nix b/pkgs/default.nix index 80d0fad..8178242 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,7 +1,7 @@ { pkgs, ... }: - -{ - ark = pkgs.callPackage ./ark.nix { }; - runic = pkgs.callPackage ./runic.nix {}; - sc4pac = pkgs.callPackage ./sc4pac.nix { }; +with pkgs; { + ark = callPackage ./ark.nix { }; + jlfmt = callPackage ./jlfmt.nix { }; + runic = callPackage ./runic.nix { }; + sc4pac = callPackage ./sc4pac.nix { }; } diff --git a/pkgs/jlfmt.nix b/pkgs/jlfmt.nix new file mode 100644 index 0000000..21916a4 --- /dev/null +++ b/pkgs/jlfmt.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: +with pkgs; +let + juliaWithPkgs = julia-bin.withPackages.override { setDefaultDepot = false; } + [ "JuliaFormatter" ]; + depotWithPkgs = runCommand "getDepot" { } '' + ${juliaWithPkgs}/bin/julia -e 'println(first(DEPOT_PATH))' | tee $out + ''; +in writeShellScriptBin "jlfmt" '' + export JULIA_DEPOT_PATH=$(< ${depotWithPkgs}) + exec ${juliaWithPkgs}/bin/julia --startup-file=no -e 'using JuliaFormatter; print(format_text(String(read(stdin))));' -- "$@" +'' From e823b4804cba31a0b4ac9c6adb67f8688933121b Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:56:07 -0600 Subject: [PATCH 73/75] shell: Remove JuliaFormatter project --- homes/common.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/homes/common.nix b/homes/common.nix index a7566a9..78d70a0 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -70,11 +70,6 @@ micromamba = "mamba"; }; sessionPath = [ "$HOME/.local/bin" ]; - activation = { - installJuliaFormatter = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - run ${pkgs.julia-bin}/bin/julia --project=@JuliaFormatter --startup-file=no -e 'using Pkg; Pkg.add(name="JuliaFormatter", version="2.1.6")' - ''; - }; }; programs = { home-manager.enable = true; From bdedf7a69e0f511c5ba912e152a8947b4e983c69 Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:56:23 -0600 Subject: [PATCH 74/75] config (zed): Switch Julia syntax formatting to cli --- programs/zed.nix | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/programs/zed.nix b/programs/zed.nix index dfbbef0..6985d69 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -43,19 +43,7 @@ } ]; languages = { - Julia = { - formatter = { - external = { - command = "julia"; - arguments = [ - "--project=@JuliaFormatter" - "--startup-file=no" - "-e" - "using JuliaFormatter; print(format_text(String(read(stdin))));" - ]; - }; - }; - }; + Julia = { formatter = { external = { command = "jlfmt"; }; }; }; LaTeX = { formatter = { external = { From 74e2bde66f9727d4e4374af2d32f98d27b93ca1c Mon Sep 17 00:00:00 2001 From: "Thomas A. Christensen II" <25492070+MillironX@users.noreply.github.com> Date: Fri, 2 Jan 2026 14:49:20 -0600 Subject: [PATCH 75/75] secrets: Rekey for new odyssey ssh key --- secrets.nix | 2 +- secrets/ansible-vault-password.age | Bin 685 -> 685 bytes secrets/authentik.toml.age | Bin 1222 -> 1222 bytes secrets/borgmatic-passphrase.age | Bin 891 -> 891 bytes secrets/borgmatic-ssh-config.age | 29 ++++++++++++++-------------- secrets/darwin-policies-json.age | Bin 1214 -> 1214 bytes secrets/freshrss.toml.age | Bin 1185 -> 1185 bytes secrets/network-information.age | 30 ++++++++++++++--------------- 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/secrets.nix b/secrets.nix index 45783ee..ed1352e 100644 --- a/secrets.nix +++ b/secrets.nix @@ -15,7 +15,7 @@ let mcentire-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOdC6eNx2nBi3PWK/n4GJMbVf+NlQJv13aUqxse/h1kL millironx@mcentire"; odyssey-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKM5Q2zl3b91j+foqcVeQT+wb5DFEp+MbgotTTaKqZZi millironx@odyssey"; system-administrators = [ anderson-millironx bosephus-millironx diff --git a/secrets/ansible-vault-password.age b/secrets/ansible-vault-password.age index c5b657899971cdff5c4f51077d04eee9528417c7..6c1379f07a11ae876f03ba95fae500711d156c79 100644 GIT binary patch literal 685 zcmZ9_JCBoa008h!BVWLk!NG)7pp=6yCf5Sx(H^fBN}~hthw_G_yq!&4FFLw7I664# z=Hls~$;}#L;&{3723MW?`vO0E?~T07E&HMh^XySx?$HK^MvvjcAsBgJOp^E%4ih37 zR9Mf?*P0ywwA&aSS}>_95Yd|4V#&Ib+n}cdw;E%98zvKIQ(J{3V^@h^isu08*b|GVm8TP{a~NY)+ZTTMJ^e z%6BYvCk89QkMN$~7i*wzaB{$wfJDb_f}O6FGt4|`k2g+J8{rhTCxcZL7H2Hb}pXtx(s?mZIn#KgTP*Do@29Ah{fKn z%V`K%lg4P48FN}|Lnz88Gd-JP*-o2pVzNmKK~q-cOHIK-dytLx2NU3yWhY3xF|pV E0|CkGTL1t6 literal 685 zcmZY5JFk;q0LF0#Czi81Xe3T5sRc?~a4>1}(leD5`F<&a$dAa=IFw1@WdJEx1l~QD6}gmSh?2ZMj@e2wt19P}5{h%#^}o z*Bb~H5@kMH!&%Sa!yy;b(h!qHjTMG|_xRl9Zm{DlqM#ak13tsGA!S zg0GfjwRgwau*RA;iZiQG`0(P_Bz zcf52Fqlu(eqJ01 zGdL}Eq}S`AY_vayfxLCK!Ydj8j48&=EvXWOd7sL-PDF*62Pz=FS(=@9WRL HhJU+%Y*pp< diff --git a/secrets/authentik.toml.age b/secrets/authentik.toml.age index 1ef8f6e277acf7a7b989bfa87f553f5f1d1d0ac8..d3c91cca5c23bc224a0f53a2dfff20c254edd975 100644 GIT binary patch literal 1222 zcmZ9_`)?Bk003ZufLj-aFtZ4Qt|A0NDZOiZj{;fj7650`Gtz&}|X(&U`Iuk$ee|hY3;=Q&vO5yQ_(yKV9+^!#T*o zVVH#5S;7#2w8CPhOgtWts|Lx(SNV0q0b)1+CqV-XCJG|k<@e|cEf*zJ!L;JU4b0f9 zx^Bs$Vn)N>45SV3bw43ke+)7Zp~?+OXHZb5mslqzx+Z@wMH(+N=Qic%pi7AgAG z5aCNpXw>5+bfYRnJtlW9oC0vL%$95ZDCXiRD&RtBAsZmwbT(cIVPTpj(=KO+KRR)9 zDjlVA#v%a#UhNk2@allmAF+C}-E^WIj)C5C5@lF06qhvyauWG4<}uN=!0J_U0ryC} zjH!IYkdPQziPS`w41#nd$T-Q2*j~mu z>2TMA)(Qz#GmMEK*c8|mq~nZixWh8huG(cv(%>2pP~otWkMSAO4r4|N zb4}c=K7fs7ENCKMDR6L=u|*led*w#)SI<0A z+Z@itmNaR{7QS-vwfT>mW^X(7^8KS%v3bKa-|;i4 z;jvh~_}fe;DE1uupoBWKK?do+1OIA*A{P4}A(=Wa8#hnM2 z4>#9MZ@NEFzrz9i!ml-(&OP4}q&joJD^o7r zTs~RyuTj=1%gM1j4W}m65#|%hq@!)NLo)Vic3xAm4hwz2nT4OP-dx_d=80FG_1(6X z`M2kewf?<-ytS_LwzZm{ab?$LEc9u*d2#C~&H4VhUYGCrruf2OGym4kv->uWTs(J; z$^JQZa>bS(<_xuczu>^ylkd{UrXh`E{hpiqxb-&{9$CNZ>#Jw3n9CRUPKh*>=a`S| HJ$dkdKC95P literal 1222 zcmZY4>u(bU003~zNPtQJGXe}9)UhD$GJ0+AXm33Gyz66qTzh>DNUpu>_1f!o?e*?@ zhs%KBruZPTY>o(sKsF;j!ec-NI6t5P1p=6W43LPB03w6ML;_|Qzs|qlmmkT{jWnMs zDXnF;z%MP77@efoG_KMLLZ*?X3^1%mv@B=j)S%X+Qyo~v>MND-v>Hu#Q;5L?O5w7> z73Z2=B3@*&32z`mazs!=mLzXBg^CK1T}Gt6Qa<7aqXB`;M4eE~nr|g5E{POv8AqXc zqNZnb6IRS6bL!?<_j?{&PLLmh3V$^LSEl{#Z|95L_)KcC8=6A}x!71b6m_KZhz`T=l z`Qf0sxsXqZVW&C7ILa)Xb!a;7-?tA{bz_~-o`vtdFb~hEIkJEITMc`r9~@+xc0L+= zspZeZdBeyi&6$JacV0e(u0Co~77wm&Upr;20a;zc&YC=@2637veS$6+?5Yba;x9Zs zwe8n|@Y3q4f}FWd^%It?XYTFKuJ`L3>VeJ=HtxE5ZPn&(_(jck;PLt}d2Y0K^SuxE z%(~IHb?>4lwGSV>{xs43)2j1b>XOj|-We^`$IgB<^6bWgTlzkcJU!(?!u8G%l|QI? zEv}~9na9%1sprZYzQ1zMzVnN5vcB`EZsE`ncXeIgordSzB0G1lNRiIRTX#P^eAx7U zsrOx>|D=UFxsSWKa`+H@v8C>ERMiTaSC0SU9-qAUY3Yy|J$w2MY1{g{Z|>@rR=jp9 zf4cY9`oYi7cMeRFo}C>2XZx33;fwye$CmUVJ=-^=91bXXbabG4?nAk1?QhDJX&p!O zYij*Vt<$?+eRk>je0oP{9`n_SGvM3KsR!qsBS(g>W#sgwj>#K79$aqtbj|E7?FZi3 zdpYJ?vGMWp9^?Ftwfl}WAk{NRcGUfR;?Xzq!j{^WzXu+)&7L7{s&Bf#u3c%X3r_R& zT->rAnxoJ4OdT2@oqID$2ET1<;<0{pezZ4S9vcaUYq=`Jg0_|I9bY@IpZR@klKsh# J`)~X;@-Hw|+A;tD diff --git a/secrets/borgmatic-passphrase.age b/secrets/borgmatic-passphrase.age index ba13eb39250c07f4450f6815c5c08ecb87d3ddba..c3969d2a005182a25adf2b4d779cb3b58e148be1 100644 GIT binary patch literal 891 zcmZ9}&CA;a0LO6!K?n+7=I|f{4?CFEG)dd!89GSXrb*f~?@1e#(KIj3dy}?#6EEBF z>_9v?5k%Q!h!5!DL6pgy;6xb;G9Twba2|#Sck&>3aOeI5zt0c83(sje$uh6kTR%-+ zNOKP^5TJDy+-z1Y$40wd8C>!W zcpVEfZwNHjL|e>-A)MNrzav#vZWjqvh#VOZo>=M;K18$C!`;<x#XFeeUDl5lJ8AE(Orb)9v z4YL?1oP-IcZiM@qZH*nK1QEU1>RMiTs#2@n%&zMLZdn(s>Dtkn%F##}jPM2LEe#3a zl#!D=Zqld7RIz%Kp*oq;P%If0X6R}+E(Z9(ZVGzcZ1y!Q6Sq4L99gMC@m4z@$9>Lp zh-5)DZ4*@$fpJ4IoEe@RMQSH&!W7sZ$X%<=1TH_F)n&uPi)KI>S>g5unqSk7ScX;3 zrbhbk*@>8QpJwKL5*Ut$yS9lS@bNm-XpuJMp-6?ut4(xN#x5`+jlsrt>Xw=l0dN>^sm8 zpZ|XS?(FHam*Howl{a3d?l&K`E&)g1)z97g;+r$QudY9F5&q-w!RsHq`qE>!Ui&l6djN?Q{1Y`R`Zpvqv@V<3F!nIDG0DxuS;u Gw*Lpx-aY96 literal 891 zcmZY6&&%6%0LO6$gF!*WgD5H(+3BIw{A$vKxo5OZ)1>LIG)cd0Rj_HAZ+$HIcx@FyG{sAmT_ldJ%F-Yx3TF}9BfUaKHofW0!zMFo+Z}cjVLj;TM%^5wKtwri zsmzm3+mzLoJr1U&iO2YDC2atQf*sJsT#e=YEkBo4uA?{W%rp-Iw6+>#aduS0A-c^n zgjZb1FJiadFVbE(as4eZWyTgYb?T@RxelHam}_f31F+I)G#QuOM!UHYb-9{=FiNeF z#h0gcSIlu^h6@nTb?e0mK3F+cT%cvkbUKF;RrHrz7R5QH-;&b>Tu=D5%+ zMYR}ISFj2#s1I#`3#`-HNM(*EsAY3$thup0UV}D$_|X5fCI&_jS;LK#ND774jEHL# z10xqyk)#)O%M@wHiA|mqU~4Rsd{*j=Ib~{wMgvS0QpfqtVPXv@V>Zxc%ocaDjEuvG zP{r!uwn_yFHlvnC8QMg2>;_|{*Pljznp)!edpL$ z)ZU9f@BVu2!I^(Pesq2RyKfJ6pS((Z_VktKzI?f}bG+nY(dWi*f6?NFA6^%@(_dhp KoUL9s@zj6RnmmXA diff --git a/secrets/borgmatic-ssh-config.age b/secrets/borgmatic-ssh-config.age index ba01275..63dd59f 100644 --- a/secrets/borgmatic-ssh-config.age +++ b/secrets/borgmatic-ssh-config.age @@ -1,15 +1,16 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ 9QYGvIhYSyGcFmNdjK6qo2PnX+/t4LnU7eO3+TilFk8 -/6TLFd43tAdI5JKOPVk5YgBLzqdoc++CHtpYqBVMus8 --> ssh-ed25519 1g/xww RV80BUKnJCyP2CsExGXqnEmXk1XAPkSyVEN+hByUcDo -IpbyT1t33/DCt8iP3Jy64FC88SqQTeTLB1bur3g5qzk --> ssh-ed25519 dbKeHw CjnqCn7n/6pLpSaF7Q1u2vFBoLOswOaYSoQYwEu0yik -CSykNB4CmGuLWURDJWSAhtAhLcJ4iaeaYNKVsG9w/S4 --> ssh-ed25519 3qPtug yNNOpEPutJhoRfkXQVnyUJ28Rtyh0oSClXLBVT77mWQ -Yr5TcwBZZbskLUmudPYnyIFvtcxbe+xKnde/5fAW4Dg --> ssh-ed25519 +kBihw wf+3MXdvYBGBXUci/SiBfL+VPbVkuM1kl9jOHOxr9x8 -3Cgmhh7uI/Hrv3474FrkqspOx0kooNZcG5untJguvYI --> ssh-ed25519 +C0WRg XJILB7Fa+o5NQPy+sQTt5z5S/WcxzEKTqR4dadFnphU -sdrs/Yf2lf14Dy22hFpzaTgCwvaDaWaXWMlERS58izk ---- 8zj6q3V/OQPbTiHOfin0sXT9gbVNYMCRSWoXMKxYFDo -PVzRbc1Q1T:rU kbXTk䑡ɧ釣ךUG XRl~ҷ8B:.:z?ɐıxED OמQ} `uPI3p|W!3U{mG2F7T)2 \ No newline at end of file +-> ssh-ed25519 il3lzQ 6815+wa1JjdVUu8U8vaRah8kVsjR3Fsot99HKWl4SSA +hPYVZuN1yTKQYFIQvIRdmr400aijXleA22Bxh1nXKdc +-> ssh-ed25519 1g/xww BPxSszlrjPTVJC+YOvo1N6ICUUdL7WKZX3DeambLjBY +JkJQFPGtxDtqeGj8Z1YtVq/pm6hgYKwzMW9MbtkvOwY +-> ssh-ed25519 dbKeHw PU5cZrKCkAvUjI/opkboDQKSWJ8osAOQiI62f9lbfRY +ef1z6ZcBASkhC4fdcN+RRE7q28rB/DN8CVdoNVkC81I +-> ssh-ed25519 3qPtug RWCMZiLQlS+bOOIBRGmoECOfqEI2uoaWCq/4ZuI86B4 +VOaLaH1VYnGoQzjb8seU6wVviB94W3qCdYW9Wf4PGIc +-> ssh-ed25519 FRQvIA LCDwNMNVtTcI3GHPR2mcgtR16yAYYwLplI2nKUwNxDQ +vwXBIDlK7FBOsKt48Zv8mp0WFA/TKH2UJxtUxZoxzMI +-> ssh-ed25519 +C0WRg a/R13LfNMjVjJxt2TtTHaqZOhsYJLY+HUGMHEDnkZWo +T2EfeE/a4W4bFvauynfh+4aJL1jhCpO8iBG2aTmKtyM +--- o7tyupfhbxh3dwSrBLsYX0V61va0USlqxheNsdBjVuQ +A q,:_aɪ)j12 #t,G* +XT(U5t6B皩80 *i׆^ߨ@aB@̃+oFwPci27YSXd g̲J \ No newline at end of file diff --git a/secrets/darwin-policies-json.age b/secrets/darwin-policies-json.age index 77d73854bd711eab398e705e736311d2fd8e19b0..3f900dd98f12f2c4188a731b966770860ab1de37 100644 GIT binary patch literal 1214 zcmZY2>vPit003}M*|>7Y*a12Ou^hw4mC{GrB|(Kt`hKRbHR%AQP0}Q7(l%|9rbWDC zdMb(&PbzODM(yC zwRvhP6dA>GTxixPx*KR>dzyEKvXn^NgA@KF&y3$pj6p4z zwGyHh#=s&bKPQjIicy<7x0SW%H+n~h`{(I|luX$EjS#HY(pz>-4C zXjd0K@hu39weg43^WJudD*FWBdk) zAxUPma3l~{Q@lhAW*0@~?3jwD1V_Lt1#AlC&qb-ABcDmoHl9dm3~W|MD|sUZ6H<$W zyAv&D)SQTs1;kfWti^N=6jBC^z;n6m_{|v!D;`8!Qoy_}T?FikF#~`ymX&1)KxG-k zMRV0=m*prCCK7p;XF28<6k!KH#`; zQaU(s$iMS$*X*DF2@jv1c;~*Ot!r-#4sKn)5}Nv)vV6uLPiq?nq1ui<@6~e$9y6SI z+4Rw;?*MbhUaxZ>>*qeMnX_#1rQL<@OMCF?SLTs3cHiE=Y^-BN?dI7v;TO>_Gq+5C zPMD4zfgEQKtZRgh`-Wee)_ISa3B3A-*xFl}d2t?c=Vl$Wrsw3o%X6q56Amo@aAfDG zcm8B%Nqzgu*=^I?J+;@5)J#jSAVEbQe@Sp(~sQUl1kU~ ze}IJQ8asCNO@0V%-4GqVXI{T8J-}TVIo#8E+!;LRG&UTad+UAez|BGU5Ze1Wv$}EM zOkeWMrgQLv-+f(i)IUFKQrCNXU)XL zSq+Ql)t6pc9RB;f1K-MbZ87brOx{!9JAC-ms_s`tEgQQHsY5dyOSfmHxO;r`!nay) zhfegu7m2||k3Y5d$#3>mrv4D>+-{$=;PD{%x-e97=Yp>VdwQH}}$8CVF*T>!Zy7qc~ zF)3u@p+XoDidVI*MOku@}Xpoo=MLD{S;Q7Sa?d60>DOp?Ub zb8d!|<6cQeH8kTELPv>CqY0p`D(xb*EDPF57&aQAS~V2Y6$=G*JQOAhfb1wHc(wp? zc^`pU5w|bNL1i`)M!+D$CS6Dx7o9d#MKXbmAmZUXCy^LWE4ahQBN9&r6v`(M{%o@g z5tv+1K^qJk?@S5k84=8ox}>8ligwl*G6^{7#F9d&$rP6ZhEj&I=qWBq7a6;%wrq6P zyCjT9Q;{g-$vX&#J9SxrErPbNQWe1z-(XLB@ih3a{m|F^D2aquyPlMSCt|qXiozn(`5U z0P_1nX)7bUX)I*nRa&i9Es&l71&c()MTXN1Vl^64icA#ZGKJRDL78zhVQ7?sgQ-$l zHTS9UGq*IJ?ntw8`|W|RViVIV7H+z&8TU)&%Jt4~KHTxdq)Yg#cls_L=~*&7|ID5h z^Jh~|#4(_44kKZrJBdq;IG?&$A&aBJtK-`qP^e+F{fbaz`X zRvqiza`w4r`VX{HjvGf@k?V5@_kFRQs(X6IamTXCHqDQ_5j3lQTMKlVpWU#0T9;ND zkvezyK_$81^zaMso$9F`tWqDMC$(T7Uzl98eEghE-ACsn_FrUsf^$b5`aQNADSy9e zU}>@LY_I#tfe(P{pAQ92R~8K?GegI#=bc~DX4S7Tuj@QmGY8kaw8Q)S$*G}ke4M-; z9@{TnbHTg3+C^8VPjv!=XF2ztp`|sCoyt7Abo1Jc%2sA`BY8}7cuJf4)0ZpvM_ayy zX0@GqF>t>3;e?vq>-WN6bHGXwtb2H7Yv+3q^er9tM;;jW)1&uW6wgWO4*A+WVt(Jde6*#plUHRg z-WrK~nO~oBg?D1>+O-?q8{eG0;_f~vz1Xs82DmTAUE6QatX=_6(qx1f_G1_=$k9XkLmVW_Z)y3KX diff --git a/secrets/freshrss.toml.age b/secrets/freshrss.toml.age index e253b881a3ab7741cedfcd65baaf390014ecedea..096f601ffcbf9a110d7d380b888a0096598e795e 100644 GIT binary patch literal 1185 zcmZ9_>u(bU003|asN0D%K|yq2D#8@I?H;}Bwc%x7*K2!yUAy*LWZ1j*`ndMm-d*q7 zBeG!#3=kX)km(0QoERPvOw=IiWCUV@I2dS@!3R+s2@r%3o{8Z1{r-VpDx2xZh@8}@ zDEYG3S(dV(3IiQW4YHi;$fOYrgRO>q(NxsKhDgZjS5YocmW#Q7SJTO`Es2Ij6tBj8 zMMZ;g2}KhGO8FudfI?Dk&KOB6pq;^zNDvenX3cMj;bwugIY^_Cwz+H$EGSBr$s3#n z>zZcBHS`z}ClcqK5TblJ{NX@`|!7j>?O~`7r9Ik*SGExYZYN@Ko zk}fTaIf5X}BQon z-i!_?PG=2@NL32HOswF|d+qfE>`S?5)|!)?M#)=Ac-@5Gj+>)JCT#NqafhB}E3UGa zt;GXTMNWWh%@GYj8P#N!os^67J0iGO)~rrH(9zLhC=zrin!O*7 zkPIZeQiE$wY_l%xq1(x>U;iDqUv)RV4!&`xb?wo*wDq+E|NU}k zZ*_Q0N_e#R%x(L?p|J-~p8EdL+vkMS%cVKXof@Z+hLfqt>? z&&V}1aoYj_)ZMird-C2)beZS=!kZJN?>bjBP5fNG7S7C>-8Oyp(1B60@9ygTEx+B^ zHMsTo1%1os7uS6;PMO=CqZeCUEjPydpS^BvU)owv-1=t4p2FDB_9It5cu(bU003}| z6jv520$7K2hL`o#YR15Gh{*)o^x3>IuhDwi>_I_~HyU>drT|R}!8C5fsDN1RWY9>& z6}9{A8e|sPfGX&GBB4pN6E{+5x*~dvsan(lK|vla6e*BYf=(~)_GEG%9tuy_U;$KQ zSs#x|-YOcmleJKlh8VLPgpIt-nx;tH&j6fcV-O^quQ34!t>Xo)lEm?pT}c!yEFtC~ zzY_)#EbP-#6p=+jw22Wlz$AIvrfXcv$Gc^HI^@a36@SHfaWBi9L!=lgvywUSVf4DK(YubooO^`!D|`5lH)z{bj?_% zq?(|Qfo0rOK|=*QO-7k|-2(Bn3IZ_#w^kD+OHeI>*#cI!rClDKz{YJcObLsS>LG`nZ0Vj zB3r6dED~^+IZi4vsLml43V@r_2uqfC=vxTveRz> z21SE{UIgg~n}j(U7OLi)S@k&t9_1M}i?I%yxq!P;sWJzL0ue~ou?3ICt}+2W4WuyC z;;YLjz{tFrtI|lWyjoFlx z0HQLjEMN`Xzp_6ZyKIar4KDOzq`EY1PZmh!5p8t# zrtXCk+eb^?mlold)#2~fd~dwfJ3eK-)3}}_A$npA;R^ zanw3-e9Osj10Dct2Sph(M82J#(K}qyM1hL*M*ql z+*0?cx$2s(uE}}b9pTf-#?CvJRt`b8{^-TKp|vA_&zOXFExGda@{y0m`^Y1``wu ssh-ed25519 il3lzQ YxgllrvBeqfXMCWKq2JF9aqyoq5CUTHXW5Y/DhxEDzE -55NxukxXnmQ27WqW/yjkvTLd/3QmcO8uxCxsGu95rHM --> ssh-ed25519 1g/xww yIGdDpxlTv5I1LyueRLGY4LxpKHIYDVEN/fkcMlNvD4 -0vvuzTeqH59Kw+JFzmITJI8bgEevwJdPtqknuTx0QAU --> ssh-ed25519 dbKeHw ZZEDohW79lqKjT4TTQSGvjav+n6mESo1RALb+Xbbcw8 -gwj6rEy0G95IYBAgB1F8W5wXhRP1n+1SUTIp6/XWCHU --> ssh-ed25519 3qPtug 9kX4TyecOvRgb+KCk3FAC3QbhhxU55VRiQGNOytGFSM -LpBauBXhI4vfBHEfw/d1l4ao7qkEe/Daaow4CyDtpJM --> ssh-ed25519 +kBihw Qiyi1AaxGLyXdsNFu+TcNQ/xxOLEkYUbTIWYClVw+Qg -ocPR0AsEh3OPRWa1kWTlXcoit/yv/iywHfcgJZh/iFA --> ssh-ed25519 jb0ALQ 7OFB68omi4iWdrKdywc+f6f69mGThijWPTktuAbA2ws -XzZnyv3qsGFM/25KapNdM4n/poisk2sTzgy1ECqWODk ---- RCAULQI2W/aA4Smb0LaA0xrT1GiH+bOGrMRLVY8O41E -Y~2mEA)L+ b oX5Cѕ^Hvq]N $n)X¬xlVgT)%M6aT2YM5Y ~ -HpS n&x(̞i? -K C̔KpMbCq*v ಽMl$ \ No newline at end of file +-> ssh-ed25519 il3lzQ nMWnoZD14ATpcKx1ahDxWQTvgs/58FsiAyVMkCP4kGM +N2VoaUiAxAmwY0gHSveE+LnsgYpUdXnwoT4xtLbe8LM +-> ssh-ed25519 1g/xww ZxXXcLbTTeGemgBkk8gDT2137C041/vpfEtVnW8c+EU +CmXD00jt0xQ9bEOXSZIJ8HjnDKPujJ8/JnRVIxYfEw8 +-> ssh-ed25519 dbKeHw V0Z06Hl6E0J2y/D5U/3m4pIOa7w1Ja9w/R5joR7xRS4 +jSxNxMhgeho8OFyOhe3Ha3pa8BohO9gF1o5y/Ho1grI +-> ssh-ed25519 3qPtug PWzembnWLaMz2gq2rzbmRXW8HHuiJMHgfoXlkLy5M1o +8zSuzvJwdDP2K+PBkH85/0Y9LACIhbxAxE9UBUdbT+8 +-> ssh-ed25519 FRQvIA 2CVWLyG/XvphNqABxcO/K2KLZmvFydPaXG3xP7PytXI +3Uozzj/e/ANvuL2WYjpATf3Oh5kQPAwUrAGanACLSOY +-> ssh-ed25519 jb0ALQ DK8euAthdXCXDiIA8+dWOWyx17CFUh1SlwrXT2me718 +5ucvnjUSC8aKGI+vfUPbBD2CATTQq155mGRpRz0aD7s +--- 1qYd6bwSytOqJLrWin7RSjqindVSb+zoT1tKK3s3k98 +%Îv-/P<Wy,SD6HWkk/c]!EqEl)h8fuV9xf[ʴ)ͻ|{Vkb=ԍ`f],kx%Qsu5i獚FU–x^Nn \ No newline at end of file