{ "schema": 1, "updated": "2026-09-12", "apps": { "aiui": { "version": "0.1.0", "manifest": { "app": { "id": "aiui", "name": "AI Assistant", "version": "0.1.0", "upstream": { "kind": "internal" }, "description": "Conversational AI interface for Archipelago. Quarantined \u2014 communicates only via context broker.", "internal": true, "container": { "image": "localhost/archipelago-aiui:latest", "pull_policy": "always" }, "resources": { "cpu_limit": 1, "memory_limit": "512Mi", "disk_limit": "1Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "user": 1000, "seccomp_profile": "default", "network_policy": "isolated", "apparmor_profile": "aiui" }, "ports": [ { "host": 5180, "container": 80, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "health_check": { "type": "http", "endpoint": "http://localhost:80", "path": "/", "interval": "60s", "timeout": "5s", "retries": 3 } } } }, "alby-hub": { "version": "1.23.0", "manifest": { "app": { "id": "alby-hub", "name": "Alby Hub", "version": "1.23.0", "upstream": { "kind": "github", "repo": "getAlby/hub" }, "description": "Self-custodial Lightning wallet hub. Runs its own Lightning node on your Archipelago and connects your apps to it over Nostr Wallet Connect \u2014 one hub, every app pays through it.", "category": "money", "container": { "image": "source.archipelago-foundation.org/lfg2025/alby-hub:v1.24.0", "pull_policy": "if-not-present" }, "dependencies": [ { "storage": "1Gi" } ], "resources": { "cpu_limit": 1, "memory_limit": "512Mi", "disk_limit": "2Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "network_policy": "bridge" }, "ports": [ { "host": 8187, "container": 8080, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/alby-hub", "target": "/data", "options": [ "rw" ] } ], "environment": [ "WORK_DIR=/data", "PORT=8080", "LOG_LEVEL=info" ], "health_check": { "type": "http", "endpoint": "http://localhost:8080", "path": "/", "interval": "30s", "timeout": "5s", "retries": 5 }, "interfaces": { "main": { "name": "Web UI", "description": "Alby Hub wallet interface", "type": "ui", "port": 8187, "protocol": "http" } }, "metadata": { "icon": "/assets/img/app-icons/alby-hub.svg", "repo": "https://github.com/getAlby/hub", "tier": "optional", "launch": { "open_in_new_tab": false }, "features": [ "Self-custodial Lightning node (LDK) with a friendly wallet UI", "Connect wallets and apps via Nostr Wallet Connect (NWC)", "Per-app budgets and isolated sub-wallets", "Works with the Alby browser extension and mobile app" ] } } } }, "archipelago-source": { "version": "0.4.0", "manifest": { "app": { "id": "archipelago-source", "name": "GitWorkshop", "version": "0.4.0", "upstream": { "kind": "github", "repo": "DanConwayDev/gitworkshop" }, "description": "Get Archipelago's source, clone it with ngit, and contribute issues, patches, and reviews over Nostr using the upstream GitWorkshop client.", "category": "development", "container": { "build": { "context": "/opt/archipelago/docker/archipelago-source", "dockerfile": "Dockerfile", "tag": "localhost/archipelago-source:local" } }, "resources": { "cpu_limit": 1, "memory_limit": "64Mi", "disk_limit": "64Mi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "network_policy": "host" }, "ports": [ { "host": 8337, "container": 8337, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated", "session_passthrough": true } ], "volumes": [ { "type": "tmpfs", "target": "/tmp", "tmpfs_options": "rw,noexec,nosuid,size=16m,mode=1777" } ], "environment": [], "health_check": { "type": "http", "endpoint": "http://127.0.0.1:8337", "path": "/healthz", "interval": "30s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "GitWorkshop", "description": "NIP-34 repository browser, issues, pull requests, and review", "type": "ui", "port": 8337, "protocol": "http", "path": "/" } }, "metadata": { "icon": "/assets/img/app-icons/gitworkshop-dc36db6.svg", "author": "GitWorkshop contributors", "repo": "https://github.com/DanConwayDev/gitworkshop", "maintainer_npub": "npub1w3sqdkrhn0gyuvsex32effzgnfpyde6qrrc4u467flg5e9txh4wsfn5vjg", "tier": "optional", "launch": { "requires_host_frame": false }, "features": [ "NIP-34 repository discovery and browsing", "Bandwidth-efficient Git explorer over GRASP", "Nostr issues, pull requests, and code review", "NIP-07 extension and NIP-46 remote-signer support", "Archipelago node identity through explicit signing consent" ] } } } }, "archy-btcpay-db": { "version": "15.17", "manifest": { "app": { "id": "archy-btcpay-db", "name": "BTCPay Postgres", "version": "15.17", "upstream": { "kind": "dockerhub", "repo": "library/postgres" }, "description": "Postgres backend for BTCPay and NBXplorer.", "container": { "image": "source.archipelago-foundation.org/lfg2025/postgres:15.17", "pull_policy": "if-not-present", "network": "archy-net", "data_uid": "100998:100998", "secret_env": [ { "key": "POSTGRES_PASSWORD", "secret_file": "btcpay-db-password" } ] }, "dependencies": [ { "storage": "20Gi" } ], "resources": { "memory_limit": "1Gi", "disk_limit": "20Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/postgres-btcpay", "target": "/var/lib/postgresql/data", "options": [ "rw" ] } ], "environment": [ "POSTGRES_DB=btcpay", "POSTGRES_USER=btcpay" ], "health_check": { "type": "tcp", "endpoint": "localhost:5432", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "none", "sync_required": false } } } }, "archy-mempool-db": { "version": "11.4.10", "manifest": { "app": { "id": "archy-mempool-db", "name": "Mempool MariaDB", "version": "11.4.10", "upstream": { "kind": "dockerhub", "repo": "library/mariadb" }, "description": "MariaDB backend for the mempool explorer stack.", "container": { "image": "source.archipelago-foundation.org/lfg2025/mariadb:11.4.10", "pull_policy": "if-not-present", "network": "archy-net", "data_uid": "100998:100998", "secret_env": [ { "key": "MYSQL_PASSWORD", "secret_file": "mempool-db-password" }, { "key": "MYSQL_ROOT_PASSWORD", "secret_file": "mysql-root-db-password" } ] }, "dependencies": [ { "storage": "20Gi" } ], "resources": { "memory_limit": "512Mi", "disk_limit": "20Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/mysql-mempool", "target": "/var/lib/mysql", "options": [ "rw" ] } ], "environment": [ "MYSQL_DATABASE=mempool", "MYSQL_USER=mempool" ], "health_check": { "type": "tcp", "endpoint": "localhost:3306", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "none", "sync_required": false } } } }, "archy-mempool-web": { "version": "3.0.1", "manifest": { "app": { "id": "archy-mempool-web", "name": "Mempool Web", "version": "3.0.1", "upstream": { "kind": "github", "repo": "mempool/mempool" }, "description": "Frontend web UI for mempool explorer.", "container_name": "mempool", "container": { "image": "source.archipelago-foundation.org/lfg2025/mempool-frontend:v3.3.1", "pull_policy": "if-not-present", "network": "archy-net" }, "dependencies": [ { "app_id": "mempool-api", "version": ">=3.0.0" } ], "resources": { "memory_limit": "512Mi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 4080, "container": 8080, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "environment": [ "FRONTEND_HTTP_PORT=8080", "BACKEND_MAINNET_HTTP_HOST=mempool-api" ], "health_check": { "type": "http", "endpoint": "http://127.0.0.1:8080", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "none", "sync_required": false } } } }, "archy-nbxplorer": { "version": "2.6.0", "manifest": { "app": { "id": "archy-nbxplorer", "name": "NBXplorer", "version": "2.6.0", "upstream": { "kind": "github", "repo": "dgarage/NBXplorer" }, "description": "BTCPay blockchain indexer service.", "container": { "image": "source.archipelago-foundation.org/lfg2025/nbxplorer:2.6.0", "pull_policy": "if-not-present", "network": "archy-net", "secret_env": [ { "key": "NBXPLORER_BTCRPCPASSWORD", "secret_file": "bitcoin-rpc-password" }, { "key": "BTCPAY_DB_PASS", "secret_file": "btcpay-db-password" } ] }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=26.0" }, { "app_id": "archy-btcpay-db", "version": ">=15.17" } ], "resources": { "memory_limit": "2Gi", "disk_limit": "20Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 32838, "container": 32838, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/nbxplorer", "target": "/data", "options": [ "rw" ] } ], "environment": [ "NBXPLORER_DATADIR=/data", "NBXPLORER_NETWORK=mainnet", "NBXPLORER_CHAINS=btc", "NBXPLORER_BIND=0.0.0.0:32838", "NBXPLORER_BTCRPCURL=http://bitcoin-knots:8332", "NBXPLORER_BTCRPCUSER=archipelago", "NBXPLORER_BTCNODEENDPOINT=bitcoin-knots:8333", "NBXPLORER_NOAUTH=1", "NBXPLORER_POSTGRES=Username=btcpay;Password=${BTCPAY_DB_PASS};Host=archy-btcpay-db;Port=5432;Database=nbxplorer" ], "health_check": { "type": "http", "endpoint": "http://localhost:32838", "path": "/", "interval": "30s", "timeout": "30s", "retries": 5 }, "bitcoin_integration": { "rpc_access": "read-only", "sync_required": true } } } }, "barkd": { "version": "0.3.0", "manifest": { "app": { "id": "barkd", "name": "Ark Wallet", "version": "0.3.0", "upstream": { "kind": "gitlab", "repo": "ark-bitcoin/bark" }, "description": "Ark protocol wallet daemon (barkd). Lets the node hold self-custodial off-chain bitcoin via an Ark server; the wallet talks to it over a local REST API. Signet by default while Ark matures.", "container": { "image": "source.archipelago-foundation.org/lfg2025/barkd:0.3.0", "pull_policy": "if-not-present", "network": "archy-net", "generated_secrets": [ { "name": "barkd-secret", "kind": "hex32" } ], "secret_env": [ { "key": "BARKD_SECRET", "secret_file": "barkd-secret" } ], "data_uid": "1000:1000" }, "dependencies": [ { "storage": "1Gi" } ], "resources": { "cpu_limit": 1, "memory_limit": "512Mi", "disk_limit": "1Gi" }, "security": { "readonly_root": true, "network_policy": "bridge" }, "ports": [ { "host": 3535, "container": 3535, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/barkd", "target": "/data", "options": [ "rw" ] } ], "environment": [ "BARKD_DATADIR=/data", "BARKD_BIND_HOST=0.0.0.0", "BARKD_BIND_PORT=3535" ], "health_check": { "type": "tcp", "endpoint": "localhost:3535", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "bitcoin-core": { "version": "latest", "manifest": { "app": { "id": "bitcoin-core", "name": "Bitcoin Core", "version": "28.4.0", "upstream": { "kind": "github", "repo": "bitcoin/bitcoin" }, "description": "Reference Bitcoin Core node with dynamic prune/full-mode startup based on host disk.", "container_name": "bitcoin-core", "container": { "image": "source.archipelago-foundation.org/lfg2025/bitcoin:28.4", "pull_policy": "if-not-present", "network": "archy-net", "entrypoint": [ "sh", "-lc" ], "custom_args": [ "BITCOIND=\"$(command -v bitcoind || true)\"; if [ -z \"$BITCOIND\" ]; then\n BITCOIND=\"$(find /opt -path '*/bin/bitcoind' -type f 2>/dev/null | sort | tail -n 1)\";\nfi; if [ -z \"$BITCOIND\" ]; then\n echo \"bitcoind not found in image\" >&2;\n exit 127;\nfi; RPC_USER=\"$(printenv BITCOIN_RPC_USER)\"; RPC_PASS=\"$(printenv BITCOIN_RPC_PASS)\"; RPC_CONF=\"/tmp/rpc.conf\"; umask 077; { echo \"rpcuser=$RPC_USER\"; echo \"rpcpassword=$RPC_PASS\"; } > \"$RPC_CONF\"; if [ -f /home/bitcoin/.bitcoin/bitcoin.conf ]; then\n echo \"archipelago: ignoring legacy datadir bitcoin.conf; RPC config comes from $RPC_CONF\" >&2;\nfi; RPC_TXRELAY_AUTH=\"$(printenv BITCOIN_RPC_TXRELAY_RPCAUTH || true)\"; DISK_GB_VALUE=\"$(printenv DISK_GB || true)\"; RPC_HEADROOM=\"-rpcthreads=16 -rpcworkqueue=256\"; RPC_TXRELAY_FLAGS=\"-rpcwhitelistdefault=0\"; if [ -n \"$RPC_TXRELAY_AUTH\" ]; then\n RPC_TXRELAY_FLAGS=\"$RPC_TXRELAY_FLAGS -rpcauth=$RPC_TXRELAY_AUTH -rpcwhitelist=txrelay:sendrawtransaction,submitpackage,testmempoolaccept,getmempoolinfo,getrawmempool,getmempoolentry,getnetworkinfo,getblockchaininfo,getblockcount,getblockhash,getblock,getblockheader,getrawtransaction,gettxout,gettxspendingprevout,decoderawtransaction,decodescript,estimatesmartfee,uptime,ping,getconnectioncount,getpeerinfo,getindexinfo,getdeploymentinfo,getchaintips\";\nfi; if [ \"${DISK_GB_VALUE:-0}\" -lt 1000 ]; then\n exec \"$BITCOIND\" -datadir=/home/bitcoin/.bitcoin -conf=\"$RPC_CONF\" -allowignoredconf=1 -printtoconsole=0 -server=1 -prune=50000 -rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 -listen=1 -bind=0.0.0.0:8333 -dbcache=1024 -par=0 -maxconnections=125 $RPC_HEADROOM $RPC_TXRELAY_FLAGS;\nelse\n exec \"$BITCOIND\" -datadir=/home/bitcoin/.bitcoin -conf=\"$RPC_CONF\" -allowignoredconf=1 -printtoconsole=0 -server=1 -txindex=1 -rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 -listen=1 -bind=0.0.0.0:8333 -dbcache=4096 -par=0 -maxconnections=125 $RPC_HEADROOM $RPC_TXRELAY_FLAGS;\nfi" ], "derived_env": [ { "key": "DISK_GB", "template": "{{DISK_GB}}" } ], "secret_env": [ { "key": "BITCOIN_RPC_PASS", "secret_file": "bitcoin-rpc-password" }, { "key": "BITCOIN_RPC_TXRELAY_RPCAUTH", "secret_file": "bitcoin-rpc-txrelay-rpcauth" } ], "data_uid": "100101:100101" }, "dependencies": [ { "storage": "500Gi" } ], "resources": { "cpu_limit": 0, "memory_limit": "4Gi", "disk_limit": "500Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8332, "container": 8332, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" }, { "host": 8333, "container": 8333, "protocol": "tcp", "auth": "none", "auth_rationale": "Bitcoin p2p gossip. Peers are anonymous by design and speak the Bitcoin wire protocol, not HTTP." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/bitcoin", "target": "/home/bitcoin/.bitcoin", "options": [ "rw" ] } ], "environment": [ "BITCOIN_RPC_USER=archipelago" ], "health_check": { "type": "tcp", "endpoint": "localhost:8332", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "admin", "sync_required": true, "testnet_support": false, "pruning_support": true } } }, "versions": [ { "version": "latest", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:latest", "default": true }, { "version": "31.0", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:31.0" }, { "version": "30.2", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:30.2" }, { "version": "29.3", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:29.3" }, { "version": "29.2", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:29.2" }, { "version": "28.4.0", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:28.4" }, { "version": "27.2", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:27.2" }, { "version": "26.2", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:26.2", "deprecated": true }, { "version": "25.2", "image": "source.archipelago-foundation.org/lfg2025/bitcoin:25.2", "deprecated": true } ] }, "bitcoin-knots": { "version": "29.3.knots20260210", "image": "source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.3.knots20260210", "manifest": { "app": { "id": "bitcoin-knots", "name": "Bitcoin Knots", "version": "28.1.0", "upstream": { "kind": "github", "repo": "bitcoinknots/bitcoin" }, "description": "Full Bitcoin Knots node with dynamic prune/full-mode startup based on host disk.", "container_name": "bitcoin-knots", "container": { "image": "source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.3.knots20260210", "pull_policy": "if-not-present", "network": "archy-net", "entrypoint": [ "sh", "-lc" ], "custom_args": [ "BITCOIND=\"$(command -v bitcoind || true)\"; if [ -z \"$BITCOIND\" ]; then\n BITCOIND=\"$(find /opt -path '*/bin/bitcoind' -type f 2>/dev/null | sort | tail -n 1)\";\nfi; if [ -z \"$BITCOIND\" ]; then\n echo \"bitcoind not found in image\" >&2;\n exit 127;\nfi; RPC_USER=\"$(printenv BITCOIN_RPC_USER)\"; RPC_PASS=\"$(printenv BITCOIN_RPC_PASS)\"; RPC_CONF=\"/tmp/rpc.conf\"; umask 077; { echo \"rpcuser=$RPC_USER\"; echo \"rpcpassword=$RPC_PASS\"; } > \"$RPC_CONF\"; if [ -f /home/bitcoin/.bitcoin/bitcoin.conf ]; then\n echo \"archipelago: ignoring legacy datadir bitcoin.conf; RPC config comes from $RPC_CONF\" >&2;\nfi; RPC_TXRELAY_AUTH=\"$(printenv BITCOIN_RPC_TXRELAY_RPCAUTH || true)\"; DISK_GB_VALUE=\"$(printenv DISK_GB || true)\"; RPC_HEADROOM=\"-rpcthreads=16 -rpcworkqueue=256\"; RPC_TXRELAY_FLAGS=\"-rpcwhitelistdefault=0\"; if [ -n \"$RPC_TXRELAY_AUTH\" ]; then\n RPC_TXRELAY_FLAGS=\"$RPC_TXRELAY_FLAGS -rpcauth=$RPC_TXRELAY_AUTH -rpcwhitelist=txrelay:sendrawtransaction,submitpackage,testmempoolaccept,getmempoolinfo,getrawmempool,getmempoolentry,getnetworkinfo,getblockchaininfo,getblockcount,getblockhash,getblock,getblockheader,getrawtransaction,gettxout,gettxspendingprevout,decoderawtransaction,decodescript,estimatesmartfee,uptime,ping,getconnectioncount,getpeerinfo,getindexinfo,getdeploymentinfo,getchaintips\";\nfi; if [ \"${DISK_GB_VALUE:-0}\" -lt 1000 ]; then\n exec \"$BITCOIND\" -datadir=/home/bitcoin/.bitcoin -conf=\"$RPC_CONF\" -allowignoredconf=1 -printtoconsole=0 -server=1 -prune=50000 -rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 -listen=1 -bind=0.0.0.0:8333 -dbcache=2048 -par=0 -maxconnections=125 $RPC_HEADROOM $RPC_TXRELAY_FLAGS;\nelse\n exec \"$BITCOIND\" -datadir=/home/bitcoin/.bitcoin -conf=\"$RPC_CONF\" -allowignoredconf=1 -printtoconsole=0 -server=1 -txindex=1 -rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 -listen=1 -bind=0.0.0.0:8333 -dbcache=4096 -par=0 -maxconnections=125 $RPC_HEADROOM $RPC_TXRELAY_FLAGS;\nfi" ], "derived_env": [ { "key": "DISK_GB", "template": "{{DISK_GB}}" } ], "secret_env": [ { "key": "BITCOIN_RPC_PASS", "secret_file": "bitcoin-rpc-password" }, { "key": "BITCOIN_RPC_TXRELAY_RPCAUTH", "secret_file": "bitcoin-rpc-txrelay-rpcauth" } ], "data_uid": "100101:100101" }, "dependencies": [ { "storage": "500Gi" } ], "resources": { "cpu_limit": 0, "memory_limit": "8Gi", "disk_limit": "500Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8332, "container": 8332, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" }, { "host": 8333, "container": 8333, "protocol": "tcp", "auth": "none", "auth_rationale": "Bitcoin p2p gossip. Peers are anonymous by design and speak the Bitcoin wire protocol, not HTTP." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/bitcoin", "target": "/home/bitcoin/.bitcoin", "options": [ "rw" ] } ], "environment": [ "BITCOIN_RPC_USER=archipelago" ], "health_check": { "type": "tcp", "endpoint": "localhost:8332", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "admin", "sync_required": true, "testnet_support": false, "pruning_support": true } } }, "versions": [ { "version": "29.3.knots20260210", "image": "source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.3.knots20260210", "default": true }, { "version": "29.3.knots20260508", "image": "source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.3.knots20260508" }, { "version": "29.3.knots20260507", "image": "source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.3.knots20260507" }, { "version": "29.2.knots20251110", "image": "source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.2.knots20251110" } ] }, "bitcoin-ui": { "version": "1.7.123-alpha", "image": "source.archipelago-foundation.org/lfg2025/bitcoin-ui:1.7.123-alpha", "manifest": { "app": { "id": "bitcoin-ui", "name": "Bitcoin UI", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "Archipelago-native HTTP proxy + static site for interacting with the\nBitcoin Core / Bitcoin Knots JSON-RPC. Runs nginx inside a container\nand reverse-proxies /bitcoin-rpc/ to 127.0.0.1:8332 on the host. The\nupstream Authorization header is substituted from\n/var/lib/archipelago/secrets/bitcoin-rpc-password by the prod\norchestrator's pre-start hook, rendered into an nginx.conf that is\nbind-mounted read-only at container start.\n", "container": { "build": { "context": "/opt/archipelago/docker/bitcoin-ui", "dockerfile": "Dockerfile", "tag": "localhost/bitcoin-ui:local" } }, "dependencies": [ { "app_id": "bitcoin-core" } ], "resources": { "memory_limit": "128Mi" }, "security": { "readonly_root": false, "network_policy": "host" }, "ports": [ { "host": 8334, "container": 8334, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated", "session_passthrough": true } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/bitcoin-ui/nginx.conf", "target": "/etc/nginx/conf.d/default.conf", "options": [ "ro" ] } ], "environment": [], "health_check": { "type": "http", "endpoint": "http://127.0.0.1:8334", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "botfights": { "version": "1.2.11", "manifest": { "app": { "id": "botfights", "name": "BotFights", "version": "1.2.11", "upstream": { "kind": "internal" }, "description": "Bot competition arena with 2-player arcade fighting mode. AI bots battle in trivia challenges while humans duke it out with controllers. Built for Bitcoiners.", "category": "community", "container": { "image": "source.archipelago-foundation.org/lfg2025/botfights:1.2.11", "pull_policy": "always", "generated_secrets": [ { "name": "botfights-jwt-secret", "kind": "hex32" } ], "secret_env": [ { "key": "JWT_SECRET", "secret_file": "botfights-jwt-secret" } ], "data_uid": "999:999" }, "dependencies": [ { "storage": "500Mi" } ], "resources": { "cpu_limit": 2, "memory_limit": "512Mi", "disk_limit": "500Mi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "user": 999, "seccomp_profile": "default", "network_policy": "bridge", "apparmor_profile": "default" }, "ports": [ { "host": 9100, "container": 9100, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/botfights", "target": "/app/server/data" }, { "type": "tmpfs", "target": "/tmp", "options": [ "rw", "noexec", "nosuid", "size=64m" ] } ], "environment": [ "NODE_ENV=production", "PORT=9100", "ARENA_UPSTREAM_URL=https://botfights.archipelago-foundation.org", "ARCHY_EMBEDDED=1" ], "health_check": { "type": "http", "endpoint": "http://localhost:9100", "path": "/api/health", "interval": "30s", "timeout": "10s", "retries": 3, "start_period": "30s" }, "interfaces": { "main": { "name": "Web UI", "description": "Bot arena and arcade fighter with controller support", "type": "ui", "port": 9100, "protocol": "http", "path": "/" } }, "metadata": { "author": "Dorian", "repo": "https://botfights.net", "icon": "/assets/img/app-icons/botfights.svg", "license": "MIT", "tags": [ "bitcoin", "gaming", "arcade", "fighter", "bots", "competition", "controller" ] } } } }, "btcpay": { "version": "2.4.3", "image": "docker.io/btcpayserver/btcpayserver:2.4.3", "images": { "btcpay-server": "docker.io/btcpayserver/btcpayserver:2.4.3", "archy-nbxplorer": "source.archipelago-foundation.org/lfg2025/nbxplorer:2.6.0", "archy-btcpay-db": "source.archipelago-foundation.org/lfg2025/postgres:15.17" } }, "btcpay-server": { "version": "2.4.3", "manifest": { "app": { "id": "btcpay-server", "name": "BTCPay Server", "version": "2.4.3", "upstream": { "kind": "github", "repo": "btcpayserver/btcpayserver" }, "description": "Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries.", "container": { "image": "docker.io/btcpayserver/btcpayserver:2.4.3", "pull_policy": "if-not-present", "network": "archy-net", "secret_env": [ { "key": "BTCPAY_BTCRPCPASSWORD", "secret_file": "bitcoin-rpc-password" }, { "key": "BTCPAY_DB_PASS", "secret_file": "btcpay-db-password" }, { "key": "BTCPAY_BTCLIGHTNING", "secret_file": "btcpay-lnd-connection", "optional": true } ], "derived_env": [ { "key": "BTCPAY_HOST", "template": "{{HOST_IP}}:23000" } ] }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=26.0" }, { "app_id": "archy-btcpay-db", "version": ">=15.17" }, { "app_id": "archy-nbxplorer", "version": ">=2.6.0" } ], "resources": { "cpu_limit": 2, "memory_limit": "2Gi", "disk_limit": "20Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 23000, "container": 49392, "protocol": "tcp", "bind": "127.0.0.1", "auth": "open", "auth_rationale": "BTCPay enforces its own login for administration, and its checkout, invoice and webhook endpoints are designed to be reached by anonymous payers and payment processors." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/btcpay", "target": "/datadir", "options": [ "rw" ] } ], "environment": [ "ASPNETCORE_URLS=http://0.0.0.0:49392", "BTCPAY_PROTOCOL=http", "BTCPAY_CHAINS=btc", "BTCPAY_PLUGINDIR=/datadir/Plugins", "BTCPAY_BTCEXPLORERURL=http://archy-nbxplorer:32838", "BTCPAY_BTCRPCURL=http://bitcoin-knots:8332", "BTCPAY_BTCRPCUSER=archipelago", "BTCPAY_POSTGRES=Username=btcpay;Password=${BTCPAY_DB_PASS};Host=archy-btcpay-db;Port=5432;Database=btcpay" ], "health_check": { "type": "http", "endpoint": "http://localhost:49392", "path": "/", "interval": "30s", "timeout": "30s", "retries": 5 }, "bitcoin_integration": { "rpc_access": "read-only", "sync_required": true }, "lightning_integration": { "payment_processing": false, "invoice_management": true }, "interfaces": { "main": { "name": "Web UI", "description": "BTCPay Server dashboard", "type": "ui", "port": 23000, "protocol": "http", "path": "/" } }, "metadata": { "launch": { "open_in_new_tab": true } } } } }, "core-lightning": { "version": "23.08.2", "manifest": { "app": { "id": "core-lightning", "name": "Core Lightning (CLN)", "version": "23.08.2", "upstream": { "kind": "github", "repo": "ElementsProject/lightning" }, "description": "Lightning Network implementation in C. Lightweight alternative to LND.", "container": { "image": "elementsproject/lightningd:v23.08.2", "image_signature": "cosign://...", "pull_policy": "verify-signature" }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=26.0" } ], "resources": { "cpu_limit": 1, "memory_limit": "512Mi", "disk_limit": "5Gi" }, "security": { "capabilities": [ "NET_BIND_SERVICE" ], "readonly_root": true, "no_new_privileges": true, "user": 1000, "seccomp_profile": "default", "network_policy": "isolated", "apparmor_profile": "core-lightning" }, "ports": [ { "host": 9736, "container": 9735, "protocol": "tcp", "auth": "none", "auth_rationale": "Lightning p2p. The BOLT-8 noise handshake authenticates and encrypts the channel itself." }, { "host": 9835, "container": 9835, "protocol": "tcp", "auth": "none", "auth_rationale": "Core Lightning gRPC, authenticated by mutual TLS client certificates." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/core-lightning", "target": "/home/clightning/.lightning", "options": [ "rw" ] } ], "environment": [ "BITCOIND_RPCURL=http://bitcoin-core:8332", "BITCOIND_RPCUSER=${BITCOIN_RPC_USER}", "BITCOIND_RPCPASS=${BITCOIN_RPC_PASSWORD}", "NETWORK=bitcoin" ], "health_check": { "type": "exec", "endpoint": "lightning-cli getinfo", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "admin", "sync_required": true }, "lightning_integration": { "channel_management": true, "payment_routing": true } } } }, "cuprate": { "version": "0.1.0-preview", "manifest": { "app": { "id": "cuprate", "name": "Cuprate", "version": "0.1.0-preview", "upstream": { "kind": "github", "repo": "Cuprate/cuprate" }, "description": "Alternative Monero node implementation in Rust. Independently validates Monero consensus rules, providing a layer of security and redundancy for the network.", "category": "money", "container": { "image": "source.archipelago-foundation.org/lfg2025/cuprate:0.1.0-preview-18-g618ff14", "pull_policy": "if-not-present", "network": "archy-net", "custom_args": [ "--config-file", "/home/cuprate/Cuprated.toml" ], "data_uid": "1000:1000" }, "dependencies": [ { "storage": "300Gi" } ], "resources": { "cpu_limit": 0, "memory_limit": "10Gi", "disk_limit": "300Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "network_policy": "isolated" }, "ports": [ { "host": 18183, "container": 18080, "protocol": "tcp", "auth": "none", "auth_rationale": "Monero p2p gossip. Peers are anonymous by design and speak the Monero wire protocol, not HTTP." }, { "host": 18090, "container": 18089, "protocol": "tcp", "auth": "open", "auth_rationale": "Monero restricted RPC \u2014 the subset upstream considers safe for public/remote-node use. Wallets (Feather, monero-wallet-rpc, GUI) connect directly over plain HTTP JSON-RPC and cannot complete a browser login or hold a dashboard session cookie." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/cuprate", "target": "/home/cuprate", "options": [ "rw" ] } ], "files": [ { "path": "/var/lib/archipelago/cuprate/Cuprated.toml", "content": "network = \"Mainnet\"\nfast_sync = true\ntarget_max_memory = 8589934592\n\n[rpc.restricted]\nenable = true\n\n[tracing.stdout]\nlevel = \"info\"\n\n[tracing.file]\nlevel = \"info\"\nmax_log_files = 14\n", "overwrite": false } ], "health_check": { "type": "tcp", "endpoint": "localhost:18090", "interval": "30s", "timeout": "5s", "retries": 3, "start_period": "5m" }, "metadata": { "icon": "/assets/img/app-icons/cuprate.svg", "category": "money", "tier": "optional", "author": "Cuprate", "repo": "https://github.com/Cuprate/cuprate" } } } }, "electrs-ui": { "version": "1.7.123-alpha", "image": "source.archipelago-foundation.org/lfg2025/electrs-ui:1.7.123-alpha", "manifest": { "app": { "id": "electrs-ui", "name": "Electrs UI", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "Archipelago-native HTTP frontend for electrs/electrumx status. Runs\nnginx inside a container, serves static assets, and proxies\n/electrs-status to the archipelago backend on 127.0.0.1:5678.\n", "container": { "build": { "context": "/opt/archipelago/docker/electrs-ui", "dockerfile": "Dockerfile", "tag": "localhost/electrs-ui:local" } }, "dependencies": [], "resources": { "memory_limit": "64Mi" }, "security": { "readonly_root": false, "network_policy": "host" }, "ports": [ { "host": 50002, "container": 50002, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated", "session_passthrough": true } ], "volumes": [], "environment": [], "health_check": { "type": "http", "endpoint": "http://127.0.0.1:50002", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "electrumx": { "version": "v1.18.0", "image": "source.archipelago-foundation.org/lfg2025/electrumx:v1.18.0", "manifest": { "app": { "id": "electrumx", "name": "ElectrumX", "version": "1.18.0", "upstream": { "kind": "github", "repo": "spesmilo/electrumx" }, "description": "Electrum server indexing Bitcoin chain data for lightweight wallet queries.", "container": { "image": "source.archipelago-foundation.org/lfg2025/electrumx:v1.18.0", "pull_policy": "if-not-present", "network": "archy-net", "data_uid": "1000:1000", "entrypoint": [ "sh", "-lc" ], "custom_args": [ "for h in bitcoin-knots bitcoin-core; do if getent hosts \"$h\" >/dev/null 2>&1; then BTC_HOST=\"$h\"; break; fi; done; export DAEMON_URL=\"http://archipelago:$(printenv BITCOIN_RPC_PASS)@${BTC_HOST:-bitcoin-knots}:8332/\"; exec electrumx_server" ], "secret_env": [ { "key": "BITCOIN_RPC_PASS", "secret_file": "bitcoin-rpc-password" } ] }, "dependencies": [ { "app_id": "bitcoin-knots", "version": ">=26.0" }, { "storage": "50Gi" }, "bitcoin:archival" ], "resources": { "cpu_limit": 0, "memory_limit": "6Gi", "disk_limit": "50Gi" }, "security": { "capabilities": [ "DAC_OVERRIDE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 50001, "container": 50001, "protocol": "tcp", "auth": "none", "auth_rationale": "Electrum wire protocol over TCP. Electrum wallets speak it directly and cannot hold a session cookie." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/electrumx", "target": "/data", "options": [ "rw" ] } ], "environment": [ "COIN=Bitcoin", "DB_DIRECTORY=/data", "SERVICES=tcp://:50001,rpc://0.0.0.0:8000", "CACHE_MB=1024", "MAX_SEND=10000000" ], "interfaces": { "main": { "name": "Web UI", "description": "ElectrumX server status and connection details", "type": "ui", "port": 50002, "protocol": "http" } }, "health_check": { "type": "tcp", "endpoint": "localhost:50001", "interval": "30s", "timeout": "5s", "retries": 3, "start_period": "10m" }, "bitcoin_integration": { "rpc_access": "read-only", "sync_required": true, "pruning_support": false } } } }, "fedimint": { "version": "v0.10.1", "image": "source.archipelago-foundation.org/lfg2025/fedimintd:v0.10.1", "manifest": { "app": { "id": "fedimint", "name": "Fedimint Guardian", "version": "0.10.0", "upstream": { "kind": "github", "repo": "fedimint/fedimint" }, "description": "Federated Bitcoin minting service with built-in Guardian UI. Privacy-preserving Bitcoin custody.", "container": { "image": "source.archipelago-foundation.org/lfg2025/fedimintd:v0.10.1", "pull_policy": "if-not-present", "network": "archy-net", "entrypoint": [ "sh", "-lc" ], "custom_args": [ "until state=\"$(curl -sS --connect-timeout 5 -m 45 -u \"$FM_BITCOIND_USERNAME:$FM_BITCOIND_PASSWORD\" -H \"Content-Type: application/json\" --data-binary '{\"jsonrpc\":\"1.0\",\"id\":\"fedimint-wait\",\"method\":\"getblockchaininfo\",\"params\":[]}' \"$FM_BITCOIND_URL/\")\" && echo \"$state\" | grep -q '\"initialblockdownload\":false'; do\n echo \"Waiting for Bitcoin RPC sync at $FM_BITCOIND_URL...\";\n sleep 30;\ndone;\nexec fedimintd" ], "derived_env": [ { "key": "FM_P2P_URL", "template": "fedimint://{{HOST_MDNS}}:8173" }, { "key": "FM_API_URL", "template": "ws://{{HOST_MDNS}}:8174" }, { "key": "FM_BITCOIND_URL", "template": "http://{{BITCOIN_HOST}}:8332" } ], "secret_env": [ { "key": "FM_BITCOIND_PASSWORD", "secret_file": "bitcoin-rpc-password" } ], "data_uid": "1000:1000" }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=26.0" }, { "storage": "20Gi" } ], "resources": { "cpu_limit": 4, "memory_limit": "4Gi", "disk_limit": "20Gi" }, "security": { "capabilities": [], "readonly_root": true, "network_policy": "isolated" }, "ports": [ { "host": 8173, "container": 8173, "protocol": "tcp", "auth": "none", "auth_rationale": "Fedimint guardian consensus. Other guardians speak the federation's own authenticated protocol here; a login page would break consensus." }, { "host": 8174, "container": 8174, "protocol": "tcp", "auth": "none", "auth_rationale": "Fedimint guardian API for federation clients, which authenticate to the federation itself and cannot hold a browser session." }, { "host": 8177, "container": 8175, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/fedimint", "target": "/data", "options": [ "rw" ] } ], "environment": [ "FM_DATA_DIR=/data", "FM_BITCOIND_USERNAME=archipelago", "FM_BITCOIN_NETWORK=bitcoin", "FM_BIND_P2P=0.0.0.0:8173", "FM_BIND_API=0.0.0.0:8174", "FM_BIND_UI=0.0.0.0:8175" ], "health_check": { "type": "http", "endpoint": "http://localhost:8175", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "Guardian UI", "description": "Fedimint Guardian wait/proxy UI", "type": "ui", "port": 8175, "protocol": "http", "path": "/" } }, "bitcoin_integration": { "rpc_access": "admin", "sync_required": true } } } }, "fedimint-clientd": { "version": "0.8.0", "manifest": { "app": { "id": "fedimint-clientd", "name": "Fedimint Client", "version": "0.8.0", "upstream": { "kind": "github", "repo": "fedimint/fedimint-clientd" }, "description": "Fedimint ecash client daemon (fmcd). Lets the node hold Fedimint ecash and join federations; the wallet talks to it over a local REST API.", "container": { "image": "source.archipelago-foundation.org/lfg2025/fmcd:0.8.1", "pull_policy": "if-not-present", "network": "archy-net", "generated_secrets": [ { "name": "fmcd-password", "kind": "hex16" } ], "secret_env": [ { "key": "FMCD_PASSWORD", "secret_file": "fmcd-password" } ], "data_uid": "1000:1000" }, "dependencies": [ { "storage": "2Gi" } ], "resources": { "cpu_limit": 1, "memory_limit": "1Gi", "disk_limit": "2Gi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "FOWNER", "SETUID", "SETGID" ], "readonly_root": true, "network_policy": "bridge" }, "ports": [ { "host": 8178, "container": 8080, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/fmcd", "target": "/data", "options": [ "rw" ] } ], "environment": [ "FMCD_ADDR=0.0.0.0:8080", "FMCD_MODE=rest", "FMCD_DATA_DIR=/data", "FMCD_INVITE_CODE=fed11qgqyj3mfwfhksw309uuxywtxxfjrjc35xuexverpxdsnxcnrxucxvenzveskgc3kvvun2c34xp3k2ep38yunzdpexcekxe3hvd3rvvmx8pnrvdenx5mnzvtzqqqjqt0t6pc3s5z0ynqjw9s4njf6svwgu59kweawc0vvrddcjeemw6yyn4pcdp" ], "health_check": { "type": "tcp", "endpoint": "localhost:8080", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "fedimint-gateway": { "version": "v0.10.1", "image": "source.archipelago-foundation.org/lfg2025/gatewayd:v0.10.1", "manifest": { "app": { "id": "fedimint-gateway", "name": "Fedimint Gateway", "version": "0.10.0", "upstream": { "kind": "github", "repo": "fedimint/fedimint" }, "description": "Fedimint gateway service with automatic LND-or-LDK backend selection.", "container": { "image": "source.archipelago-foundation.org/lfg2025/gatewayd:v0.10.1", "pull_policy": "if-not-present", "network": "archy-net", "entrypoint": [ "sh", "-lc" ], "custom_args": [ "if [ -f /lnd/tls.cert ] && [ -f /lnd/data/chain/bitcoin/mainnet/admin.macaroon ]; then\n exec gatewayd --data-dir /data --listen 0.0.0.0:8176 --bcrypt-password-hash \"$FEDI_HASH\" --network bitcoin --bitcoind-url \"$FM_BITCOIND_URL\" --bitcoind-username \"$FM_BITCOIND_USERNAME\" --bitcoind-password \"$FM_BITCOIND_PASSWORD\" lnd --lnd-rpc-host lnd:10009 --lnd-tls-cert /lnd/tls.cert --lnd-macaroon /lnd/data/chain/bitcoin/mainnet/admin.macaroon;\nelse\n exec gatewayd --data-dir /data --listen 0.0.0.0:8176 --bcrypt-password-hash \"$FEDI_HASH\" --network bitcoin --bitcoind-url \"$FM_BITCOIND_URL\" --bitcoind-username \"$FM_BITCOIND_USERNAME\" --bitcoind-password \"$FM_BITCOIND_PASSWORD\" ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway;\nfi" ], "derived_env": [ { "key": "FM_BITCOIND_URL", "template": "http://{{BITCOIN_HOST}}:8332" } ], "generated_secrets": [ { "name": "fedimint-gateway-hash", "kind": "bcrypt" } ], "secret_env": [ { "key": "FM_BITCOIND_PASSWORD", "secret_file": "bitcoin-rpc-password" }, { "key": "FEDI_HASH", "secret_file": "fedimint-gateway-hash" } ], "data_uid": "1000:1000" }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=26.0" }, { "app_id": "fedimint", "version": ">=0.10.0" } ], "resources": { "cpu_limit": 2, "memory_limit": "2Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [], "readonly_root": true, "network_policy": "isolated" }, "ports": [ { "host": 8176, "container": 8176, "protocol": "tcp", "auth": "none", "auth_rationale": "Fedimint gateway API, protected by its own bcrypt password (--bcrypt-password-hash) and reached by federation peers and clients that cannot hold a browser session." }, { "host": 9737, "container": 9737, "protocol": "tcp", "auth": "none", "auth_rationale": "LDK Lightning p2p for the gateway. The BOLT-8 noise handshake authenticates and encrypts the connection itself." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/fedimint-gateway", "target": "/data", "options": [ "rw" ] }, { "type": "bind", "source": "/var/lib/archipelago/lnd", "target": "/lnd", "options": [ "ro" ] } ], "environment": [ "FM_BITCOIND_USERNAME=archipelago" ], "health_check": { "type": "http", "endpoint": "http://localhost:8176", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "admin", "sync_required": true } } } }, "filebrowser": { "version": "v2.63.23", "image": "source.archipelago-foundation.org/lfg2025/filebrowser:v2.63.23", "manifest": { "app": { "id": "filebrowser", "name": "File Browser", "version": "2.63.23", "upstream": { "kind": "github", "repo": "filebrowser/filebrowser" }, "description": "Baseline Archipelago file manager service.", "container": { "image": "source.archipelago-foundation.org/lfg2025/filebrowser:v2.63.23", "pull_policy": "if-not-present", "network": "archy-net", "custom_args": [ "--config", "/data/.filebrowser.json" ], "data_uid": "100000:100000" }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "memory_limit": "256Mi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE", "NET_BIND_SERVICE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8083, "container": 80, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/filebrowser", "target": "/srv", "options": [ "rw" ] }, { "type": "bind", "source": "/var/lib/archipelago/filebrowser-data", "target": "/data", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "http", "endpoint": "http://localhost:80", "path": "/health", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "none", "sync_required": false } } } }, "fips-ui": { "version": "1.0.0", "manifest": { "app": { "id": "fips-ui", "name": "FIPS Mesh", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "Archipelago-native dashboard for the FIPS mesh transport. Runs nginx\ninside a container with host networking, serves a static dashboard on\n:8336, and reverse-proxies /rpc/v1 to the archipelago backend on\n127.0.0.1:5678. All FIPS controls (status, seed anchors, reconnect,\nrestart, and stable-channel daemon updates) go through the existing\nfips.* RPC methods, authenticated by the browser's own archipelago\nsession \u2014 there is no separate secret to manage.\n", "container": { "build": { "context": "/opt/archipelago/docker/fips-ui", "dockerfile": "Dockerfile", "tag": "localhost/fips-ui:local" } }, "resources": { "memory_limit": "128Mi" }, "security": { "readonly_root": false, "network_policy": "host" }, "ports": [ { "host": 8336, "container": 8336, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated", "session_passthrough": true } ], "volumes": [], "environment": [], "health_check": { "type": "http", "endpoint": "http://127.0.0.1:8336", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "gitea": { "version": "1.27.3", "manifest": { "app": { "id": "gitea", "name": "Gitea", "version": "1.27.3", "upstream": { "kind": "github", "repo": "go-gitea/gitea" }, "description": "Self-hosted Git service with built-in container registry, CI/CD, and package hosting.", "category": "development", "container": { "image": "source.archipelago-foundation.org/lfg2025/gitea:1.27.3", "pull_policy": "if-not-present" }, "dependencies": [ { "storage": "50Gi" } ], "resources": { "memory_limit": "256Mi", "disk_limit": "50Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE", "NET_BIND_SERVICE" ], "readonly_root": false, "no_new_privileges": false, "network_policy": "bridge" }, "ports": [ { "host": 3001, "container": 3000, "protocol": "tcp", "bind": "127.0.0.1", "auth": "open", "auth_rationale": "Gitea enforces its own account login on every page and API route; git clients authenticate with basic-auth/tokens and cannot complete a browser login challenge." }, { "host": 2222, "container": 22, "protocol": "tcp", "auth": "none", "auth_rationale": "Git over SSH, authenticated by the user's own SSH keypair. Not HTTP, so the gate cannot serve a login page here." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/gitea/data", "target": "/data", "options": [ "rw" ] }, { "type": "bind", "source": "/var/lib/archipelago/gitea/config", "target": "/etc/gitea", "options": [ "rw" ] } ], "environment": [ "GITEA__database__DB_TYPE=sqlite3", "GITEA__server__SSH_PORT=2222", "GITEA__server__SSH_LISTEN_PORT=22", "GITEA__server__LFS_START_SERVER=true", "GITEA__packages__ENABLED=true", "GITEA__packages__LIMIT_TOTAL_OWNER_SIZE=-1", "GITEA__packages__LIMIT_SIZE_CONTAINER=-1", "GITEA__repository_0x2Erelease__FILE_MAX_SIZE=10240", "GITEA__repository_0x2Erelease__MAX_FILES=20", "GITEA__repository__ENABLE_PUSH_CREATE_USER=true", "GITEA__repository__ENABLE_PUSH_CREATE_ORG=true" ], "health_check": { "type": "http", "endpoint": "http://localhost:3000", "path": "/", "interval": "120s", "timeout": "30s", "retries": 5 }, "interfaces": { "main": { "name": "Web UI", "description": "Gitea web interface", "type": "ui", "port": 3001, "protocol": "http", "path": "/" } }, "metadata": { "icon": "/assets/img/app-icons/gitea.svg", "repo": "https://gitea.com", "tier": "optional", "launch": { "open_in_new_tab": true }, "features": [ "Git repositories with web UI", "Built-in container/package registry", "Issue tracking and pull requests", "CI/CD via Gitea Actions", "Lightweight SQLite deployment" ] }, "nginx_proxy": { "listen": 3000, "proxy_pass": "http://127.0.0.1:3001", "extra_headers": [ "proxy_hide_header X-Frame-Options", "proxy_hide_header Content-Security-Policy" ] } } } }, "grafana": { "version": "10.2.0", "image": "source.archipelago-foundation.org/lfg2025/grafana:10.2.0", "manifest": { "app": { "id": "grafana", "name": "Grafana", "version": "10.2.0", "upstream": { "kind": "github", "repo": "grafana/grafana" }, "description": "Analytics and monitoring platform. Visualize metrics and create dashboards.", "container": { "image": "source.archipelago-foundation.org/lfg2025/grafana:10.2.0", "image_signature": "cosign://...", "pull_policy": "if-not-present", "data_uid": "472:472" }, "dependencies": [ { "storage": "5Gi" } ], "resources": { "cpu_limit": 2, "memory_limit": "1Gi", "disk_limit": "5Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "user": 1000, "seccomp_profile": "default", "network_policy": "isolated", "apparmor_profile": "grafana" }, "ports": [ { "host": 3000, "container": 3000, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/grafana", "target": "/var/lib/grafana", "options": [ "rw" ] } ], "environment": [ "GF_SECURITY_ADMIN_USER=admin", "GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}", "GF_SERVER_ROOT_URL=http://localhost:3000", "GF_INSTALL_PLUGINS=" ], "health_check": { "type": "http", "endpoint": "http://localhost:3000", "path": "/api/health", "interval": "30s", "timeout": "30s", "retries": 5 }, "metadata": { "launch": { "open_in_new_tab": true } } } } }, "homeassistant": { "version": "2026.8.3", "image": "source.archipelago-foundation.org/lfg2025/home-assistant:2026.8.3", "manifest": { "app": { "id": "homeassistant", "name": "Home Assistant", "version": "2026.8.3", "upstream": { "kind": "github", "repo": "home-assistant/core" }, "description": "Open source home automation platform. Control and monitor your smart home devices.", "container": { "image": "source.archipelago-foundation.org/lfg2025/home-assistant:2026.8.3", "pull_policy": "if-not-present", "network": "pasta" }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "cpu_limit": 2, "memory_limit": "512Mi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE", "NET_BIND_SERVICE", "NET_RAW" ], "readonly_root": false, "no_new_privileges": true, "user": 1000, "seccomp_profile": "default", "network_policy": "isolated", "apparmor_profile": "home-assistant" }, "ports": [ { "host": 8123, "container": 8123, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/home-assistant", "target": "/config", "options": [ "rw" ] } ], "devices": [], "environment": [ "TZ=UTC" ], "health_check": { "type": "tcp", "endpoint": "localhost:8123", "interval": "30s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "Web UI", "description": "Home Assistant dashboard", "type": "ui", "port": 8123, "protocol": "http", "path": "/" } }, "metadata": { "icon": "/assets/img/app-icons/homeassistant.png", "category": "home", "author": "Home Assistant", "repo": "https://github.com/home-assistant/core", "launch": { "open_in_new_tab": true } } } } }, "immich": { "version": "release", "image": "source.archipelago-foundation.org/lfg2025/immich-server:release", "images": { "immich_server": "source.archipelago-foundation.org/lfg2025/immich-server:release", "immich_postgres": "source.archipelago-foundation.org/lfg2025/immich-postgres:14-vectorchord0.4.3-pgvectors0.2.0", "immich_redis": "source.archipelago-foundation.org/lfg2025/redis:7.4.8" }, "manifest": { "app": { "id": "immich", "name": "Immich", "version": "2.7.4", "upstream": { "kind": "github", "repo": "immich-app/immich" }, "description": "Self-hosted photo and video backup with mobile apps and search.", "container_name": "immich_server", "container": { "image": "source.archipelago-foundation.org/lfg2025/immich-server:release", "pull_policy": "if-not-present", "network": "archy-net", "secret_env": [ { "key": "DB_PASSWORD", "secret_file": "immich-db-password" } ] }, "dependencies": [ { "app_id": "immich-postgres" }, { "app_id": "immich-redis" }, { "storage": "200Gi" } ], "resources": { "memory_limit": "2Gi", "disk_limit": "200Gi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "FOWNER" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 2283, "container": 2283, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/immich", "target": "/usr/src/app/upload", "options": [ "rw" ] } ], "environment": [ "DB_HOSTNAME=immich_postgres", "DB_USERNAME=postgres", "DB_DATABASE_NAME=immich", "REDIS_HOSTNAME=immich_redis", "UPLOAD_LOCATION=/usr/src/app/upload" ], "health_check": { "type": "http", "endpoint": "http://localhost:2283", "path": "/api/server/ping", "interval": "30s", "timeout": "5s", "retries": 20 }, "interfaces": { "main": { "name": "Web UI", "description": "Immich photo library", "type": "ui", "port": 2283, "protocol": "http", "path": "/" } }, "metadata": { "launch": { "open_in_new_tab": true } } } } }, "immich-postgres": { "version": "14-vectorchord0.4.3-pgvectors0.2.0", "manifest": { "app": { "id": "immich-postgres", "name": "Immich Postgres", "version": "14-vectorchord0.4.3-pgvectors0.2.0", "upstream": { "kind": "ghcr", "repo": "immich-app/postgres" }, "description": "Postgres (pgvecto.rs / vectorchord) backend for Immich.", "container_name": "immich_postgres", "container": { "image": "source.archipelago-foundation.org/lfg2025/immich-postgres:14-vectorchord0.4.3-pgvectors0.2.0", "pull_policy": "if-not-present", "network": "archy-net", "data_uid": "100998:100998", "generated_secrets": [ { "name": "immich-db-password", "kind": "hex32" } ], "secret_env": [ { "key": "POSTGRES_PASSWORD", "secret_file": "immich-db-password" } ] }, "dependencies": [ { "storage": "40Gi" } ], "resources": { "memory_limit": "2Gi", "disk_limit": "40Gi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "FOWNER", "SETGID", "SETUID" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/immich-db", "target": "/var/lib/postgresql/data", "options": [ "rw" ] } ], "environment": [ "POSTGRES_USER=postgres", "POSTGRES_DB=immich" ], "health_check": { "type": "tcp", "endpoint": "localhost:5432", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "immich-redis": { "version": "7-alpine", "manifest": { "app": { "id": "immich-redis", "name": "Immich Redis", "version": "7-alpine", "upstream": { "kind": "dockerhub", "repo": "valkey/valkey" }, "description": "Valkey (Redis-compatible) cache for Immich.", "container_name": "immich_redis", "container": { "image": "source.archipelago-foundation.org/lfg2025/valkey:7-alpine", "pull_policy": "if-not-present", "network": "archy-net" }, "dependencies": [], "resources": { "memory_limit": "128Mi" }, "security": { "capabilities": [ "SETGID", "SETUID" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:6379", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "indeedhub": { "version": "1.0.0", "image": "source.archipelago-foundation.org/lfg2025/indeedhub:1.0.0", "images": { "indeedhub": "source.archipelago-foundation.org/lfg2025/indeedhub:1.0.0", "indeedhub-api": "source.archipelago-foundation.org/lfg2025/indeedhub-api:1.0.0", "indeedhub-ffmpeg": "source.archipelago-foundation.org/lfg2025/indeedhub-ffmpeg:1.0.0" }, "manifest": { "app": { "id": "indeedhub", "name": "IndeeHub", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "Bitcoin documentary streaming platform featuring God Bless Bitcoin and other educational content about Bitcoin, sovereignty, and decentralized technology. Sign in with your Nostr identity.", "category": "community", "container_name": "indeedhub", "container": { "image": "source.archipelago-foundation.org/lfg2025/indeedhub:1.0.0", "pull_policy": "if-not-present", "network": "indeedhub-net" }, "dependencies": [ { "app_id": "indeedhub-api" }, { "storage": "1Gi" } ], "resources": { "memory_limit": "512Mi", "disk_limit": "1Gi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 7778, "container": 7777, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "tmpfs", "target": "/run", "options": [ "rw", "nosuid", "nodev", "size=16m" ] }, { "type": "tmpfs", "target": "/var/cache/nginx", "options": [ "rw", "nosuid", "nodev", "size=32m" ] } ], "environment": [], "hooks": { "post_install": [ { "exec": [ "sed", "-i", "/X-Frame-Options/d", "/etc/nginx/conf.d/default.conf" ] }, { "copy_from_host": { "src": "web-ui/nostr-provider.js", "dest": "/usr/share/nginx/html/nostr-provider.js" } }, { "exec": [ "sh", "-c", "grep -qF 'location = /nostr-provider.js {' /etc/nginx/conf.d/default.conf || sed -i '/location = /sw.js {/i\\ location = /nostr-provider.js {\\n add_header Cache-Control \"no-cache, no-store, must-revalidate\";\\n expires off;\\n }\\n' /etc/nginx/conf.d/default.conf" ] }, { "exec": [ "sh", "-c", "grep -q nostr-provider /etc/nginx/conf.d/default.conf || sed -i 's###' /etc/nginx/conf.d/default.conf" ] }, { "exec": [ "sed", "-i", "s#tab-signer-v2#tab-signer-v4#g; s#tab-signer-v3#tab-signer-v4#g", "/etc/nginx/conf.d/default.conf" ] }, { "exec": [ "sed", "-i", "s#src=\"/nostr-provider.js\"#src=\"/nostr-provider.js?v=tab-signer-v4\"#g", "/etc/nginx/conf.d/default.conf" ] }, { "exec": [ "nginx", "-s", "reload" ] } ] }, "health_check": { "type": "tcp", "endpoint": "localhost:7777", "interval": "30s", "timeout": "5s", "retries": 5, "start_period": "30s" }, "interfaces": { "main": { "name": "Web UI", "description": "Stream Bitcoin documentaries with Nostr identity", "type": "ui", "port": 7778, "protocol": "http", "path": "/" } }, "metadata": { "author": "Indeehub Team", "icon": "/assets/img/app-icons/indeedhub.png", "website": "https://indeedhub.com", "repo": "https://github.com/indeedhub/indeedhub", "license": "MIT", "tags": [ "bitcoin", "documentary", "streaming", "media", "education", "nostr" ] } } } }, "indeedhub-api": { "version": "1.0.0", "manifest": { "app": { "id": "indeedhub-api", "name": "IndeedHub API", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "IndeedHub backend API (Nostr auth, media, payments).", "category": "community", "container_name": "indeedhub-api", "container": { "image": "source.archipelago-foundation.org/lfg2025/indeedhub-api:1.0.0", "pull_policy": "if-not-present", "network": "indeedhub-net", "network_aliases": [ "api" ], "generated_secrets": [ { "name": "indeedhub-jwt", "kind": "hex32" }, { "name": "indeedhub-aes-master", "kind": "hex16" } ], "secret_env": [ { "key": "DATABASE_PASSWORD", "secret_file": "indeedhub-db-password" }, { "key": "AWS_SECRET_KEY", "secret_file": "indeedhub-minio-password" }, { "key": "NOSTR_JWT_SECRET", "secret_file": "indeedhub-jwt" }, { "key": "AES_MASTER_SECRET", "secret_file": "indeedhub-aes-master" } ] }, "dependencies": [ { "app_id": "indeedhub-postgres" }, { "app_id": "indeedhub-redis" }, { "app_id": "indeedhub-minio" } ], "resources": { "memory_limit": "2Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [], "environment": [ "PORT=4000", "DATABASE_HOST=postgres", "DATABASE_PORT=5432", "DATABASE_USER=indeedhub", "DATABASE_NAME=indeedhub", "QUEUE_HOST=redis", "QUEUE_PORT=6379", "S3_ENDPOINT=http://minio:9000", "AWS_REGION=us-east-1", "AWS_ACCESS_KEY=indeeadmin", "S3_PUBLIC_BUCKET_NAME=indeedhub-public", "S3_PRIVATE_BUCKET_NAME=indeedhub-private", "S3_PUBLIC_BUCKET_URL=/storage", "NOSTR_JWT_EXPIRES_IN=7d", "ENVIRONMENT=production" ], "health_check": { "type": "tcp", "endpoint": "localhost:4000", "interval": "30s", "timeout": "5s", "retries": 10 } } } }, "indeedhub-ffmpeg": { "version": "1.0.0", "manifest": { "app": { "id": "indeedhub-ffmpeg", "name": "IndeedHub FFmpeg Worker", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "IndeedHub background media transcoding worker.", "category": "community", "container_name": "indeedhub-ffmpeg", "container": { "image": "source.archipelago-foundation.org/lfg2025/indeedhub-ffmpeg:1.0.0", "pull_policy": "if-not-present", "network": "indeedhub-net", "secret_env": [ { "key": "DATABASE_PASSWORD", "secret_file": "indeedhub-db-password" }, { "key": "AWS_SECRET_KEY", "secret_file": "indeedhub-minio-password" }, { "key": "AES_MASTER_SECRET", "secret_file": "indeedhub-aes-master" } ] }, "dependencies": [ { "app_id": "indeedhub-api" } ], "resources": { "memory_limit": "4Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [], "environment": [ "DATABASE_HOST=postgres", "DATABASE_PORT=5432", "DATABASE_USER=indeedhub", "DATABASE_NAME=indeedhub", "QUEUE_HOST=redis", "QUEUE_PORT=6379", "S3_ENDPOINT=http://minio:9000", "AWS_REGION=us-east-1", "AWS_ACCESS_KEY=indeeadmin", "S3_PUBLIC_BUCKET_NAME=indeedhub-public", "S3_PRIVATE_BUCKET_NAME=indeedhub-private", "ENVIRONMENT=production" ] } } }, "indeedhub-minio": { "version": "RELEASE.2024-11-07T00-52-20Z", "manifest": { "app": { "id": "indeedhub-minio", "name": "IndeedHub MinIO", "version": "RELEASE.2024-11-07T00-52-20Z", "upstream": { "kind": "github", "repo": "minio/minio" }, "description": "MinIO S3-compatible object storage for IndeedHub media.", "category": "community", "container_name": "indeedhub-minio", "container": { "image": "source.archipelago-foundation.org/lfg2025/minio:RELEASE.2024-11-07T00-52-20Z", "pull_policy": "if-not-present", "network": "indeedhub-net", "network_aliases": [ "minio" ], "custom_args": [ "server", "/data" ], "generated_secrets": [ { "name": "indeedhub-minio-password", "kind": "hex32" } ], "secret_env": [ { "key": "MINIO_ROOT_PASSWORD", "secret_file": "indeedhub-minio-password" } ] }, "dependencies": [ { "storage": "50Gi" } ], "resources": { "memory_limit": "1Gi", "disk_limit": "50Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "volume", "source": "indeedhub-minio-data", "target": "/data", "options": [ "rw" ] } ], "environment": [ "MINIO_ROOT_USER=indeeadmin" ], "health_check": { "type": "http", "endpoint": "http://localhost:9000", "path": "/minio/health/live", "interval": "30s", "timeout": "5s", "retries": 5 } } } }, "indeedhub-postgres": { "version": "16.13-alpine", "manifest": { "app": { "id": "indeedhub-postgres", "name": "IndeedHub Postgres", "version": "16.13-alpine", "upstream": { "kind": "dockerhub", "repo": "library/postgres" }, "description": "Postgres database backend for IndeedHub.", "category": "community", "container_name": "indeedhub-postgres", "container": { "image": "source.archipelago-foundation.org/lfg2025/postgres:16.13-alpine", "pull_policy": "if-not-present", "network": "indeedhub-net", "network_aliases": [ "postgres" ], "generated_secrets": [ { "name": "indeedhub-db-password", "kind": "hex32" } ], "secret_env": [ { "key": "POSTGRES_PASSWORD", "secret_file": "indeedhub-db-password" } ] }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "memory_limit": "1Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "FOWNER", "SETGID", "SETUID" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "volume", "source": "indeedhub-postgres-data", "target": "/var/lib/postgresql/data", "options": [ "rw" ] } ], "environment": [ "POSTGRES_USER=indeedhub", "POSTGRES_DB=indeedhub" ], "health_check": { "type": "tcp", "endpoint": "localhost:5432", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "indeedhub-redis": { "version": "7.4.8-alpine", "manifest": { "app": { "id": "indeedhub-redis", "name": "IndeedHub Redis", "version": "7.4.8-alpine", "upstream": { "kind": "dockerhub", "repo": "library/redis" }, "description": "Redis queue/cache backend for IndeedHub.", "category": "community", "container_name": "indeedhub-redis", "container": { "image": "source.archipelago-foundation.org/lfg2025/redis:7.4.8-alpine", "pull_policy": "if-not-present", "network": "indeedhub-net", "network_aliases": [ "redis" ] }, "dependencies": [ { "storage": "1Gi" } ], "resources": { "memory_limit": "256Mi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "volume", "source": "indeedhub-redis-data", "target": "/data", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:6379", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "indeedhub-relay": { "version": "0.9.0", "manifest": { "app": { "id": "indeedhub-relay", "name": "IndeedHub Nostr Relay", "version": "0.9.0", "upstream": { "kind": "github", "repo": "scsibug/nostr-rs-relay" }, "description": "nostr-rs-relay backing IndeedHub's Nostr identity + comments.", "category": "community", "container_name": "indeedhub-relay", "container": { "image": "source.archipelago-foundation.org/lfg2025/nostr-rs-relay:0.10.0", "pull_policy": "if-not-present", "network": "indeedhub-net", "network_aliases": [ "relay" ] }, "dependencies": [ { "storage": "2Gi" } ], "resources": { "memory_limit": "256Mi", "disk_limit": "2Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [ { "type": "volume", "source": "indeedhub-relay-data", "target": "/usr/src/app/db", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:8080", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "jellyfin": { "version": "10.11.11", "image": "source.archipelago-foundation.org/lfg2025/jellyfin:10.11.11", "manifest": { "app": { "id": "jellyfin", "name": "Jellyfin", "version": "10.8.13", "upstream": { "kind": "github", "repo": "jellyfin/jellyfin" }, "description": "Free media server. Stream movies, music, and photos.", "container": { "image": "source.archipelago-foundation.org/lfg2025/jellyfin:10.11.11", "pull_policy": "if-not-present", "network": "pasta" }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "memory_limit": "1Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8096, "container": 8096, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/jellyfin/config", "target": "/config", "options": [ "rw" ] }, { "type": "bind", "source": "/var/lib/archipelago/jellyfin/cache", "target": "/cache", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:8096", "interval": "30s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "Web UI", "description": "Jellyfin media dashboard", "type": "ui", "port": 8096, "protocol": "http", "path": "/" } }, "metadata": { "icon": "/assets/img/app-icons/jellyfin.webp", "category": "data", "author": "Jellyfin", "repo": "https://github.com/jellyfin/jellyfin" } } } }, "lnd": { "version": "v0.21.2-beta", "image": "source.archipelago-foundation.org/lfg2025/lnd:v0.21.2-beta", "manifest": { "app": { "id": "lnd", "name": "LND", "version": "0.21.2", "upstream": { "kind": "github", "repo": "lightningnetwork/lnd" }, "description": "Lightning Network implementation by Lightning Labs. Enables instant, low-cost Bitcoin payments.", "container": { "image": "source.archipelago-foundation.org/lfg2025/lnd:v0.21.2-beta", "pull_policy": "if-not-present", "network": "archy-net", "derived_env": [ { "key": "BITCOIND_HOST", "template": "{{BITCOIN_HOST}}" } ], "secret_env": [ { "key": "BITCOIND_RPCPASS", "secret_file": "bitcoin-rpc-password" } ], "data_uid": "100000:100000" }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=26.0" } ], "resources": { "cpu_limit": 2, "memory_limit": "1Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "FOWNER", "SETUID", "SETGID", "DAC_OVERRIDE", "NET_RAW" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 9735, "container": 9735, "protocol": "tcp", "auth": "none", "auth_rationale": "Lightning p2p. The BOLT-8 noise handshake authenticates and encrypts the channel itself." }, { "host": 10009, "container": 10009, "protocol": "tcp", "auth": "none", "auth_rationale": "LND gRPC, authenticated by macaroon over TLS. Zeus and other remote wallets depend on reaching this directly." }, { "host": 18080, "container": 8080, "protocol": "tcp", "auth": "none", "auth_rationale": "LND REST, authenticated by macaroon over TLS. A browser login page would break Zeus and every non-browser wallet client." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/lnd", "target": "/root/.lnd", "options": [ "rw" ] } ], "environment": [ "BITCOIND_RPCUSER=archipelago", "NETWORK=mainnet" ], "health_check": { "type": "tcp", "endpoint": "localhost:10009", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "admin", "sync_required": true }, "lightning_integration": { "channel_management": true, "payment_routing": true } } } }, "lnd-ui": { "version": "1.7.123-alpha", "image": "source.archipelago-foundation.org/lfg2025/lnd-ui:1.7.123-alpha", "manifest": { "app": { "id": "lnd-ui", "name": "LND UI", "version": "1.0.0", "upstream": { "kind": "internal" }, "description": "Archipelago-native HTTP frontend for LND. Runs nginx inside a\ncontainer and serves static assets. LND connection info is fetched\nvia an absolute URL that the host nginx routes to the archipelago\nbackend on 127.0.0.1:5678, so no upstream auth is baked in.\n", "container": { "build": { "context": "/opt/archipelago/docker/lnd-ui", "dockerfile": "Dockerfile", "tag": "localhost/lnd-ui:local" } }, "dependencies": [ { "app_id": "lnd" } ], "resources": { "memory_limit": "64Mi" }, "security": { "readonly_root": false, "network_policy": "host" }, "ports": [ { "host": 18083, "container": 18083, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated", "session_passthrough": true } ], "volumes": [], "environment": [], "health_check": { "type": "http", "endpoint": "http://127.0.0.1:18083", "path": "/", "interval": "30s", "timeout": "5s", "retries": 3 } } } }, "mempool": { "version": "v3.3.1", "image": "source.archipelago-foundation.org/lfg2025/mempool-frontend:v3.3.1", "images": { "archy-mempool-web": "source.archipelago-foundation.org/lfg2025/mempool-frontend:v3.3.1", "mempool-api": "source.archipelago-foundation.org/lfg2025/mempool-backend:v3.3.1", "archy-mempool-db": "source.archipelago-foundation.org/lfg2025/mariadb:11.4.10" }, "manifest": { "app": { "id": "mempool", "name": "Mempool Explorer", "version": "3.0.0", "upstream": { "kind": "github", "repo": "mempool/mempool" }, "description": "Bitcoin mempool and blockchain explorer. Real-time transaction and block visualization.", "container": { "image": "source.archipelago-foundation.org/lfg2025/mempool-frontend:v3.3.1", "image_signature": "cosign://...", "pull_policy": "if-not-present" }, "dependencies": [ { "app_id": "bitcoin-core", "version": ">=24.0" }, { "storage": "20Gi" }, "bitcoin:archival" ], "resources": { "cpu_limit": 2, "memory_limit": "2Gi", "disk_limit": "20Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "user": 1000, "seccomp_profile": "default", "network_policy": "isolated", "apparmor_profile": "mempool" }, "ports": [ { "host": 4080, "container": 8080, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/mempool", "target": "/data", "options": [ "rw" ] } ], "environment": [ "MEMPOOL_BACKEND=electrum", "MEMPOOL_BITCOIN_HOST=bitcoin-core", "MEMPOOL_BITCOIN_PORT=8332", "MEMPOOL_BITCOIN_USER=${BITCOIN_RPC_USER}", "MEMPOOL_BITCOIN_PASSWORD=${BITCOIN_RPC_PASSWORD}" ], "health_check": { "type": "http", "endpoint": "http://localhost:4080", "path": "/api/health", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "read-only", "sync_required": true } } } }, "mempool-api": { "version": "3.0.0", "manifest": { "app": { "id": "mempool-api", "name": "Mempool API", "version": "3.0.0", "upstream": { "kind": "github", "repo": "mempool/mempool" }, "description": "Backend API for mempool explorer.", "container": { "image": "source.archipelago-foundation.org/lfg2025/mempool-backend:v3.3.1", "pull_policy": "if-not-present", "network": "archy-net", "derived_env": [ { "key": "CORE_RPC_HOST", "template": "{{BITCOIN_HOST}}" } ], "secret_env": [ { "key": "CORE_RPC_PASSWORD", "secret_file": "bitcoin-rpc-password" }, { "key": "DATABASE_PASSWORD", "secret_file": "mempool-db-password" } ] }, "dependencies": [ { "app_id": "bitcoin-knots", "version": ">=26.0" }, { "app_id": "electrumx", "version": ">=1.18.0" }, { "app_id": "archy-mempool-db", "version": ">=11.4.10" }, "bitcoin:archival" ], "resources": { "memory_limit": "2Gi", "disk_limit": "20Gi" }, "security": { "capabilities": [], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8999, "container": 8999, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/mempool", "target": "/data", "options": [ "rw" ] } ], "environment": [ "MEMPOOL_BACKEND=electrum", "ELECTRUM_HOST=electrumx", "ELECTRUM_PORT=50001", "ELECTRUM_TLS_ENABLED=false", "CORE_RPC_PORT=8332", "CORE_RPC_USERNAME=archipelago", "DATABASE_ENABLED=true", "DATABASE_HOST=archy-mempool-db", "DATABASE_DATABASE=mempool", "DATABASE_USERNAME=mempool" ], "health_check": { "type": "http", "endpoint": "http://localhost:8999", "path": "/api/v1/backend-info", "interval": "30s", "timeout": "5s", "retries": 3 }, "bitcoin_integration": { "rpc_access": "read-only", "sync_required": true, "pruning_support": false } } } }, "netbird": { "version": "2.38.0", "manifest": { "app": { "id": "netbird", "name": "NetBird", "version": "2.38.0", "upstream": { "kind": "dockerhub", "repo": "library/nginx" }, "description": "Self-hosted WireGuard mesh VPN control plane with dashboard, embedded identity provider, management API, signal, relay, and STUN. The user-facing entry point \u2014 a TLS proxy in front of the dashboard + server.", "category": "networking", "container_name": "netbird", "container": { "image": "docker.io/library/nginx:1.31.4-alpine", "pull_policy": "if-not-present", "network": "netbird-net", "generated_certs": [ { "crt": "/var/lib/archipelago/netbird/tls.crt", "key": "/var/lib/archipelago/netbird/tls.key" } ] }, "dependencies": [ { "app_id": "netbird-server" }, { "app_id": "netbird-dashboard" }, { "storage": "1Gi" } ], "resources": { "memory_limit": "256Mi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID", "NET_BIND_SERVICE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8087, "container": 443, "protocol": "tcp", "auth": "none", "auth_rationale": "NetBird dashboard over TLS, with its own login. The gate speaks plain HTTP, so fronting this port would break the secure context the dashboard requires (issue #15) and the certificate clients pin." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/netbird/nginx.conf", "target": "/etc/nginx/conf.d/default.conf", "options": [ "ro" ] }, { "type": "bind", "source": "/var/lib/archipelago/netbird/tls.crt", "target": "/etc/nginx/tls.crt", "options": [ "ro" ] }, { "type": "bind", "source": "/var/lib/archipelago/netbird/tls.key", "target": "/etc/nginx/tls.key", "options": [ "ro" ] } ], "environment": [], "files": [ { "path": "/var/lib/archipelago/netbird/nginx.conf", "overwrite": true, "content": "server {\n listen 443 ssl;\n server_name _;\n\n # netbird's dashboard needs a secure context (window.crypto.subtle for\n # OIDC PKCE), so the proxy terminates TLS with a self-signed cert (#15).\n ssl_certificate /etc/nginx/tls.crt;\n ssl_certificate_key /etc/nginx/tls.key;\n\n # Rootless Podman can hand a container a new IP across restarts/reboots.\n # nginx resolves a literal upstream name ONCE at startup and caches it,\n # so after the IP moves every request 502s with \"host unreachable\"\n # (issue #15, observed live on .198: nginx pinned to a dead\n # netbird-dashboard IP). Fix: point `resolver` at the netbird-net\n # gateway (Podman's aardvark DNS) and use VARIABLE upstreams, which\n # forces nginx to re-resolve the container names at request time.\n resolver {{NETWORK_GATEWAY}} valid=10s ipv6=off;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_http_version 1.1;\n\n location ~ ^/(relay|ws-proxy/) {\n set $nb_server netbird-server;\n proxy_pass http://$nb_server:80;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";\n proxy_read_timeout 1d;\n }\n\n location ~ ^/(api|oauth2)(/|$) {\n # The dashboard is a SPA whose API/OIDC base URL is baked at build\n # time to one host:port. A single box is reached via several\n # addresses, so those fetches are cross-origin and the browser\n # blocks them with no Access-Control-Allow-Origin (#15, live on\n # .198). Reflect the caller's Origin and answer the CORS preflight.\n if ($request_method = OPTIONS) {\n add_header Access-Control-Allow-Origin $http_origin always;\n add_header Access-Control-Allow-Credentials true always;\n add_header Access-Control-Allow-Methods \"GET, POST, PUT, PATCH, DELETE, OPTIONS\" always;\n add_header Access-Control-Allow-Headers \"Authorization, Content-Type, Accept\" always;\n add_header Access-Control-Max-Age 86400 always;\n add_header Content-Length 0;\n return 204;\n }\n add_header Access-Control-Allow-Origin $http_origin always;\n add_header Access-Control-Allow-Credentials true always;\n add_header Access-Control-Allow-Methods \"GET, POST, PUT, PATCH, DELETE, OPTIONS\" always;\n add_header Access-Control-Allow-Headers \"Authorization, Content-Type, Accept\" always;\n set $nb_server netbird-server;\n proxy_pass http://$nb_server:80;\n }\n\n location ~ ^/(signalexchange\\.SignalExchange|management\\.ManagementService|management\\.ProxyService)/ {\n set $nb_server netbird-server;\n grpc_pass grpc://$nb_server:80;\n grpc_read_timeout 1d;\n grpc_send_timeout 1d;\n }\n\n # OIDC callback routes are client-side SPA routes with NO prebuilt page\n # in the dashboard bundle, so proxying them straight through 404s \u2014\n # which crashes the dashboard's auth init and shows \"Unauthenticated\"\n # with dead buttons (#15, live on .198: /nb-auth + /nb-silent-auth\n # returned 404). Serve index.html at these paths (URL unchanged) so\n # react-oidc boots and completes the login / silent-SSO.\n location ~ ^/(nb-auth|nb-silent-auth) {\n set $nb_dashboard netbird-dashboard;\n rewrite ^.*$ /index.html break;\n proxy_pass http://$nb_dashboard:80;\n }\n\n location / {\n set $nb_dashboard netbird-dashboard;\n proxy_pass http://$nb_dashboard:80;\n }\n}\n" } ], "health_check": { "type": "tcp", "endpoint": "localhost:443", "interval": "30s", "timeout": "5s", "retries": 5, "start_period": "20s" }, "interfaces": { "main": { "name": "Dashboard", "description": "Manage your self-hosted NetBird mesh VPN", "type": "ui", "port": 8087, "protocol": "https", "path": "/" } }, "metadata": { "author": "NetBird", "icon": "/assets/img/app-icons/netbird.svg", "website": "https://netbird.io", "repo": "https://github.com/netbirdio/netbird", "license": "BSD-3-Clause", "tags": [ "networking", "vpn", "wireguard", "mesh" ] } } } }, "netbird-dashboard": { "version": "2.38.0", "manifest": { "app": { "id": "netbird-dashboard", "name": "NetBird Dashboard", "version": "2.38.0", "upstream": { "kind": "github", "repo": "netbirdio/dashboard" }, "description": "NetBird management dashboard (SPA). Internal stack member served through the netbird proxy.", "category": "networking", "container_name": "netbird-dashboard", "container": { "image": "docker.io/netbirdio/dashboard:v2.38.0", "pull_policy": "if-not-present", "network": "netbird-net", "network_aliases": [ "netbird-dashboard" ], "derived_env": [ { "key": "NETBIRD_MGMT_API_ENDPOINT", "template": "https://{{HOST_IP}}:8087" }, { "key": "NETBIRD_MGMT_GRPC_API_ENDPOINT", "template": "https://{{HOST_IP}}:8087" }, { "key": "AUTH_AUTHORITY", "template": "https://{{HOST_IP}}:8087/oauth2" } ] }, "dependencies": [ { "app_id": "netbird-server" } ], "resources": { "memory_limit": "256Mi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID", "NET_BIND_SERVICE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [], "volumes": [], "environment": [ "AUTH_AUDIENCE=netbird-dashboard", "AUTH_CLIENT_ID=netbird-dashboard", "AUTH_CLIENT_SECRET=", "USE_AUTH0=false", "AUTH_SUPPORTED_SCOPES=openid profile email groups", "AUTH_REDIRECT_URI=/nb-auth", "AUTH_SILENT_REDIRECT_URI=/nb-silent-auth", "NETBIRD_TOKEN_SOURCE=idToken", "NGINX_SSL_PORT=443", "LETSENCRYPT_DOMAIN=none" ], "health_check": { "type": "tcp", "endpoint": "localhost:80", "interval": "30s", "timeout": "5s", "retries": 5, "start_period": "20s" }, "metadata": { "author": "NetBird", "icon": "/assets/img/app-icons/netbird.svg", "website": "https://netbird.io", "repo": "https://github.com/netbirdio/dashboard", "license": "BSD-3-Clause", "tags": [ "networking", "vpn", "dashboard" ] } } } }, "netbird-server": { "version": "0.71.2", "manifest": { "app": { "id": "netbird-server", "name": "NetBird Server", "version": "0.71.2", "upstream": { "kind": "github", "repo": "netbirdio/netbird" }, "description": "NetBird combined management / signal / relay server with an embedded identity provider and STUN. Backend for the self-hosted NetBird mesh VPN.", "category": "networking", "container_name": "netbird-server", "container": { "image": "docker.io/netbirdio/netbird-server:0.71.2", "pull_policy": "if-not-present", "network": "netbird-net", "network_aliases": [ "netbird-server" ], "generated_secrets": [ { "name": "netbird-relay-auth-secret", "kind": "base64" }, { "name": "netbird-store-encryption-key", "kind": "base64" } ], "custom_args": [ "--config", "/etc/netbird/config.yaml" ] }, "dependencies": [ { "storage": "1Gi" } ], "resources": { "memory_limit": "1Gi" }, "security": { "capabilities": [ "NET_BIND_SERVICE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8086, "container": 80, "protocol": "tcp", "auth": "none", "auth_rationale": "NetBird management API and its OIDC issuer. Enrolled devices authenticate themselves with setup keys and JWTs, and they cannot hold a browser session \u2014 a login page here would disconnect every VPN client on the network." }, { "host": 3478, "container": 3478, "protocol": "udp", "auth": "none", "auth_rationale": "STUN over UDP for NAT traversal; it must answer unauthenticated probes to do its job at all." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/netbird/data", "target": "/var/lib/netbird", "options": [ "rw" ] }, { "type": "bind", "source": "/var/lib/archipelago/netbird/config.yaml", "target": "/etc/netbird/config.yaml", "options": [ "ro" ] } ], "environment": [], "files": [ { "path": "/var/lib/archipelago/netbird/config.yaml", "overwrite": true, "content": "server:\n listenAddress: \":80\"\n exposedAddress: \"https://{{HOST_IP}}:8087\"\n stunPorts:\n - 3478\n metricsPort: 9090\n healthcheckAddress: \":9000\"\n logLevel: \"info\"\n logFile: \"console\"\n authSecret: \"{{secret:netbird-relay-auth-secret}}\"\n dataDir: \"/var/lib/netbird\"\n auth:\n issuer: \"https://{{HOST_IP}}:8087/oauth2\"\n localAuthDisabled: false\n signKeyRefreshEnabled: false\n dashboardRedirectURIs:\n - \"https://{{HOST_IP}}:8087/nb-auth\"\n - \"https://{{HOST_IP}}:8087/nb-silent-auth\"\n dashboardPostLogoutRedirectURIs:\n - \"https://{{HOST_IP}}:8087/\"\n cliRedirectURIs:\n - \"http://localhost:53000/\"\n store:\n engine: \"sqlite\"\n encryptionKey: \"{{secret:netbird-store-encryption-key}}\"\n" } ], "health_check": { "type": "tcp", "endpoint": "localhost:80", "interval": "30s", "timeout": "5s", "retries": 10, "start_period": "30s" }, "metadata": { "author": "NetBird", "icon": "/assets/img/app-icons/netbird.svg", "website": "https://netbird.io", "repo": "https://github.com/netbirdio/netbird", "license": "BSD-3-Clause", "tags": [ "networking", "vpn", "wireguard", "mesh" ] } } } }, "nextcloud": { "version": "29", "image": "source.archipelago-foundation.org/lfg2025/nextcloud:29", "manifest": { "app": { "id": "nextcloud", "name": "Nextcloud", "version": "29", "upstream": { "kind": "github", "repo": "nextcloud/server" }, "description": "Your own private cloud. File sync, calendars, contacts.", "container": { "image": "source.archipelago-foundation.org/lfg2025/nextcloud:29", "pull_policy": "if-not-present", "network": "pasta" }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "memory_limit": "1Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "SETUID", "SETGID", "DAC_OVERRIDE", "NET_BIND_SERVICE" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 8085, "container": 80, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/nextcloud", "target": "/var/www/html", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:80", "interval": "30s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "Web UI", "description": "Nextcloud file and collaboration dashboard", "type": "ui", "port": 8085, "protocol": "http", "path": "/" } }, "metadata": { "icon": "/assets/img/app-icons/nextcloud.webp", "category": "data", "author": "Nextcloud", "repo": "https://github.com/nextcloud/server", "launch": { "open_in_new_tab": true } } } } }, "nginx-proxy-manager": { "version": "latest", "image": "source.archipelago-foundation.org/lfg2025/nginx-proxy-manager:latest", "manifest": { "app": { "id": "nginx-proxy-manager", "name": "Nginx Proxy Manager", "version": "2.12.1", "upstream": { "kind": "github", "repo": "NginxProxyManager/nginx-proxy-manager" }, "description": "Reverse proxy with SSL. Beautiful web interface for managing proxies. On a node, this manages its admin UI and upstream configuration \u2014 the proxy's own :80/:443 listeners are not published (the node's web server owns those ports).", "container": { "image": "source.archipelago-foundation.org/lfg2025/nginx-proxy-manager:latest", "pull_policy": "if-not-present", "network": "pasta" }, "dependencies": [ { "storage": "1Gi" } ], "resources": { "memory_limit": "512Mi", "disk_limit": "1Gi" }, "security": { "capabilities": [ "CHOWN", "SETUID", "SETGID", "DAC_OVERRIDE", "NET_BIND_SERVICE" ], "readonly_root": false, "no_new_privileges": true, "network_policy": "isolated" }, "ports": [ { "host": 8081, "container": 81, "protocol": "tcp", "bind": "127.0.0.1", "auth": "open", "auth_rationale": "Nginx Proxy Manager enforces its own admin account on every page; the initial setup wizard also has to answer before any account exists." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/nginx-proxy-manager", "target": "/data", "options": [ "rw" ] }, { "type": "bind", "source": "/var/lib/archipelago/nginx-proxy-manager/letsencrypt", "target": "/etc/letsencrypt", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:81", "interval": "30s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "Admin UI", "description": "Nginx Proxy Manager admin interface", "type": "ui", "port": 8081, "protocol": "http", "path": "/" } }, "metadata": { "author": "Nginx Proxy Manager", "category": "networking", "icon": "/assets/img/app-icons/nginx.svg", "repo": "https://github.com/NginxProxyManager/nginx-proxy-manager", "tier": "optional" } } } }, "nostr-rs-relay": { "version": "0.10.0", "image": "source.archipelago-foundation.org/lfg2025/nostr-rs-relay:0.10.0", "manifest": { "app": { "id": "nostr-rs-relay", "name": "Nostr Relay (Rust)", "version": "0.10.0", "upstream": { "kind": "github", "repo": "scsibug/nostr-rs-relay" }, "description": "High-performance Nostr relay written in Rust. Host your own decentralized social media relay and earn networking profits.", "container": { "image": "scsibug/nostr-rs-relay:0.10.0", "image_signature": "cosign://...", "pull_policy": "verify-signature", "data_uid": "1000:1000" }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "cpu_limit": 2, "memory_limit": "1Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "user": 1000, "seccomp_profile": "default", "network_policy": "isolated", "apparmor_profile": "nostr-relay" }, "ports": [ { "host": 18081, "container": 8080, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/nostr-relay", "target": "/usr/src/app/db", "options": [ "rw" ] } ], "environment": [ "RELAY_NAME=Archipelago Nostr Relay", "RELAY_DESCRIPTION=Self-hosted Nostr relay on Archipelago", "MAX_EVENTS=1000000", "MAX_SUBSCRIPTIONS=100" ], "health_check": { "type": "http", "endpoint": "http://localhost:8080", "path": "/", "interval": "30s", "timeout": "30s", "retries": 5 }, "nostr_integration": { "relay_type": "public", "monetization_enabled": true, "event_storage": "sqlite" } } } }, "ollama": { "version": "latest", "image": "source.archipelago-foundation.org/lfg2025/ollama:latest", "manifest": { "app": { "id": "ollama", "name": "Ollama", "version": "0.5.4", "upstream": { "kind": "github", "repo": "ollama/ollama" }, "description": "Run large language models locally. Download and run AI models like Llama, Mistral on your own hardware \u2014 served on the node's loopback for the AI assistant (Settings \u2192 Claude Auth \u2192 model backend), never exposed to the network.", "container": { "image": "source.archipelago-foundation.org/lfg2025/ollama:latest", "pull_policy": "if-not-present", "network": "pasta" }, "dependencies": [ { "storage": "50Gi" } ], "resources": { "disk_limit": "50Gi" }, "security": { "capabilities": [], "readonly_root": false, "no_new_privileges": true, "network_policy": "isolated" }, "ports": [ { "host": 11434, "container": 11434, "protocol": "tcp", "bind": "127.0.0.1", "auth": "local" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/ollama", "target": "/root/.ollama", "options": [ "rw" ] } ], "environment": [], "health_check": { "type": "tcp", "endpoint": "localhost:11434", "interval": "30s", "timeout": "5s", "retries": 3 }, "metadata": { "author": "Ollama", "category": "community", "icon": "/assets/img/app-icons/ollama.png", "repo": "https://github.com/ollama/ollama", "tier": "optional" } } } }, "phoenixd": { "version": "0.9.0", "manifest": { "app": { "id": "phoenixd", "name": "phoenixd", "version": "0.9.0", "upstream": { "kind": "github", "repo": "ACINQ/phoenixd" }, "description": "Headless Lightning daemon by ACINQ (the Phoenix wallet team). No screen of its own \u2014 it exposes a small local API that other apps and tools use to send and receive Lightning payments. Channel liquidity is managed automatically for a fee.", "category": "money", "container": { "image": "source.archipelago-foundation.org/lfg2025/phoenixd:0.9.0", "pull_policy": "if-not-present", "data_uid": "1000:1000" }, "dependencies": [ { "storage": "500Mi" } ], "resources": { "cpu_limit": 1, "memory_limit": "512Mi", "disk_limit": "1Gi" }, "security": { "capabilities": [], "readonly_root": true, "no_new_privileges": true, "network_policy": "bridge" }, "ports": [ { "host": 9740, "container": 9740, "protocol": "tcp", "bind": "127.0.0.1", "auth": "none", "auth_rationale": "Loopback-only JSON API, not a web page. Every request is authenticated by the http password phoenixd generates in its own data directory on first run; the app gate's browser login page would break the API clients this port exists for." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/phoenixd", "target": "/data", "options": [ "rw" ] } ], "environment": [ "PHOENIX_DATADIR=/data" ], "health_check": { "type": "tcp", "endpoint": "localhost:9740", "interval": "30s", "timeout": "5s", "retries": 5 }, "metadata": { "icon": "/assets/img/app-icons/phoenixd.svg", "repo": "https://github.com/ACINQ/phoenixd", "tier": "optional", "features": [ "Ultra-light Lightning node \u2014 no bitcoin node required", "Automated channel and liquidity management (fees apply)", "Simple HTTP API + websockets for payments", "Backed by the team behind the Phoenix mobile wallet" ] } } } }, "photoprism": { "version": "240915", "image": "source.archipelago-foundation.org/lfg2025/photoprism:240915", "manifest": { "app": { "id": "photoprism", "name": "PhotoPrism", "version": "240915", "upstream": { "kind": "github", "repo": "photoprism/photoprism" }, "description": "AI-powered photo management with facial recognition.", "container": { "image": "source.archipelago-foundation.org/lfg2025/photoprism:240915", "pull_policy": "if-not-present" }, "dependencies": [ { "storage": "10Gi" } ], "resources": { "memory_limit": "1Gi", "disk_limit": "10Gi" }, "security": { "capabilities": [ "CHOWN", "SETUID", "SETGID" ], "readonly_root": false, "network_policy": "isolated" }, "ports": [ { "host": 2342, "container": 2342, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/photoprism", "target": "/photoprism/storage", "options": [ "rw" ] } ], "environment": [ "PHOTOPRISM_ADMIN_PASSWORD=archipelago", "PHOTOPRISM_DEFAULT_LOCALE=en" ], "health_check": { "type": "tcp", "endpoint": "localhost:2342", "interval": "60s", "timeout": "5s", "retries": 3 }, "interfaces": { "main": { "name": "Web UI", "description": "PhotoPrism photo library", "type": "ui", "port": 2342, "protocol": "http", "path": "/" } }, "metadata": { "icon": "/assets/img/app-icons/photoprism.svg", "category": "data", "author": "PhotoPrism", "repo": "https://github.com/photoprism/photoprism", "launch": { "open_in_new_tab": true } } } } }, "pine": { "version": "1.3.0", "manifest": { "app": { "id": "pine", "name": "Pine", "version": "1.3.0", "upstream": { "kind": "dockerhub", "repo": "library/nginx" }, "description": "A private voice assistant for your home. Pine runs speech-to-text (Whisper), text-to-speech (Piper) and wake-word detection (openWakeWord) on your own node and pairs with a PineVoice satellite speaker, so Home Assistant Assist works locally with nothing sent to the cloud. Ask it about your node \u2014 block height, sync, peers, Lightning balance \u2014 and, when a Claude API key is set, anything else.", "category": "home", "container_name": "pine", "container": { "image": "docker.io/library/nginx:1.31.4-alpine", "pull_policy": "if-not-present", "network": "archy-net", "network_aliases": [ "pine" ], "generated_certs": [ { "crt": "/var/lib/archipelago/pine/tls.crt", "key": "/var/lib/archipelago/pine/tls.key" } ] }, "dependencies": [ { "app_id": "pine-whisper" }, { "app_id": "pine-piper" }, { "app_id": "pine-openwakeword" }, { "storage": "128Mi" } ], "resources": { "memory_limit": "64Mi" }, "security": { "capabilities": [ "CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID", "NET_BIND_SERVICE" ], "readonly_root": false, "no_new_privileges": true, "network_policy": "isolated" }, "ports": [ { "host": 10380, "container": 80, "protocol": "tcp", "bind": "127.0.0.1", "auth": "gated" }, { "host": 10381, "container": 443, "protocol": "tcp", "auth": "none", "auth_rationale": "Pine's TLS listener. The gate speaks plain HTTP, so fronting this port would break the secure context navigator.bluetooth needs for WiFi provisioning. The plain-HTTP entry point (10380) is gated, and it is what the UI opens." } ], "volumes": [ { "type": "bind", "source": "/var/lib/archipelago/pine/nginx.conf", "target": "/etc/nginx/conf.d/default.conf", "options": [ "ro" ] }, { "type": "bind", "source": "/var/lib/archipelago/pine/tls.crt", "target": "/etc/nginx/tls.crt", "options": [ "ro" ] }, { "type": "bind", "source": "/var/lib/archipelago/pine/tls.key", "target": "/etc/nginx/tls.key", "options": [ "ro" ] }, { "type": "bind", "source": "/var/lib/archipelago/pine/index.html", "target": "/usr/share/nginx/html/index.html", "options": [ "ro" ] } ], "environment": [], "files": [ { "path": "/var/lib/archipelago/pine/nginx.conf", "overwrite": true, "content": "server {\n listen 80;\n server_name _;\n return 301 https://$host:10381$request_uri;\n}\nserver {\n listen 443 ssl;\n server_name _;\n ssl_certificate /etc/nginx/tls.crt;\n ssl_certificate_key /etc/nginx/tls.key;\n root /usr/share/nginx/html;\n index index.html;\n # Live node facts for the status card \u2014 proxied to the node's\n # public status tier so the (https) page can fetch same-origin.\n location = /node-status {\n proxy_pass http://host.containers.internal:80/api/pine/status;\n proxy_http_version 1.1;\n proxy_set_header Host $host;\n proxy_connect_timeout 5s;\n proxy_read_timeout 10s;\n }\n location / { try_files $uri $uri/ /index.html; }\n}\n" }, { "path": "/var/lib/archipelago/pine/index.html", "overwrite": true, "content": "\n\n
\n \n \nConnect your speaker \u2014 everything stays on your node.
:10300:10200:10400)After WiFi joins, one manual step remains \u2014 pair the\n speaker in Home Assistant: Settings \u2192 Devices & services \u2192\n Add Wyoming Protocol, host = the speaker\u2019s IP, port\n 10700. Whisper, Piper, openWakeWord and the Assist pipeline\n are wired up automatically when Pine installs. Wake word:\n \u201cHey Jarvis.\u201d Ask node things like \u201cwhat\u2019s the block\n height?\u201d, \u201chow many peers?\u201d, \u201cis the node\n synced?\u201d or \u201cwhat\u2019s my lightning balance?\u201d \u2014 and when a\n Claude API key is set on the node, anything else gets answered by\n Claude. New mesh messages are announced on the speaker too.
\nTroubleshooting: if it hears you (LED reacts) but answers\n are silent, unplug and replug the speaker \u2014 an interrupted answer can\n wedge its audio output until it reboots.
\n