my nix configs for my servers and desktop

add headscale and syncthing

Changed files
+533 -29
home
regent
hosts
buer
focalor
modules
headscale
syncthing
secrets
+25 -25
flake.lock
··· 8 8 "systems": "systems" 9 9 }, 10 10 "locked": { 11 - "lastModified": 1747575206, 12 - "narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=", 11 + "lastModified": 1750173260, 12 + "narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", 13 13 "owner": "ryantm", 14 14 "repo": "agenix", 15 - "rev": "4835b1dc898959d8547a871ef484930675cb47f1", 15 + "rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", 16 16 "type": "github" 17 17 }, 18 18 "original": { ··· 26 26 "nixpkgs": "nixpkgs_2" 27 27 }, 28 28 "locked": { 29 - "lastModified": 1750013871, 30 - "narHash": "sha256-UQx3rC3QDjD/sIen51+5Juk1rqN3y/sTeMY1WinmhqQ=", 29 + "lastModified": 1751021896, 30 + "narHash": "sha256-L9u68mNPPiuW7+OV5BKbXaj/AENTiiuEx8+QnMBjRlU=", 31 31 "owner": "catppuccin", 32 32 "repo": "nix", 33 - "rev": "fe78fa558d6603481c03eb03a946eadb970d1801", 33 + "rev": "a6b0e34d083c79f08efabb1fd6ccf12b882daae6", 34 34 "type": "github" 35 35 }, 36 36 "original": { ··· 158 158 ] 159 159 }, 160 160 "locked": { 161 - "lastModified": 1750127463, 162 - "narHash": "sha256-K2xFtlD3PcKAZriOE3LaBLYmVfGQu+rIF4Jr1RFYR0Q=", 161 + "lastModified": 1751384836, 162 + "narHash": "sha256-7xRbl/VLXxE5DzJmk1wdKWJmPx8rAfNC/a6mXtqp5cc=", 163 163 "owner": "nix-community", 164 164 "repo": "home-manager", 165 - "rev": "28eef8722d1af18ca13e687dbf485e1c653a0402", 165 + "rev": "479f8889675770881033878a1c114fbfc6de7a4d", 166 166 "type": "github" 167 167 }, 168 168 "original": { ··· 236 236 "spectrum": "spectrum" 237 237 }, 238 238 "locked": { 239 - "lastModified": 1750196518, 240 - "narHash": "sha256-HJYnJg3TvzFZjVgYHZgH3NtwqkqKiGVCJXpZlO4Y4EE=", 239 + "lastModified": 1750358184, 240 + "narHash": "sha256-17EYMeY5v8KRk9HW6Z4dExY8Wg4y/zM2eM2wbbx+vMs=", 241 241 "owner": "astro", 242 242 "repo": "microvm.nix", 243 - "rev": "094da86a3e68f2f0d93b654e97b5d42398ead67d", 243 + "rev": "fd9f5dba1ffee5ad6f29394b2a9e4c66c1ce77dc", 244 244 "type": "github" 245 245 }, 246 246 "original": { ··· 251 251 }, 252 252 "nixos-hardware": { 253 253 "locked": { 254 - "lastModified": 1750083401, 255 - "narHash": "sha256-ynqbgIYrg7P1fAKYqe8I/PMiLABBcNDYG9YaAP/d/C4=", 254 + "lastModified": 1751393906, 255 + "narHash": "sha256-I1x6K61ZcdFlqc07weRBy3erCAB0lVkX10i0c9eXjDI=", 256 256 "owner": "nixos", 257 257 "repo": "nixos-hardware", 258 - "rev": "61837d2a33ccc1582c5fabb7bf9130d39fee59ad", 258 + "rev": "f49bb3b4107a0917ee144337bb02d311033ee1ba", 259 259 "type": "github" 260 260 }, 261 261 "original": { ··· 299 299 }, 300 300 "nixpkgs_3": { 301 301 "locked": { 302 - "lastModified": 1750005367, 303 - "narHash": "sha256-h/aac1dGLhS3qpaD2aZt25NdKY7b+JT0ZIP2WuGsJMU=", 302 + "lastModified": 1751271578, 303 + "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", 304 304 "owner": "nixos", 305 305 "repo": "nixpkgs", 306 - "rev": "6c64dabd3aa85e0c02ef1cdcb6e1213de64baee3", 306 + "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", 307 307 "type": "github" 308 308 }, 309 309 "original": { 310 310 "owner": "nixos", 311 - "ref": "nixos-25.05", 311 + "ref": "nixos-unstable", 312 312 "repo": "nixpkgs", 313 313 "type": "github" 314 314 } ··· 422 422 "nixpkgs": "nixpkgs_4" 423 423 }, 424 424 "locked": { 425 - "lastModified": 1729422940, 426 - "narHash": "sha256-DlvJv33ml5UTKgu4b0HauOfFIoDx6QXtbqUF3vWeRCY=", 425 + "lastModified": 1750353031, 426 + "narHash": "sha256-Bx7DOPLhkr8Z60U9Qw4l0OidzHoqLDKQH5rDV5ef59A=", 427 427 "owner": "nix-community", 428 428 "repo": "nixos-vscode-server", 429 - "rev": "8b6db451de46ecf9b4ab3d01ef76e59957ff549f", 429 + "rev": "4ec4859b12129c0436b0a471ed1ea6dd8a317993", 430 430 "type": "github" 431 431 }, 432 432 "original": { ··· 443 443 ] 444 444 }, 445 445 "locked": { 446 - "lastModified": 1750091187, 447 - "narHash": "sha256-mjAol6qR+onnZwLUdYjmuBr/tnyozUBXz75tSePVU00=", 446 + "lastModified": 1751383329, 447 + "narHash": "sha256-52dUY8jEkuXEIZINYb+AVsrmw6FxMhBAG3K9J/2qiSo=", 448 448 "owner": "0xc000022070", 449 449 "repo": "zen-browser-flake", 450 - "rev": "cfdf98dac59a42e1642c533a5dbfb5bb242903b3", 450 + "rev": "f29a4fece3b76c3e4579d67e2cf0cb8037f6a351", 451 451 "type": "github" 452 452 }, 453 453 "original": {
+3 -1
flake.nix
··· 1 1 # flake.nix 2 2 { 3 3 inputs = { 4 - nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; 4 + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 5 5 nixos-hardware.url = "github:nixos/nixos-hardware/master"; 6 6 7 7 lix-module = { ··· 64 64 system = "x86_64-linux"; 65 65 }; 66 66 } 67 + 68 + { imports = builtins.attrValues nixosModules; } 67 69 ]; 68 70 }; 69 71
+1
home/regent/home.nix
··· 149 149 output = [ 150 150 "HDMI-A-1" 151 151 "DP-1" 152 + "DP-2" 152 153 ]; 153 154 modules-left = [ 154 155 "sway/workspaces"
-3
hosts/buer/default.nix
··· 79 79 virtualisation.docker = { 80 80 enable = true; 81 81 enableOnBoot = true; 82 - package = pkgs.docker.override { 83 - buildGoModule = pkgs.buildGo123Module; 84 - }; 85 82 }; 86 83 87 84 # =============================================================================
+6
hosts/focalor/default.nix
··· 29 29 ../../host-secrets.nix 30 30 ]; 31 31 32 + modules.syncthing = { 33 + enable = true; 34 + openDefaultPorts = true; 35 + disableDefaultFolder = true; 36 + }; 37 + 32 38 # ============================================================================= 33 39 # SYSTEM CONFIGURATION 34 40 # =============================================================================
+229
modules/headscale/default.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + let 5 + cfg = config.modules.headscale; 6 + in 7 + { 8 + options = { 9 + modules = { 10 + headscale = { 11 + enable = mkEnableOption "Deploy headscale"; 12 + 13 + oidcClientSecretPath = mkOption { 14 + type = types.str; 15 + default = "/etc/headscale/oidc_client_secret.key"; 16 + description = "Path to OIDC client secret file"; 17 + example = "config.age.secrets.headscale-oidc-key.path"; 18 + }; 19 + 20 + litestream = { 21 + enable = mkEnableOption "Enable litestream for headscale database backups"; 22 + 23 + replicas = mkOption { 24 + type = types.listOf (types.attrsOf types.anything); 25 + default = []; 26 + description = "List of litestream replica configurations"; 27 + example = [ 28 + { 29 + url = "s3://your-backup-bucket/headscale/db"; 30 + access-key-id = "$LITESTREAM_ACCESS_KEY_ID"; 31 + secret-access-key = "$LITESTREAM_SECRET_ACCESS_KEY"; 32 + region = "us-east-1"; 33 + } 34 + ]; 35 + }; 36 + 37 + backupPath = mkOption { 38 + type = types.nullOr types.str; 39 + default = null; 40 + description = "Local backup path (alternative to S3)"; 41 + example = "/backup/headscale"; 42 + }; 43 + 44 + syncInterval = mkOption { 45 + type = types.str; 46 + default = "1s"; 47 + description = "How often to sync to replicas"; 48 + }; 49 + 50 + retention = mkOption { 51 + type = types.str; 52 + default = "72h"; 53 + description = "How long to retain snapshots"; 54 + }; 55 + 56 + environmentFile = mkOption { 57 + type = types.nullOr types.path; 58 + default = null; 59 + description = "Environment file containing S3 credentials (can be agenix secret)"; 60 + example = "config.age.secrets.litestream-env.path"; 61 + }; 62 + }; 63 + }; 64 + }; 65 + }; 66 + 67 + config = mkIf cfg.enable { 68 + services.headscale = { 69 + enable = true; 70 + address = "0.0.0.0"; 71 + port = 8080; 72 + 73 + settings = { 74 + server_url = "https://headscale.nekomimi.pet"; 75 + 76 + # Metrics and gRPC 77 + metrics_listen_addr = "127.0.0.1:9090"; 78 + grpc_listen_addr = "127.0.0.1:50443"; 79 + grpc_allow_insecure = false; 80 + 81 + # Prefixes 82 + prefixes = { 83 + v4 = "100.64.0.0/10"; 84 + v6 = "fd7a:115c:a1e0::/48"; 85 + allocation = "sequential"; 86 + }; 87 + 88 + # Database 89 + database = { 90 + type = "sqlite"; 91 + sqlite = { 92 + path = "/var/lib/headscale/db.sqlite"; 93 + write_ahead_log = true; 94 + }; 95 + }; 96 + 97 + # Noise 98 + noise = { 99 + private_key_path = "/var/lib/headscale/noise_private.key"; 100 + }; 101 + 102 + # DERP 103 + derp = { 104 + urls = [ 105 + "https://controlplane.tailscale.com/derpmap/default" 106 + ]; 107 + paths = []; 108 + auto_update_enabled = true; 109 + update_frequency = "24h"; 110 + server = { 111 + enabled = false; 112 + region_id = 999; 113 + region_code = "headscale"; 114 + region_name = "Headscale Embedded DERP"; 115 + stun_listen_addr = "0.0.0.0:3478"; 116 + private_key_path = "/var/lib/headscale/derp_server_private.key"; 117 + automatically_add_embedded_derp_region = true; 118 + ipv4 = "1.2.3.4"; 119 + ipv6 = "2001:db8::1"; 120 + }; 121 + }; 122 + 123 + # DNS 124 + dns = { 125 + magic_dns = true; 126 + base_domain = "dns.sharkgirl.pet"; 127 + nameservers = { 128 + global = [ 129 + "100.64.0.7" 130 + "1.1.1.1" 131 + "1.0.0.1" 132 + "2606:4700:4700::1111" 133 + "2606:4700:4700::1001" 134 + ]; 135 + }; 136 + search_domains = []; 137 + }; 138 + 139 + # OIDC with configurable secret path 140 + oidc = { 141 + only_start_if_oidc_is_available = true; 142 + issuer = "https://pocketid.nekomimi.pet"; 143 + client_id = "f345acad-3eac-45b7-9d91-57f388987a57"; 144 + client_secret_path = cfg.oidcClientSecretPath; 145 + pkce = { 146 + enabled = true; 147 + method = "S256"; 148 + }; 149 + }; 150 + 151 + # Policy 152 + policy = { 153 + mode = "database"; 154 + }; 155 + 156 + # TLS/ACME 157 + acme_url = "https://acme-v02.api.letsencrypt.org/directory"; 158 + acme_email = ""; 159 + tls_letsencrypt_hostname = ""; 160 + tls_letsencrypt_cache_dir = "/var/lib/headscale/cache"; 161 + tls_letsencrypt_challenge_type = "HTTP-01"; 162 + tls_letsencrypt_listen = ":http"; 163 + tls_cert_path = ""; 164 + tls_key_path = ""; 165 + 166 + # Logging 167 + log = { 168 + format = "text"; 169 + level = "info"; 170 + }; 171 + 172 + # Misc settings 173 + disable_check_updates = false; 174 + ephemeral_node_inactivity_timeout = "30m"; 175 + unix_socket = "/var/run/headscale/headscale.sock"; 176 + unix_socket_permission = "0770"; 177 + logtail = { 178 + enabled = false; 179 + }; 180 + randomize_client_port = false; 181 + }; 182 + }; 183 + 184 + # Configurable Litestream for SQLite database backups 185 + services.litestream = mkIf cfg.litestream.enable { 186 + enable = true; 187 + settings = { 188 + dbs = [ 189 + { 190 + path = "/var/lib/headscale/db.sqlite"; 191 + sync-interval = cfg.litestream.syncInterval; 192 + retention = cfg.litestream.retention; 193 + replicas = 194 + # Use custom replicas if provided 195 + if cfg.litestream.replicas != [] then 196 + cfg.litestream.replicas 197 + # Otherwise use local backup if path is provided 198 + else if cfg.litestream.backupPath != null then 199 + [{ path = cfg.litestream.backupPath; }] 200 + # Default empty (user must configure) 201 + else 202 + []; 203 + } 204 + ]; 205 + }; 206 + }; 207 + 208 + # Configure systemd service to use agenix secrets 209 + systemd.services.headscale.serviceConfig = mkMerge [ 210 + { 211 + SupplementaryGroups = [ "headscale-secrets" ]; 212 + } 213 + # Add environment file for litestream if specified 214 + (mkIf (cfg.litestream.enable && cfg.litestream.environmentFile != null) { 215 + EnvironmentFile = cfg.litestream.environmentFile; 216 + }) 217 + ]; 218 + 219 + # Configure litestream service with environment file if specified 220 + systemd.services.litestream = mkIf (cfg.litestream.enable && cfg.litestream.environmentFile != null) { 221 + serviceConfig = { 222 + EnvironmentFile = cfg.litestream.environmentFile; 223 + }; 224 + }; 225 + 226 + # Create a group for accessing secrets 227 + users.groups.headscale-secrets = {}; 228 + }; 229 + }
+257
modules/syncthing/default.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + let 5 + cfg = config.modules.syncthing; 6 + 7 + # Helper function to create a serviceConfig entry if the condition is met 8 + mkServiceConfigOption = name: value: mkIf (value != null) { "${name}" = value; }; 9 + 10 + # Construct the settings object for Syncthing 11 + syncthingSettings = mkMerge [ 12 + # GUI configuration 13 + (mkIf cfg.gui.enable { 14 + gui = mkMerge [ 15 + (mkIf (cfg.gui.user != null) { 16 + user = cfg.gui.user; 17 + }) 18 + ]; 19 + }) 20 + 21 + # Devices configuration 22 + (mkIf (cfg.devices != {}) { 23 + devices = mapAttrs (name: device: { 24 + id = device.id; 25 + } // optionalAttrs (device.name != null) { 26 + name = device.name; 27 + } // optionalAttrs (device.addresses != []) { 28 + addresses = device.addresses; 29 + }) cfg.devices; 30 + }) 31 + 32 + # Folders configuration 33 + (mkIf (cfg.folders != {}) { 34 + folders = mapAttrs (name: folder: { 35 + path = folder.path; 36 + devices = folder.devices; 37 + } // optionalAttrs (folder.ignorePerms != null) { 38 + ignorePerms = folder.ignorePerms; 39 + } // optionalAttrs (folder.type != null) { 40 + type = folder.type; 41 + } // optionalAttrs (folder.rescanIntervalS != null) { 42 + rescanIntervalS = folder.rescanIntervalS; 43 + } // optionalAttrs (folder.versioning != null) { 44 + versioning = folder.versioning; 45 + }) cfg.folders; 46 + }) 47 + 48 + # Extra options 49 + cfg.extraOptions 50 + ]; 51 + in 52 + { 53 + options = { 54 + modules.syncthing = { 55 + enable = mkEnableOption "Deploy syncthing"; 56 + 57 + openDefaultPorts = mkOption { 58 + type = types.bool; 59 + default = true; 60 + description = "Open ports in the firewall for Syncthing"; 61 + }; 62 + 63 + disableDefaultFolder = mkOption { 64 + type = types.bool; 65 + default = true; 66 + description = "Don't create default ~/Sync folder"; 67 + }; 68 + 69 + gui = { 70 + enable = mkEnableOption "Enable GUI configuration"; 71 + 72 + user = mkOption { 73 + type = types.nullOr types.str; 74 + default = null; 75 + description = "GUI username"; 76 + example = "myuser"; 77 + }; 78 + 79 + passwordFile = mkOption { 80 + type = types.nullOr types.path; 81 + default = null; 82 + description = "Path to file containing GUI password"; 83 + example = "config.age.secrets.syncthing-gui-password.path"; 84 + }; 85 + }; 86 + 87 + identity = { 88 + keyPath = mkOption { 89 + type = types.nullOr types.path; 90 + default = null; 91 + description = "Path to Syncthing private key for stable device ID"; 92 + example = "config.age.secrets.syncthing-key.path"; 93 + }; 94 + 95 + certPath = mkOption { 96 + type = types.nullOr types.path; 97 + default = null; 98 + description = "Path to Syncthing certificate for stable device ID"; 99 + example = "config.age.secrets.syncthing-cert.path"; 100 + }; 101 + }; 102 + 103 + devices = mkOption { 104 + type = types.attrsOf (types.submodule { 105 + options = { 106 + id = mkOption { 107 + type = types.str; 108 + description = "Device ID"; 109 + example = "DMWVMM6-MKEQVB4-I4UZTRH-5A6E24O-XHQTL3K-AAI5R5L-MXNMUGX-QTGRHQ2"; 110 + }; 111 + 112 + name = mkOption { 113 + type = types.nullOr types.str; 114 + default = null; 115 + description = "Device name (optional)"; 116 + }; 117 + 118 + addresses = mkOption { 119 + type = types.listOf types.str; 120 + default = []; 121 + description = "Device addresses"; 122 + example = [ "tcp://192.168.1.100:22000" ]; 123 + }; 124 + }; 125 + }); 126 + default = {}; 127 + description = "Syncthing devices configuration"; 128 + example = { 129 + "laptop" = { 130 + id = "DMWVMM6-MKEQVB4-I4UZTRH-5A6E24O-XHQTL3K-AAI5R5L-MXNMUGX-QTGRHQ2"; 131 + }; 132 + "phone" = { 133 + id = "ANOTHER-DEVICE-ID-GOES-HERE"; 134 + addresses = [ "tcp://192.168.1.101:22000" ]; 135 + }; 136 + }; 137 + }; 138 + 139 + folders = mkOption { 140 + type = types.attrsOf (types.submodule { 141 + options = { 142 + path = mkOption { 143 + type = types.str; 144 + description = "Local folder path"; 145 + example = "/home/myuser/Documents"; 146 + }; 147 + 148 + devices = mkOption { 149 + type = types.listOf (types.either types.str (types.submodule { 150 + options = { 151 + name = mkOption { 152 + type = types.str; 153 + description = "Device name"; 154 + }; 155 + 156 + encryptionPasswordFile = mkOption { 157 + type = types.path; 158 + description = "Path to file containing encryption password"; 159 + }; 160 + }; 161 + })); 162 + default = []; 163 + description = "List of devices that can access this folder"; 164 + example = [ "laptop" "phone" ]; 165 + }; 166 + 167 + ignorePerms = mkOption { 168 + type = types.nullOr types.bool; 169 + default = null; 170 + description = "Whether to ignore file permissions"; 171 + }; 172 + 173 + type = mkOption { 174 + type = types.nullOr (types.enum [ "sendreceive" "sendonly" "receiveonly" ]); 175 + default = null; 176 + description = "Folder type"; 177 + }; 178 + 179 + rescanIntervalS = mkOption { 180 + type = types.nullOr types.int; 181 + default = null; 182 + description = "Rescan interval in seconds"; 183 + }; 184 + 185 + versioning = mkOption { 186 + type = types.nullOr (types.submodule { 187 + options = { 188 + type = mkOption { 189 + type = types.enum [ "external" "simple" "staggered" "trashcan" ]; 190 + description = "Versioning type"; 191 + }; 192 + 193 + params = mkOption { 194 + type = types.attrsOf types.str; 195 + default = {}; 196 + description = "Versioning parameters"; 197 + }; 198 + }; 199 + }); 200 + default = null; 201 + description = "Folder versioning configuration"; 202 + }; 203 + }; 204 + }); 205 + default = {}; 206 + description = "Syncthing folders configuration"; 207 + example = { 208 + "Documents" = { 209 + path = "/home/myuser/Documents"; 210 + devices = [ "laptop" "phone" ]; 211 + ignorePerms = false; 212 + }; 213 + "Sensitive" = { 214 + path = "/home/myuser/Sensitive"; 215 + devices = [ 216 + "laptop" 217 + { 218 + name = "phone"; 219 + encryptionPasswordFile = "/run/secrets/syncthing-sensitive-password"; 220 + } 221 + ]; 222 + }; 223 + }; 224 + }; 225 + 226 + extraOptions = mkOption { 227 + type = types.attrsOf types.anything; 228 + default = {}; 229 + description = "Additional Syncthing configuration options"; 230 + }; 231 + }; 232 + }; 233 + 234 + config = mkIf cfg.enable { 235 + services.syncthing = { 236 + enable = true; 237 + openDefaultPorts = cfg.openDefaultPorts; 238 + # Set stable identity if provided 239 + key = mkIf (cfg.identity.keyPath != null) cfg.identity.keyPath; 240 + cert = mkIf (cfg.identity.certPath != null) cfg.identity.certPath; 241 + # Combine all settings 242 + settings = syncthingSettings; 243 + }; 244 + 245 + # Configure systemd service options collectively 246 + systemd.services.syncthing = { 247 + # Add environment variable to disable default folder creation 248 + environment.STNODEFAULTFOLDER = mkIf cfg.disableDefaultFolder "true"; 249 + 250 + # Add supplementary groups for secret access 251 + serviceConfig.SupplementaryGroups = [ "syncthing-secrets" ]; 252 + }; 253 + 254 + # Create a group for accessing secrets 255 + users.groups.syncthing-secrets = {}; 256 + }; 257 + }
+11
secrets/headscale-oidc-key.path
··· 1 + age-encryption.org/v1 2 + -> ssh-ed25519 i9wBeA DynOTJFDKsSyHKTG9XFAAcZf/T//KKyK8UG4aGgVH2c 3 + o+ggJe/HZmPU+Ezw4u4m+l9bQ1furG7G4Oo7xS8PMAs 4 + -> ssh-ed25519 UbxDgg b1XiosrWXL9WI1B7YnNSw16l1p4oa3zjDCCgkU/FxiU 5 + MY8oubHMth/wDKn9kNOUkaY9ODvrKIn7DeZTuGxj4/g 6 + -> ssh-ed25519 YYzA7Q 6ql+gutJfteQM75WL6ywEDA1+fIcYSpLPaTSKhqE1ic 7 + tbwXx/feysvpOrxwpDi5B5PveSIbFH0qSsV6/xmo4hk 8 + -> ssh-ed25519 3RWqPQ hNVnobsB1OB9woXtn1T1tXJL+1Dbasc9N2tjZdXa0Bw 9 + 9HlWIX7aroc8kTUW3rPlxvMSTSGJXbMcOEipdoQqnbw 10 + --- h8toQGhp/wUgMkJ+RU0bV7E6pHRUM8mKLPcrDmbZ5NQ 11 + !Ŵ�j֖n$�Z���$s9f���ωk�.ro�`�CU>˻�R�F;H;�}J�(�0��� U�YP
+1
secrets/secrets.nix
··· 16 16 "garage-metrics-token.age".publicKeys = users ++ systems; 17 17 18 18 "headscale-authkey.age".publicKeys = users ++ systems; 19 + "headscale-oidc-key.path".publicKeys = users ++ systems; 19 20 }