🏡 my personal home lab
1
fork

Configure Feed

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

add tangled spindle

+278 -127
+1
flake.nix
··· 109 109 sops-nix.nixosModules.sops 110 110 tranquil-pds.nixosModules.default 111 111 tangled.nixosModules.knot 112 + tangled.nixosModules.spindle 112 113 ./hosts/${name}.nix 113 114 ]; 114 115 };
+3 -1
hosts/rk1-node-1.nix
··· 7 7 ../modules/paperless.nix 8 8 ../modules/tranquil-pds.nix 9 9 ../modules/tangled-knot.nix 10 + ../modules/tangled-spindle.nix 11 + ../modules/garage.nix 10 12 ]; 11 13 12 14 system.stateVersion = "25.11"; 13 15 14 16 virtualisation.podman = { 15 17 enable = true; 16 - dockerCompat = true; 17 18 defaultNetwork.settings.dns_enabled = true; 18 19 }; 20 + virtualisation.oci-containers.backend = "podman"; 19 21 }
+1 -1
hosts/rk1-node-2.nix
··· 15 15 16 16 virtualisation.podman = { 17 17 enable = true; 18 - dockerCompat = true; 19 18 defaultNetwork.settings.dns_enabled = true; 20 19 }; 20 + virtualisation.oci-containers.backend = "podman"; 21 21 }
+13 -16
modules/bambuddy.nix
··· 1 1 { config, ... }: 2 2 { 3 - virtualisation.oci-containers = { 4 - backend = "podman"; 5 - containers.bambuddy = { 6 - image = "ghcr.io/maziggy/bambuddy:latest"; 7 - volumes = [ 8 - "/var/lib/bambuddy/data:/app/data" 9 - "/var/lib/bambuddy/logs:/app/logs" 10 - ]; 11 - extraOptions = [ 12 - "--network=host" 13 - "--cap-add=NET_BIND_SERVICE" 14 - ]; 15 - environment = { 16 - TZ = config.time.timeZone; 17 - PORT = "8001"; 18 - }; 3 + virtualisation.oci-containers.containers.bambuddy = { 4 + image = "ghcr.io/maziggy/bambuddy:latest"; 5 + volumes = [ 6 + "/var/lib/bambuddy/data:/app/data" 7 + "/var/lib/bambuddy/logs:/app/logs" 8 + ]; 9 + extraOptions = [ 10 + "--network=host" 11 + "--cap-add=NET_BIND_SERVICE" 12 + ]; 13 + environment = { 14 + TZ = config.time.timeZone; 15 + PORT = "8001"; 19 16 }; 20 17 }; 21 18
+19
modules/caddy.nix
··· 65 65 security { 66 66 ${mkCaddySecurity "tasks" "tasks.goo.garden"} 67 67 ${mkCaddySecurity "bambuddy" "bambu.goo.garden"} 68 + ${mkCaddySecurity "garage" "s3.goo.garden"} 68 69 } 69 70 ''; 70 71 virtualHosts = { ··· 162 163 "knot.goo.garden" = vhost '' 163 164 reverse_proxy rk1-node-1:5555 164 165 ''; 166 + "spindle.goo.garden" = vhost '' 167 + reverse_proxy rk1-node-1:6555 168 + ''; 169 + "s3.goo.garden" = vhost '' 170 + route /oauth2/* { 171 + authenticate with garage_portal 172 + } 173 + route { 174 + authorize with garage_policy 175 + reverse_proxy rk1-node-1:3909 176 + } 177 + ''; 165 178 "probe.outerwilds.space" = vhost '' 166 179 reverse_proxy cm4-node-2:3001 167 180 ''; ··· 181 194 BAMBUDDY_OIDC_CLIENT_ID=${config.sops.placeholder.bambuddy-oidc-client-id} 182 195 BAMBUDDY_OIDC_CLIENT_SECRET=${config.sops.placeholder.bambuddy-oidc-client-secret} 183 196 BAMBUDDY_JWT_SHARED_KEY=${config.sops.placeholder.bambuddy-jwt-shared-key} 197 + GARAGE_OIDC_CLIENT_ID=${config.sops.placeholder.garage-oidc-client-id} 198 + GARAGE_OIDC_CLIENT_SECRET=${config.sops.placeholder.garage-oidc-client-secret} 199 + GARAGE_JWT_SHARED_KEY=${config.sops.placeholder.garage-jwt-shared-key} 184 200 ''; 185 201 sops.secrets.tasks-oidc-client-id = { }; 186 202 sops.secrets.tasks-oidc-client-secret = { }; ··· 188 204 sops.secrets.bambuddy-oidc-client-id = { }; 189 205 sops.secrets.bambuddy-oidc-client-secret = { }; 190 206 sops.secrets.bambuddy-jwt-shared-key = { }; 207 + sops.secrets.garage-oidc-client-id = { }; 208 + sops.secrets.garage-oidc-client-secret = { }; 209 + sops.secrets.garage-jwt-shared-key = { }; 191 210 192 211 networking.firewall.allowedTCPPorts = [ 193 212 80
+10 -13
modules/fusion.nix
··· 1 1 { config, ... }: 2 2 { 3 - virtualisation.oci-containers = { 4 - backend = "podman"; 5 - containers = { 6 - fusion = { 7 - image = "ghcr.io/0x2e/fusion:latest"; 8 - ports = [ "8080:8080" ]; 9 - environmentFiles = [ config.sops.templates."fusion.env".path ]; 10 - environment = { 11 - TZ = config.time.timeZone; 12 - }; 13 - volumes = [ 14 - "/var/lib/fusion:/data" 15 - ]; 3 + virtualisation.oci-containers.containers = { 4 + fusion = { 5 + image = "ghcr.io/0x2e/fusion:latest"; 6 + ports = [ "8080:8080" ]; 7 + environmentFiles = [ config.sops.templates."fusion.env".path ]; 8 + environment = { 9 + TZ = config.time.timeZone; 16 10 }; 11 + volumes = [ 12 + "/var/lib/fusion:/data" 13 + ]; 17 14 }; 18 15 }; 19 16
+91
modules/garage.nix
··· 1 + { 2 + config, 3 + pkgs, 4 + ... 5 + }: 6 + { 7 + services.garage = { 8 + enable = true; 9 + package = pkgs.garage_2; 10 + environmentFile = config.sops.templates."garage.env".path; 11 + settings = { 12 + replication_factor = 1; 13 + rpc_bind_addr = "[::]:3901"; 14 + rpc_public_addr = "[::]:3901"; 15 + 16 + s3_api = { 17 + api_bind_addr = "[::]:3900"; 18 + s3_region = "goo-garden"; 19 + }; 20 + 21 + admin = { 22 + api_bind_addr = "[::]:3903"; 23 + }; 24 + }; 25 + }; 26 + 27 + # Community web UI for garage. Replace with official garage-webadmin once 28 + # it ships (targeted for v2.2): https://git.deuxfleurs.fr/Deuxfleurs/garage-webadmin 29 + virtualisation.oci-containers.containers.garage-webui = { 30 + image = "khairul169/garage-webui:latest"; 31 + environment = { 32 + API_BASE_URL = "http://127.0.0.1:3903"; 33 + S3_ENDPOINT_URL = "http://127.0.0.1:3900"; 34 + S3_REGION = "goo-garden"; 35 + }; 36 + environmentFiles = [ config.sops.templates."garage-webui.env".path ]; 37 + extraOptions = [ "--network=host" ]; 38 + }; 39 + 40 + sops.templates."garage.env".content = '' 41 + GARAGE_RPC_SECRET=${config.sops.placeholder.garage-rpc-secret} 42 + GARAGE_ADMIN_TOKEN=${config.sops.placeholder.garage-admin-token} 43 + ''; 44 + sops.templates."garage-webui.env".content = '' 45 + API_ADMIN_KEY=${config.sops.placeholder.garage-admin-token} 46 + ''; 47 + sops.secrets.garage-rpc-secret = { }; 48 + sops.secrets.garage-admin-token = { }; 49 + 50 + networking.firewall.allowedTCPPorts = [ 3909 ]; 51 + 52 + # garage requires its node to be assigned a role in the cluster layout before 53 + # it accepts any data operations. For a single-node setup this only needs to 54 + # happen once on first boot. 55 + systemd.services.garage-bootstrap = { 56 + description = "Assign cluster layout for single-node garage"; 57 + after = [ "garage.service" ]; 58 + wants = [ "garage.service" ]; 59 + wantedBy = [ "multi-user.target" ]; 60 + serviceConfig = { 61 + Type = "oneshot"; 62 + RemainAfterExit = true; 63 + EnvironmentFile = config.sops.templates."garage.env".path; 64 + }; 65 + path = [ config.services.garage.package ]; 66 + script = '' 67 + # Wait for the garage RPC port to accept connections. 68 + for i in $(seq 1 30); do 69 + if garage status >/dev/null 2>&1; then 70 + break 71 + fi 72 + sleep 1 73 + done 74 + 75 + status_output=$(garage status 2>&1) 76 + echo "garage status output:" 77 + echo "$status_output" 78 + 79 + # Only assign a layout if our node hasn't been given a role yet. 80 + if echo "$status_output" | grep -q "NO ROLE ASSIGNED"; then 81 + node_id=$(garage node id -q | cut -d@ -f1) 82 + echo "Assigning layout to node $node_id" 83 + garage layout assign -z dc1 -c 10G "$node_id" 84 + echo "Applying layout version 1" 85 + garage layout apply --version 1 86 + else 87 + echo "Node already has a role, skipping layout assignment" 88 + fi 89 + ''; 90 + }; 91 + }
+14 -17
modules/home-assistant.nix
··· 16 16 }; 17 17 in 18 18 { 19 - virtualisation.oci-containers = { 20 - backend = "podman"; 21 - containers.home-assistant = { 22 - image = "ghcr.io/home-assistant/home-assistant:stable"; 23 - volumes = [ 24 - "/var/lib/homeassistant:/config" 25 - "/run/dbus:/run/dbus:ro" 26 - "${httpConfig}:/config/http.yaml:ro" 27 - ]; 28 - extraOptions = [ 29 - "--network=host" 30 - "--cap-add=NET_ADMIN" 31 - "--cap-add=NET_RAW" 32 - ]; 33 - environment = { 34 - TZ = config.time.timeZone; 35 - }; 19 + virtualisation.oci-containers.containers.home-assistant = { 20 + image = "ghcr.io/home-assistant/home-assistant:stable"; 21 + volumes = [ 22 + "/var/lib/homeassistant:/config" 23 + "/run/dbus:/run/dbus:ro" 24 + "${httpConfig}:/config/http.yaml:ro" 25 + ]; 26 + extraOptions = [ 27 + "--network=host" 28 + "--cap-add=NET_ADMIN" 29 + "--cap-add=NET_RAW" 30 + ]; 31 + environment = { 32 + TZ = config.time.timeZone; 36 33 }; 37 34 }; 38 35
+17 -20
modules/kitchenowl.nix
··· 4 4 ... 5 5 }: 6 6 { 7 - virtualisation.oci-containers = { 8 - backend = "podman"; 9 - containers = { 10 - kitchenowl-web = { 11 - image = "tombursch/kitchenowl-web:latest"; 12 - dependsOn = [ "kitchenowl" ]; 13 - ports = [ "9080:80" ]; 14 - environment = { 15 - BACK_URL = "kitchenowl:5000"; 16 - }; 7 + virtualisation.oci-containers.containers = { 8 + kitchenowl-web = { 9 + image = "tombursch/kitchenowl-web:latest"; 10 + dependsOn = [ "kitchenowl" ]; 11 + ports = [ "9080:80" ]; 12 + environment = { 13 + BACK_URL = "kitchenowl:5000"; 17 14 }; 15 + }; 18 16 19 - kitchenowl = { 20 - image = "tombursch/kitchenowl-backend:latest"; 21 - environmentFiles = [ config.sops.templates."kitchenowl.env".path ]; 22 - environment = { 23 - TZ = config.time.timeZone; 24 - }; 25 - volumes = [ 26 - "/var/lib/kitchenowl:/data" 27 - "/run/postgresql:/run/postgresql" 28 - ]; 17 + kitchenowl = { 18 + image = "tombursch/kitchenowl-backend:latest"; 19 + environmentFiles = [ config.sops.templates."kitchenowl.env".path ]; 20 + environment = { 21 + TZ = config.time.timeZone; 29 22 }; 23 + volumes = [ 24 + "/var/lib/kitchenowl:/data" 25 + "/run/postgresql:/run/postgresql" 26 + ]; 30 27 }; 31 28 }; 32 29
+18 -21
modules/paperless.nix
··· 24 24 }; 25 25 }; 26 26 27 - virtualisation.oci-containers = { 28 - backend = "podman"; 29 - containers.paperless-gpt = { 30 - image = "icereed/paperless-gpt:latest"; 31 - extraOptions = [ "--network=host" ]; 32 - environmentFiles = [ config.sops.templates."paperless-gpt.env".path ]; 33 - environment = { 34 - PAPERLESS_BASE_URL = "http://localhost:28981"; 35 - LLM_PROVIDER = "ollama"; 36 - LLM_MODEL = "qwen2.5vl:3b"; 37 - LLM_LANGUAGE = "deu"; 38 - VISION_LLM_PROVIDER = "ollama"; 39 - VISION_LLM_MODEL = "qwen2.5vl:3b"; 40 - OLLAMA_HOST = "http://localhost:11434"; 41 - OLLAMA_CONTEXT_LENGTH = "8192"; 42 - TOKEN_LIMIT = "1000"; 43 - LOG_LEVEL = "info"; 44 - }; 45 - volumes = [ 46 - "/var/lib/paperless-gpt/prompts:/app/prompts" 47 - ]; 27 + virtualisation.oci-containers.containers.paperless-gpt = { 28 + image = "icereed/paperless-gpt:latest"; 29 + extraOptions = [ "--network=host" ]; 30 + environmentFiles = [ config.sops.templates."paperless-gpt.env".path ]; 31 + environment = { 32 + PAPERLESS_BASE_URL = "http://localhost:28981"; 33 + LLM_PROVIDER = "ollama"; 34 + LLM_MODEL = "qwen2.5vl:3b"; 35 + LLM_LANGUAGE = "deu"; 36 + VISION_LLM_PROVIDER = "ollama"; 37 + VISION_LLM_MODEL = "qwen2.5vl:3b"; 38 + OLLAMA_HOST = "http://localhost:11434"; 39 + OLLAMA_CONTEXT_LENGTH = "8192"; 40 + TOKEN_LIMIT = "1000"; 41 + LOG_LEVEL = "info"; 48 42 }; 43 + volumes = [ 44 + "/var/lib/paperless-gpt/prompts:/app/prompts" 45 + ]; 49 46 }; 50 47 51 48 services.ollama = {
+9 -12
modules/rustical.nix
··· 1 1 { config, pkgs, ... }: 2 2 { 3 - virtualisation.oci-containers = { 4 - backend = "podman"; 5 - containers.rustical = { 6 - image = "ghcr.io/lennart-k/rustical:0.12"; 7 - ports = [ "4000:4000" ]; 8 - volumes = [ 9 - "/var/lib/rustical:/var/lib/rustical" 10 - "${config.sops.templates."rustical.toml".path}:/etc/rustical/config.toml:ro" 11 - ]; 12 - environment = { 13 - TZ = config.time.timeZone; 14 - }; 3 + virtualisation.oci-containers.containers.rustical = { 4 + image = "ghcr.io/lennart-k/rustical:0.12"; 5 + ports = [ "4000:4000" ]; 6 + volumes = [ 7 + "/var/lib/rustical:/var/lib/rustical" 8 + "${config.sops.templates."rustical.toml".path}:/etc/rustical/config.toml:ro" 9 + ]; 10 + environment = { 11 + TZ = config.time.timeZone; 15 12 }; 16 13 }; 17 14
+55
modules/tangled-spindle.nix
··· 1 + { config, ... }: 2 + { 3 + services.tangled.spindle = { 4 + enable = true; 5 + server = { 6 + hostname = "spindle.goo.garden"; 7 + owner = "did:plc:jwgnraovgs3eeenh23tlllyk"; 8 + listenAddr = "[::]:6555"; 9 + }; 10 + pipelines.logBucket = "tangled-logs"; 11 + environmentFile = config.sops.templates."tangled-spindle.env".path; 12 + }; 13 + 14 + sops.templates."tangled-spindle.env".content = '' 15 + AWS_ACCESS_KEY_ID=${config.sops.placeholder.garage-s3-access-key} 16 + AWS_SECRET_ACCESS_KEY=${config.sops.placeholder.garage-s3-secret-key} 17 + AWS_REGION=goo-garden 18 + AWS_ENDPOINT_URL=http://127.0.0.1:3900 19 + GARAGE_RPC_SECRET=${config.sops.placeholder.garage-rpc-secret} 20 + ''; 21 + sops.secrets.garage-s3-access-key = { }; 22 + sops.secrets.garage-s3-secret-key = { }; 23 + sops.secrets.garage-rpc-secret = { }; 24 + 25 + systemd.services.spindle-bucket-init = { 26 + description = "Create tangled-logs bucket on garage for spindle"; 27 + after = [ "garage-bootstrap.service" ]; 28 + wants = [ "garage-bootstrap.service" ]; 29 + before = [ "spindle.service" ]; 30 + requiredBy = [ "spindle.service" ]; 31 + serviceConfig = { 32 + Type = "oneshot"; 33 + RemainAfterExit = true; 34 + EnvironmentFile = config.sops.templates."tangled-spindle.env".path; 35 + # Retry until garage's layout is fully propagated. 36 + Restart = "on-failure"; 37 + RestartSec = "5s"; 38 + }; 39 + startLimitBurst = 30; 40 + startLimitIntervalSec = 300; 41 + path = [ config.services.garage.package ]; 42 + script = '' 43 + # Import key (idempotent — errors if key already exists). 44 + garage key import --yes "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" -n spindle 2>/dev/null || true 45 + # Create bucket (idempotent — errors if bucket already exists). 46 + garage bucket create ${config.services.tangled.spindle.pipelines.logBucket} 2>/dev/null || true 47 + # Grant the spindle key full access to the bucket. 48 + garage bucket allow --read --write --owner \ 49 + --key "$AWS_ACCESS_KEY_ID" \ 50 + ${config.services.tangled.spindle.pipelines.logBucket} 51 + ''; 52 + }; 53 + 54 + networking.firewall.allowedTCPPorts = [ 6555 ]; 55 + }
+8 -11
modules/tasks-md.nix
··· 1 1 { ... }: 2 2 { 3 - virtualisation.oci-containers = { 4 - backend = "podman"; 5 - containers = { 6 - tasks-md = { 7 - image = "baldissaramatheus/tasks.md:3"; 8 - ports = [ "8080:8080" ]; 9 - volumes = [ 10 - "/mnt/nas/data/tasks-md/tasks:/tasks" 11 - "/mnt/nas/data/tasks-md/config:/config" 12 - ]; 13 - }; 3 + virtualisation.oci-containers.containers = { 4 + tasks-md = { 5 + image = "baldissaramatheus/tasks.md:3"; 6 + ports = [ "8080:8080" ]; 7 + volumes = [ 8 + "/mnt/nas/data/tasks-md/tasks:/tasks" 9 + "/mnt/nas/data/tasks-md/config:/config" 10 + ]; 14 11 }; 15 12 }; 16 13
+10 -13
modules/wallos.nix
··· 1 1 { config, ... }: 2 2 { 3 - virtualisation.oci-containers = { 4 - backend = "podman"; 5 - containers = { 6 - wallos = { 7 - image = "bellamy/wallos:latest"; 8 - ports = [ "8282:80" ]; 9 - volumes = [ 10 - "/var/lib/wallos/db:/var/www/html/db" 11 - "/var/lib/wallos/logos:/var/www/html/images/uploads/logos" 12 - ]; 13 - environment = { 14 - TZ = config.time.timeZone; 15 - }; 3 + virtualisation.oci-containers.containers = { 4 + wallos = { 5 + image = "bellamy/wallos:latest"; 6 + ports = [ "8282:80" ]; 7 + volumes = [ 8 + "/var/lib/wallos/db:/var/www/html/db" 9 + "/var/lib/wallos/logos:/var/www/html/images/uploads/logos" 10 + ]; 11 + environment = { 12 + TZ = config.time.timeZone; 16 13 }; 17 14 }; 18 15 };
+9 -2
secrets/secrets.yaml
··· 32 32 bambuddy-oidc-client-id: ENC[AES256_GCM,data:Oix5LL0Th0+x9B0ZcRShYBDPkqRDYTXBi+HP+2ox7F7SrRDn,iv:K31M5y7unTZSqiPJWpiApa5o/LN2lcDcw6vZ/nCDGYA=,tag:iVTBQ6q91WQMqelh+N8gHQ==,type:str] 33 33 bambuddy-oidc-client-secret: ENC[AES256_GCM,data:WPpwYFZhKk9vXvdXiyqSJP2NNRT40GL5VQYStwMr19E=,iv:cUu/r2SPvT80FYLF+5iXxXdoNXoPfwBbgIqykEYp+5M=,tag:c6T4+w0gEvkivMM1nlIGXg==,type:str] 34 34 bambuddy-jwt-shared-key: ENC[AES256_GCM,data:7dWR3WF77NqhGc/supdLx36c4y/2rDQDaOqp7uWXgoMbcFlkM5VAE3BhS63GB8PO5hcF2SCwA1oh598rsZcRhw==,iv:WZgGv2igXCu9edd2q7fD6zzarmCYLNtEJRr5gJWxEUI=,tag:2TDpmlFYnVNFzMAMog1MyQ==,type:str] 35 + garage-rpc-secret: ENC[AES256_GCM,data:iXlhJ0m52DXn48TxFWtUd5Vjbvry3Yaa2RuzrVlByMktWX6OdbZeWO6wsA8fP6CCwTVg4RzRWLB7dhegsy42hg==,iv:MohTNItcrPeeZ812o+yB4Xe+f+NALPp48ksE0cnKDok=,tag:qR2ezUU9qFYLW/t1I45e0A==,type:str] 36 + garage-admin-token: ENC[AES256_GCM,data:Ngsj2GzDI80DiVww7EhYCGtQ/jPeYJug97LFgi3OcOSY6vIiKfWf4yjFMoB6zMCMflnUOfqdCuwbrOsGgWL87w==,iv:5ntob1of3Q4IoPQomkepFMBBRXsZW7WXzLPUhKFSdZA=,tag:bag0/j6wxxfXdshCXMW97A==,type:str] 37 + garage-s3-access-key: ENC[AES256_GCM,data:WfwSvIUhbnMNrfE0spd3Q5Y+9WXNSHfgUuU=,iv:GscJS7D8YfCAeXzU7b/NTvj6nzTZa0TF99iynsSxlBs=,tag:3FjZWsDJ3sOrDMOv6cu2CQ==,type:str] 38 + garage-s3-secret-key: ENC[AES256_GCM,data:bccZVJvTqQwqQmlHpAkS0LTFXwOe1KjjmLDxHGAhJLHUBNQwpFa4U4SsyVK43Xe4UOqfG1nsL5iFTUS7yOt4zA==,iv:vGFSkKPnja7kZb77lFgNtqmmhlqOAo/q8LS6QpJEMtY=,tag:BMcsbHBiSu0MUJo6sYbVsw==,type:str] 39 + garage-oidc-client-id: ENC[AES256_GCM,data:J5D3levHmxeWhmgMAjS9wPDk1SQ7u7vkY6nb8+iKozjsj/eI,iv:VcK/sGX+EXLBC6WVRFeWVp60xxDnnohzsVL8f7UGv9I=,tag:xRAxdeUr07xPa9aiNRK37Q==,type:str] 40 + garage-oidc-client-secret: ENC[AES256_GCM,data:gxnreI30zNytCYJetu5YHA28QFnJeBbvgZVzhwAPtSM=,iv:05L77VFDETER3LH0zcPkf0FF5Y2DuXsX6huQYrEUGY4=,tag:9gKw2gOaDax9lev45+1+mA==,type:str] 41 + garage-jwt-shared-key: ENC[AES256_GCM,data:tipooVIAIfyjkDB9r1fIjktUTfAfHYh0LehWTuTWI/qt6BLPROLfJWc+Zb9bGQMBCjACPWVWz0xc00d5Va6Neg==,iv:DcAb8LjE/TYzkZq79xJjAy3hjGgZ0XnAVtUFI5HbO7k=,tag:mpm7v73hVOhGU14ZSgvMBw==,type:str] 35 42 mumble-password: ENC[AES256_GCM,data:/GA5G4CEVQ==,iv:Ri70GW9Ln7vv3Nf0CSNW0PwypLUNvh+kvJjUqu393ig=,tag:NY+u/RxcKudlaZStgnGVTw==,type:str] 36 43 backup-repository: ENC[AES256_GCM,data:v6tUjTwVsym8i52jcapjSRXPIjX2xNFY+bZRkHnVsp4AebcksHzHEDX6N4BF3OuQ2KepOfHngMn61Mk=,iv:HPV+8aCPpvFnytja6RUA7hJdtz2BMI1zsH01w1J9r2w=,tag:znMIFmrcsKTIq2TowhAV0w==,type:str] 37 44 backup-identity: ENC[AES256_GCM,data:8TJP7vSWJAj56AcczQhMRoQqahxM4EGzPm+wk1apMD+L3pybXh/4LPp0DNcGugOb3RPTyjki6jZArDgiirS+ltbldaNQPZaZ4cFrtiJVt8D/iQlsgM9tR8oC7bcR4KV+UoVeeXJN0fWqy5U+IzJ87ZRKKyb9i8WKhPuWFIftb4KqZRyada7jhl/SzwuoIcw9BagMJPLv6BaUmNp1j5fOHvo7RseImiIqsbVo37NTqMMQf7PKM5gsMU6bbeAMjtdeC2RNVG21eop8JlO5uYVyjGxyl5wfU+PwMSRc+XNpgeVEv9mjdo6dkG3QC2poHZ77ot4py6HzQPUZjwLyFsr0ccC4e6e0PNOBtTPtku/LnXHsV45LB9Q3X7t9VSYCTtlJul2W8huZuCRnv7crvIUW21ZMTWiwMbqNEqDUJTBcPLDi42Ea4CvA+I6ODJP8n5g7GTHW0ggy6FtjVXH5DzhzJJULQ27kq97EWi43bSRv0N+N5C1viM+j+hs6tM5eQ15niRVB,iv:YpRoGlD8YFxZ+RChb6T4Eh665AMTTeTJXRFR0xa7l3k=,tag:FWOVonF+SYbbgQoopa2lhA==,type:str] ··· 82 89 ajA5bDZCY1BnblVYRGQ1QTE2S2I4M2cKSIGmFBP6sqiiM+cvTMQuZHit9fN5Vffk 83 90 1pWz8xSen/tqoywqipRf3LqzFb2K7Bx15vwazHbm6LJJa+ZQaruVMg== 84 91 -----END AGE ENCRYPTED FILE----- 85 - lastmodified: "2026-04-07T12:27:58Z" 86 - mac: ENC[AES256_GCM,data:2XYwg8e1g7k6lOI/YoucOLw8pcg8+Lyjj/LbuVjW1/Hgcsm8esT+YOoUnj9mQxNle2RidP2JGLedRHGY74atIH1thtpr3zxstmemZZ5BVTjG9ICe3dsMSxRJ+KIenyt0R254mWMFmY1C4wqL8NlCVpj0eTAhCC1KUksd63qsOhM=,iv:qxF4w+1t0nG5eEg7dfHabUPTLo7GY1hvPpos8TXdVFI=,tag:JLwKBfpFnj8aCANU9D7DOg==,type:str] 92 + lastmodified: "2026-04-07T21:05:32Z" 93 + mac: ENC[AES256_GCM,data:8cwQ2EvFwhLXHleSsa0LOXOrC2+p9tsk5KrkWX0Vm+fQhiNqEahihUCD0n30Ju4koBp3PaRHY1n+xOhlPGroeB8GF1J1Wsb0O1rWnOW80D98xE5NTdwuIPi+9RhtI3QuH9rVheFNfTzBNP4YZ7EIxWYSmWaEbptckivSSIoTrjM=,iv:OaK3axSjmv7HQDAOC5Wg8KH58ucco7Ix3OT6yNZgzhA=,tag:y9jbAFwc5a2FvwTPr6L4tg==,type:str] 87 94 unencrypted_suffix: _unencrypted 88 95 version: 3.12.2