My nix-darwin and NixOS config
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: auto-connect Tailscale and pre-seed Nextcloud on desktop hosts

- Add encrypted tailscale-auth-key secret (laptop + user keys only)
- Wire services.tailscale.authKeyFile and openFirewall on all desktop hosts
- Add XDG autostart entry to launch nextcloud-client --background on login
- Pre-seed nextcloud.cfg with server URL and username on first activation
- Note 90-day key expiry (re-auth required 2026-05-29)

+87 -1
+3
.gitignore
··· 28 28 !/secrets/nextcloud-smtp-pass 29 29 !/secrets/forgejo-user-token 30 30 31 + # 2.1 will need to re-auth on 29 May, 2026 as per Tailscale maximum 90-day window. 32 + !/secrets/tailscale-auth-key 33 + 31 34 # 3. Explicitly block sensitive patterns everywhere just in case 32 35 *.txt 33 36 *.key
+9
.sops.yaml
··· 33 33 - *ewan 34 34 - *server 35 35 36 + # ── Desktop-only secrets ───────────────────────────────────────────────────── 37 + # tailscale-auth-key: used by the NixOS tailscale module on the laptop to 38 + # automatically authenticate on first boot without a manual `tailscale up`. 39 + - path_regex: secrets/tailscale-auth-key$ 40 + key_groups: 41 + - age: 42 + - *ewan 43 + - *laptop 44 + 36 45 # ── Fallback: any other file under secrets/ ───────────────────────────────── 37 46 - path_regex: secrets/.* 38 47 key_groups:
+38
home/default.nix
··· 297 297 '' 298 298 ); 299 299 300 + # ── Nextcloud client autostart (Linux desktop) ───────────────────────────── 301 + # Writes an XDG autostart entry so nextcloud-client launches in the background 302 + # on every login. On macOS the client is installed as a cask and manages its 303 + # own login item, so this is Linux-only. 304 + xdg.configFile."autostart/Nextcloud.desktop" = lib.mkIf (cfg.isDesktop && !isDarwin) { 305 + text = '' 306 + [Desktop Entry] 307 + Categories=Network 308 + Comment=Nextcloud desktop sync client 309 + Exec=nextcloud --background 310 + GenericName=File Synchronizer 311 + Icon=Nextcloud 312 + Name=Nextcloud 313 + StartupNotify=false 314 + Type=Application 315 + X-GNOME-Autostart-enabled=true 316 + X-KDE-autostart-after=panel 317 + ''; 318 + }; 319 + 320 + # ── Nextcloud server pre-seed ───────────────────────────────────────────── 321 + # If no Nextcloud account has been configured yet (nextcloud.cfg missing or 322 + # has no [Accounts] section), write a minimal config seeding the server URL 323 + # and username. The client will open its OAuth flow to finish authentication 324 + # on first launch — credentials are stored in KWallet, never in this file. 325 + home.activation.nextcloudPreSeed = lib.mkIf (cfg.isDesktop && !isDarwin) ( 326 + lib.hm.dag.entryAfter [ "writeBoundary" ] '' 327 + nc_cfg="$HOME/.config/Nextcloud/nextcloud.cfg" 328 + if [ ! -f "$nc_cfg" ] || ! grep -q "^\[Accounts\]" "$nc_cfg"; then 329 + $DRY_RUN_CMD mkdir -p "$(dirname "$nc_cfg")" 330 + echo "nextcloud: pre-seeding server URL in nextcloud.cfg" 331 + if [ -z "$DRY_RUN_CMD" ]; then 332 + printf '[Accounts]\n0\\authType=webflow\n0\\davUser=${cfg.user.username}\n0\\serverUrl=https://${cfg.nextcloud.hostname}\n0\\url=https://${cfg.nextcloud.hostname}\ncount=1\n\n[General]\n' > "$nc_cfg" 333 + fi 334 + fi 335 + '' 336 + ); 337 + 300 338 # Allow syncing files of any size (client default blocks files over ~500 MB). 301 339 home.activation.nextcloudMaxSize = lib.mkIf cfg.isDesktop ( 302 340 lib.hm.dag.entryAfter [ "writeBoundary" ] ''
+19 -1
modules/services.nix
··· 36 36 37 37 services.dbus.enable = true; 38 38 services.udisks2.enable = true; 39 - services.tailscale.enable = true; 39 + 40 + # ── Tailscale ────────────────────────────────────────────────────────────── 41 + # authKeyFile causes a one-shot systemd service (tailscale-autoconnect) to run 42 + # `tailscale up --auth-key <key>` on boot if the node is not already authed. 43 + # Generate a reusable (or ephemeral) key at https://login.tailscale.com/admin/settings/keys 44 + # then encrypt it: echo -n "tskey-auth-..." > secrets/tailscale-auth-key 45 + # sops --encrypt --in-place secrets/tailscale-auth-key 46 + sops.secrets."tailscale-auth-key" = { 47 + sopsFile = ../secrets/tailscale-auth-key; 48 + format = "binary"; 49 + }; 50 + 51 + services.tailscale = { 52 + enable = true; 53 + # Open the Tailscale UDP port so direct (non-relay) connections work. 54 + openFirewall = true; 55 + # Auto-authenticate on first boot using the pre-provisioned auth key. 56 + authKeyFile = config.sops.secrets."tailscale-auth-key".path; 57 + }; 40 58 }
+18
secrets/tailscale-auth-key
··· 1 + { 2 + "data": "ENC[AES256_GCM,data:mQEjFQv+Zv7LRcPMda5xD5hyLihHU4fsEaIDdkMWjHaATQa9ETVuquwbAmU0UUMlEv7AFUeHEQ51Ua4SZg==,iv:p753tcDz2AdfWtzFSPn87Hk+FcZDm6EPOyTOVAScMdM=,tag:emJqoXMLsCCCa894GJDW7g==,type:str]", 3 + "sops": { 4 + "age": [ 5 + { 6 + "recipient": "age17ulnk7akn9zfwtc87vsexrr809xj6gkkcp2rkez6xtzyrqclpshqfew5wy", 7 + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSRlZMZDh4RGliTEZFYWty\nT2dLR21JNDBSbmo0T0ZkTWxqSHlDR0hMWjJnCk9NcnpJaVFWeUpOZ1N6Ujh5V2lx\nWCtNTHlIRWpKR3VCYUppcVc5L3VWZk0KLS0tIG9hdFhVa05wdUpFVkF2V2VKdFRV\nZEpGL3d0dG9nWmxhN2xnNU44QlhIb0UK/a12bw+eUc2EMagQCrm8QvSEPzXApkV7\nxOW710X9pegIHsNf69oWrioCffG+IcIvclhhbTPwJA8EiOOIXkDRhA==\n-----END AGE ENCRYPTED FILE-----\n" 8 + }, 9 + { 10 + "recipient": "age1s4exn5venvd2rkrvw9g6g9rua05quut62m6le8k79st0dryhcy3qq4n55k", 11 + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3cW11aElONmJiYnI4MDlo\nVENhbnl3NmJCSUpvc0JvclNvdkkyc3dsNFVnCmw4cUR2UXhCZ09Vc1NhRVpuVURw\nMjlpd3RWbXg5ZHI3cHNoc2RlUHdrNTQKLS0tIEpISklaekZsK3E4UldBb2QwVGJD\nSUpCSWMybVdkVmhoNHFvMWRrWWJRWUUKnqLgaAoisHJGxhEFLauJG4fTeruSG5F5\nSuysR8NQL35WFA7BiFtcelskGLIa6/E5Qr/JHxlzydpRv/LZxbFp3w==\n-----END AGE ENCRYPTED FILE-----\n" 12 + } 13 + ], 14 + "lastmodified": "2026-02-28T15:20:30Z", 15 + "mac": "ENC[AES256_GCM,data:47EeptU6uZTvDkPeTv0ENei/fzrGx5UXW9fuwqhog/qj9TrQnFoMUpuW6hRhfNi3HyPgUMvavRY7imVAVVRubsnT7vllDANtxSN/QJz2X8Iyrc5gk4X5+OX8Hx0jp/Yz8j5biYElEJB3/ZEKNPEam6TsUdhptxDH6sDZpiBKbXg=,iv:xAP8yt1DFYfNxcbjzBz1E95rJQIyrhDu5CbuHDMgeWw=,tag:qq69CWm1nbNZOmO12K+X/w==,type:str]", 16 + "version": "3.12.1" 17 + } 18 + }