2026-06-23 23:45:31 -04:00
{
"apps" : {
"adguardhome" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/adguardhome:v0.107.55" ,
"version" : "v0.107.55"
2026-06-23 23:45:31 -04:00
} ,
"aiui" : {
"manifest" : {
"app" : {
"container" : {
"image" : "localhost/archipelago-aiui:latest" ,
"pull_policy" : "always"
} ,
2026-07-02 09:01:34 -04:00
"description" : "Conversational AI interface for Archipelago. Quarantined — communicates only via context broker." ,
"health_check" : {
"endpoint" : "http://localhost:80" ,
"interval" : "60s" ,
"path" : "/" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "aiui" ,
"internal" : true ,
"name" : "AI Assistant" ,
"ports" : [
{
"bind" : "127.0.0.1" ,
"container" : 80 ,
"host" : 5180 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 1 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "1Gi" ,
"memory_limit" : "512Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"apparmor_profile" : "aiui" ,
2026-06-23 23:45:31 -04:00
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : true ,
2026-06-23 23:45:31 -04:00
"seccomp_profile" : "default" ,
2026-07-02 09:01:34 -04:00
"user" : 1000
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "0.1.0"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "0.1.0"
2026-06-23 23:45:31 -04:00
} ,
"archy-btcpay-db" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "none" ,
"sync_required" : false
} ,
2026-06-23 23:45:31 -04:00
"container" : {
2026-07-02 09:01:34 -04:00
"data_uid" : "100998:100998" ,
2026-06-23 23:45:31 -04:00
"image" : "git.tx1138.com/lfg2025/postgres:15.17" ,
"network" : "archy-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "POSTGRES_PASSWORD" ,
"secret_file" : "btcpay-db-password"
}
]
} ,
"dependencies" : [
{
"storage" : "20Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Postgres backend for BTCPay and NBXplorer." ,
"environment" : [
"POSTGRES_DB=btcpay" ,
"POSTGRES_USER=btcpay"
] ,
"health_check" : {
"endpoint" : "localhost:5432" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "archy-btcpay-db" ,
"name" : "BTCPay Postgres" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "20Gi" ,
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "15.17" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/postgres-btcpay" ,
"target" : "/var/lib/postgresql/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "15.17"
2026-06-23 23:45:31 -04:00
} ,
"archy-mempool-db" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "none" ,
"sync_required" : false
} ,
2026-06-23 23:45:31 -04:00
"container" : {
2026-07-02 09:01:34 -04:00
"data_uid" : "100998:100998" ,
2026-06-23 23:45:31 -04:00
"image" : "git.tx1138.com/lfg2025/mariadb:11.4.10" ,
"network" : "archy-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "MYSQL_PASSWORD" ,
"secret_file" : "mempool-db-password"
} ,
{
"key" : "MYSQL_ROOT_PASSWORD" ,
"secret_file" : "mysql-root-db-password"
}
]
} ,
"dependencies" : [
{
"storage" : "20Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "MariaDB backend for the mempool explorer stack." ,
"environment" : [
"MYSQL_DATABASE=mempool" ,
"MYSQL_USER=mempool"
] ,
"health_check" : {
"endpoint" : "localhost:3306" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "archy-mempool-db" ,
"name" : "Mempool MariaDB" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "20Gi" ,
"memory_limit" : "512Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "11.4.10" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/mysql-mempool" ,
"target" : "/var/lib/mysql" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "11.4.10"
2026-06-23 23:45:31 -04:00
} ,
"archy-mempool-web" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "none" ,
"sync_required" : false
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"image" : "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1" ,
2026-07-02 09:01:34 -04:00
"network" : "archy-net" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "mempool" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "mempool-api" ,
"version" : ">=3.0.0"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Frontend web UI for mempool explorer." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"FRONTEND_HTTP_PORT=8080" ,
"BACKEND_MAINNET_HTTP_HOST=mempool-api"
] ,
"health_check" : {
2026-06-28 15:09:34 -04:00
"endpoint" : "http://127.0.0.1:8080" ,
2026-06-23 23:45:31 -04:00
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "archy-mempool-web" ,
"name" : "Mempool Web" ,
"ports" : [
{
"container" : 8080 ,
"host" : 4080 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"memory_limit" : "512Mi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "3.0.1"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "3.0.1"
2026-06-23 23:45:31 -04:00
} ,
"archy-nbxplorer" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "read-only" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"image" : "git.tx1138.com/lfg2025/nbxplorer:2.6.0" ,
"network" : "archy-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"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"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "BTCPay blockchain indexer service." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "http://localhost:32838" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 5 ,
2026-06-23 23:45:31 -04:00
"timeout" : "30s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "archy-nbxplorer" ,
"name" : "NBXplorer" ,
"ports" : [
{
"container" : 32838 ,
"host" : 32838 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"disk_limit" : "20Gi" ,
"memory_limit" : "2Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "2.6.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/nbxplorer" ,
"target" : "/data" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "2.6.0"
2026-06-23 23:45:31 -04:00
} ,
"bitcoin-core" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"pruning_support" : true ,
"rpc_access" : "admin" ,
"sync_required" : true ,
"testnet_support" : false
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"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"
] ,
2026-07-02 09:01:34 -04:00
"data_uid" : "100101:100101" ,
2026-06-23 23:45:31 -04:00
"derived_env" : [
{
"key" : "DISK_GB" ,
"template" : "{{DISK_GB}}"
}
] ,
2026-07-02 09:01:34 -04:00
"entrypoint" : [
"sh" ,
"-lc"
] ,
"image" : "146.59.87.168:3000/lfg2025/bitcoin:28.4" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "BITCOIN_RPC_PASS" ,
"secret_file" : "bitcoin-rpc-password"
} ,
{
"key" : "BITCOIN_RPC_TXRELAY_RPCAUTH" ,
"secret_file" : "bitcoin-rpc-txrelay-rpcauth"
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "bitcoin-core" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "500Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Reference Bitcoin Core node with dynamic prune/full-mode startup based on host disk." ,
"environment" : [
"BITCOIN_RPC_USER=archipelago"
] ,
"health_check" : {
"endpoint" : "localhost:8332" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "bitcoin-core" ,
"name" : "Bitcoin Core" ,
"ports" : [
{
"container" : 8332 ,
"host" : 8332 ,
"protocol" : "tcp"
} ,
{
"container" : 8333 ,
"host" : 8333 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 0 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "500Gi" ,
"memory_limit" : "4Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "28.4.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/bitcoin" ,
"target" : "/home/bitcoin/.bitcoin" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "latest" ,
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
"versions" : [
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
{
2026-07-02 09:01:34 -04:00
"default" : true ,
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:latest" ,
2026-07-02 09:01:34 -04:00
"version" : "latest"
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
} ,
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:31.0" ,
"version" : "31.0"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:30.2" ,
"version" : "30.2"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:29.3" ,
"version" : "29.3"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:29.2" ,
"version" : "29.2"
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
} ,
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:28.4" ,
"version" : "28.4.0"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:27.2" ,
"version" : "27.2"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"deprecated" : true ,
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:26.2" ,
2026-07-02 09:01:34 -04:00
"version" : "26.2"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"deprecated" : true ,
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin:25.2" ,
2026-07-02 09:01:34 -04:00
"version" : "25.2"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
}
]
2026-06-23 23:45:31 -04:00
} ,
"bitcoin-knots" : {
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:latest" ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"pruning_support" : true ,
"rpc_access" : "admin" ,
"sync_required" : true ,
"testnet_support" : false
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"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"
] ,
2026-07-02 09:01:34 -04:00
"data_uid" : "100101:100101" ,
2026-06-23 23:45:31 -04:00
"derived_env" : [
{
"key" : "DISK_GB" ,
"template" : "{{DISK_GB}}"
}
] ,
2026-07-02 09:01:34 -04:00
"entrypoint" : [
"sh" ,
"-lc"
] ,
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:latest" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "BITCOIN_RPC_PASS" ,
"secret_file" : "bitcoin-rpc-password"
} ,
{
"key" : "BITCOIN_RPC_TXRELAY_RPCAUTH" ,
"secret_file" : "bitcoin-rpc-txrelay-rpcauth"
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "bitcoin-knots" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "500Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Full Bitcoin Knots node with dynamic prune/full-mode startup based on host disk." ,
"environment" : [
"BITCOIN_RPC_USER=archipelago"
] ,
"health_check" : {
"endpoint" : "localhost:8332" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "bitcoin-knots" ,
"name" : "Bitcoin Knots" ,
"ports" : [
{
"container" : 8332 ,
"host" : 8332 ,
"protocol" : "tcp"
} ,
{
"container" : 8333 ,
"host" : 8333 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 0 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "500Gi" ,
"memory_limit" : "8Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "28.1.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/bitcoin" ,
"target" : "/home/bitcoin/.bitcoin" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "latest" ,
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
"versions" : [
{
2026-07-02 09:01:34 -04:00
"default" : true ,
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:29.3.knots20260508" ,
2026-07-02 09:01:34 -04:00
"version" : "latest"
2026-06-28 19:56:49 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:29.3.knots20260508" ,
"version" : "29.3.knots20260508"
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:29.3.knots20260507" ,
"version" : "29.3.knots20260507"
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:29.3.knots20260210" ,
"version" : "29.3.knots20260210"
fix(bitcoin): bulletproof multi-version switching (Knots & Core)
Three stacked bugs made "switch version" silently fail / crash-loop, and
the data-access mismatch corrupted a node's index during recovery attempts.
Backend renderer:
- sync_quadlet_unit ignored the per-app pinned version and re-rendered the
quadlet with the manifest's :latest every reconcile tick, reverting any
switch. Factor the install-time catalog/pin resolution into a shared
resolve_catalog_image() and call it in BOTH install_fresh and
sync_quadlet_unit.
- The renderer folded manifest `entrypoint: ["sh","-lc"]` into Exec=, which
only worked when the image entrypoint was a passthrough shell wrapper. The
versioned images use ENTRYPOINT ["bitcoind"], so Exec=sh -lc ... became
`bitcoind sh -lc ...` and crash-looped. Emit a real Entrypoint= override;
exec_changed now also compares Entrypoint=.
Images:
- Build all bitcoin images (Core + Knots, every version) as container-root
(USER removed) like the legacy :latest image. Chain data is owned by the
data_uid (container uid 102); root reads it via CAP_DAC_OVERRIDE (granted in
the manifest). A non-root USER (the previous uid 1000) can't read existing
chain data → "Error initializing block database". Still fully rootless:
container-root maps to the unprivileged host service user.
Catalog:
- bitcoin-knots versions[]: 29.3.knots20260508/20260507/20260210 +
29.2.knots20251110, "latest" tracking newest.
- bitcoin-core versions[]: add 29.2 + a "latest" entry. All images rebuilt
root and published to the mirror.
Frontend:
- AppSidebar version dropdown: rename the latest option to "Always use the
latest version" (no v prefix), fix right padding, and guarantee the current
selection matches a real option (was rendering blank).
- New InstallVersionModal: full-screen version chooser shown from the App
Store / Discover install button for multi-version apps (Bitcoin Knots/Core),
app icon + "Install <name>", latest pre-selected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 05:46:04 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/bitcoin-knots:29.2.knots20251110" ,
"version" : "29.2.knots20251110"
feat(bitcoin): multi-version support for Core & Knots (install/switch/pin/auto-update)
Lets a node runner choose which Bitcoin Core / Knots version to install
(latest pre-selected), then switch, pin, or opt into auto-update from the
app's interface — all manifest/catalog-driven, rootless, signed-registry,
zero-data-loss. Motivated by upcoming BIP-110 signalling: runners need a
real choice of software version.
Backend:
- version_config.rs: per-app pin + auto-update persistence (atomic, merge-
preserving), downgrade detection, auto-update enumeration (+ unit tests).
- app_catalog.rs: CatalogVersion / versions[] schema, catalog_versions(),
catalog_image_for_version() (same-repo guard); a pin suppresses the update
badge.
- prod_orchestrator.rs: pinned version wins over the catalog default on every
install/recreate.
- install.rs: install-time `version` param persisted (default = unpinned).
- set_config.rs: package.versions (read) + package.set-config (write) RPCs;
downgrade is gated behind explicit confirm (warn + confirm + allow).
- update.rs/main.rs: hourly per-app auto-update tick via the orchestrator
(opt-in, pin-respecting); fix handle_package_update to be non-fatal for
orchestrator-managed apps lacking a catalog primary image (bitcoin-core).
UI:
- MarketplaceAppDetails.vue: install-time version selector (shown when an app
offers >=2 versions).
- appDetails/AppSidebar.vue: "Version & Updates" card (switch / pin / auto-
update toggle / downgrade warning), per app.
- rpc-client.ts + en.json: RPC methods, types, strings.
Phase 0 image pipeline:
- scripts/build-bitcoin-image.sh: download official tarball + SHA256SUMS(.asc),
verify SHA-256 + pinned-maintainer OpenPGP signature (fail-closed), build a
minimal rootless image, smoke-test, tag + push.
- apps/bitcoin-core/Dockerfile rewritten (drops stale community base);
apps/bitcoin-knots/Dockerfile added.
- generate-app-catalog.sh: emit curated versions[]; published + catalog now
offers Core 25.2/26.2/27.2/28.4/29.3/30.2/31.0 + Knots 29.3.knots20260508.
docs/bitcoin-multi-version-design.md: live progress tracker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 18:46:17 -04:00
}
]
2026-06-23 23:45:31 -04:00
} ,
"bitcoin-ui" : {
"image" : "146.59.87.168:3000/lfg2025/bitcoin-ui:1.7.84-alpha" ,
"manifest" : {
"app" : {
"container" : {
"build" : {
"context" : "/opt/archipelago/docker/bitcoin-ui" ,
"dockerfile" : "Dockerfile" ,
"tag" : "localhost/bitcoin-ui:local"
}
} ,
"dependencies" : [
{
"app_id" : "bitcoin-core"
}
] ,
2026-07-02 09:01:34 -04:00
"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" ,
"environment" : [ ] ,
"health_check" : {
"endpoint" : "http://127.0.0.1:8334" ,
"interval" : "30s" ,
"path" : "/" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "bitcoin-ui" ,
"name" : "Bitcoin UI" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"memory_limit" : "128Mi"
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"network_policy" : "host" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "1.0.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"ro"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/bitcoin-ui/nginx.conf" ,
"target" : "/etc/nginx/conf.d/default.conf" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.7.84-alpha"
2026-06-23 23:45:31 -04:00
} ,
"botfights" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
"image" : "146.59.87.168:3000/lfg2025/botfights:1.1.0" ,
"pull_policy" : "always"
} ,
"dependencies" : [
{
"storage" : "500Mi"
}
] ,
2026-07-02 09:01:34 -04:00
"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." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"NODE_ENV=production"
] ,
"health_check" : {
"endpoint" : "http://localhost:9100" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/api/health" ,
2026-06-23 23:45:31 -04:00
"retries" : 3 ,
2026-07-02 09:01:34 -04:00
"start_period" : "30s" ,
"timeout" : "10s" ,
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "botfights" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Bot arena and arcade fighter with controller support" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 9100 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "Dorian" ,
"icon" : "/assets/img/app-icons/botfights.svg" ,
"license" : "MIT" ,
2026-07-02 09:01:34 -04:00
"repo" : "https://botfights.net" ,
2026-06-23 23:45:31 -04:00
"tags" : [
"bitcoin" ,
"gaming" ,
"arcade" ,
"fighter" ,
"bots" ,
"competition" ,
"controller"
]
2026-07-02 09:01:34 -04:00
} ,
"name" : "BotFights" ,
"ports" : [
{
"container" : 9100 ,
"host" : 9100 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "500Mi" ,
"memory_limit" : "512Mi"
} ,
"security" : {
"apparmor_profile" : "default" ,
"capabilities" : [ ] ,
"network_policy" : "bridge" ,
"no_new_privileges" : true ,
"readonly_root" : true ,
"seccomp_profile" : "default" ,
"user" : 1001
} ,
"version" : "1.1.0" ,
"volumes" : [
{
"source" : "botfights-data" ,
"target" : "/app/server/data" ,
"type" : "bind"
} ,
{
"options" : [
"rw" ,
"noexec" ,
"nosuid" ,
"size=64m"
] ,
"target" : "/tmp" ,
"type" : "tmpfs"
}
]
}
} ,
"version" : "1.1.0"
} ,
"btcpay" : {
"image" : "docker.io/btcpayserver/btcpayserver:2.3.9" ,
"images" : {
"archy-btcpay-db" : "146.59.87.168:3000/lfg2025/postgres:15.17" ,
2026-06-23 23:45:31 -04:00
"archy-nbxplorer" : "146.59.87.168:3000/lfg2025/nbxplorer:2.6.0" ,
2026-07-02 09:01:34 -04:00
"btcpay-server" : "docker.io/btcpayserver/btcpayserver:2.3.9"
} ,
"version" : "2.3.9"
2026-06-23 23:45:31 -04:00
} ,
"btcpay-server" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "read-only" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
2026-07-02 09:01:34 -04:00
"derived_env" : [
{
"key" : "BTCPAY_HOST" ,
"template" : "{{HOST_IP}}:23000"
}
] ,
2026-06-23 23:45:31 -04:00
"image" : "docker.io/btcpayserver/btcpayserver:2.3.9" ,
"network" : "archy-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "BTCPAY_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"
} ,
{
"app_id" : "archy-nbxplorer" ,
"version" : ">=2.6.0"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "http://localhost:49392" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 5 ,
2026-06-23 23:45:31 -04:00
"timeout" : "30s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "btcpay-server" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "BTCPay Server dashboard" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 23000 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
2026-07-02 09:01:34 -04:00
"lightning_integration" : {
"invoice_management" : true ,
"payment_processing" : false
} ,
2026-06-23 23:45:31 -04:00
"metadata" : {
"launch" : {
"open_in_new_tab" : true
}
2026-07-02 09:01:34 -04:00
} ,
"name" : "BTCPay Server" ,
"ports" : [
{
"container" : 49392 ,
"host" : 23000 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "20Gi" ,
"memory_limit" : "2Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "2.3.9" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/btcpay" ,
"target" : "/datadir" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "2.3.9"
2026-06-23 23:45:31 -04:00
} ,
"core-lightning" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "admin" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"image" : "elementsproject/lightningd:v23.08.2" ,
"image_signature" : "cosign://..." ,
"pull_policy" : "verify-signature"
} ,
"dependencies" : [
{
"app_id" : "bitcoin-core" ,
"version" : ">=26.0"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Lightning Network implementation in C. Lightweight alternative to LND." ,
"environment" : [
"BITCOIND_RPCURL=http://bitcoin-core:8332" ,
"BITCOIND_RPCUSER=${BITCOIN_RPC_USER}" ,
"BITCOIND_RPCPASS=${BITCOIN_RPC_PASSWORD}" ,
"NETWORK=bitcoin"
] ,
"health_check" : {
"endpoint" : "lightning-cli getinfo" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "exec"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "core-lightning" ,
"lightning_integration" : {
"channel_management" : true ,
"payment_routing" : true
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "Core Lightning (CLN)" ,
2026-06-23 23:45:31 -04:00
"ports" : [
{
"container" : 9735 ,
2026-07-02 09:01:34 -04:00
"host" : 9736 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 9835 ,
2026-07-02 09:01:34 -04:00
"host" : 9835 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 1 ,
"disk_limit" : "5Gi" ,
"memory_limit" : "512Mi"
} ,
"security" : {
"apparmor_profile" : "core-lightning" ,
"capabilities" : [
"NET_BIND_SERVICE"
] ,
"network_policy" : "isolated" ,
"no_new_privileges" : true ,
"readonly_root" : true ,
"seccomp_profile" : "default" ,
"user" : 1000
} ,
"version" : "23.08.2" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/core-lightning" ,
"target" : "/home/clightning/.lightning" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "23.08.2"
2026-06-23 23:45:31 -04:00
} ,
"cryptpad" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/cryptpad:2024.12.0" ,
"version" : "2024.12.0"
2026-06-23 23:45:31 -04:00
} ,
"did-wallet" : {
"manifest" : {
"app" : {
"container" : {
"image" : "archipelago/did-wallet:1.0.0" ,
"image_signature" : "cosign://..." ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "2Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Web5 wallet with Decentralized Identifier (DID) support. Manage your digital identity and Web5 assets." ,
"environment" : [
"WALLET_STORAGE=/app/wallet"
] ,
"health_check" : {
"endpoint" : "http://localhost:8083" ,
"interval" : "30s" ,
"path" : "/health" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "did-wallet" ,
"name" : "Web5 DID Wallet" ,
"ports" : [
{
"container" : 8080 ,
"host" : 8083 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 1 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "2Gi" ,
"memory_limit" : "512Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"apparmor_profile" : "did-wallet" ,
2026-06-23 23:45:31 -04:00
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : true ,
2026-06-23 23:45:31 -04:00
"seccomp_profile" : "default" ,
2026-07-02 09:01:34 -04:00
"user" : 1000
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "1.0.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/did-wallet" ,
"target" : "/app/wallet" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
] ,
"web5_integration" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : true ,
2026-06-23 23:45:31 -04:00
"did_support" : true ,
2026-07-02 09:01:34 -04:00
"wallet_functionality" : true
2026-06-23 23:45:31 -04:00
}
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"electrs-ui" : {
"image" : "146.59.87.168:3000/lfg2025/electrs-ui:latest" ,
"manifest" : {
"app" : {
"container" : {
"build" : {
"context" : "/opt/archipelago/docker/electrs-ui" ,
"dockerfile" : "Dockerfile" ,
"tag" : "localhost/electrs-ui:local"
}
} ,
"dependencies" : [ ] ,
2026-07-02 09:01:34 -04:00
"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" ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"health_check" : {
"endpoint" : "http://127.0.0.1:50002" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
} ,
"id" : "electrs-ui" ,
"name" : "Electrs UI" ,
"ports" : [ ] ,
"resources" : {
"memory_limit" : "64Mi"
} ,
"security" : {
"network_policy" : "host" ,
"readonly_root" : false
} ,
"version" : "1.0.0" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "latest"
2026-06-23 23:45:31 -04:00
} ,
"electrumx" : {
"image" : "146.59.87.168:3000/lfg2025/electrumx:v1.18.0" ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"pruning_support" : false ,
"rpc_access" : "read-only" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
2026-07-02 09:01:34 -04:00
"custom_args" : [
"export DAEMON_URL=\"http://archipelago:$(printenv BITCOIN_RPC_PASS)@bitcoin-knots:8332/\"; exec electrumx_server"
] ,
2026-06-23 23:45:31 -04:00
"data_uid" : "1000:1000" ,
"entrypoint" : [
"sh" ,
"-lc"
] ,
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/electrumx:v1.18.0" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "BITCOIN_RPC_PASS" ,
"secret_file" : "bitcoin-rpc-password"
}
]
} ,
"dependencies" : [
{
"app_id" : "bitcoin-knots" ,
"version" : ">=26.0"
} ,
{
"storage" : "50Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Electrum server indexing Bitcoin chain data for lightweight wallet queries." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"COIN=Bitcoin" ,
"DB_DIRECTORY=/data" ,
"SERVICES=tcp://:50001,rpc://0.0.0.0:8000" ,
"CACHE_MB=1024" ,
"MAX_SEND=10000000"
] ,
2026-07-02 09:01:34 -04:00
"health_check" : {
"endpoint" : "localhost:50001" ,
"interval" : "30s" ,
"retries" : 3 ,
"start_period" : "10m" ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "electrumx" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "ElectrumX server status and connection details" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
2026-06-23 23:45:31 -04:00
"port" : 50002 ,
2026-07-02 09:01:34 -04:00
"protocol" : "http" ,
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
2026-07-02 09:01:34 -04:00
"name" : "ElectrumX" ,
"ports" : [
{
"container" : 50001 ,
"host" : 50001 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"cpu_limit" : 0 ,
"disk_limit" : "50Gi" ,
"memory_limit" : "6Gi"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"security" : {
"capabilities" : [
"DAC_OVERRIDE"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "1.18.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/electrumx" ,
"target" : "/data" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "v1.18.0"
2026-06-23 23:45:31 -04:00
} ,
"fedimint" : {
"image" : "146.59.87.168:3000/lfg2025/fedimintd:v0.10.0" ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "admin" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"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"
] ,
2026-07-02 09:01:34 -04:00
"data_uid" : "1000:1000" ,
2026-06-23 23:45:31 -04:00
"derived_env" : [
{
"key" : "FM_P2P_URL" ,
"template" : "fedimint://{{HOST_MDNS}}:8173"
} ,
{
"key" : "FM_API_URL" ,
"template" : "ws://{{HOST_MDNS}}:8174"
}
] ,
2026-07-02 09:01:34 -04:00
"entrypoint" : [
"sh" ,
"-lc"
] ,
"image" : "146.59.87.168:3000/lfg2025/fedimintd:v0.10.0" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "FM_BITCOIND_PASSWORD" ,
"secret_file" : "bitcoin-rpc-password"
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"app_id" : "bitcoin-core" ,
"version" : ">=26.0"
} ,
{
"storage" : "20Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Federated Bitcoin minting service with built-in Guardian UI. Privacy-preserving Bitcoin custody." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "http://localhost:8175" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "fedimint" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Fedimint Guardian wait/proxy UI" ,
2026-07-02 09:01:34 -04:00
"name" : "Guardian UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 8175 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
2026-07-02 09:01:34 -04:00
"name" : "Fedimint Guardian" ,
"ports" : [
{
"container" : 8173 ,
"host" : 8173 ,
"protocol" : "tcp"
} ,
{
"container" : 8174 ,
"host" : 8174 ,
"protocol" : "tcp"
} ,
{
"container" : 8175 ,
"host" : 8177 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"cpu_limit" : 4 ,
"disk_limit" : "20Gi" ,
"memory_limit" : "4Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : true
} ,
"version" : "0.10.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/fedimint" ,
"target" : "/data" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "v0.10.0"
2026-06-23 23:45:31 -04:00
} ,
"fedimint-clientd" : {
"manifest" : {
"app" : {
"container" : {
2026-07-02 09:01:34 -04:00
"data_uid" : "1000:1000" ,
2026-06-23 23:45:31 -04:00
"generated_secrets" : [
{
2026-07-02 09:01:34 -04:00
"kind" : "hex16" ,
"name" : "fmcd-password"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/fmcd:0.8.1" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "FMCD_PASSWORD" ,
"secret_file" : "fmcd-password"
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "2Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"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." ,
"environment" : [
"FMCD_ADDR=0.0.0.0:8080" ,
"FMCD_MODE=rest" ,
"FMCD_DATA_DIR=/data" ,
"FMCD_INVITE_CODE=fed11qgqyj3mfwfhksw309uuxywtxxfjrjc35xuexverpxdsnxcnrxucxvenzveskgc3kvvun2c34xp3k2ep38yunzdpexcekxe3hvd3rvvmx8pnrvdenx5mnzvtzqqqjqt0t6pc3s5z0ynqjw9s4njf6svwgu59kweawc0vvrddcjeemw6yyn4pcdp"
] ,
"health_check" : {
"endpoint" : "localhost:8080" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "fedimint-clientd" ,
"name" : "Fedimint Client" ,
2026-06-23 23:45:31 -04:00
"ports" : [
{
"container" : 8080 ,
2026-07-02 09:01:34 -04:00
"host" : 8178 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 1 ,
"disk_limit" : "2Gi" ,
"memory_limit" : "1Gi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"DAC_OVERRIDE" ,
"FOWNER" ,
"SETUID" ,
"SETGID"
] ,
"network_policy" : "bridge" ,
"readonly_root" : true
} ,
"version" : "0.8.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/fmcd" ,
"target" : "/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "0.8.0"
2026-06-23 23:45:31 -04:00
} ,
"fedimint-gateway" : {
"image" : "146.59.87.168:3000/lfg2025/gatewayd:v0.10.0" ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "admin" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
2026-07-02 09:01:34 -04:00
"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"
] ,
"data_uid" : "1000:1000" ,
2026-06-23 23:45:31 -04:00
"entrypoint" : [
"sh" ,
"-lc"
] ,
"generated_secrets" : [
{
2026-07-02 09:01:34 -04:00
"kind" : "bcrypt" ,
"name" : "fedimint-gateway-hash"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"image" : "git.tx1138.com/lfg2025/gatewayd:v0.10.0" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "FM_BITCOIND_PASSWORD" ,
"secret_file" : "bitcoin-rpc-password"
} ,
{
"key" : "FEDI_HASH" ,
"secret_file" : "fedimint-gateway-hash"
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"app_id" : "bitcoin-core" ,
"version" : ">=26.0"
} ,
{
"app_id" : "fedimint" ,
"version" : ">=0.10.0"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Fedimint gateway service with automatic LND-or-LDK backend selection." ,
"environment" : [
"FM_BITCOIND_USERNAME=archipelago"
] ,
"health_check" : {
"endpoint" : "http://localhost:8176" ,
"interval" : "30s" ,
"path" : "/" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "fedimint-gateway" ,
"name" : "Fedimint Gateway" ,
2026-06-23 23:45:31 -04:00
"ports" : [
{
"container" : 8176 ,
2026-07-02 09:01:34 -04:00
"host" : 8176 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 9737 ,
2026-07-02 09:01:34 -04:00
"host" : 9737 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "10Gi" ,
"memory_limit" : "2Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : true
} ,
"version" : "0.10.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/fedimint-gateway" ,
"target" : "/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
} ,
{
"options" : [
"ro"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/lnd" ,
"target" : "/lnd" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "v0.10.0"
2026-06-23 23:45:31 -04:00
} ,
"filebrowser" : {
"image" : "146.59.87.168:3000/lfg2025/filebrowser:v2.27.0" ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "none" ,
"sync_required" : false
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"custom_args" : [
"--config" ,
"/data/.filebrowser.json"
] ,
2026-07-02 09:01:34 -04:00
"data_uid" : "100000:100000" ,
"image" : "git.tx1138.com/lfg2025/filebrowser:v2.27.0" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "10Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Baseline Archipelago file manager service." ,
"environment" : [ ] ,
"health_check" : {
"endpoint" : "http://localhost:80" ,
"interval" : "30s" ,
"path" : "/health" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "filebrowser" ,
"name" : "File Browser" ,
"ports" : [
{
"container" : 80 ,
"host" : 8083 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "10Gi" ,
"memory_limit" : "256Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE" ,
"NET_BIND_SERVICE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "2.27.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/filebrowser" ,
"target" : "/srv" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
} ,
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/filebrowser-data" ,
"target" : "/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "v2.27.0"
2026-06-23 23:45:31 -04:00
} ,
"fips" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/fips:v0.1.0" ,
"version" : "v0.1.0"
2026-06-23 23:45:31 -04:00
} ,
"fips-ui" : {
"manifest" : {
"app" : {
"container" : {
"build" : {
"context" : "/opt/archipelago/docker/fips-ui" ,
"dockerfile" : "Dockerfile" ,
"tag" : "localhost/fips-ui:local"
}
} ,
2026-07-02 09:01:34 -04:00
"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 — there is no separate secret to manage.\n" ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"health_check" : {
"endpoint" : "http://127.0.0.1:8336" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
} ,
"id" : "fips-ui" ,
"name" : "FIPS Mesh" ,
"ports" : [ ] ,
"resources" : {
"memory_limit" : "128Mi"
} ,
"security" : {
"network_policy" : "host" ,
"readonly_root" : false
} ,
"version" : "1.0.0" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"gitea" : {
"manifest" : {
"app" : {
"category" : "development" ,
"container" : {
"image" : "docker.io/gitea/gitea:1.23" ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "500Mi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Self-hosted Git service with built-in container registry, CI/CD, and package hosting." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "http://localhost:3000" ,
"interval" : "120s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 5 ,
2026-06-23 23:45:31 -04:00
"timeout" : "30s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "gitea" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Gitea web interface" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 3001 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"features" : [
"Git repositories with web UI" ,
"Built-in container/package registry" ,
"Issue tracking and pull requests" ,
"CI/CD via Gitea Actions" ,
"Lightweight SQLite deployment"
2026-07-02 09:01:34 -04:00
] ,
"icon" : "/assets/img/app-icons/gitea.svg" ,
"launch" : {
"open_in_new_tab" : true
} ,
"repo" : "https://gitea.com" ,
"tier" : "optional"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "Gitea" ,
2026-06-23 23:45:31 -04:00
"nginx_proxy" : {
"extra_headers" : [
"proxy_hide_header X-Frame-Options" ,
"proxy_hide_header Content-Security-Policy"
2026-07-02 09:01:34 -04:00
] ,
"listen" : 3000 ,
"proxy_pass" : "http://127.0.0.1:3001"
} ,
"ports" : [
{
"container" : 3000 ,
"host" : 3001 ,
"protocol" : "tcp"
} ,
{
"container" : 22 ,
"host" : 2222 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"disk_limit" : "500Mi" ,
"memory_limit" : "256Mi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE" ,
"NET_BIND_SERVICE"
] ,
"network_policy" : "bridge" ,
"no_new_privileges" : false ,
"readonly_root" : false
} ,
"version" : "1.23" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/gitea/data" ,
"target" : "/data" ,
"type" : "bind"
} ,
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/gitea/config" ,
"target" : "/etc/gitea" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.23"
2026-06-23 23:45:31 -04:00
} ,
"grafana" : {
"image" : "146.59.87.168:3000/lfg2025/grafana:10.2.0" ,
"manifest" : {
"app" : {
"container" : {
2026-07-02 09:01:34 -04:00
"data_uid" : "472:472" ,
2026-06-23 23:45:31 -04:00
"image" : "grafana/grafana:10.2.0" ,
"image_signature" : "cosign://..." ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "5Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Analytics and monitoring platform. Visualize metrics and create dashboards." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "http://localhost:3000" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/api/health" ,
"retries" : 5 ,
2026-06-23 23:45:31 -04:00
"timeout" : "30s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "grafana" ,
2026-06-23 23:45:31 -04:00
"metadata" : {
"launch" : {
"open_in_new_tab" : true
}
} ,
2026-07-02 09:01:34 -04:00
"name" : "Grafana" ,
"ports" : [
2026-06-23 23:45:31 -04:00
{
2026-07-02 09:01:34 -04:00
"container" : 3000 ,
"host" : 3000 ,
"protocol" : "tcp"
2026-06-23 23:45:31 -04:00
}
] ,
"resources" : {
"cpu_limit" : 2 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "5Gi" ,
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"apparmor_profile" : "grafana" ,
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : true ,
2026-06-23 23:45:31 -04:00
"seccomp_profile" : "default" ,
2026-07-02 09:01:34 -04:00
"user" : 1000
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "10.2.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/grafana" ,
"target" : "/var/lib/grafana" ,
"type" : "bind"
}
]
}
} ,
"version" : "10.2.0"
} ,
"homeassistant" : {
"image" : "146.59.87.168:3000/lfg2025/home-assistant:2024.1" ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/home-assistant:2024.1" ,
"network" : "pasta" ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "10Gi"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Open source home automation platform. Control and monitor your smart home devices." ,
2026-06-23 23:45:31 -04:00
"devices" : [ ] ,
"environment" : [
"TZ=UTC"
] ,
"health_check" : {
"endpoint" : "localhost:8123" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "homeassistant" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Home Assistant dashboard" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 8123 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "Home Assistant" ,
2026-07-02 09:01:34 -04:00
"category" : "home" ,
"icon" : "/assets/img/app-icons/homeassistant.png" ,
2026-06-23 23:45:31 -04:00
"launch" : {
"open_in_new_tab" : true
2026-07-02 09:01:34 -04:00
} ,
"repo" : "https://github.com/home-assistant/core"
} ,
"name" : "Home Assistant" ,
"ports" : [
{
"container" : 8123 ,
"host" : 8123 ,
"protocol" : "tcp"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
] ,
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "10Gi" ,
"memory_limit" : "512Mi"
} ,
"security" : {
"apparmor_profile" : "home-assistant" ,
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE" ,
"NET_BIND_SERVICE" ,
"NET_RAW"
] ,
"network_policy" : "isolated" ,
"no_new_privileges" : true ,
"readonly_root" : false ,
"seccomp_profile" : "default" ,
"user" : 1000
} ,
"version" : "2024.1.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/home-assistant" ,
"target" : "/config" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "2024.1"
2026-06-23 23:45:31 -04:00
} ,
"immich" : {
"image" : "146.59.87.168:3000/lfg2025/immich-server:release" ,
"images" : {
"immich_postgres" : "146.59.87.168:3000/lfg2025/immich-postgres:14-vectorchord0.4.3-pgvectors0.2.0" ,
2026-07-02 09:01:34 -04:00
"immich_redis" : "146.59.87.168:3000/lfg2025/redis:7.4.8" ,
"immich_server" : "146.59.87.168:3000/lfg2025/immich-server:release"
2026-06-23 23:45:31 -04:00
} ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/immich-server:release" ,
"network" : "archy-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "DB_PASSWORD" ,
"secret_file" : "immich-db-password"
}
]
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "immich_server" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "immich-postgres"
} ,
{
"app_id" : "immich-redis"
} ,
{
"storage" : "200Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Self-hosted photo and video backup with mobile apps and search." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"DB_HOSTNAME=immich_postgres" ,
"DB_USERNAME=postgres" ,
"DB_DATABASE_NAME=immich" ,
"REDIS_HOSTNAME=immich_redis" ,
"UPLOAD_LOCATION=/usr/src/app/upload"
] ,
"health_check" : {
"endpoint" : "http://localhost:2283" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/api/server/ping" ,
"retries" : 20 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "immich" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Immich photo library" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 2283 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"launch" : {
"open_in_new_tab" : true
}
2026-07-02 09:01:34 -04:00
} ,
"name" : "Immich" ,
"ports" : [
{
"container" : 2283 ,
"host" : 2283 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"disk_limit" : "200Gi" ,
"memory_limit" : "2Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "2.7.4" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/immich" ,
"target" : "/usr/src/app/upload" ,
"type" : "bind"
}
]
}
} ,
"version" : "release"
} ,
"immich-postgres" : {
2026-06-23 23:45:31 -04:00
"manifest" : {
"app" : {
"container" : {
"data_uid" : "100998:100998" ,
"generated_secrets" : [
{
2026-07-02 09:01:34 -04:00
"kind" : "hex32" ,
"name" : "immich-db-password"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/immich-postgres:14-vectorchord0.4.3-pgvectors0.2.0" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "POSTGRES_PASSWORD" ,
"secret_file" : "immich-db-password"
}
]
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "immich_postgres" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "40Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Postgres (pgvecto.rs / vectorchord) backend for Immich." ,
"environment" : [
"POSTGRES_USER=postgres" ,
"POSTGRES_DB=immich"
] ,
"health_check" : {
"endpoint" : "localhost:5432" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "immich-postgres" ,
"name" : "Immich Postgres" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "40Gi" ,
"memory_limit" : "2Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"DAC_OVERRIDE" ,
"FOWNER" ,
"SETGID" ,
"SETUID"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "14-vectorchord0.4.3-pgvectors0.2.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/immich-db" ,
"target" : "/var/lib/postgresql/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "14-vectorchord0.4.3-pgvectors0.2.0"
2026-06-23 23:45:31 -04:00
} ,
"immich-redis" : {
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/valkey:7-alpine" ,
2026-07-02 09:01:34 -04:00
"network" : "archy-net" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "immich_redis" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [ ] ,
2026-07-02 09:01:34 -04:00
"description" : "Valkey (Redis-compatible) cache for Immich." ,
"environment" : [ ] ,
"health_check" : {
"endpoint" : "localhost:6379" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "immich-redis" ,
"name" : "Immich Redis" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"memory_limit" : "128Mi"
} ,
"security" : {
"capabilities" : [
"SETGID" ,
"SETUID"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "7-alpine" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "7-alpine"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub" : {
"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" : {
"category" : "community" ,
"container" : {
"image" : "146.59.87.168:3000/lfg2025/indeedhub:1.0.0" ,
2026-07-02 09:01:34 -04:00
"network" : "indeedhub-net" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "indeedhub-api"
} ,
{
"storage" : "1Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"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." ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
2026-07-02 09:01:34 -04:00
"health_check" : {
"endpoint" : "localhost:7777" ,
"interval" : "30s" ,
"retries" : 5 ,
"start_period" : "30s" ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
2026-06-23 23:45:31 -04:00
"hooks" : {
"post_install" : [
{
"exec" : [
"sed" ,
"-i" ,
"/X-Frame-Options/d" ,
"/etc/nginx/conf.d/default.conf"
]
} ,
{
"copy_from_host" : {
2026-07-02 09:01:34 -04:00
"dest" : "/usr/share/nginx/html/nostr-provider.js" ,
"src" : "web-ui/nostr-provider.js"
2026-06-23 23:45:31 -04:00
}
} ,
{
"exec" : [
"sh" ,
"-c" ,
"grep -q nostr-provider /etc/nginx/conf.d/default.conf || sed -i 's#</head>#<script src=\"/nostr-provider.js\"></script></head>#' /etc/nginx/conf.d/default.conf"
]
} ,
{
"exec" : [
"nginx" ,
"-s" ,
"reload"
]
}
]
} ,
2026-07-02 09:01:34 -04:00
"id" : "indeedhub" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Stream Bitcoin documentaries with Nostr identity" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 7778 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "Indeehub Team" ,
"icon" : "/assets/img/app-icons/indeedhub.png" ,
"license" : "MIT" ,
2026-07-02 09:01:34 -04:00
"repo" : "https://github.com/indeedhub/indeedhub" ,
2026-06-23 23:45:31 -04:00
"tags" : [
"bitcoin" ,
"documentary" ,
"streaming" ,
"media" ,
"education" ,
"nostr"
2026-07-02 09:01:34 -04:00
] ,
"website" : "https://indeedhub.com"
} ,
"name" : "IndeeHub" ,
"ports" : [
{
"container" : 7777 ,
"host" : 7778 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"disk_limit" : "1Gi" ,
"memory_limit" : "512Mi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"DAC_OVERRIDE" ,
"SETGID" ,
"SETUID"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "1.0.0" ,
"volumes" : [
{
"options" : [
"rw" ,
"nosuid" ,
"nodev" ,
"size=16m"
] ,
"target" : "/run" ,
"type" : "tmpfs"
} ,
{
"options" : [
"rw" ,
"nosuid" ,
"nodev" ,
"size=32m"
] ,
"target" : "/var/cache/nginx" ,
"type" : "tmpfs"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub-api" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
2026-07-02 09:01:34 -04:00
"generated_secrets" : [
{
"kind" : "hex32" ,
"name" : "indeedhub-jwt"
}
] ,
2026-06-23 23:45:31 -04:00
"image" : "146.59.87.168:3000/lfg2025/indeedhub-api:1.0.0" ,
"network" : "indeedhub-net" ,
"network_aliases" : [
"api"
] ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"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"
}
]
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub-api" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "indeedhub-postgres"
} ,
{
"app_id" : "indeedhub-redis"
} ,
{
"app_id" : "indeedhub-minio"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "IndeedHub backend API (Nostr auth, media, payments)." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "localhost:4000" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"retries" : 10 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "tcp"
} ,
"id" : "indeedhub-api" ,
"name" : "IndeedHub API" ,
"ports" : [ ] ,
"resources" : {
"memory_limit" : "2Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "1.0.0" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub-ffmpeg" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
"image" : "146.59.87.168:3000/lfg2025/indeedhub-ffmpeg:1.0.0" ,
"network" : "indeedhub-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "DATABASE_PASSWORD" ,
"secret_file" : "indeedhub-db-password"
} ,
{
"key" : "AWS_SECRET_KEY" ,
"secret_file" : "indeedhub-minio-password"
}
]
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub-ffmpeg" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "indeedhub-api"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "IndeedHub background media transcoding worker." ,
2026-06-23 23:45:31 -04:00
"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"
2026-07-02 09:01:34 -04:00
] ,
"id" : "indeedhub-ffmpeg" ,
"name" : "IndeedHub FFmpeg Worker" ,
"ports" : [ ] ,
"resources" : {
"memory_limit" : "4Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "1.0.0" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub-minio" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
"custom_args" : [
"server" ,
"/data"
] ,
"generated_secrets" : [
{
2026-07-02 09:01:34 -04:00
"kind" : "hex32" ,
"name" : "indeedhub-minio-password"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/minio:RELEASE.2024-11-07T00-52-20Z" ,
"network" : "indeedhub-net" ,
"network_aliases" : [
"minio"
] ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "MINIO_ROOT_PASSWORD" ,
"secret_file" : "indeedhub-minio-password"
}
]
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub-minio" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "50Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "MinIO S3-compatible object storage for IndeedHub media." ,
"environment" : [
"MINIO_ROOT_USER=indeeadmin"
] ,
"health_check" : {
"endpoint" : "http://localhost:9000" ,
"interval" : "30s" ,
"path" : "/minio/health/live" ,
"retries" : 5 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "indeedhub-minio" ,
"name" : "IndeedHub MinIO" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "50Gi" ,
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "RELEASE.2024-11-07T00-52-20Z" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "indeedhub-minio-data" ,
"target" : "/data" ,
"type" : "volume"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "RELEASE.2024-11-07T00-52-20Z"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub-postgres" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
2026-07-02 09:01:34 -04:00
"generated_secrets" : [
{
"kind" : "hex32" ,
"name" : "indeedhub-db-password"
}
] ,
2026-06-23 23:45:31 -04:00
"image" : "146.59.87.168:3000/lfg2025/postgres:16.13-alpine" ,
"network" : "indeedhub-net" ,
"network_aliases" : [
"postgres"
] ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "POSTGRES_PASSWORD" ,
"secret_file" : "indeedhub-db-password"
}
]
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub-postgres" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "10Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Postgres database backend for IndeedHub." ,
"environment" : [
"POSTGRES_USER=indeedhub" ,
"POSTGRES_DB=indeedhub"
] ,
"health_check" : {
"endpoint" : "localhost:5432" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "indeedhub-postgres" ,
"name" : "IndeedHub Postgres" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "10Gi" ,
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"DAC_OVERRIDE" ,
"FOWNER" ,
"SETGID" ,
"SETUID"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "16.13-alpine" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "indeedhub-postgres-data" ,
"target" : "/var/lib/postgresql/data" ,
"type" : "volume"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "16.13-alpine"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub-redis" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
"image" : "146.59.87.168:3000/lfg2025/redis:7.4.8-alpine" ,
"network" : "indeedhub-net" ,
"network_aliases" : [
"redis"
2026-07-02 09:01:34 -04:00
] ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub-redis" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "1Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Redis queue/cache backend for IndeedHub." ,
"environment" : [ ] ,
"health_check" : {
"endpoint" : "localhost:6379" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "indeedhub-redis" ,
"name" : "IndeedHub Redis" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"memory_limit" : "256Mi"
} ,
"security" : {
"capabilities" : [
"SETGID" ,
"SETUID"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "7.4.8-alpine" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "indeedhub-redis-data" ,
"target" : "/data" ,
"type" : "volume"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "7.4.8-alpine"
2026-06-23 23:45:31 -04:00
} ,
"indeedhub-relay" : {
"manifest" : {
"app" : {
"category" : "community" ,
"container" : {
"image" : "146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.0" ,
"network" : "indeedhub-net" ,
"network_aliases" : [
"relay"
2026-07-02 09:01:34 -04:00
] ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "indeedhub-relay" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "2Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "nostr-rs-relay backing IndeedHub's Nostr identity + comments." ,
"environment" : [ ] ,
"health_check" : {
"endpoint" : "localhost:8080" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
} ,
"id" : "indeedhub-relay" ,
"name" : "IndeedHub Nostr Relay" ,
"ports" : [ ] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "2Gi" ,
"memory_limit" : "256Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "0.9.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "indeedhub-relay-data" ,
"target" : "/usr/src/app/db" ,
"type" : "volume"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "0.9.0"
2026-06-23 23:45:31 -04:00
} ,
"jellyfin" : {
"image" : "146.59.87.168:3000/lfg2025/jellyfin:10.8.13" ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/jellyfin:10.8.13" ,
2026-07-02 09:01:34 -04:00
"network" : "pasta" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "10Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Free media server. Stream movies, music, and photos." ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"health_check" : {
"endpoint" : "localhost:8096" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "jellyfin" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Jellyfin media dashboard" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 8096 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "Jellyfin" ,
2026-07-02 09:01:34 -04:00
"category" : "data" ,
"icon" : "/assets/img/app-icons/jellyfin.webp" ,
2026-06-23 23:45:31 -04:00
"repo" : "https://github.com/jellyfin/jellyfin"
2026-07-02 09:01:34 -04:00
} ,
"name" : "Jellyfin" ,
"ports" : [
{
"container" : 8096 ,
"host" : 8096 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"disk_limit" : "10Gi" ,
"memory_limit" : "1Gi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "10.8.13" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/jellyfin/config" ,
"target" : "/config" ,
"type" : "bind"
} ,
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/jellyfin/cache" ,
"target" : "/cache" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "10.8.13"
2026-06-23 23:45:31 -04:00
} ,
"lightning-stack" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "admin" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"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"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Complete Lightning Network implementation. Includes LND, CLN, and management tools." ,
"environment" : [
"BITCOIND_HOST=bitcoin-core" ,
"BITCOIND_RPCUSER=${BITCOIN_RPC_USER}" ,
"BITCOIND_RPCPASS=${BITCOIN_RPC_PASSWORD}" ,
"NETWORK=mainnet"
] ,
"health_check" : {
"endpoint" : "http://localhost:8087" ,
"interval" : "30s" ,
"path" : "/v1/getinfo" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "lightning-stack" ,
"lightning_integration" : {
"channel_management" : true ,
"payment_routing" : true
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "Lightning Stack" ,
2026-06-23 23:45:31 -04:00
"ports" : [
{
"container" : 9735 ,
2026-07-02 09:01:34 -04:00
"host" : 9737 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 10009 ,
2026-07-02 09:01:34 -04:00
"host" : 10010 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 8080 ,
2026-07-02 09:01:34 -04:00
"host" : 8087 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 4 ,
"disk_limit" : "50Gi" ,
"memory_limit" : "4Gi"
} ,
"security" : {
"apparmor_profile" : "lightning-stack" ,
"capabilities" : [
"NET_BIND_SERVICE"
] ,
"network_policy" : "isolated" ,
"no_new_privileges" : true ,
"readonly_root" : true ,
"seccomp_profile" : "default" ,
"user" : 1000
} ,
"version" : "0.12.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/lightning-stack" ,
"target" : "/root/.lightning" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "0.12.0"
2026-06-23 23:45:31 -04:00
} ,
"lnd" : {
"image" : "146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta" ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "admin" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
2026-07-02 09:01:34 -04:00
"data_uid" : "100000:100000" ,
2026-06-23 23:45:31 -04:00
"image" : "146.59.87.168:3000/lfg2025/lnd:v0.18.4-beta" ,
"network" : "archy-net" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"secret_env" : [
{
"key" : "BITCOIND_RPCPASS" ,
"secret_file" : "bitcoin-rpc-password"
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"app_id" : "bitcoin-core" ,
"version" : ">=26.0"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Lightning Network implementation by Lightning Labs. Enables instant, low-cost Bitcoin payments." ,
"environment" : [
"BITCOIND_HOST=bitcoin-knots" ,
"BITCOIND_RPCUSER=archipelago" ,
"NETWORK=mainnet"
] ,
"health_check" : {
"endpoint" : "localhost:10009" ,
"interval" : "30s" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "lnd" ,
"lightning_integration" : {
"channel_management" : true ,
"payment_routing" : true
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "LND" ,
2026-06-23 23:45:31 -04:00
"ports" : [
{
"container" : 9735 ,
2026-07-02 09:01:34 -04:00
"host" : 9735 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 10009 ,
2026-07-02 09:01:34 -04:00
"host" : 10009 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 8080 ,
2026-07-02 09:01:34 -04:00
"host" : 18080 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "10Gi" ,
"memory_limit" : "1Gi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"FOWNER" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE" ,
"NET_RAW"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "0.18.4" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/lnd" ,
"target" : "/root/.lnd" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "v0.18.4-beta"
2026-06-23 23:45:31 -04:00
} ,
"lnd-ui" : {
"image" : "146.59.87.168:3000/lfg2025/lnd-ui:latest" ,
"manifest" : {
"app" : {
"container" : {
"build" : {
"context" : "/opt/archipelago/docker/lnd-ui" ,
"dockerfile" : "Dockerfile" ,
"tag" : "localhost/lnd-ui:local"
}
} ,
"dependencies" : [
{
"app_id" : "lnd"
}
] ,
2026-07-02 09:01:34 -04:00
"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" ,
"environment" : [ ] ,
"health_check" : {
"endpoint" : "http://127.0.0.1:18083" ,
"interval" : "30s" ,
"path" : "/" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "lnd-ui" ,
"name" : "LND UI" ,
2026-06-23 23:45:31 -04:00
"ports" : [
{
"container" : 80 ,
2026-07-02 09:01:34 -04:00
"host" : 18083 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"memory_limit" : "64Mi"
} ,
"security" : {
"network_policy" : "bridge" ,
"readonly_root" : false
} ,
"version" : "1.0.0" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "latest"
2026-06-23 23:45:31 -04:00
} ,
"mempool" : {
"image" : "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1" ,
"images" : {
2026-07-02 09:01:34 -04:00
"archy-mempool-db" : "146.59.87.168:3000/lfg2025/mariadb:11.4.10" ,
2026-06-23 23:45:31 -04:00
"archy-mempool-web" : "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1" ,
2026-07-02 09:01:34 -04:00
"mempool-api" : "146.59.87.168:3000/lfg2025/mempool-backend:v3.0.0"
2026-06-23 23:45:31 -04:00
} ,
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"rpc_access" : "read-only" ,
"sync_required" : true
} ,
"container" : {
"image" : "146.59.87.168:3000/lfg2025/mempool-frontend:v3.0.1" ,
"image_signature" : "cosign://..." ,
2026-06-23 23:45:31 -04:00
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"app_id" : "bitcoin-core" ,
"version" : ">=24.0"
} ,
{
"storage" : "20Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Bitcoin mempool and blockchain explorer. Real-time transaction and block visualization." ,
"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" : {
"endpoint" : "http://localhost:4080" ,
"interval" : "30s" ,
"path" : "/api/health" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "mempool" ,
"name" : "Mempool Explorer" ,
"ports" : [
{
"container" : 8080 ,
"host" : 4080 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 2 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "20Gi" ,
"memory_limit" : "2Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"apparmor_profile" : "mempool" ,
2026-06-23 23:45:31 -04:00
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : true ,
2026-06-23 23:45:31 -04:00
"seccomp_profile" : "default" ,
2026-07-02 09:01:34 -04:00
"user" : 1000
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "3.0.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/mempool" ,
"target" : "/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "v3.0.1"
2026-06-23 23:45:31 -04:00
} ,
"mempool-api" : {
"manifest" : {
"app" : {
2026-07-02 09:01:34 -04:00
"bitcoin_integration" : {
"pruning_support" : false ,
"rpc_access" : "read-only" ,
"sync_required" : true
} ,
2026-06-23 23:45:31 -04:00
"container" : {
"derived_env" : [
{
"key" : "CORE_RPC_HOST" ,
"template" : "{{BITCOIN_HOST}}"
}
] ,
2026-07-02 09:01:34 -04:00
"image" : "git.tx1138.com/lfg2025/mempool-backend:v3.0.0" ,
"network" : "archy-net" ,
"pull_policy" : "if-not-present" ,
2026-06-23 23:45:31 -04:00
"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"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Backend API for mempool explorer." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "http://localhost:8999" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/api/v1/backend-info" ,
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "mempool-api" ,
"name" : "Mempool API" ,
"ports" : [
{
"container" : 8999 ,
"host" : 8999 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"disk_limit" : "20Gi" ,
"memory_limit" : "2Gi"
} ,
"security" : {
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "3.0.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/mempool" ,
"target" : "/data" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "3.0.0"
2026-06-23 23:45:31 -04:00
} ,
"morphos-server" : {
"manifest" : {
"app" : {
"container" : {
"image" : "archipelago/morphos-server:1.0.0" ,
"image_signature" : "cosign://..." ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "5Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "MorphOS server platform. Decentralized application server." ,
"environment" : [
"MORPHOS_ENV=production" ,
"MORPHOS_DATA_DIR=/app/data"
] ,
"health_check" : {
"endpoint" : "http://localhost:8086" ,
"interval" : "30s" ,
"path" : "/health" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
} ,
"id" : "morphos-server" ,
"name" : "MorphOS Server" ,
"ports" : [
{
"container" : 8080 ,
"host" : 8086 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 2 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "5Gi" ,
"memory_limit" : "2Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"apparmor_profile" : "morphos-server" ,
2026-06-23 23:45:31 -04:00
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : true ,
2026-06-23 23:45:31 -04:00
"seccomp_profile" : "default" ,
2026-07-02 09:01:34 -04:00
"user" : 1000
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "1.0.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/morphos-server" ,
"target" : "/app/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"netbird" : {
"manifest" : {
"app" : {
"category" : "networking" ,
"container" : {
"generated_certs" : [
{
"crt" : "/var/lib/archipelago/netbird/tls.crt" ,
"key" : "/var/lib/archipelago/netbird/tls.key"
}
2026-07-02 09:01:34 -04:00
] ,
"image" : "docker.io/library/nginx:1.27-alpine" ,
"network" : "netbird-net" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "netbird" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "netbird-server"
} ,
{
"app_id" : "netbird-dashboard"
} ,
{
"storage" : "1Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Self-hosted WireGuard mesh VPN control plane with dashboard, embedded identity provider, management API, signal, relay, and STUN. The user-facing entry point — a TLS proxy in front of the dashboard + server." ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"files" : [
{
2026-07-02 09:01:34 -04:00
"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 —\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" ,
2026-06-23 23:45:31 -04:00
"overwrite" : true ,
2026-07-02 09:01:34 -04:00
"path" : "/var/lib/archipelago/netbird/nginx.conf"
2026-06-23 23:45:31 -04:00
}
] ,
"health_check" : {
"endpoint" : "localhost:443" ,
"interval" : "30s" ,
"retries" : 5 ,
2026-07-02 09:01:34 -04:00
"start_period" : "20s" ,
"timeout" : "5s" ,
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "netbird" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Manage your self-hosted NetBird mesh VPN" ,
2026-07-02 09:01:34 -04:00
"name" : "Dashboard" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 8087 ,
"protocol" : "https" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "NetBird" ,
"icon" : "/assets/img/app-icons/netbird.svg" ,
"license" : "BSD-3-Clause" ,
2026-07-02 09:01:34 -04:00
"repo" : "https://github.com/netbirdio/netbird" ,
2026-06-23 23:45:31 -04:00
"tags" : [
"networking" ,
"vpn" ,
"wireguard" ,
"mesh"
2026-07-02 09:01:34 -04:00
] ,
"website" : "https://netbird.io"
} ,
"name" : "NetBird" ,
"ports" : [
{
"container" : 443 ,
"host" : 8087 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"memory_limit" : "256Mi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"DAC_OVERRIDE" ,
"SETGID" ,
"SETUID" ,
"NET_BIND_SERVICE"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "2.38.0" ,
"volumes" : [
{
"options" : [
"ro"
] ,
"source" : "/var/lib/archipelago/netbird/nginx.conf" ,
"target" : "/etc/nginx/conf.d/default.conf" ,
"type" : "bind"
} ,
{
"options" : [
"ro"
] ,
"source" : "/var/lib/archipelago/netbird/tls.crt" ,
"target" : "/etc/nginx/tls.crt" ,
"type" : "bind"
} ,
{
"options" : [
"ro"
] ,
"source" : "/var/lib/archipelago/netbird/tls.key" ,
"target" : "/etc/nginx/tls.key" ,
"type" : "bind"
}
]
}
} ,
"version" : "2.38.0"
} ,
2026-06-23 23:45:31 -04:00
"netbird-dashboard" : {
"manifest" : {
"app" : {
"category" : "networking" ,
"container" : {
"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"
}
2026-07-02 09:01:34 -04:00
] ,
"image" : "docker.io/netbirdio/dashboard:v2.38.0" ,
"network" : "netbird-net" ,
"network_aliases" : [
"netbird-dashboard"
] ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "netbird-dashboard" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"app_id" : "netbird-server"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "NetBird management dashboard (SPA). Internal stack member served through the netbird proxy." ,
2026-06-23 23:45:31 -04:00
"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" : {
"endpoint" : "localhost:80" ,
"interval" : "30s" ,
"retries" : 5 ,
2026-07-02 09:01:34 -04:00
"start_period" : "20s" ,
"timeout" : "5s" ,
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "netbird-dashboard" ,
2026-06-23 23:45:31 -04:00
"metadata" : {
"author" : "NetBird" ,
"icon" : "/assets/img/app-icons/netbird.svg" ,
"license" : "BSD-3-Clause" ,
2026-07-02 09:01:34 -04:00
"repo" : "https://github.com/netbirdio/dashboard" ,
2026-06-23 23:45:31 -04:00
"tags" : [
"networking" ,
"vpn" ,
"dashboard"
2026-07-02 09:01:34 -04:00
] ,
"website" : "https://netbird.io"
} ,
"name" : "NetBird Dashboard" ,
"ports" : [ ] ,
"resources" : {
"memory_limit" : "256Mi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"DAC_OVERRIDE" ,
"SETGID" ,
"SETUID" ,
"NET_BIND_SERVICE"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "2.38.0" ,
"volumes" : [ ]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "2.38.0"
2026-06-23 23:45:31 -04:00
} ,
"netbird-server" : {
"manifest" : {
"app" : {
"category" : "networking" ,
"container" : {
2026-07-02 09:01:34 -04:00
"custom_args" : [
"--config" ,
"/etc/netbird/config.yaml"
2026-06-23 23:45:31 -04:00
] ,
"generated_secrets" : [
{
2026-07-02 09:01:34 -04:00
"kind" : "base64" ,
"name" : "netbird-relay-auth-secret"
2026-06-23 23:45:31 -04:00
} ,
{
2026-07-02 09:01:34 -04:00
"kind" : "base64" ,
"name" : "netbird-store-encryption-key"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"image" : "docker.io/netbirdio/netbird-server:0.71.2" ,
"network" : "netbird-net" ,
"network_aliases" : [
"netbird-server"
] ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"container_name" : "netbird-server" ,
2026-06-23 23:45:31 -04:00
"dependencies" : [
{
"storage" : "1Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "NetBird combined management / signal / relay server with an embedded identity provider and STUN. Backend for the self-hosted NetBird mesh VPN." ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"files" : [
{
2026-07-02 09:01:34 -04:00
"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" ,
2026-06-23 23:45:31 -04:00
"overwrite" : true ,
2026-07-02 09:01:34 -04:00
"path" : "/var/lib/archipelago/netbird/config.yaml"
2026-06-23 23:45:31 -04:00
}
] ,
"health_check" : {
"endpoint" : "localhost:80" ,
"interval" : "30s" ,
"retries" : 10 ,
2026-07-02 09:01:34 -04:00
"start_period" : "30s" ,
"timeout" : "5s" ,
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "netbird-server" ,
2026-06-23 23:45:31 -04:00
"metadata" : {
"author" : "NetBird" ,
"icon" : "/assets/img/app-icons/netbird.svg" ,
"license" : "BSD-3-Clause" ,
2026-07-02 09:01:34 -04:00
"repo" : "https://github.com/netbirdio/netbird" ,
2026-06-23 23:45:31 -04:00
"tags" : [
"networking" ,
"vpn" ,
"wireguard" ,
"mesh"
2026-07-02 09:01:34 -04:00
] ,
"website" : "https://netbird.io"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "NetBird Server" ,
"ports" : [
2026-06-23 23:45:31 -04:00
{
2026-07-02 09:01:34 -04:00
"container" : 80 ,
"host" : 8086 ,
"protocol" : "tcp"
} ,
{
"container" : 3478 ,
"host" : 3478 ,
"protocol" : "udp"
2026-06-23 23:45:31 -04:00
}
] ,
"resources" : {
2026-07-02 09:01:34 -04:00
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"NET_BIND_SERVICE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "0.71.2" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/netbird/data" ,
"target" : "/var/lib/netbird" ,
"type" : "bind"
} ,
{
"options" : [
"ro"
] ,
"source" : "/var/lib/archipelago/netbird/config.yaml" ,
"target" : "/etc/netbird/config.yaml" ,
"type" : "bind"
}
]
}
} ,
"version" : "0.71.2"
} ,
"nextcloud" : {
"image" : "146.59.87.168:3000/lfg2025/nextcloud:29" ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/nextcloud:29" ,
"network" : "pasta" ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "10Gi"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Your own private cloud. File sync, calendars, contacts." ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"health_check" : {
"endpoint" : "localhost:80" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "nextcloud" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Nextcloud file and collaboration dashboard" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 8085 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "Nextcloud" ,
2026-07-02 09:01:34 -04:00
"category" : "data" ,
"icon" : "/assets/img/app-icons/nextcloud.webp" ,
2026-06-23 23:45:31 -04:00
"launch" : {
"open_in_new_tab" : true
2026-07-02 09:01:34 -04:00
} ,
"repo" : "https://github.com/nextcloud/server"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "Nextcloud" ,
"ports" : [
2026-06-23 23:45:31 -04:00
{
2026-07-02 09:01:34 -04:00
"container" : 80 ,
"host" : 8085 ,
"protocol" : "tcp"
2026-06-23 23:45:31 -04:00
}
] ,
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "10Gi" ,
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"capabilities" : [
"CHOWN" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE" ,
"NET_BIND_SERVICE"
] ,
2026-06-23 23:45:31 -04:00
"network_policy" : "isolated" ,
2026-07-02 09:01:34 -04:00
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "29" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/nextcloud" ,
"target" : "/var/www/html" ,
"type" : "bind"
}
]
}
} ,
"version" : "29"
} ,
"nginx-proxy-manager" : {
"image" : "146.59.87.168:3000/lfg2025/nginx-proxy-manager:latest" ,
"version" : "latest"
} ,
"nostr-rs-relay" : {
"image" : "146.59.87.168:3000/lfg2025/nostr-rs-relay:0.9.0" ,
"manifest" : {
"app" : {
"container" : {
"data_uid" : "1000:1000" ,
"image" : "scsibug/nostr-rs-relay:0.8.9" ,
"image_signature" : "cosign://..." ,
"pull_policy" : "verify-signature"
} ,
"dependencies" : [
{
"storage" : "10Gi"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "High-performance Nostr relay written in Rust. Host your own decentralized social media relay and earn networking profits." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"RELAY_NAME=Archipelago Nostr Relay" ,
"RELAY_DESCRIPTION=Self-hosted Nostr relay on Archipelago" ,
"MAX_EVENTS=1000000" ,
"MAX_SUBSCRIPTIONS=100"
] ,
"health_check" : {
"endpoint" : "http://localhost:8080" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 5 ,
2026-06-23 23:45:31 -04:00
"timeout" : "30s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "nostr-rs-relay" ,
"name" : "Nostr Relay (Rust)" ,
2026-06-23 23:45:31 -04:00
"nostr_integration" : {
2026-07-02 09:01:34 -04:00
"event_storage" : "sqlite" ,
2026-06-23 23:45:31 -04:00
"monetization_enabled" : true ,
2026-07-02 09:01:34 -04:00
"relay_type" : "public"
} ,
"ports" : [
{
"container" : 8080 ,
"host" : 18081 ,
"protocol" : "tcp"
}
] ,
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "10Gi" ,
"memory_limit" : "1Gi"
} ,
"security" : {
"apparmor_profile" : "nostr-relay" ,
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"no_new_privileges" : true ,
"readonly_root" : true ,
"seccomp_profile" : "default" ,
"user" : 1000
} ,
"version" : "0.8.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/nostr-relay" ,
"target" : "/usr/src/app/db" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "0.9.0"
2026-06-23 23:45:31 -04:00
} ,
"nostr-vpn" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/nostr-vpn:v0.3.7" ,
"version" : "v0.3.7"
2026-06-23 23:45:31 -04:00
} ,
"ollama" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/ollama:latest" ,
"version" : "latest"
2026-06-23 23:45:31 -04:00
} ,
"penpot" : {
"image" : "146.59.87.168:3000/lfg2025/penpot-frontend:2.4" ,
"images" : {
"penpot-backend" : "146.59.87.168:3000/lfg2025/penpot-backend:2.4" ,
"penpot-exporter" : "146.59.87.168:3000/lfg2025/penpot-exporter:2.4" ,
2026-07-02 09:01:34 -04:00
"penpot-frontend" : "146.59.87.168:3000/lfg2025/penpot-frontend:2.4" ,
2026-06-23 23:45:31 -04:00
"penpot-postgres" : "146.59.87.168:3000/lfg2025/postgres:15" ,
"penpot-valkey" : "146.59.87.168:3000/lfg2025/valkey:8.1"
2026-07-02 09:01:34 -04:00
} ,
"version" : "2.4"
2026-06-23 23:45:31 -04:00
} ,
"photoprism" : {
"image" : "146.59.87.168:3000/lfg2025/photoprism:240915" ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/photoprism:240915" ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "10Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "AI-powered photo management with facial recognition." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"PHOTOPRISM_ADMIN_PASSWORD=archipelago" ,
"PHOTOPRISM_DEFAULT_LOCALE=en"
] ,
"health_check" : {
"endpoint" : "localhost:2342" ,
"interval" : "60s" ,
2026-07-02 09:01:34 -04:00
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "photoprism" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "PhotoPrism photo library" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 2342 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "PhotoPrism" ,
2026-07-02 09:01:34 -04:00
"category" : "data" ,
"icon" : "/assets/img/app-icons/photoprism.svg" ,
2026-06-23 23:45:31 -04:00
"launch" : {
"open_in_new_tab" : true
2026-07-02 09:01:34 -04:00
} ,
"repo" : "https://github.com/photoprism/photoprism"
} ,
"name" : "PhotoPrism" ,
"ports" : [
{
"container" : 2342 ,
"host" : 2342 ,
"protocol" : "tcp"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
] ,
"resources" : {
"disk_limit" : "10Gi" ,
"memory_limit" : "1Gi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"SETUID" ,
"SETGID"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "240915" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/photoprism" ,
"target" : "/photoprism/storage" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "240915"
2026-06-23 23:45:31 -04:00
} ,
"portainer" : {
"image" : "146.59.87.168:3000/lfg2025/portainer:2.19.4" ,
"manifest" : {
"app" : {
"category" : "development" ,
"container" : {
2026-07-02 09:01:34 -04:00
"data_uid" : "1000:1000" ,
2026-06-23 23:45:31 -04:00
"image" : "146.59.87.168:3000/lfg2025/portainer:2.19.4" ,
2026-07-02 09:01:34 -04:00
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "1Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Container management web UI for the local Podman socket." ,
"environment" : [ ] ,
"id" : "portainer" ,
"interfaces" : {
"main" : {
"description" : "Portainer web interface" ,
"name" : "Web UI" ,
"path" : "/" ,
"port" : 9000 ,
"protocol" : "http" ,
"type" : "ui"
}
} ,
"metadata" : {
"features" : [
"Container management dashboard" ,
"Local Podman socket access" ,
"Compose stack storage"
] ,
"icon" : "/assets/img/app-icons/portainer.webp" ,
"launch" : {
"open_in_new_tab" : true
} ,
"tier" : "optional"
} ,
"name" : "Portainer" ,
"ports" : [
{
"container" : 9000 ,
"host" : 9000 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "1Gi" ,
"memory_limit" : "256Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"SETUID" ,
"SETGID" ,
"DAC_OVERRIDE"
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "2.19.4" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/portainer" ,
"target" : "/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
} ,
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/portainer/compose" ,
"target" : "/data/compose" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
} ,
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/run/user/1000/podman/podman.sock" ,
"target" : "/var/run/docker.sock" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
}
} ,
"version" : "2.19.4"
} ,
"router" : {
"manifest" : {
"app" : {
"container" : {
"image" : "archipelago/router:1.0.0" ,
"image_signature" : "cosign://..." ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "500Mi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Mesh routing and local network management. Provides device discovery, routing, and network topology visualization." ,
"environment" : [
"NETWORK_INTERFACE=eth0" ,
"MESH_ENABLED=true" ,
"DEVICE_DISCOVERY=true"
] ,
"health_check" : {
"endpoint" : "http://localhost:8084" ,
"interval" : "30s" ,
"path" : "/health" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "router" ,
"name" : "Mesh Router" ,
"networking" : {
"device_discovery" : true ,
"local_network_access" : true ,
"mesh_enabled" : true ,
"routing_protocols" : [
"olsr" ,
"babel"
]
2026-06-23 23:45:31 -04:00
} ,
"ports" : [
{
"container" : 8080 ,
2026-07-02 09:01:34 -04:00
"host" : 8084 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
} ,
{
"container" : 5353 ,
2026-07-02 09:01:34 -04:00
"host" : 5353 ,
2026-06-23 23:45:31 -04:00
"protocol" : "udp"
} ,
{
"container" : 1900 ,
2026-07-02 09:01:34 -04:00
"host" : 1900 ,
2026-06-23 23:45:31 -04:00
"protocol" : "udp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 2 ,
"disk_limit" : "500Mi" ,
"memory_limit" : "512Mi"
} ,
"security" : {
"apparmor_profile" : "router" ,
"capabilities" : [
"NET_ADMIN" ,
"NET_RAW"
] ,
"network_policy" : "host" ,
"no_new_privileges" : true ,
"readonly_root" : true ,
"seccomp_profile" : "default" ,
"user" : 1000
} ,
"version" : "1.0.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/router" ,
"target" : "/app/data" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
} ,
{
"options" : [
"ro"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/run/dbus" ,
"target" : "/var/run/dbus" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.0.0"
2026-06-23 23:45:31 -04:00
} ,
"routstr" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/routstr:v0.4.3" ,
"version" : "v0.4.3"
2026-06-23 23:45:31 -04:00
} ,
"searxng" : {
"image" : "146.59.87.168:3000/lfg2025/searxng:latest" ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/searxng:latest" ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "2Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Privacy-respecting metasearch engine. Search the web without tracking." ,
"environment" : [
"SEARXNG_HOSTNAME=localhost" ,
"SEARXNG_BIND_ADDRESS=0.0.0.0:8080"
] ,
"health_check" : {
"endpoint" : "http://localhost:8080" ,
"interval" : "30s" ,
"path" : "/" ,
"retries" : 5 ,
"timeout" : "30s" ,
"type" : "http"
} ,
"id" : "searxng" ,
"name" : "SearXNG" ,
"ports" : [
{
"container" : 8080 ,
"host" : 8888 ,
"protocol" : "tcp"
}
] ,
2026-06-23 23:45:31 -04:00
"resources" : {
"cpu_limit" : 2 ,
2026-07-02 09:01:34 -04:00
"disk_limit" : "2Gi" ,
"memory_limit" : "1Gi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
2026-07-02 09:01:34 -04:00
"apparmor_profile" : "searxng" ,
2026-06-23 23:45:31 -04:00
"capabilities" : [ ] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
2026-06-23 23:45:31 -04:00
"no_new_privileges" : true ,
2026-07-02 09:01:34 -04:00
"readonly_root" : true ,
2026-06-23 23:45:31 -04:00
"seccomp_profile" : "default" ,
2026-07-02 09:01:34 -04:00
"user" : 1000
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "1.0.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/searxng" ,
"target" : "/etc/searxng" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "latest"
2026-06-23 23:45:31 -04:00
} ,
"strfry" : {
"manifest" : {
"app" : {
"container" : {
"image" : "dockurr/strfry:1.0.4" ,
"image_signature" : "cosign://..." ,
"pull_policy" : "verify-signature"
} ,
"dependencies" : [
{
"storage" : "5Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Lightweight Nostr relay written in C++. Alternative to nostr-rs-relay with lower resource usage." ,
"environment" : [
"RELAY_NAME=Archipelago Strfry Relay"
] ,
"health_check" : {
"endpoint" : "http://localhost:8082" ,
"interval" : "30s" ,
"path" : "/health" ,
"retries" : 3 ,
"timeout" : "5s" ,
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "strfry" ,
"name" : "Strfry Nostr Relay" ,
"nostr_integration" : {
"monetization_enabled" : true ,
"relay_type" : "public"
2026-06-23 23:45:31 -04:00
} ,
"ports" : [
{
"container" : 8080 ,
2026-07-02 09:01:34 -04:00
"host" : 8082 ,
2026-06-23 23:45:31 -04:00
"protocol" : "tcp"
}
] ,
2026-07-02 09:01:34 -04:00
"resources" : {
"cpu_limit" : 1 ,
"disk_limit" : "5Gi" ,
"memory_limit" : "512Mi"
} ,
"security" : {
"apparmor_profile" : "nostr-relay" ,
"capabilities" : [ ] ,
"network_policy" : "isolated" ,
"no_new_privileges" : true ,
"readonly_root" : true ,
"seccomp_profile" : "default" ,
"user" : 1000
} ,
"version" : "0.9.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/strfry" ,
"target" : "/strfry" ,
"type" : "bind"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "0.9.0"
2026-06-23 23:45:31 -04:00
} ,
"tailscale" : {
2026-07-02 09:01:34 -04:00
"image" : "146.59.87.168:3000/lfg2025/tailscale:stable" ,
"version" : "stable"
2026-06-23 23:45:31 -04:00
} ,
"uptime-kuma" : {
"image" : "146.59.87.168:3000/lfg2025/uptime-kuma:1" ,
"manifest" : {
"app" : {
"container" : {
"custom_args" : [
"--" ,
"node" ,
"server/server.js"
2026-07-02 09:01:34 -04:00
] ,
"image" : "146.59.87.168:3000/lfg2025/uptime-kuma:1" ,
"network" : "pasta" ,
"pull_policy" : "if-not-present"
2026-06-23 23:45:31 -04:00
} ,
"dependencies" : [
{
"storage" : "1Gi"
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Self-hosted uptime monitoring." ,
2026-06-23 23:45:31 -04:00
"environment" : [
"TZ=UTC"
] ,
"health_check" : {
"endpoint" : "localhost:3001" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"path" : "/" ,
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "http"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "uptime-kuma" ,
2026-06-23 23:45:31 -04:00
"metadata" : {
"author" : "Uptime Kuma" ,
2026-07-02 09:01:34 -04:00
"category" : "data" ,
"icon" : "/assets/img/app-icons/uptime-kuma.webp" ,
2026-06-23 23:45:31 -04:00
"launch" : {
"open_in_new_tab" : true
2026-07-02 09:01:34 -04:00
} ,
"repo" : "https://github.com/louislam/uptime-kuma" ,
"tier" : "recommended"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"name" : "Uptime Kuma" ,
"ports" : [
2026-06-23 23:45:31 -04:00
{
2026-07-02 09:01:34 -04:00
"container" : 3001 ,
"host" : 3002 ,
"protocol" : "tcp"
2026-06-23 23:45:31 -04:00
}
] ,
"resources" : {
2026-07-02 09:01:34 -04:00
"disk_limit" : "1Gi" ,
"memory_limit" : "256Mi"
2026-06-23 23:45:31 -04:00
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
2026-07-02 09:01:34 -04:00
"FOWNER" ,
2026-06-23 23:45:31 -04:00
"SETUID" ,
2026-07-02 09:01:34 -04:00
"SETGID"
2026-06-23 23:45:31 -04:00
] ,
2026-07-02 09:01:34 -04:00
"network_policy" : "isolated" ,
"readonly_root" : false
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"version" : "1.23.0" ,
2026-06-23 23:45:31 -04:00
"volumes" : [
{
"options" : [
"rw"
2026-07-02 09:01:34 -04:00
] ,
"source" : "/var/lib/archipelago/uptime-kuma" ,
"target" : "/app/data" ,
"type" : "bind"
}
]
}
} ,
"version" : "1"
} ,
"vaultwarden" : {
"image" : "146.59.87.168:3000/lfg2025/vaultwarden:1.30.0-alpine" ,
"manifest" : {
"app" : {
"container" : {
"image" : "146.59.87.168:3000/lfg2025/vaultwarden:1.30.0-alpine" ,
"network" : "pasta" ,
"pull_policy" : "if-not-present"
} ,
"dependencies" : [
{
"storage" : "1Gi"
2026-06-23 23:45:31 -04:00
}
] ,
2026-07-02 09:01:34 -04:00
"description" : "Self-hosted password vault with zero-knowledge encryption." ,
2026-06-23 23:45:31 -04:00
"environment" : [ ] ,
"health_check" : {
"endpoint" : "localhost:80" ,
"interval" : "30s" ,
2026-07-02 09:01:34 -04:00
"retries" : 3 ,
2026-06-23 23:45:31 -04:00
"timeout" : "5s" ,
2026-07-02 09:01:34 -04:00
"type" : "tcp"
2026-06-23 23:45:31 -04:00
} ,
2026-07-02 09:01:34 -04:00
"id" : "vaultwarden" ,
2026-06-23 23:45:31 -04:00
"interfaces" : {
"main" : {
"description" : "Vaultwarden web vault" ,
2026-07-02 09:01:34 -04:00
"name" : "Web UI" ,
"path" : "/" ,
2026-06-23 23:45:31 -04:00
"port" : 8082 ,
"protocol" : "http" ,
2026-07-02 09:01:34 -04:00
"type" : "ui"
2026-06-23 23:45:31 -04:00
}
} ,
"metadata" : {
"author" : "Vaultwarden" ,
2026-07-02 09:01:34 -04:00
"category" : "data" ,
"icon" : "/assets/img/app-icons/vaultwarden.webp" ,
2026-06-23 23:45:31 -04:00
"launch" : {
"open_in_new_tab" : true
2026-07-02 09:01:34 -04:00
} ,
"repo" : "https://github.com/dani-garcia/vaultwarden" ,
"tier" : "recommended"
} ,
"name" : "Vaultwarden" ,
"ports" : [
{
"container" : 80 ,
"host" : 8082 ,
"protocol" : "tcp"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
] ,
"resources" : {
"disk_limit" : "1Gi" ,
"memory_limit" : "256Mi"
} ,
"security" : {
"capabilities" : [
"CHOWN" ,
"SETUID" ,
"SETGID" ,
"NET_BIND_SERVICE"
] ,
"network_policy" : "isolated" ,
"readonly_root" : false
} ,
"version" : "1.30.0" ,
"volumes" : [
{
"options" : [
"rw"
] ,
"source" : "/var/lib/archipelago/vaultwarden" ,
"target" : "/data" ,
"type" : "bind"
}
]
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"version" : "1.30.0-alpine"
2026-06-23 23:45:31 -04:00
}
2026-07-02 09:01:34 -04:00
} ,
"schema" : 1 ,
"signature" : "0e8bd98743c5ac56ef350964e99f72358fd05d051c002dcd92a7d3e089bd7fddad4ae2870b39ae35e6b2fc386780f8bca53f6eb10dfefd295977e17ec239ac0a" ,
"signed_by" : "did:key:z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur" ,
"updated" : "2026-06-29"
2026-06-23 23:45:31 -04:00
}