diff --git a/releases/app-catalog.json b/releases/app-catalog.json new file mode 100644 index 00000000..1f02e4e3 --- /dev/null +++ b/releases/app-catalog.json @@ -0,0 +1,4262 @@ +{ + "schema": 1, + "updated": "2026-06-24", + "apps": { + "adguardhome": { + "version": "v0.107.55", + "image": "146.59.87.168:3000/lfg2025/adguardhome:v0.107.55" + }, + "aiui": { + "version": "0.1.0", + "manifest": { + "app": { + "id": "aiui", + "name": "AI Assistant", + "version": "0.1.0", + "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" + } + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:80", + "path": "/", + "interval": "60s", + "timeout": "5s", + "retries": 3 + } + } + } + }, + "archy-btcpay-db": { + "version": "15.17", + "manifest": { + "app": { + "id": "archy-btcpay-db", + "name": "BTCPay Postgres", + "version": 15.17, + "description": "Postgres backend for BTCPay and NBXplorer.", + "container": { + "image": "git.tx1138.com/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", + "description": "MariaDB backend for the mempool explorer stack.", + "container": { + "image": "git.tx1138.com/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", + "description": "Frontend web UI for mempool explorer.", + "container_name": "mempool", + "container": { + "image": "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.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" + } + ], + "environment": [ + "FRONTEND_HTTP_PORT=8080", + "BACKEND_MAINNET_HTTP_HOST=mempool-api" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost: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", + "description": "BTCPay blockchain indexer service.", + "container": { + "image": "git.tx1138.com/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" + } + ], + "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 + } + } + } + }, + "bitcoin-core": { + "version": "28.4.0", + "manifest": { + "app": { + "id": "bitcoin-core", + "name": "Bitcoin Core", + "version": "28.4.0", + "description": "Reference Bitcoin Core node with dynamic prune/full-mode startup based on host disk.", + "container_name": "bitcoin-core", + "container": { + "image": "146.59.87.168:3000/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_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 -noconf -server=1 -prune=550 -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 -rpcuser=\"$RPC_USER\" -rpcpassword=\"$RPC_PASS\";\nelse\n exec \"$BITCOIND\" -datadir=/home/bitcoin/.bitcoin -noconf -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 -rpcuser=\"$RPC_USER\" -rpcpassword=\"$RPC_PASS\";\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" + }, + { + "host": 8333, + "container": 8333, + "protocol": "tcp" + } + ], + "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 + } + } + } + }, + "bitcoin-knots": { + "version": "latest", + "image": "146.59.87.168:3000/lfg2025/bitcoin-knots:latest", + "manifest": { + "app": { + "id": "bitcoin-knots", + "name": "Bitcoin Knots", + "version": "28.1.0", + "description": "Full Bitcoin Knots node with dynamic prune/full-mode startup based on host disk.", + "container_name": "bitcoin-knots", + "container": { + "image": "146.59.87.168:3000/lfg2025/bitcoin-knots:latest", + "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_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 -noconf -server=1 -prune=550 -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 -rpcuser=\"$RPC_USER\" -rpcpassword=\"$RPC_PASS\";\nelse\n exec \"$BITCOIND\" -datadir=/home/bitcoin/.bitcoin -noconf -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 -rpcuser=\"$RPC_USER\" -rpcpassword=\"$RPC_PASS\";\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" + }, + { + "host": 8333, + "container": 8333, + "protocol": "tcp" + } + ], + "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 + } + } + } + }, + "bitcoin-ui": { + "version": "1.7.84-alpha", + "image": "146.59.87.168:3000/lfg2025/bitcoin-ui:1.7.84-alpha", + "manifest": { + "app": { + "id": "bitcoin-ui", + "name": "Bitcoin UI", + "version": "1.0.0", + "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": [], + "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.1.0", + "manifest": { + "app": { + "id": "botfights", + "name": "BotFights", + "version": "1.1.0", + "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": "146.59.87.168:3000/lfg2025/botfights:1.1.0", + "pull_policy": "always" + }, + "dependencies": [ + { + "storage": "500Mi" + } + ], + "resources": { + "cpu_limit": 2, + "memory_limit": "512Mi", + "disk_limit": "500Mi" + }, + "security": { + "capabilities": [], + "readonly_root": true, + "no_new_privileges": true, + "user": 1001, + "seccomp_profile": "default", + "network_policy": "bridge", + "apparmor_profile": "default" + }, + "ports": [ + { + "host": 9100, + "container": 9100, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "botfights-data", + "target": "/app/server/data" + }, + { + "type": "tmpfs", + "target": "/tmp", + "options": [ + "rw", + "noexec", + "nosuid", + "size=64m" + ] + } + ], + "environment": [ + "NODE_ENV=production" + ], + "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.3.9", + "image": "docker.io/btcpayserver/btcpayserver:2.3.9", + "images": { + "btcpay-server": "docker.io/btcpayserver/btcpayserver:2.3.9", + "archy-nbxplorer": "146.59.87.168:3000/lfg2025/nbxplorer:2.6.0", + "archy-btcpay-db": "146.59.87.168:3000/lfg2025/postgres:15.17" + } + }, + "btcpay-server": { + "version": "2.3.9", + "manifest": { + "app": { + "id": "btcpay-server", + "name": "BTCPay Server", + "version": "2.3.9", + "description": "Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries.", + "container": { + "image": "docker.io/btcpayserver/btcpayserver:2.3.9", + "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" + } + ], + "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" + } + ], + "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_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", + "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" + }, + { + "host": 9835, + "container": 9835, + "protocol": "tcp" + } + ], + "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 + } + } + } + }, + "cryptpad": { + "version": "2024.12.0", + "image": "146.59.87.168:3000/lfg2025/cryptpad:2024.12.0" + }, + "did-wallet": { + "version": "1.0.0", + "manifest": { + "app": { + "id": "did-wallet", + "name": "Web5 DID Wallet", + "version": "1.0.0", + "description": "Web5 wallet with Decentralized Identifier (DID) support. Manage your digital identity and Web5 assets.", + "container": { + "image": "archipelago/did-wallet:1.0.0", + "image_signature": "cosign://...", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "storage": "2Gi" + } + ], + "resources": { + "cpu_limit": 1, + "memory_limit": "512Mi", + "disk_limit": "2Gi" + }, + "security": { + "capabilities": [], + "readonly_root": true, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "isolated", + "apparmor_profile": "did-wallet" + }, + "ports": [ + { + "host": 8083, + "container": 8080, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/did-wallet", + "target": "/app/wallet", + "options": [ + "rw" + ] + } + ], + "environment": [ + "WALLET_STORAGE=/app/wallet" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:8083", + "path": "/health", + "interval": "30s", + "timeout": "5s", + "retries": 3 + }, + "web5_integration": { + "did_support": true, + "wallet_functionality": true, + "bitcoin_integration": true + } + } + } + }, + "electrs-ui": { + "version": "latest", + "image": "146.59.87.168:3000/lfg2025/electrs-ui:latest", + "manifest": { + "app": { + "id": "electrs-ui", + "name": "Electrs UI", + "version": "1.0.0", + "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": [], + "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": "146.59.87.168:3000/lfg2025/electrumx:v1.18.0", + "manifest": { + "app": { + "id": "electrumx", + "name": "ElectrumX", + "version": "1.18.0", + "description": "Electrum server indexing Bitcoin chain data for lightweight wallet queries.", + "container": { + "image": "146.59.87.168:3000/lfg2025/electrumx:v1.18.0", + "pull_policy": "if-not-present", + "network": "archy-net", + "data_uid": "1000:1000", + "entrypoint": [ + "sh", + "-lc" + ], + "custom_args": [ + "export DAEMON_URL=\"http://archipelago:$(printenv BITCOIN_RPC_PASS)@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" + } + ], + "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" + } + ], + "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.0", + "image": "146.59.87.168:3000/lfg2025/fedimintd:v0.10.0", + "manifest": { + "app": { + "id": "fedimint", + "name": "Fedimint Guardian", + "version": "0.10.0", + "description": "Federated Bitcoin minting service with built-in Guardian UI. Privacy-preserving Bitcoin custody.", + "container": { + "image": "146.59.87.168:3000/lfg2025/fedimintd:v0.10.0", + "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" + } + ], + "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" + }, + { + "host": 8174, + "container": 8174, + "protocol": "tcp" + }, + { + "host": 8177, + "container": 8175, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/fedimint", + "target": "/data", + "options": [ + "rw" + ] + } + ], + "environment": [ + "FM_DATA_DIR=/data", + "FM_BITCOIND_URL=http://bitcoin-knots:8332", + "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", + "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": "146.59.87.168:3000/lfg2025/fmcd:0.8.0", + "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" + } + ], + "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.0", + "image": "146.59.87.168:3000/lfg2025/gatewayd:v0.10.0", + "manifest": { + "app": { + "id": "fedimint-gateway", + "name": "Fedimint Gateway", + "version": "0.10.0", + "description": "Fedimint gateway service with automatic LND-or-LDK backend selection.", + "container": { + "image": "git.tx1138.com/lfg2025/gatewayd:v0.10.0", + "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 http://host.archipelago:8332 --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 http://host.archipelago:8332 --bitcoind-username \"$FM_BITCOIND_USERNAME\" --bitcoind-password \"$FM_BITCOIND_PASSWORD\" ldk --ldk-lightning-port 9737 --ldk-alias archipelago-gateway;\nfi" + ], + "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" + }, + { + "host": 9737, + "container": 9737, + "protocol": "tcp" + } + ], + "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.27.0", + "image": "146.59.87.168:3000/lfg2025/filebrowser:v2.27.0", + "manifest": { + "app": { + "id": "filebrowser", + "name": "File Browser", + "version": "2.27.0", + "description": "Baseline Archipelago file manager service.", + "container": { + "image": "git.tx1138.com/lfg2025/filebrowser:v2.27.0", + "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" + } + ], + "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": { + "version": "v0.1.0", + "image": "146.59.87.168:3000/lfg2025/fips:v0.1.0" + }, + "fips-ui": { + "version": "1.0.0", + "manifest": { + "app": { + "id": "fips-ui", + "name": "FIPS Mesh", + "version": "1.0.0", + "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": [], + "volumes": [], + "environment": [], + "health_check": { + "type": "http", + "endpoint": "http://127.0.0.1:8336", + "path": "/", + "interval": "30s", + "timeout": "5s", + "retries": 3 + } + } + } + }, + "gitea": { + "version": "1.23", + "manifest": { + "app": { + "id": "gitea", + "name": "Gitea", + "version": "1.23", + "description": "Self-hosted Git service with built-in container registry, CI/CD, and package hosting.", + "category": "development", + "container": { + "image": "docker.io/gitea/gitea:1.23", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "storage": "500Mi" + } + ], + "resources": { + "memory_limit": "256Mi", + "disk_limit": "500Mi" + }, + "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" + }, + { + "host": 2222, + "container": 22, + "protocol": "tcp" + } + ], + "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__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": "146.59.87.168:3000/lfg2025/grafana:10.2.0", + "manifest": { + "app": { + "id": "grafana", + "name": "Grafana", + "version": "10.2.0", + "description": "Analytics and monitoring platform. Visualize metrics and create dashboards.", + "container": { + "image": "grafana/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" + } + ], + "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": "2024.1", + "image": "146.59.87.168:3000/lfg2025/home-assistant:2024.1", + "manifest": { + "app": { + "id": "homeassistant", + "name": "Home Assistant", + "version": "2024.1.0", + "description": "Open source home automation platform. Control and monitor your smart home devices.", + "container": { + "image": "146.59.87.168:3000/lfg2025/home-assistant:2024.1", + "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" + } + ], + "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": "146.59.87.168:3000/lfg2025/immich-server:release", + "images": { + "immich_server": "146.59.87.168:3000/lfg2025/immich-server:release", + "immich_postgres": "146.59.87.168:3000/lfg2025/immich-postgres:14-vectorchord0.4.3-pgvectors0.2.0", + "immich_redis": "146.59.87.168:3000/lfg2025/redis:7.4.8" + }, + "manifest": { + "app": { + "id": "immich", + "name": "Immich", + "version": "2.7.4", + "description": "Self-hosted photo and video backup with mobile apps and search.", + "container_name": "immich_server", + "container": { + "image": "146.59.87.168:3000/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": [], + "readonly_root": false, + "network_policy": "isolated" + }, + "ports": [ + { + "host": 2283, + "container": 2283, + "protocol": "tcp" + } + ], + "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", + "description": "Postgres (pgvecto.rs / vectorchord) backend for Immich.", + "container_name": "immich_postgres", + "container": { + "image": "146.59.87.168:3000/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", + "description": "Valkey (Redis-compatible) cache for Immich.", + "container_name": "immich_redis", + "container": { + "image": "146.59.87.168:3000/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": "146.59.87.168:3000/lfg2025/indeedhub:1.0.0", + "images": { + "indeedhub": "146.59.87.168:3000/lfg2025/indeedhub:1.0.0", + "indeedhub-api": "146.59.87.168:3000/lfg2025/indeedhub-api:1.0.0", + "indeedhub-ffmpeg": "146.59.87.168:3000/lfg2025/indeedhub-ffmpeg:1.0.0" + }, + "manifest": { + "app": { + "id": "indeedhub", + "name": "IndeeHub", + "version": "1.0.0", + "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": "146.59.87.168:3000/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" + } + ], + "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 -q nostr-provider /etc/nginx/conf.d/default.conf || sed -i 's###' /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", + "description": "IndeedHub backend API (Nostr auth, media, payments).", + "category": "community", + "container_name": "indeedhub-api", + "container": { + "image": "146.59.87.168:3000/lfg2025/indeedhub-api:1.0.0", + "pull_policy": "if-not-present", + "network": "indeedhub-net", + "network_aliases": [ + "api" + ], + "generated_secrets": [ + { + "name": "indeedhub-jwt", + "kind": "hex32" + } + ], + "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" + } + ] + }, + "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", + "AES_MASTER_SECRET=0123456789abcdef0123456789abcdef", + "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", + "description": "IndeedHub background media transcoding worker.", + "category": "community", + "container_name": "indeedhub-ffmpeg", + "container": { + "image": "146.59.87.168:3000/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" + } + ] + }, + "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", + "AES_MASTER_SECRET=0123456789abcdef0123456789abcdef" + ] + } + } + }, + "indeedhub-minio": { + "version": "RELEASE.2024-11-07T00-52-20Z", + "manifest": { + "app": { + "id": "indeedhub-minio", + "name": "IndeedHub MinIO", + "version": "RELEASE.2024-11-07T00-52-20Z", + "description": "MinIO S3-compatible object storage for IndeedHub media.", + "category": "community", + "container_name": "indeedhub-minio", + "container": { + "image": "146.59.87.168:3000/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", + "description": "Postgres database backend for IndeedHub.", + "category": "community", + "container_name": "indeedhub-postgres", + "container": { + "image": "146.59.87.168:3000/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", + "description": "Redis queue/cache backend for IndeedHub.", + "category": "community", + "container_name": "indeedhub-redis", + "container": { + "image": "146.59.87.168:3000/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": [ + "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", + "description": "nostr-rs-relay backing IndeedHub's Nostr identity + comments.", + "category": "community", + "container_name": "indeedhub-relay", + "container": { + "image": "146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.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.8.13", + "image": "146.59.87.168:3000/lfg2025/jellyfin:10.8.13", + "manifest": { + "app": { + "id": "jellyfin", + "name": "Jellyfin", + "version": "10.8.13", + "description": "Free media server. Stream movies, music, and photos.", + "container": { + "image": "146.59.87.168:3000/lfg2025/jellyfin:10.8.13", + "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" + } + ], + "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" + } + } + } + }, + "lightning-stack": { + "version": "0.12.0", + "manifest": { + "app": { + "id": "lightning-stack", + "name": "Lightning Stack", + "version": "0.12.0", + "description": "Complete Lightning Network implementation. Includes LND, CLN, and management tools.", + "container": { + "image": "lightninglabs/lightning-stack:v0.12.0", + "image_signature": "cosign://...", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "app_id": "bitcoin-core", + "version": ">=24.0" + }, + { + "storage": "50Gi" + } + ], + "resources": { + "cpu_limit": 4, + "memory_limit": "4Gi", + "disk_limit": "50Gi" + }, + "security": { + "capabilities": [ + "NET_BIND_SERVICE" + ], + "readonly_root": true, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "isolated", + "apparmor_profile": "lightning-stack" + }, + "ports": [ + { + "host": 9737, + "container": 9735, + "protocol": "tcp" + }, + { + "host": 10010, + "container": 10009, + "protocol": "tcp" + }, + { + "host": 8087, + "container": 8080, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/lightning-stack", + "target": "/root/.lightning", + "options": [ + "rw" + ] + } + ], + "environment": [ + "BITCOIND_HOST=bitcoin-core", + "BITCOIND_RPCUSER=${BITCOIN_RPC_USER}", + "BITCOIND_RPCPASS=${BITCOIN_RPC_PASSWORD}", + "NETWORK=mainnet" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:8087", + "path": "/v1/getinfo", + "interval": "30s", + "timeout": "5s", + "retries": 3 + }, + "bitcoin_integration": { + "rpc_access": "admin", + "sync_required": true + }, + "lightning_integration": { + "channel_management": true, + "payment_routing": true + } + } + } + }, + "lnd": { + "version": "v0.18.4-beta", + "image": "146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta", + "manifest": { + "app": { + "id": "lnd", + "name": "LND", + "version": "0.18.4", + "description": "Lightning Network implementation by Lightning Labs. Enables instant, low-cost Bitcoin payments.", + "container": { + "image": "146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta", + "pull_policy": "if-not-present", + "network": "archy-net", + "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" + }, + { + "host": 10009, + "container": 10009, + "protocol": "tcp" + }, + { + "host": 18080, + "container": 8080, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/lnd", + "target": "/root/.lnd", + "options": [ + "rw" + ] + } + ], + "environment": [ + "BITCOIND_HOST=bitcoin-knots", + "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": "latest", + "image": "146.59.87.168:3000/lfg2025/lnd-ui:latest", + "manifest": { + "app": { + "id": "lnd-ui", + "name": "LND UI", + "version": "1.0.0", + "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": "bridge" + }, + "ports": [ + { + "host": 18083, + "container": 80, + "protocol": "tcp" + } + ], + "volumes": [], + "environment": [], + "health_check": { + "type": "http", + "endpoint": "http://127.0.0.1:18083", + "path": "/", + "interval": "30s", + "timeout": "5s", + "retries": 3 + } + } + } + }, + "mempool": { + "version": "v3.0.1", + "image": "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1", + "images": { + "archy-mempool-web": "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1", + "mempool-api": "146.59.87.168:3000/lfg2025/mempool-backend:v3.0.0", + "archy-mempool-db": "146.59.87.168:3000/lfg2025/mariadb:11.4.10" + }, + "manifest": { + "app": { + "id": "mempool", + "name": "Mempool Explorer", + "version": "3.0.0", + "description": "Bitcoin mempool and blockchain explorer. Real-time transaction and block visualization.", + "container": { + "image": "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1", + "image_signature": "cosign://...", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "app_id": "bitcoin-core", + "version": ">=24.0" + }, + { + "storage": "20Gi" + } + ], + "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": 4080, + "protocol": "tcp" + } + ], + "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", + "description": "Backend API for mempool explorer.", + "container": { + "image": "git.tx1138.com/lfg2025/mempool-backend:v3.0.0", + "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" + } + ], + "resources": { + "memory_limit": "2Gi", + "disk_limit": "20Gi" + }, + "security": { + "capabilities": [], + "readonly_root": false, + "network_policy": "isolated" + }, + "ports": [ + { + "host": 8999, + "container": 8999, + "protocol": "tcp" + } + ], + "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 + } + } + } + }, + "meshtastic": { + "version": "2-daily-alpine", + "manifest": { + "app": { + "id": "meshtastic", + "name": "Meshtastic", + "version": "2-daily-alpine", + "description": "Open-source mesh networking for LoRa radios. Create decentralized communication networks.", + "container": { + "image": "docker.io/meshtastic/meshtasticd:daily-alpine", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "storage": "1Gi" + } + ], + "resources": { + "cpu_limit": 1, + "memory_limit": "512Mi", + "disk_limit": "1Gi" + }, + "security": { + "capabilities": [ + "NET_ADMIN", + "SYS_ADMIN" + ], + "readonly_root": false, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "host", + "apparmor_profile": "meshtastic" + }, + "ports": [ + { + "host": 4403, + "container": 4403, + "protocol": "tcp" + } + ], + "devices": [ + "/dev/ttyUSB0" + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/meshtastic", + "target": "/var/lib/meshtasticd", + "options": [ + "rw" + ] + } + ], + "files": [ + { + "path": "/var/lib/archipelago/meshtastic/config.yaml", + "content": "General:\n MACAddress: AA:BB:CC:DD:EE:01\nWebserver:\n Port: 4403\n" + } + ], + "environment": [ + "MESHTASTIC_PORT=/dev/ttyUSB0", + "MESHTASTIC_SERIAL=true" + ], + "health_check": { + "type": "cmd", + "endpoint": "test -f /var/lib/meshtasticd/config.yaml", + "interval": "30s", + "timeout": "30s", + "retries": 5 + }, + "networking": { + "mesh_enabled": true, + "local_network_access": true + }, + "metadata": { + "icon": "/assets/img/app-icons/meshcore.svg", + "category": "networking", + "tier": "recommended", + "repo": "https://github.com/meshtastic/firmware" + } + } + } + }, + "morphos-server": { + "version": "1.0.0", + "manifest": { + "app": { + "id": "morphos-server", + "name": "MorphOS Server", + "version": "1.0.0", + "description": "MorphOS server platform. Decentralized application server.", + "container": { + "image": "archipelago/morphos-server:1.0.0", + "image_signature": "cosign://...", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "storage": "5Gi" + } + ], + "resources": { + "cpu_limit": 2, + "memory_limit": "2Gi", + "disk_limit": "5Gi" + }, + "security": { + "capabilities": [], + "readonly_root": true, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "isolated", + "apparmor_profile": "morphos-server" + }, + "ports": [ + { + "host": 8086, + "container": 8080, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/morphos-server", + "target": "/app/data", + "options": [ + "rw" + ] + } + ], + "environment": [ + "MORPHOS_ENV=production", + "MORPHOS_DATA_DIR=/app/data" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:8086", + "path": "/health", + "interval": "30s", + "timeout": "5s", + "retries": 3 + } + } + } + }, + "netbird": { + "version": "2.38.0", + "manifest": { + "app": { + "id": "netbird", + "name": "NetBird", + "version": "2.38.0", + "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.27-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" + } + ], + "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", + "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", + "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" + }, + { + "host": 3478, + "container": 3478, + "protocol": "udp" + } + ], + "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": "146.59.87.168:3000/lfg2025/nextcloud:29", + "manifest": { + "app": { + "id": "nextcloud", + "name": "Nextcloud", + "version": "29", + "description": "Your own private cloud. File sync, calendars, contacts.", + "container": { + "image": "146.59.87.168:3000/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" + } + ], + "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": "146.59.87.168:3000/lfg2025/nginx-proxy-manager:latest" + }, + "nostr-rs-relay": { + "version": "0.9.0", + "image": "146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.0", + "manifest": { + "app": { + "id": "nostr-rs-relay", + "name": "Nostr Relay (Rust)", + "version": "0.8.0", + "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.8.9", + "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" + } + ], + "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" + } + } + } + }, + "nostr-vpn": { + "version": "v0.3.7", + "image": "146.59.87.168:3000/lfg2025/nostr-vpn:v0.3.7" + }, + "ollama": { + "version": "latest", + "image": "146.59.87.168:3000/lfg2025/ollama:latest" + }, + "penpot": { + "version": "2.4", + "image": "146.59.87.168:3000/lfg2025/penpot-frontend:2.4", + "images": { + "penpot-frontend": "146.59.87.168:3000/lfg2025/penpot-frontend:2.4", + "penpot-backend": "146.59.87.168:3000/lfg2025/penpot-backend:2.4", + "penpot-exporter": "146.59.87.168:3000/lfg2025/penpot-exporter:2.4", + "penpot-postgres": "146.59.87.168:3000/lfg2025/postgres:15", + "penpot-valkey": "146.59.87.168:3000/lfg2025/valkey:8.1" + } + }, + "photoprism": { + "version": "240915", + "image": "146.59.87.168:3000/lfg2025/photoprism:240915", + "manifest": { + "app": { + "id": "photoprism", + "name": "PhotoPrism", + "version": "240915", + "description": "AI-powered photo management with facial recognition.", + "container": { + "image": "146.59.87.168:3000/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" + } + ], + "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 + } + } + } + } + }, + "portainer": { + "version": "2.19.4", + "image": "146.59.87.168:3000/lfg2025/portainer:2.19.4", + "manifest": { + "app": { + "id": "portainer", + "name": "Portainer", + "version": "2.19.4", + "description": "Container management web UI for the local Podman socket.", + "category": "development", + "container": { + "image": "146.59.87.168:3000/lfg2025/portainer:2.19.4", + "pull_policy": "if-not-present", + "data_uid": "1000:1000" + }, + "dependencies": [ + { + "storage": "1Gi" + } + ], + "resources": { + "memory_limit": "256Mi", + "disk_limit": "1Gi" + }, + "security": { + "capabilities": [ + "CHOWN", + "SETUID", + "SETGID", + "DAC_OVERRIDE" + ], + "readonly_root": false, + "no_new_privileges": true, + "network_policy": "isolated" + }, + "ports": [ + { + "host": 9000, + "container": 9000, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/portainer", + "target": "/data", + "options": [ + "rw" + ] + }, + { + "type": "bind", + "source": "/var/lib/archipelago/portainer/compose", + "target": "/data/compose", + "options": [ + "rw" + ] + }, + { + "type": "bind", + "source": "/run/user/1000/podman/podman.sock", + "target": "/var/run/docker.sock", + "options": [ + "rw" + ] + } + ], + "environment": [], + "interfaces": { + "main": { + "name": "Web UI", + "description": "Portainer web interface", + "type": "ui", + "port": 9000, + "protocol": "http", + "path": "/" + } + }, + "metadata": { + "icon": "/assets/img/app-icons/portainer.webp", + "tier": "optional", + "launch": { + "open_in_new_tab": true + }, + "features": [ + "Container management dashboard", + "Local Podman socket access", + "Compose stack storage" + ] + } + } + } + }, + "router": { + "version": "1.0.0", + "manifest": { + "app": { + "id": "router", + "name": "Mesh Router", + "version": "1.0.0", + "description": "Mesh routing and local network management. Provides device discovery, routing, and network topology visualization.", + "container": { + "image": "archipelago/router:1.0.0", + "image_signature": "cosign://...", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "storage": "500Mi" + } + ], + "resources": { + "cpu_limit": 2, + "memory_limit": "512Mi", + "disk_limit": "500Mi" + }, + "security": { + "capabilities": [ + "NET_ADMIN", + "NET_RAW" + ], + "readonly_root": true, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "host", + "apparmor_profile": "router" + }, + "ports": [ + { + "host": 8084, + "container": 8080, + "protocol": "tcp" + }, + { + "host": 5353, + "container": 5353, + "protocol": "udp" + }, + { + "host": 1900, + "container": 1900, + "protocol": "udp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/router", + "target": "/app/data", + "options": [ + "rw" + ] + }, + { + "type": "bind", + "source": "/var/run/dbus", + "target": "/var/run/dbus", + "options": [ + "ro" + ] + } + ], + "environment": [ + "NETWORK_INTERFACE=eth0", + "MESH_ENABLED=true", + "DEVICE_DISCOVERY=true" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:8084", + "path": "/health", + "interval": "30s", + "timeout": "5s", + "retries": 3 + }, + "networking": { + "mesh_enabled": true, + "local_network_access": true, + "device_discovery": true, + "routing_protocols": [ + "olsr", + "babel" + ] + } + } + } + }, + "routstr": { + "version": "v0.4.3", + "image": "146.59.87.168:3000/lfg2025/routstr:v0.4.3" + }, + "searxng": { + "version": "latest", + "image": "146.59.87.168:3000/lfg2025/searxng:latest", + "manifest": { + "app": { + "id": "searxng", + "name": "SearXNG", + "version": "1.0.0", + "description": "Privacy-respecting metasearch engine. Search the web without tracking.", + "container": { + "image": "146.59.87.168:3000/lfg2025/searxng:latest", + "pull_policy": "if-not-present" + }, + "dependencies": [ + { + "storage": "2Gi" + } + ], + "resources": { + "cpu_limit": 2, + "memory_limit": "1Gi", + "disk_limit": "2Gi" + }, + "security": { + "capabilities": [], + "readonly_root": true, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "isolated", + "apparmor_profile": "searxng" + }, + "ports": [ + { + "host": 8888, + "container": 8080, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/searxng", + "target": "/etc/searxng", + "options": [ + "rw" + ] + } + ], + "environment": [ + "SEARXNG_HOSTNAME=localhost", + "SEARXNG_BIND_ADDRESS=0.0.0.0:8080" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:8080", + "path": "/", + "interval": "30s", + "timeout": "30s", + "retries": 5 + } + } + } + }, + "strfry": { + "version": "0.9.0", + "manifest": { + "app": { + "id": "strfry", + "name": "Strfry Nostr Relay", + "version": "0.9.0", + "description": "Lightweight Nostr relay written in C++. Alternative to nostr-rs-relay with lower resource usage.", + "container": { + "image": "dockurr/strfry:1.0.4", + "image_signature": "cosign://...", + "pull_policy": "verify-signature" + }, + "dependencies": [ + { + "storage": "5Gi" + } + ], + "resources": { + "cpu_limit": 1, + "memory_limit": "512Mi", + "disk_limit": "5Gi" + }, + "security": { + "capabilities": [], + "readonly_root": true, + "no_new_privileges": true, + "user": 1000, + "seccomp_profile": "default", + "network_policy": "isolated", + "apparmor_profile": "nostr-relay" + }, + "ports": [ + { + "host": 8082, + "container": 8080, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/strfry", + "target": "/strfry", + "options": [ + "rw" + ] + } + ], + "environment": [ + "RELAY_NAME=Archipelago Strfry Relay" + ], + "health_check": { + "type": "http", + "endpoint": "http://localhost:8082", + "path": "/health", + "interval": "30s", + "timeout": "5s", + "retries": 3 + }, + "nostr_integration": { + "relay_type": "public", + "monetization_enabled": true + } + } + } + }, + "tailscale": { + "version": "stable", + "image": "146.59.87.168:3000/lfg2025/tailscale:stable" + }, + "uptime-kuma": { + "version": "1", + "image": "146.59.87.168:3000/lfg2025/uptime-kuma:1", + "manifest": { + "app": { + "id": "uptime-kuma", + "name": "Uptime Kuma", + "version": "1.23.0", + "description": "Self-hosted uptime monitoring.", + "container": { + "image": "146.59.87.168:3000/lfg2025/uptime-kuma:1", + "pull_policy": "if-not-present", + "network": "pasta", + "custom_args": [ + "--", + "node", + "server/server.js" + ] + }, + "dependencies": [ + { + "storage": "1Gi" + } + ], + "resources": { + "memory_limit": "256Mi", + "disk_limit": "1Gi" + }, + "security": { + "capabilities": [ + "CHOWN", + "FOWNER", + "SETUID", + "SETGID" + ], + "readonly_root": false, + "network_policy": "isolated" + }, + "ports": [ + { + "host": 3002, + "container": 3001, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/uptime-kuma", + "target": "/app/data", + "options": [ + "rw" + ] + } + ], + "environment": [ + "TZ=UTC" + ], + "health_check": { + "type": "http", + "endpoint": "localhost:3001", + "path": "/", + "interval": "30s", + "timeout": "5s", + "retries": 3 + }, + "metadata": { + "icon": "/assets/img/app-icons/uptime-kuma.webp", + "category": "data", + "tier": "recommended", + "author": "Uptime Kuma", + "repo": "https://github.com/louislam/uptime-kuma", + "launch": { + "open_in_new_tab": true + } + } + } + } + }, + "vaultwarden": { + "version": "1.30.0-alpine", + "image": "146.59.87.168:3000/lfg2025/vaultwarden:1.30.0-alpine", + "manifest": { + "app": { + "id": "vaultwarden", + "name": "Vaultwarden", + "version": "1.30.0", + "description": "Self-hosted password vault with zero-knowledge encryption.", + "container": { + "image": "146.59.87.168:3000/lfg2025/vaultwarden:1.30.0-alpine", + "pull_policy": "if-not-present", + "network": "pasta" + }, + "dependencies": [ + { + "storage": "1Gi" + } + ], + "resources": { + "memory_limit": "256Mi", + "disk_limit": "1Gi" + }, + "security": { + "capabilities": [ + "CHOWN", + "SETUID", + "SETGID", + "NET_BIND_SERVICE" + ], + "readonly_root": false, + "network_policy": "isolated" + }, + "ports": [ + { + "host": 8082, + "container": 80, + "protocol": "tcp" + } + ], + "volumes": [ + { + "type": "bind", + "source": "/var/lib/archipelago/vaultwarden", + "target": "/data", + "options": [ + "rw" + ] + } + ], + "environment": [], + "health_check": { + "type": "tcp", + "endpoint": "localhost:80", + "interval": "30s", + "timeout": "5s", + "retries": 3 + }, + "interfaces": { + "main": { + "name": "Web UI", + "description": "Vaultwarden web vault", + "type": "ui", + "port": 8082, + "protocol": "http", + "path": "/" + } + }, + "metadata": { + "icon": "/assets/img/app-icons/vaultwarden.webp", + "category": "data", + "tier": "recommended", + "author": "Vaultwarden", + "repo": "https://github.com/dani-garcia/vaultwarden", + "launch": { + "open_in_new_tab": true + } + } + } + } + } + } +}