nix all the things

pds on reg

+245 -30
+10
.sops.yaml
··· 1 + # https://github.com/Mic92/sops-nix 2 + keys: 3 + - &ozen age17cxj5zwkkxjkjvmpskpkyh6yt4xj4l8h6jyjxez3nmq6y9tvhqjsdp0m5j 4 + - &server_reg age1j6j2ldpsj7jmchstwl3nktvatut9hzxnemmy6py84rrga5eaf93q5w8s39 5 + creation_rules: 6 + - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$ 7 + key_groups: 8 + - age: 9 + - *ozen 10 + - *server_reg
+24 -3
flake.lock
··· 592 592 "niri": "niri", 593 593 "nixos-wsl": "nixos-wsl", 594 594 "nixpkgs": "nixpkgs_7", 595 + "sops-nix": "sops-nix", 595 596 "ssh-keys": "ssh-keys", 596 597 "stable": "stable", 597 598 "starship-jj": "starship-jj", ··· 678 679 "original": { 679 680 "owner": "oxalica", 680 681 "repo": "rust-overlay", 682 + "type": "github" 683 + } 684 + }, 685 + "sops-nix": { 686 + "inputs": { 687 + "nixpkgs": [ 688 + "nixpkgs" 689 + ] 690 + }, 691 + "locked": { 692 + "lastModified": 1760998189, 693 + "narHash": "sha256-ee2e1/AeGL5X8oy/HXsZQvZnae6XfEVdstGopKucYLY=", 694 + "owner": "Mic92", 695 + "repo": "sops-nix", 696 + "rev": "5a7d18b5c55642df5c432aadb757140edfeb70b3", 697 + "type": "github" 698 + }, 699 + "original": { 700 + "owner": "Mic92", 701 + "repo": "sops-nix", 681 702 "type": "github" 682 703 } 683 704 }, ··· 809 830 "tree-sitter-nu": { 810 831 "flake": false, 811 832 "locked": { 812 - "lastModified": 1761142283, 813 - "narHash": "sha256-OSazwPrUD7kWz/oVeStnnXEJiDDmI7itiDPmg062Kl8=", 833 + "lastModified": 1761314688, 834 + "narHash": "sha256-WY1qZbRLLTKNcyt7eQTzoQ2YKwyWSuUpVdt3YST6yx8=", 814 835 "owner": "nushell", 815 836 "repo": "tree-sitter-nu", 816 - "rev": "18b7f951e0c511f854685dfcc9f6a34981101dd6", 837 + "rev": "47d4b4f5369c0cae866724758ae88ef07e10e4f1", 817 838 "type": "github" 818 839 }, 819 840 "original": {
+5 -1
flake.nix
··· 2 2 inputs = { 3 3 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 4 stable.url = "github:NixOS/nixpkgs/nixos-25.05"; 5 - 6 5 home-manager = { 7 6 url = "github:nix-community/home-manager"; 8 7 inputs.nixpkgs.follows = "nixpkgs"; ··· 45 44 topiary-nushell = { 46 45 url = "github:blindFS/topiary-nushell"; 47 46 flake = false; 47 + }; 48 + 49 + sops-nix = { 50 + url = "github:Mic92/sops-nix"; 51 + inputs.nixpkgs.follows = "nixpkgs"; 48 52 }; 49 53 }; 50 54 outputs = inputs @ {
+9 -26
hosts/reg/default.nix
··· 4 4 username, 5 5 ... 6 6 }: { 7 - imports = [./hardware.nix]; 7 + imports = [ 8 + inputs.sops-nix.nixosModules.sops 9 + ./hardware.nix 10 + ./pds.nix 11 + ./pds-backup.nix 12 + ]; 8 13 9 14 boot.tmp.cleanOnBoot = true; 10 15 zramSwap.enable = true; 16 + sops.age.sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"]; 11 17 services = { 12 18 tailscale.enable = true; 13 19 tailscale.useRoutingFeatures = "server"; ··· 17 23 enable = true; 18 24 host = "0.0.0.0"; 19 25 }; 20 - 21 - writefreely = { 22 - enable = true; 23 - host = "notes.0xf.fr"; 24 - nginx.enable = true; 25 - acme.enable = true; 26 - settings = { 27 - server.port = 3003; 28 - app.host = "https://notes.0xf.fr"; 29 - app.site_name = "writefreely"; 30 - app.site_description = "writefreely"; 31 - app.single_user = true; 32 - }; 33 - }; 34 - }; 35 - 36 - networking.firewall.allowedTCPPorts = [80 443]; 37 - 38 - security.acme = { 39 - defaults.email = "netop@0xf.fr"; 40 - acceptTerms = true; 41 26 }; 42 27 43 28 users.users = { 44 29 ${username}.openssh.authorizedKeys.keyFiles = [inputs.ssh-keys]; 45 30 }; 46 31 47 - environment.systemPackages = with pkgs; [helix writefreely]; 32 + environment.systemPackages = with pkgs; [helix]; 48 33 server = true; 49 34 50 - system = { 51 - stateVersion = "25.05"; 52 - }; 35 + system.stateVersion = "25.05"; 53 36 }
+109
hosts/reg/pds-backup.nix
··· 1 + { 2 + config, 3 + pkgs, 4 + ... 5 + }: let 6 + restoreScript = pkgs.writeShellScriptBin "pds-restore" '' 7 + set -e 8 + 9 + echo "Starting PDS restore..." 10 + 11 + set -a 12 + source ${config.sops.secrets.s3.path} 13 + set +a 14 + 15 + LATEST=$(${pkgs.awscli2}/bin/aws s3 ls s3://$S3_BUCKET/backups/ | sort | tail -1 | awk '{print $4}') 16 + [ -z "$LATEST" ] && echo "No backups found." && exit 1 17 + 18 + echo "Latest backup: $LATEST" 19 + ${pkgs.awscli2}/bin/aws s3 cp s3://$S3_BUCKET/backups/$LATEST /tmp/$LATEST 20 + 21 + systemctl stop bluesky-pds 22 + rm -rf /var/lib/pds/* 23 + 24 + ${pkgs.gnutar}/bin/tar -xzf /tmp/$LATEST -C /var/lib/pds 25 + chown -R pds:pds /var/lib/pds 26 + 27 + systemctl start bluesky-pds 28 + 29 + echo "Restore completed." 30 + ''; 31 + backupScript = pkgs.writeShellScript "pds-backup-script" '' 32 + SOURCE_DIR="$PDS_DATA_DIR" 33 + S3_BUCKET="$S3_BUCKET" 34 + LOG_DIR="/var/log/pds-backup" 35 + DATE_LABEL=$(date +"%Y%m%d-%H%M") 36 + LOG_FILE="$LOG_DIR/$DATE_LABEL.log" 37 + ARCHIVE_FILE="/tmp/pds-backup-$DATE_LABEL.tar.gz" 38 + MAX_RETRIES=3 39 + RETRY_INTERVAL=60 40 + 41 + fail() { 42 + echo "$(date): ERROR: $1" | tee -a "$LOG_FILE" 43 + systemctl restart "$PDS_SERVICE" 2>/dev/null || echo "$(date): WARNING: Failed to restart PDS service after failure." >> "$LOG_FILE" 44 + exit 1 45 + } 46 + 47 + mkdir -p "$LOG_DIR" 48 + 49 + systemctl list-units --full -all | grep -Fq "$PDS_SERVICE.service" || fail "PDS service not found." 50 + 51 + systemctl stop "$PDS_SERVICE" 2>/dev/null && echo "$(date): Stopped PDS service." >> "$LOG_FILE" || echo "$(date): Failed to stop PDS service." >> "$LOG_FILE" 52 + 53 + [ -d "$SOURCE_DIR" ] || fail "Source directory $SOURCE_DIR does not exist." 54 + "$TAR_CMD" -czf "$ARCHIVE_FILE" -C "$SOURCE_DIR" . 2>> "$LOG_FILE" || fail "Failed to create archive." 55 + 56 + attempt=1 57 + while [ $attempt -le $MAX_RETRIES ]; do 58 + if "$AWS_CMD" s3 cp "$ARCHIVE_FILE" "s3://$S3_BUCKET/backups/$DATE_LABEL.tar.gz" 2>> "$LOG_FILE"; then 59 + echo "$(date): Upload successful." >> "$LOG_FILE" 60 + break 61 + else 62 + [ $attempt -lt $MAX_RETRIES ] && sleep $RETRY_INTERVAL || fail "Upload failed after retries." 63 + fi 64 + ((attempt++)) 65 + done 66 + 67 + rm -f "$ARCHIVE_FILE" 68 + 69 + systemctl start "$PDS_SERVICE" 2>/dev/null || fail "Failed to start PDS service." 70 + 71 + find "$LOG_DIR" -name "*.log" -mtime +90 -delete 72 + [ $(find "$LOG_FILE" -mtime +30) ] && mv "$LOG_FILE" "$LOG_FILE.old" && touch "$LOG_FILE" 73 + [ $(wc -l < "$LOG_FILE") -gt 1000 ] && mv "$LOG_FILE" "$LOG_FILE.old" && touch "$LOG_FILE" 74 + 75 + echo "$(date): Backup completed." >> "$LOG_FILE" 76 + ''; 77 + in { 78 + sops.secrets.s3 = { 79 + format = "dotenv"; 80 + sopsFile = ../../secrets/pds-backup-s3.env; 81 + }; 82 + 83 + environment.systemPackages = [restoreScript]; 84 + 85 + systemd.services.pds-backup = { 86 + description = "Backup PDS data to S3"; 87 + path = [pkgs.awscli2 pkgs.coreutils pkgs.gnutar pkgs.gzip]; 88 + serviceConfig = { 89 + ExecStart = "${backupScript}"; 90 + Environment = [ 91 + "PDS_DATA_DIR=${config.services.bluesky-pds.settings.PDS_DATA_DIRECTORY}" 92 + "PDS_SERVICE=bluesky-pds" 93 + "TAR_CMD=${pkgs.gnutar}/bin/tar" 94 + "AWS_CMD=${pkgs.awscli2}/bin/aws" 95 + ]; 96 + EnvironmentFile = [config.sops.secrets.s3.path]; 97 + User = "root"; 98 + Type = "oneshot"; 99 + }; 100 + }; 101 + 102 + systemd.timers.pds-backup = { 103 + wantedBy = ["timers.target"]; 104 + timerConfig = { 105 + OnCalendar = "daily"; 106 + Persistent = true; 107 + }; 108 + }; 109 + }
+54
hosts/reg/pds.nix
··· 1 + {config, ...}: { 2 + sops = { 3 + secrets.pds = { 4 + format = "dotenv"; 5 + sopsFile = ../../secrets/pds.env; 6 + restartUnits = ["bluesky-pds.service"]; 7 + }; 8 + secrets.cloudflare-api = { 9 + format = "dotenv"; 10 + sopsFile = ../../secrets/cloudflare-api.env; 11 + }; 12 + }; 13 + 14 + services.bluesky-pds = { 15 + enable = true; 16 + settings = { 17 + PDS_HOSTNAME = "0xf.fr"; 18 + }; 19 + environmentFiles = [config.sops.secrets.pds.path]; 20 + }; 21 + 22 + networking.firewall.allowedTCPPorts = [80 443]; 23 + 24 + security.acme = { 25 + defaults.email = "netop@0xf.fr"; 26 + acceptTerms = true; 27 + 28 + certs."0xf.fr" = { 29 + dnsProvider = "cloudflare"; 30 + credentialsFile = config.sops.secrets.cloudflare-api.path; 31 + group = config.services.nginx.group; 32 + 33 + domain = "0xf.fr"; 34 + extraDomainNames = ["*.0xf.fr"]; 35 + reloadServices = ["nginx"]; 36 + }; 37 + }; 38 + 39 + services.nginx = let 40 + pass = { 41 + useACMEHost = "0xf.fr"; 42 + forceSSL = true; 43 + locations."/" = { 44 + proxyPass = "http://127.0.0.1:${builtins.toString config.services.bluesky-pds.settings.PDS_PORT}"; 45 + proxyWebsockets = true; 46 + }; 47 + }; 48 + in { 49 + enable = true; 50 + recommendedProxySettings = true; 51 + recommendedTlsSettings = true; 52 + virtualHosts."~(.*)\\.0xf\\.fr$" = pass; 53 + }; 54 + }
+9
secrets/cloudflare-api.env
··· 1 + CLOUDFLARE_DNS_API_TOKEN=ENC[AES256_GCM,data:+fg0tls3FnG8BsKs5Btl7CLJiTlKqhvI97y8NNttEODb3wcCnAikeQ==,iv:KvAw3rwYNnMrMBz45NYDs9Fmncn1zlllK40rphGA1Z0=,tag:UOPjy4YFKnmPx4Wao6O8kA==,type:str] 2 + sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4VkhkMExId0IrSllMcGdw\nZEJsWkpBYkN5ejRnVDNpUGlYK1NQN0cyRWxjClR0dDBOM1N3NytMeGljdFV0bGdB\nSkxDT3JHcllFMGJKdnUya0VXQVdqN1EKLS0tIE1XWDE0OUcvdDJwdjV5WTVUcXYr\nTkdLb09yNlMrUVBwTmNkUkJaSThVNTgKqJatfgKN9WVeN9zlUClFWq5hBfiAlfvC\nwOLPxrc/VzNeUYlP5kLpuhGtsLAhHii21r0dawZlekKFoMXaPleDLw==\n-----END AGE ENCRYPTED FILE-----\n 3 + sops_age__list_0__map_recipient=age17cxj5zwkkxjkjvmpskpkyh6yt4xj4l8h6jyjxez3nmq6y9tvhqjsdp0m5j 4 + sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4OVhveExOajZRWFBicWpI\nMG80aEdvV3cyNGI4Q2lTZmxKOTBaT2ZvU0RRCnYwWFZ1T0QxY09ESEhmVDMxUHBB\nbmZwSWpNK0dGc1dGNlp1SWwwQVJDbGsKLS0tIEdseUJUZlhkbks2TWRVVkd6TFo5\ncGhnV2I5Q1NvYkFGbTkydVRHQm5ZTUkKBECA5NN+Gw8UBMvbdZ0Ky/LNDRCqcVYd\nQHEZgfhJh3PWcbfHGhZIl9ylYdcpv9LQ+3NZRr2VgRzL5TT1mpeGgA==\n-----END AGE ENCRYPTED FILE-----\n 5 + sops_age__list_1__map_recipient=age1j6j2ldpsj7jmchstwl3nktvatut9hzxnemmy6py84rrga5eaf93q5w8s39 6 + sops_lastmodified=2025-10-24T20:43:23Z 7 + sops_mac=ENC[AES256_GCM,data:/+KeoI3T69vXm+duvhViX1a58LHmFxRXHLacpmpHZ+bDzp+8e26uPZ0hX00XqIQWv3xgez62r/LphaJmjvNoUhGe9lI12QjUpRtilAbDXLUpJVF2bYaQh08SdGcey4OhaTj7oITBMP+V2EVlhOx/T5/qfrWCZqkef4OKqSBBD7g=,iv:gWqyF7cQel9NtIEMYWGZ4vBDKWVwKbJpDTQVu9nb/Do=,tag:c+gT0jxGfhhSHRqr6YOv/g==,type:str] 8 + sops_unencrypted_suffix=_unencrypted 9 + sops_version=3.11.0
+12
secrets/pds-backup-s3.env
··· 1 + AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:5oKU0U+FeR666BTNL7gdb8Wnts/nvhCYDlGtetcq+Dc=,iv:i3i4ykyAR3tpfpDoke6renys9tZp/a6/JpRe7ajAnsg=,tag:S3yDGCIl+wG9tedXbcPbmw==,type:str] 2 + AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:3UEACvF1q20QRdSxVcTrMJNsjZmSsGHmX0fq98KMvnJJffjYO6h+ClNT+38aDhgh8Dd2VRujYMVTI6RXPn28DQ==,iv:bBEs9lMhDMoeH3HymUQEOT8Y13457xcrevKI89nXBeg=,tag:eSekCTOKUu2u1S7/Mcy9sg==,type:str] 3 + AWS_ENDPOINT_URL=ENC[AES256_GCM,data:bqp2c1pPg1ZWG2w8XF9dm+3wKMYFucxzNLmvlhoKYuIxJX5CZwUSrmDXsx4FXZtq0l2fIWUIMCRurE49Jq8QtL8M6GQ=,iv:j4uL5y6E3qd6KS7DALc/GdL2/HgpheQj2J/uuLZ7XZU=,tag:dWVbavob4IC02bY+EqfYGA==,type:str] 4 + S3_BUCKET=ENC[AES256_GCM,data:1q3k8mjG6kM=,iv:3nktB4AvrGmH6MfIijV3mPajO9088UWfuBOeM99hwCQ=,tag:cfLCokyYHWqvtCeokIGrtg==,type:str] 5 + sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2SkJUdWdYclR0U1pPUHpn\nc3pWSml5b3FOR3cvaVhNczJrbHA4NG83U1JZClVibTgyc3JBWC9LSXVJVmhZckxT\nSk1sN040MmRKd3BodUdFOVRxMTdGcUEKLS0tIHhjZUs5TXhhMm1nK3RQc3BJMTJG\nZmQ5cGlRbXNiczBwUnd1aTFaWk94bUkKjQEr03lQRuWxzQ6uTCRgpTj3C/FwBFwz\nQoYYAyqN5RBAJvN+7TFewgGgSBu+bE2RFazAxOizdXQXAmgceZnT5A==\n-----END AGE ENCRYPTED FILE-----\n 6 + sops_age__list_0__map_recipient=age17cxj5zwkkxjkjvmpskpkyh6yt4xj4l8h6jyjxez3nmq6y9tvhqjsdp0m5j 7 + sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpdEo3Nlp6RmgvZER2ZWtS\nU2dFazU0Q2FndnZBL1g2Ky9lcjNKRDBoaGlBCmlIVG9iUXVmazkzb2NTeDhXKzhT\nc3JQZjhhb0h3VjI2b2tpcGxiVG9NQmMKLS0tIG9tTjlPLzVQSjRLSkw2djM5QzQ2\nenJ6RFJUazlmQStJRStudlhuV1Rsc1UKMaAFJszBkgONafeLGMYO1zzS+dHzX3Uh\n8wwni17QDZTTE5Q2P8KPBquVWyzh7UUI3GhbxuZhANfs/RA5AQlg2w==\n-----END AGE ENCRYPTED FILE-----\n 8 + sops_age__list_1__map_recipient=age1j6j2ldpsj7jmchstwl3nktvatut9hzxnemmy6py84rrga5eaf93q5w8s39 9 + sops_lastmodified=2025-10-24T22:20:59Z 10 + sops_mac=ENC[AES256_GCM,data:h7telhUinjAmbijnepEv3NXjvtYuCvQzCfQ6PA5vqr9QY8kAUlqICLofOP9+SVocUR0LlXsoKfmLcdIMMpZG1Jb6D0PQ8RuG4sTm5BSrWvvPj+U/Cm8JuPAqtOie0vWPBsL8vHg9BQGrUWEVtiK9fBLVmEvafVj9mmKzbwBZNOg=,iv:hzi5UOVUAdQW2wY8fAxLysfaLUertVLYo1D4H9Ubz+4=,tag:fRB9Lerke0aDkmcu+OzIfw==,type:str] 11 + sops_unencrypted_suffix=_unencrypted 12 + sops_version=3.11.0
+13
secrets/pds.env
··· 1 + PDS_JWT_SECRET=ENC[AES256_GCM,data:7rkOzDdKVBgBIBDperVfo1lv39/TD5LrXeSto4+FT8s=,iv:eFUiIdDH5xxFxIxq4njilmTframihV99CYZQiKt9Wto=,tag:fHPsW6hudDKjhPnKHems0Q==,type:str] 2 + PDS_ADMIN_PASSWORD=ENC[AES256_GCM,data:GHtiwkT7SMqTDP91CpsdBvakeg==,iv:ka8bXoFJL23P3TDkXON1yuF6z1NOfFjRRaGv5L2wAB4=,tag:FriN0YZAgAE/S5nwcMoGng==,type:str] 3 + PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=ENC[AES256_GCM,data:OjAyEohVNTmWKapzJX1e/ed6ZbWL3I5+SgM93Bm89qymJWGX90ssca+fAcny38g2sZJkiJWjfUulE5sTMAbGog==,iv:vquXtXGhDMEFNJ6tqE76HTv1PZtGjtIL3+K05eY7KxE=,tag:sVDuGtkxfYL6csJ4d80+dQ==,type:str] 4 + PDS_EMAIL_SMTP_URL=ENC[AES256_GCM,data:u2ylh4YK4aR5WhOFTazwLk3i2CU71Yakcb3pyoc2D+i94KMX0xEWKLb0xKpBnKyVBEI9CLMpiLUOPR1CuJRVv/aOR4yBIA==,iv:/NuzdQxYq0r4z9iTLGRi4aa/qBxFp0NeyNIOxIoEjbY=,tag:3dhfx9BbMdTahW02mYwKjA==,type:str] 5 + PDS_EMAIL_FROM_ADDRESS=ENC[AES256_GCM,data:Xqly+3nqg8VpOQ==,iv:Dx0YD81azbMt2iT6EaqmJRXCXxhycM/pyW9eFH1cHGE=,tag:zi6bE3BNu443IFaTZDe3Wg==,type:str] 6 + sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwS0dHSU9pd2tWVzZPZDlQ\nYVd6NjF0SkFrSGNUUUprUGN0c1Yzdk5BYXpZCnBiajU0cGVDQ0UwUVl6dHg5SjFO\nU3RScFhiTlZuYUJ6aC84K1F6YnEza2cKLS0tIDNFZ21BdHRTQTFGMkR3MDBxOHhG\nOVByYktJdjlsbTlNSDMvOTkvK0FyeU0KYBMndJPeIMpnqSrAUs0Em5Pbm7GBo/0e\nsaBKyYhn/pIPtJCyOiISqfXwMFHsiWCtd3dEejunG0x9eEkjWzDKqw==\n-----END AGE ENCRYPTED FILE-----\n 7 + sops_age__list_0__map_recipient=age17cxj5zwkkxjkjvmpskpkyh6yt4xj4l8h6jyjxez3nmq6y9tvhqjsdp0m5j 8 + sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2WW9pWHVZSWl4eWdCUGUv\nT3VSdVVPdVh0bENRanFjNnJVdlhQS2JvbzNRCmY2YnZmVlNhSDFYZ2VDWnN1MHp5\nS3lyMEpOa0hmTVdFeUtIQ1lrMWZVODgKLS0tIC93Q2hzb0pxdUNySEYwa1VyUjFN\nNk9tekkvUC9JT3NpcENqTHF5TUIyWXMKJ082QrvQ6QRfJ1RZqL9sSyKCmTLi+I9R\nxuo8E1SfP/204OQaihP6+9cCbLh3yYtESaAFw2Alisnoe4PvSR2I9g==\n-----END AGE ENCRYPTED FILE-----\n 9 + sops_age__list_1__map_recipient=age1j6j2ldpsj7jmchstwl3nktvatut9hzxnemmy6py84rrga5eaf93q5w8s39 10 + sops_lastmodified=2025-10-24T21:30:51Z 11 + sops_mac=ENC[AES256_GCM,data:T7pttRlFl7HQwRY+AAXIX00wsABEyiHJsKPxXatl50Auaa+S3JJss56tVhphp2iMch7Z0nxnVT9kS03eAU1RUV0wHgCyu0QWNAib7PbUQIQvVq7pqF8SXORNuvwHJj2S9niASIDQqIenLYzUCRyq6tBnJ/XkW9JbiaOxs6w75G4=,iv:nvo7iAVjYkN45RZsqV3nGWzoaPcg74NRdhzy44lIi+Y=,tag:nIPrJy1srFn/nFTRjtdLbg==,type:str] 12 + sops_unencrypted_suffix=_unencrypted 13 + sops_version=3.11.0