My nix-darwin and NixOS config
3
fork

Configure Feed

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

feat: sharkey??

+282 -150
+1 -1
.sops.yaml
··· 27 27 creation_rules: 28 28 # ── Secrets available on all machines ────────────────────────────────────── 29 29 # ── Server-only secrets ───────────────────────────────────────────────────── 30 - - path_regex: secrets/(pds\.env|cloudflare\.token|cloudflare-acme\.env|cloudflare-acme-croft-click\.env|cf-tunnel\.json|forgejo\.env|nextcloud-admin-pass|nextcloud-smtp-pass|vaultwarden\.env|gotosocial\.env)$ 30 + - path_regex: secrets/(pds\.env|cloudflare\.token|cloudflare-acme\.env|cloudflare-acme-croft-click\.env|cf-tunnel\.json|forgejo\.env|nextcloud-admin-pass|nextcloud-smtp-pass|vaultwarden\.env|sharkey\.env)$ 31 31 key_groups: 32 32 - age: 33 33 - *ewan
+13 -13
modules/options.nix
··· 433 433 type = bool; 434 434 default = false; 435 435 }; 436 - gotosocial.enable = mkOption { 436 + sharkey.enable = mkOption { 437 437 type = bool; 438 438 default = false; 439 - description = "Enable GoToSocial ActivityPub server."; 439 + description = "Enable Sharkey ActivityPub / microblogging server."; 440 440 }; 441 441 timemachine = { 442 442 enable = mkOption { ··· 659 659 }; 660 660 }; 661 661 662 - # ── GoToSocial ───────────────────────────────────────────────────────────── 663 - gotosocial = { 662 + # ── Sharkey ─────────────────────────────────────────────────────────────── 663 + sharkey = { 664 664 hostname = mkOption { 665 665 type = str; 666 666 default = "ap.ewancroft.uk"; 667 - description = "Public hostname for GoToSocial (the \"host\" config key)."; 668 - }; 669 - accountDomain = mkOption { 670 - type = str; 671 - default = "ewancroft.uk"; 672 - description = "Domain for user handles — accounts appear as @user@accountDomain."; 667 + description = "Public hostname for Sharkey (same as the old GTS host to preserve actor URLs)."; 673 668 }; 674 669 port = mkOption { 675 670 type = int; 676 - default = 8080; 677 - description = "Internal GoToSocial HTTP port."; 671 + default = 3007; 672 + description = "Internal Sharkey HTTP port."; 678 673 }; 679 674 caddyPort = mkOption { 680 675 type = int; 681 - default = 3006; 676 + default = 3008; 682 677 description = "Caddy virtual host port — used by the Cloudflare tunnel."; 678 + }; 679 + mediaDir = mkOption { 680 + type = str; 681 + default = "/srv/sharkey/media"; 682 + description = "Directory for Sharkey uploaded media (avatars, attachments, etc.)"; 683 683 }; 684 684 }; 685 685
+2 -2
modules/server/cloudflare-tunnel.nix
··· 63 63 // lib.optionalAttrs cfg.services.forgejo.enable { 64 64 ${cfg.forgejo.hostname} = "http://127.0.0.1:${toString cfg.forgejo.caddyPort}"; 65 65 } 66 - // lib.optionalAttrs cfg.services.gotosocial.enable { 67 - ${cfg.gotosocial.hostname} = "http://127.0.0.1:${toString cfg.gotosocial.caddyPort}"; 66 + // lib.optionalAttrs cfg.services.sharkey.enable { 67 + ${cfg.sharkey.hostname} = "http://127.0.0.1:${toString cfg.sharkey.caddyPort}"; 68 68 }; 69 69 in 70 70 lib.mkIf cfg.services.cloudflare.enable {
-125
modules/server/gotosocial.nix
··· 1 - ############################################################################## 2 - # GoToSocial ActivityPub server — NixOS module. 3 - # 4 - # Architecture: 5 - # GoToSocial (127.0.0.1:cfg.gotosocial.port) 6 - # ↑ reverse proxy 7 - # Caddy (127.0.0.1:cfg.gotosocial.caddyPort — internal only, no TLS here) 8 - # ↑ Cloudflare tunnel (outbound only, no firewall ports needed) 9 - # 10 - # Account handle trick: 11 - # host = ap.ewancroft.uk (where the server lives) 12 - # account-domain = ewancroft.uk (what handles show as) 13 - # → accounts appear as @ewan@ewancroft.uk 14 - # 15 - # WebFinger: 16 - # ewancroft.uk/.well-known/webfinger redirects to 17 - # ap.ewancroft.uk/.well-known/webfinger (handled in the website repo's 18 - # vercel.json). Clients follow the redirect and GoToSocial responds normally. 19 - # 20 - # First-run (once the service is up): 21 - # gotosocial-admin account create \ 22 - # --username ewan --email contact@ewancroft.uk --password <pw> 23 - # gotosocial-admin account confirm --username ewan 24 - # gotosocial-admin account promote --username ewan 25 - ############################################################################## 26 - { 27 - config, 28 - lib, 29 - ... 30 - }: 31 - let 32 - cfg = config.myConfig; 33 - gts = cfg.gotosocial; 34 - gtsPort = toString gts.port; 35 - caddyPort = toString gts.caddyPort; 36 - in 37 - lib.mkIf cfg.services.gotosocial.enable { 38 - 39 - sops.secrets."gotosocial.env" = { 40 - sopsFile = ../../secrets/gotosocial.env; 41 - format = "dotenv"; 42 - owner = "gotosocial"; 43 - group = "gotosocial"; 44 - mode = "0400"; 45 - }; 46 - 47 - services.gotosocial = { 48 - enable = true; 49 - environmentFile = config.sops.secrets."gotosocial.env".path; 50 - settings = { 51 - host = gts.hostname; 52 - account-domain = gts.accountDomain; 53 - port = gts.port; 54 - bind-address = "127.0.0.1"; 55 - db-type = "sqlite"; 56 - db-address = "/srv/gotosocial/sqlite.db"; 57 - storage-local-base-path = "/srv/gotosocial/storage"; 58 - accounts-registration-open = false; 59 - accounts-allow-custom-css = false; 60 - letsencrypt-enabled = false; 61 - trusted-proxies = [ 62 - "127.0.0.1/32" 63 - # Cloudflare IPv4 ranges — required because requests arrive via CF → Caddy → GTS 64 - # and GTS needs to trust the full proxy chain to resolve the real client IP. 65 - # https://www.cloudflare.com/ips-v4/ 66 - "173.245.48.0/20" 67 - "103.21.244.0/22" 68 - "103.22.200.0/22" 69 - "103.31.4.0/22" 70 - "141.101.64.0/18" 71 - "108.162.192.0/18" 72 - "190.93.240.0/20" 73 - "188.114.96.0/20" 74 - "197.234.240.0/22" 75 - "198.41.128.0/17" 76 - "162.158.0.0/15" 77 - "104.16.0.0/13" 78 - "104.24.0.0/14" 79 - "172.64.0.0/13" 80 - "131.0.72.0/22" 81 - ]; 82 - # Tell federation partners this is an English-language instance. 83 - landing-page-user = "ewan"; 84 - instance-languages = [ "en" ]; 85 - # Persist the Wazero/WASM ffmpeg compilation cache across restarts. 86 - # Without this GoToSocial recompiles on every cold start (~100MiB, slow). 87 - wazero-compilation-cache = "/srv/gotosocial/wazero-cache"; 88 - # SMTP via Resend — useful for password resets even on a single-user instance. 89 - smtp-host = "smtp.resend.com"; 90 - smtp-port = 587; 91 - smtp-username = "resend"; 92 - smtp-from = "gts@server.ewancroft.uk"; 93 - # Emoji 94 - media-emoji-local-max-size = 5242880; # 5 MiB 95 - }; 96 - }; 97 - 98 - systemd.services.gotosocial = { 99 - after = [ "srv.mount" ]; 100 - wants = [ "srv.mount" ]; 101 - serviceConfig = { 102 - ReadWritePaths = [ "/srv/gotosocial" ]; 103 - Restart = lib.mkForce "always"; 104 - RestartSec = cfg.server.servicePolicy.restartSec; 105 - }; 106 - unitConfig = { 107 - StartLimitIntervalSec = cfg.server.servicePolicy.startLimitIntervalSec; 108 - StartLimitBurst = cfg.server.servicePolicy.startLimitBurst; 109 - }; 110 - }; 111 - 112 - services.caddy.virtualHosts."http://${gts.hostname}:${caddyPort}" = { 113 - extraConfig = '' 114 - handle { 115 - reverse_proxy http://127.0.0.1:${gtsPort} { 116 - # Cloudflare tunnel passes CF-Connecting-IP with the real client IP. 117 - # Forward it as X-Real-IP so GTS can resolve the actual remote address. 118 - header_up X-Forwarded-For {http.request.header.CF-Connecting-IP} 119 - header_up X-Real-IP {http.request.header.CF-Connecting-IP} 120 - } 121 - header Cache-Control "no-store, private" 122 - } 123 - ''; 124 - }; 125 - }
+107
modules/server/sharkey.nix
··· 1 + ############################################################################## 2 + # Sharkey ActivityPub / microblogging server — NixOS module. 3 + # 4 + # Architecture: 5 + # Sharkey (127.0.0.1:cfg.sharkey.port) 6 + # ↑ reverse proxy 7 + # Caddy (http://ap.ewancroft.uk:cfg.sharkey.caddyPort — internal only) 8 + # ↑ Cloudflare tunnel (outbound only, no firewall ports needed) 9 + # 10 + # Account identity: 11 + # settings.url = "https://ap.ewancroft.uk/" (Sharkey's public host) 12 + # WebFinger redirect at ewancroft.uk (Vercel) still points to 13 + # ap.ewancroft.uk, so handles resolve as @ewan@ewancroft.uk unchanged. 14 + # 15 + # PostgreSQL + Redis: 16 + # services.sharkey.setupPostgresql and setupRedis both default to true in 17 + # nixpkgs, so local instances are provisioned and wired automatically. 18 + # 19 + # Secrets (secrets/sharkey.env — sops dotenv): 20 + # MK_CONFIG_DB_PASS=... PostgreSQL password for the sharkey user 21 + # MK_CONFIG_SMTP_PASS=... Resend API key 22 + # 23 + # First-run: 24 + # Open https://ap.ewancroft.uk — Sharkey prompts for initial setup. 25 + # Then run the migration script to inject the old GTS RSA keypair. 26 + ############################################################################## 27 + { 28 + config, 29 + lib, 30 + ... 31 + }: 32 + let 33 + cfg = config.myConfig; 34 + sk = cfg.sharkey; 35 + skPort = toString sk.port; 36 + caddyPort = toString sk.caddyPort; 37 + in 38 + lib.mkIf cfg.services.sharkey.enable { 39 + 40 + sops.secrets."sharkey.env" = { 41 + sopsFile = ../../secrets/sharkey.env; 42 + format = "dotenv"; 43 + owner = "sharkey"; 44 + group = "sharkey"; 45 + mode = "0400"; 46 + }; 47 + 48 + services.sharkey = { 49 + enable = true; 50 + environmentFiles = [ config.sops.secrets."sharkey.env".path ]; 51 + 52 + # Automatically provision a local PostgreSQL database and Redis instance. 53 + # Both default to true in nixpkgs — kept explicit here for clarity. 54 + setupPostgresql = true; 55 + setupRedis = true; 56 + openFirewall = false; 57 + 58 + settings = { 59 + # Public-facing URL — do NOT change after initial setup. 60 + url = "https://${sk.hostname}/"; 61 + 62 + port = sk.port; 63 + address = "127.0.0.1"; 64 + 65 + # Media storage on /srv — survives rebuilds, same disk as other services. 66 + mediaDirectory = sk.mediaDir; 67 + 68 + # SMTP via Resend — for password resets / notifications. 69 + # Password injected via MK_CONFIG_SMTP_PASS in the env file. 70 + smtp = { 71 + host = "smtp.resend.com"; 72 + port = 587; 73 + secure = false; # STARTTLS 74 + user = "resend"; 75 + from = "sharkey@server.ewancroft.uk"; 76 + }; 77 + }; 78 + }; 79 + 80 + # ── Keep media on /srv (same physical disk as all other service data) ────── 81 + systemd.services.sharkey = { 82 + after = [ "srv.mount" ]; 83 + wants = [ "srv.mount" ]; 84 + serviceConfig = { 85 + ReadWritePaths = [ sk.mediaDir ]; 86 + Restart = lib.mkForce "always"; 87 + RestartSec = cfg.server.servicePolicy.restartSec; 88 + }; 89 + unitConfig = { 90 + StartLimitIntervalSec = cfg.server.servicePolicy.startLimitIntervalSec; 91 + StartLimitBurst = cfg.server.servicePolicy.startLimitBurst; 92 + }; 93 + }; 94 + 95 + # ── Caddy vhost — same pattern as every other CF-tunnel service ─────────── 96 + services.caddy.virtualHosts."http://${sk.hostname}:${caddyPort}" = { 97 + extraConfig = '' 98 + handle { 99 + reverse_proxy http://127.0.0.1:${skPort} { 100 + # Cloudflare tunnel passes CF-Connecting-IP with the real client IP. 101 + header_up X-Forwarded-For {http.request.header.CF-Connecting-IP} 102 + header_up X-Real-IP {http.request.header.CF-Connecting-IP} 103 + } 104 + } 105 + ''; 106 + }; 107 + }
+149
scripts/migrate-gts-to-sharkey.sh
··· 1 + #!/usr/bin/env bash 2 + # ============================================================================= 3 + # migrate-gts-to-sharkey.sh — identity-only migration 4 + # 5 + # Preserves @ewan@ewancroft.uk by: 6 + # 1. Extracting the RSA keypair from GTS SQLite 7 + # 2. Stopping GTS, switching to Sharkey via nixos-rebuild 8 + # 3. Injecting the old RSA keypair into Sharkey's PostgreSQL 9 + # 10 + # Run as root on the NixOS server. 11 + # Prereq: sharkey.nix written + secrets/sharkey.env encrypted + options updated. 12 + # ============================================================================= 13 + set -euo pipefail 14 + 15 + GTS_USERNAME="ewan" 16 + GTS_DB="/srv/gotosocial/sqlite.db" 17 + GTS_SERVICE="gotosocial" 18 + AP_HOSTNAME="ap.ewancroft.uk" 19 + ACCOUNT_DOMAIN="ewancroft.uk" 20 + SHARKEY_DB="sharkey" 21 + KEY_BACKUP="/root/gts-keypair-$(date +%Y%m%d-%H%M%S).env" 22 + 23 + RED='\033[0;31m' 24 + GREEN='\033[0;32m' 25 + YELLOW='\033[1;33m' 26 + NC='\033[0m' 27 + info() { echo -e "${GREEN}[INFO]${NC} $*"; } 28 + warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } 29 + error() { 30 + echo -e "${RED}[ERROR]${NC} $*" >&2 31 + exit 1 32 + } 33 + confirm() { 34 + read -r -p "$(echo -e "${YELLOW}${1} [y/N] ${NC}")" r 35 + [[ "${r,,}" == "y" ]] 36 + } 37 + 38 + # ── Pre-flight ──────────────────────────────────────────────────────────────── 39 + [[ "$(id -u)" -eq 0 ]] || error "Run as root." 40 + [[ -f "$GTS_DB" ]] || error "GTS DB not found: $GTS_DB" 41 + for cmd in sqlite3 psql systemctl curl jq; do 42 + command -v "$cmd" &>/dev/null || error "Missing required command: $cmd" 43 + done 44 + 45 + # ── Step 1: Extract RSA keys ────────────────────────────────────────────────── 46 + info "Extracting RSA keypair for @${GTS_USERNAME} from SQLite..." 47 + 48 + PRIVATE_KEY=$(sqlite3 "$GTS_DB" \ 49 + "SELECT private_key FROM accounts WHERE username='${GTS_USERNAME}' AND domain IS NULL LIMIT 1;") 50 + PUBLIC_KEY=$(sqlite3 "$GTS_DB" \ 51 + "SELECT public_key FROM accounts WHERE username='${GTS_USERNAME}' AND domain IS NULL LIMIT 1;") 52 + 53 + [[ -n "$PRIVATE_KEY" && -n "$PUBLIC_KEY" ]] || error "Could not extract keys — check username." 54 + 55 + # Persist to a backup file in case we need to re-run step 3 56 + { 57 + echo "PRIVATE_KEY<<EOF" 58 + echo "$PRIVATE_KEY" 59 + echo "EOF" 60 + echo "PUBLIC_KEY<<EOF" 61 + echo "$PUBLIC_KEY" 62 + echo "EOF" 63 + } >"$KEY_BACKUP" 64 + chmod 600 "$KEY_BACKUP" 65 + info "Keys backed up to: $KEY_BACKUP" 66 + 67 + # ── Step 2: Stop GTS, rebuild with Sharkey ──────────────────────────────────── 68 + warn "About to stop GoToSocial. ap.ewancroft.uk will be down until Sharkey starts." 69 + confirm "Continue?" || { 70 + info "Aborted." 71 + exit 0 72 + } 73 + 74 + info "Stopping GoToSocial..." 75 + systemctl stop "$GTS_SERVICE" 76 + 77 + warn "Now run: nixos-rebuild switch --flake .#server" 78 + warn "(services.gotosocial.enable = false, services.sharkey.enable = true)" 79 + read -r -p "$(echo -e "${YELLOW}Press Enter once nixos-rebuild switch completes...${NC}")" 80 + 81 + systemctl is-active --quiet sharkey || error "Sharkey is not running. Check: journalctl -u sharkey -n 50" 82 + systemctl is-active --quiet postgresql || error "PostgreSQL is not running." 83 + info "Sharkey + PostgreSQL are up." 84 + 85 + # ── Step 3: Create account in Sharkey ───────────────────────────────────────── 86 + warn "Create the @${GTS_USERNAME} account in the Sharkey admin panel now." 87 + warn " https://${AP_HOSTNAME} -> Admin -> Users -> Create" 88 + warn "Username must be: ${GTS_USERNAME}" 89 + read -r -p "$(echo -e "${YELLOW}Press Enter once the account exists...${NC}")" 90 + 91 + SHARKEY_USER_ID=$(sudo -u postgres psql -d "$SHARKEY_DB" -tA \ 92 + -c "SELECT id FROM \"user\" WHERE username='${GTS_USERNAME}' AND host IS NULL LIMIT 1;" 2>/dev/null || true) 93 + 94 + [[ -n "$SHARKEY_USER_ID" ]] || error "User @${GTS_USERNAME} not found in Sharkey DB. Create the account first." 95 + info "Sharkey user ID: ${SHARKEY_USER_ID}" 96 + 97 + # ── Step 4: Inject old RSA keypair ──────────────────────────────────────────── 98 + info "Injecting GTS RSA keypair into Sharkey..." 99 + 100 + HAS_KEYPAIR_TABLE=$(sudo -u postgres psql -d "$SHARKEY_DB" -tA \ 101 + -c "SELECT to_regclass('public.user_keypair');" 2>/dev/null || echo "") 102 + 103 + if [[ "$HAS_KEYPAIR_TABLE" == "user_keypair" ]]; then 104 + sudo -u postgres psql -d "$SHARKEY_DB" -c \ 105 + "INSERT INTO user_keypair (\"userId\", \"publicKey\", \"privateKey\") 106 + VALUES ('${SHARKEY_USER_ID}', \$pem\$${PUBLIC_KEY}\$pem\$, \$pem\$${PRIVATE_KEY}\$pem\$) 107 + ON CONFLICT (\"userId\") DO UPDATE 108 + SET \"publicKey\" = EXCLUDED.\"publicKey\", 109 + \"privateKey\" = EXCLUDED.\"privateKey\";" 110 + info "Updated user_keypair table." 111 + else 112 + # Older schema — keys inline on user table 113 + sudo -u postgres psql -d "$SHARKEY_DB" -c \ 114 + "UPDATE \"user\" 115 + SET \"publicKey\" = \$pem\$${PUBLIC_KEY}\$pem\$, 116 + \"privateKey\" = \$pem\$${PRIVATE_KEY}\$pem\$ 117 + WHERE id = '${SHARKEY_USER_ID}';" 118 + info "Updated user table (inline key columns)." 119 + fi 120 + 121 + info "Restarting Sharkey..." 122 + systemctl restart sharkey 123 + sleep 5 124 + systemctl is-active --quiet sharkey || error "Sharkey failed to restart." 125 + 126 + # ── Step 5: Verify ──────────────────────────────────────────────────────────── 127 + info "Verifying WebFinger..." 128 + WF=$(curl -fsSL "https://${ACCOUNT_DOMAIN}/.well-known/webfinger?resource=acct:${GTS_USERNAME}@${ACCOUNT_DOMAIN}" 2>/dev/null || true) 129 + if echo "$WF" | jq -e '.subject' &>/dev/null; then 130 + info "WebFinger OK: $(echo "$WF" | jq -r '.subject')" 131 + else 132 + warn "WebFinger returned unexpected result — check your Vercel redirect." 133 + fi 134 + 135 + info "Verifying actor public key..." 136 + ACTOR=$(curl -fsSL -H 'Accept: application/activity+json' "https://${AP_HOSTNAME}/users/${GTS_USERNAME}" 2>/dev/null || true) 137 + if echo "$ACTOR" | jq -e '.publicKey.publicKeyPem' &>/dev/null; then 138 + ACTOR_KEY=$(echo "$ACTOR" | jq -r '.publicKey.publicKeyPem') 139 + if [[ "$ACTOR_KEY" == "$PUBLIC_KEY" ]]; then 140 + info "Actor public key matches GTS original. Identity preserved." 141 + else 142 + warn "Public key mismatch — Sharkey may not have reloaded yet. Try: systemctl restart sharkey" 143 + fi 144 + else 145 + warn "Could not retrieve actor JSON — Sharkey may still be starting up." 146 + fi 147 + 148 + echo "" 149 + info "Done. Key backup retained at: ${KEY_BACKUP}"
-9
secrets/gotosocial.env
··· 1 - GTS_SMTP_PASSWORD=ENC[AES256_GCM,data:a+hO2pq/30NGBXOv4Bod2GoUfNAQidfpPXXjQ+YJjl9LQeL1,iv:eY/Er7x+wzFP7dyO12qnX5kTiD+8y0Otxg/ibWI1LM0=,tag:nU9CrItO/wfd00x9VJSPQg==,type:str] 2 - sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArMmRTczdhUFBUcS9MUDUw\nOTJ1di9ydEUyUkJISXpkeDlaZmg3VzdMVDNvCkkwblpDZ2FuMGFSVk9hNHdRT0dm\ncXNCc1R1dU82eGwrZjZHeUxJcWtIV0kKLS0tIHBINGhvMktoUzYxQjRUYUZMeWc2\nQjJnM0FXUDdUK3E2anoyWE9iemxScU0KkOWOp9bP63Cate/0eiTSk9hrkCcgO6NE\nfKiPTSahd/5/rWAN4WsmwoceqKNbbI/5AR2qjwSqAq5pDhB6wotNpQ==\n-----END AGE ENCRYPTED FILE-----\n 3 - sops_age__list_0__map_recipient=age17ulnk7akn9zfwtc87vsexrr809xj6gkkcp2rkez6xtzyrqclpshqfew5wy 4 - sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTdHlDemt4WlA5MFRxYk1h\nRlI0L1RxRk5jWmVoMzBmaERjSE1wL1k2YjA0Ckp2Mk95NGl1Zks3ckZxeEtLOUVq\nUVg0THVmU1VxL2VSMHdpa1pmWU16bzgKLS0tIERMWUpuOGg4R1Z6cjIxVndlMWxI\ndGFyN295TnpqRmVBTUdRc0Q0dFkvakkKRJksDJ9cFvbAnm8tGTJVTDG5jSX1wNi5\ncVm7pIWv6S9PFuvzUN7JxO932WLNYQ8EiJ2Oh3Ux7pYtfeNpSIuUng==\n-----END AGE ENCRYPTED FILE-----\n 5 - sops_age__list_1__map_recipient=age1xvny7h8cahajamj4lz9cew5w0dqlge0yy6tys7szj42grcrl95jqsrutsu 6 - sops_lastmodified=2026-03-14T00:05:00Z 7 - sops_mac=ENC[AES256_GCM,data:mfBOHXWFImHxMwhfD8IDRH58Mmd82cYsNmVnbVKGlnHbuvSh+FzjSpyj4Or5WakYJ0p01vHQaa/Np9xXHYlvX9sAxuQpw0xEyP7blVbOUwZhNg9+ClYPU67xnrG4opxcDedfXyxmhIdwwlWU+qZoRTrOHo8gyqzHXvPy3XlWZ+Y=,iv:hHksn+cjbTwMc9eVPvTxwYKu2Tt723p73JMVd+ZRb04=,tag:LshhH7yOBPwcqp3wcFVaaw==,type:str] 8 - sops_unencrypted_suffix=_unencrypted 9 - sops_version=3.12.1
+10
secrets/sharkey.env
··· 1 + MK_CONFIG_DB_PASS=ENC[AES256_GCM,data:CTf22AojiLUBos/xpq1aCgkOKMLAfDWvX4t7VMT63uQ+hzs2IkI6QpBgSXoI8n6uBm3y+73ku3J0k2LANb9CQZHnvDtr5Ys0b4opfUyBYhvzZloDYdLk9aP9G8i68ZHcTnIaCKzFmchMSybKtmpMUVgip478kIe7tRVSdEkfxs4=,iv:05upRsv4MzbUWyF8c2bZIczD+Gme2yjSdVkUbgF1Z4M=,tag:VeY90o3/yO4lzkZ7W7XBng==,type:str] 2 + MK_CONFIG_SMTP_PASS=ENC[AES256_GCM,data:Rb1XOIpDswqnut4sxGF9Nhrtvg1ngJh5jpxlBbFWjjzavl7M,iv:ptnKuNVhgBCQ8ctLobOc+swuFVHO3wS2bfHop7Vqaj8=,tag:mITZSdNKhSXDn9nj1FV8eA==,type:str] 3 + sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBueUFSRURHTm1RRzVaTlND\nZ0dJck9FbjV4L1V1d3EzSi9UdHlDVDdqT3hvClpvRE80TE8vZVlRV0VKcG0rTTE1\nc1lNU29DbGt2WDRUcXV6VGs2SGNyUVEKLS0tIDR2VEYveXE1VFpDeDNtZnMvV0Qx\nT202bThKeDFOTVpuVGw3aURPL3RSQncKkPWc1sVnkesMjsSN4UQOAvXLCZ3lQ8zO\nKQOPBTCG4C9ok/gjCK0ByAPQgjzI1AdCscgr1KN5E+LpQXIyHZko/w==\n-----END AGE ENCRYPTED FILE-----\n 4 + sops_age__list_0__map_recipient=age17ulnk7akn9zfwtc87vsexrr809xj6gkkcp2rkez6xtzyrqclpshqfew5wy 5 + sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAybUtQRXltWG0yL3VUeHBi\nY1BOYmNReGhqeE5Yc2VpemZxWXpIb1N3d1RzCmtISXdUODg5TXJVZHdEZmYwRzlL\naVpWbVZPMDJMNExGdU1KUzBVZXcvTmcKLS0tIFZxT1FXaEMwcjErdUdoVTU5bzZL\nUkZlSFpnVzVBRGFuMytCdFpwc0FLZ3cK05gLE4pt74v2H3tN/ZvDLK1q39htPXSB\nE53hudTzU4TuEpLtW4SH1HEXEQEBs4Nfv1AOX2MwYnRhaGP/9NyZJA==\n-----END AGE ENCRYPTED FILE-----\n 6 + sops_age__list_1__map_recipient=age1xvny7h8cahajamj4lz9cew5w0dqlge0yy6tys7szj42grcrl95jqsrutsu 7 + sops_lastmodified=2026-03-19T18:22:23Z 8 + sops_mac=ENC[AES256_GCM,data:CwT93Hcnbiu+bzUtTE/aRv35Y0ejfUVin9PrfTbjfnLd8So9mFtDvA+IqbpokIoMH3BTV/rKhB5ybVlaUUxfIVA9kquzK+jkhFl2nOYg8n/Dkb5BbAPwLe74Phv//vQhuC2YeadlRoRTXDVW261mSgcP2Amo8Lrh1AQb/SWiEOc=,iv:dbX4LknZ+lVLvF6ifWE69EHgZvhljM+1xo8a+9dN94k=,tag:XDjE0jY5pm3egLiwZvboIQ==,type:str] 9 + sops_unencrypted_suffix=_unencrypted 10 + sops_version=3.12.1