This guide walks you through deploying an Archon node, from a minimal DID-only setup to a full Lightning-enabled stack. Each section builds on the previous one — start with the core and add layers as needed.
git clone https://github.com/archetech/archon.git
cd archon
cp sample.env .env
Set your user/group IDs so containers run with the correct permissions:
# Add these to your .env
ARCHON_UID=$(id -u)
ARCHON_GID=$(id -g)
Generate an admin API key:
# Add to .env as ARCHON_ADMIN_API_KEY
openssl rand -hex 32
Internal service-to-service admin requests use the X-Archon-Admin-Key header. Reserve Authorization for user/session/OAuth-style flows.
All persistent data lives under ./data/. Create the directory and ensure it’s owned by your user:
mkdir -p data
The base docker-compose.yml runs everything needed for DID creation, resolution, and credential management.
Comment out the include: lines at the top of docker-compose.yml for any services you don’t need yet:
# include:
# - docker-compose.btc-mainnet.yml
# - docker-compose.btc-signet.yml
# - docker-compose.lightning.yml
# - docker-compose.drawbridge.yml
| Variable | Default | Description |
|---|---|---|
ARCHON_ADMIN_API_KEY |
(empty) | Required. Protects admin API routes |
ARCHON_ENCRYPTED_PASSPHRASE |
(empty) | Required. Passphrase for encrypting the wallet. Keymaster won’t start without it |
ARCHON_NODE_ID |
mynodeID |
Alias for the node’s agent DID (created on first run) |
ARCHON_NODE_NAME |
mynodeName |
Human-readable node name for peer discovery |
ARCHON_GATEKEEPER_PORT |
4224 |
Gatekeeper API port |
ARCHON_KEYMASTER_PORT |
4226 |
Keymaster API port |
ARCHON_GATEKEEPER_CLIENT_PORT |
4225 |
Gatekeeper client UI port |
ARCHON_REACT_WALLET_PORT |
4228 |
React wallet UI port |
ARCHON_GATEKEEPER_DB |
redis |
Storage backend (redis or json) |
ARCHON_GATEKEEPER_DID_PREFIX |
did:cid |
DID method prefix |
ARCHON_GATEKEEPER_REGISTRIES |
hyperswarm |
Comma-separated list of registries |
ARCHON_DEFAULT_REGISTRY |
hyperswarm |
Default registry for new DIDs |
ARCHON_PROTOCOL |
/ARCHON/v0.2-reboot |
Hyperswarm protocol identifier |
| Service | Description |
|---|---|
| mongodb | Used by satoshi mediators for Bitcoin registry state |
| redis | Primary DID data store, cache, and pub/sub |
| ipfs | Content-addressable storage |
| gatekeeper | DID resolution and management API |
| keymaster | Wallet and credential management API |
| hyperswarm-mediator | P2P DID synchronization |
| cli | Command-line interface container |
| explorer | DID explorer web app |
| gatekeeper-client | Browser UI for the Gatekeeper API |
| keymaster-client | Browser UI for the Keymaster service |
| react-wallet | Web wallet UI |
| prometheus | Metrics collection |
| grafana | Metrics dashboards |
docker compose up -d
docker compose logs -f gatekeeper # watch for startup
# Verify gatekeeper is running
curl http://localhost:4224/api/v1/version
Core UIs:
http://localhost:4225http://localhost:4226http://localhost:4228http://localhost:4000Bitcoin registries anchor DIDs on-chain via the Satoshi mediator. Each bundled network also includes a dedicated watch-only wallet service under services/mediators/satoshi-wallet. There are separate compose files per network:
| File | Network | Bitcoin Node |
|---|---|---|
docker-compose.btc-mainnet.yml |
BTC mainnet | You provide — requires an external Bitcoin Core node with RPC access |
docker-compose.btc-signet.yml |
BTC signet | Bundled — runs its own bitcoin-core container |
docker-compose.btc-testnet4.yml |
BTC testnet4 | Bundled — runs its own bitcoin-core container |
Uncomment the relevant include: line in docker-compose.yml:
include:
- docker-compose.btc-mainnet.yml
# - docker-compose.btc-signet.yml
| Variable | Default | Description |
|---|---|---|
ARCHON_BTC_HOST |
localhost |
Bitcoin RPC host |
ARCHON_BTC_PORT |
8332 |
Bitcoin RPC port |
ARCHON_BTC_USER |
bitcoin |
Bitcoin RPC username |
ARCHON_BTC_PASS |
bitcoin |
Bitcoin RPC password |
ARCHON_BTC_WALLET |
archon |
Bitcoin wallet name |
ARCHON_BTC_START_BLOCK |
934000 |
Block height to start scanning |
ARCHON_BTC_FEE_MAX |
0.00010000 |
Maximum fee per transaction (BTC) |
Signet and testnet4 have their own prefixed variables (ARCHON_SIGNET_*, ARCHON_BTC_T4_*) — see sample.env for the full list.
Add Bitcoin registries to the gatekeeper’s registry list:
ARCHON_GATEKEEPER_REGISTRIES=hyperswarm,BTC:mainnet
# Mainnet mediator metrics
curl http://localhost:4234/metrics
# Signet mediator metrics (if enabled)
curl http://localhost:4236/metrics
Drawbridge is the L402 API gateway that enables Lightning payments for API access and Lightning zaps between DIDs. The Drawbridge compose layer also brings in Herald, Herald client, Drawbridge client, the Lightning mediator, and a Tor hidden service for privacy.
Uncomment in docker-compose.yml:
include:
- docker-compose.drawbridge.yml
lightning-mediator owns Archon’s Lightning runtime integrations. Drawbridge talks to it over HTTP for L402 invoice creation and pending-invoice lifecycle, and the mediator owns the public Lightning APIs, LNBits integration, and CLN access.
Drawbridge remains the policy layer: it still owns macaroons, pricing, rate limits, and the final payment records that show which paid requests were granted. Internal admin requests between these services use X-Archon-Admin-Key.
You have two options for the mediator backend:
If you already run a Core Lightning node, point lightning-mediator at it:
ARCHON_LIGHTNING_MEDIATOR_CLN_REST_URL=https://your-cln-host:3001
ARCHON_LIGHTNING_MEDIATOR_CLN_RUNE=your-cln-rune-here
The rune needs permissions for invoice and listinvoices methods. Create one with:
lightning-cli createrune restrictions='[["method^invoice","method^listinvoices"]]'
You can optionally point to an external LNbits instance:
ARCHON_LIGHTNING_MEDIATOR_LNBITS_URL=http://your-lnbits:5000
Include the Lightning stack (see Section 5). Runes and secrets are auto-generated by init containers and shared with lightning-mediator via Docker volumes — no manual configuration needed.
| Variable | Default | Description |
|---|---|---|
ARCHON_DRAWBRIDGE_PORT |
4222 |
Drawbridge API port |
ARCHON_DRAWBRIDGE_L402_ENABLED |
false |
Enable L402 payment gates |
ARCHON_DRAWBRIDGE_DEFAULT_PRICE_SATS |
10 |
Default price per API call (sats) |
ARCHON_DRAWBRIDGE_INVOICE_EXPIRY |
3600 |
Invoice expiry in seconds |
ARCHON_LIGHTNING_MEDIATOR_URL |
http://lightning-mediator:4235 |
Drawbridge’s upstream Lightning mediator |
ARCHON_LIGHTNING_MEDIATOR_CLN_REST_URL |
https://cln:3001 |
CLN REST endpoint used by the mediator |
ARCHON_LIGHTNING_MEDIATOR_CLN_RUNE |
empty | CLN rune used by the mediator; auto-loaded from ./data/cln-mainnet/drawbridge/rune.txt in the bundled stack |
ARCHON_LIGHTNING_MEDIATOR_LNBITS_URL |
http://lnbits:5000 |
LNbits base URL used by the mediator |
ARCHON_DRAWBRIDGE_PUBLIC_HOST |
(auto) | Public Drawbridge URL used for published invoice endpoints |
ARCHON_DRAWBRIDGE_RATE_LIMIT_MAX |
100 |
Max requests per window |
ARCHON_DRAWBRIDGE_RATE_LIMIT_WINDOW |
60 |
Rate limit window in seconds |
ARCHON_DRAWBRIDGE_MACAROON_SECRET |
(auto) | L402 macaroon signing secret (auto-generated) |
The Drawbridge entrypoint script handles secrets automatically:
./data/drawbridge/macaroon-secret.txt./data/cln-mainnet/drawbridge/rune.txt (created by drawbridge-init container).onion address if not setcurl http://localhost:4222/api/v1/ready
Optional UIs when Drawbridge is enabled:
http://localhost:4231http://localhost:4223If you don’t have an existing CLN node, the bundled Lightning stack provides a complete setup with CLN, RTL, and LNbits.
Uncomment in docker-compose.yml:
include:
- docker-compose.lightning.yml
- docker-compose.drawbridge.yml
The CLN node needs access to a Bitcoin Core RPC. If you’re also running the BTC mainnet registry, these are the same credentials:
ARCHON_BTC_HOST=your-bitcoin-host
ARCHON_BTC_PORT=8332
ARCHON_BTC_USER=bitcoin
ARCHON_BTC_PASS=bitcoin
| Variable | Default | Description |
|---|---|---|
ARCHON_CLN_ALIAS |
archon |
Lightning node alias (visible to peers) |
ARCHON_CLN_RGB |
e33502 |
Node color (hex) |
ARCHON_CLN_PORT |
9736 |
Lightning P2P port |
ARCHON_CLN_NETWORK_MODE |
tor |
Network mode: tor, hybrid, or clearnet |
ARCHON_CLN_ANNOUNCE_ADDR |
(empty) | Announce address (for clearnet/hybrid modes) |
ARCHON_CLN_GOVERNANCE_MODE |
advisor |
cl-hive governance mode |
ARCHON_CLN_LOG_LEVEL |
info |
CLN log level |
ARCHON_RTL_PASSWORD |
changeme |
Change this. RTL web UI password |
ARCHON_RTL_PORT |
3002 |
RTL web UI port |
ARCHON_LNBITS_PORT |
5000 |
LNbits web UI port |
| Mode | Description |
|---|---|
tor |
Node is only reachable via Tor. Address is not publicly announced. |
hybrid |
Reachable via both Tor and clearnet. Set ARCHON_CLN_ANNOUNCE_ADDR to your public IP/domain. |
clearnet |
Clearnet only. Set ARCHON_CLN_ANNOUNCE_ADDR to your public IP/domain. |
Three one-shot init containers automatically create CLN runes:
| Container | Purpose | Rune Location |
|---|---|---|
drawbridge-init |
Creates rune restricted to invoice/listinvoices methods |
./data/cln-mainnet/drawbridge/rune.txt |
rtl-init |
Creates unrestricted rune for RTL | ./data/cln-mainnet/rtl/rune.txt |
lnbits-init |
Creates three runes (readonly, invoice, pay) + copies TLS certs | ./data/cln-mainnet/lnbits/runes.env |
These run once and exit. If a rune file already exists, they skip creation. The bundled LNbits service now runs from the published image ghcr.io/archetech/lnbits:1.5.3-archetech.1.
The ./data/cln-mainnet/ directory contains your Lightning wallet, channels, and keys. Back this up regularly. Losing this data means losing funds.
# RTL web interface
open http://localhost:3002
# LNbits web interface
open http://localhost:5000
# Lightning mediator health
curl http://localhost:4235/ready
Bind services to localhost and put them behind a reverse proxy (nginx, Caddy, etc.) for HTTPS termination:
ARCHON_BIND_ADDRESS=127.0.0.1
Only expose ports that need external access:
| Port | Needs Public Access? |
|---|---|
| CLN P2P (9736) | Yes — for Lightning peer connections |
| IPFS Swarm (4001) | Yes — for IPFS peer connections |
| Drawbridge (4222) | Yes — if accepting external API requests |
| Gatekeeper (4224) | Depends — public for DID resolution, localhost if behind proxy |
| All others | No — bind to localhost |
Back up the entire ./data/ directory regularly. Critical data:
| Path | Contents | Priority |
|---|---|---|
./data/cln-mainnet/ |
Lightning wallet, channels, keys | Critical — loss means lost funds |
./data/tor-drawbridge/ |
Tor hidden service keys | High — loss means new .onion address |
./data/mongodb/ |
Registry and wallet-side service state used by bundled Bitcoin mediators | High |
./data/redis/ |
Cache (reconstructible) | Low |
Prometheus scrapes metrics from all services. Grafana is pre-provisioned with dashboards:
admin / admin)Change the default Grafana credentials:
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=your-secure-password
| Port | Service | Default | Env Var | Binding |
|---|---|---|---|---|
| 4224 | Gatekeeper | 4224 | ARCHON_GATEKEEPER_PORT |
configurable |
| 4225 | Gatekeeper Client | 4225 | ARCHON_GATEKEEPER_CLIENT_PORT |
configurable |
| 4226 | Keymaster | 4226 | ARCHON_KEYMASTER_PORT |
configurable |
| 4223 | Drawbridge Client | 4223 | ARCHON_DRAWBRIDGE_CLIENT_PORT |
configurable |
| 4228 | React Wallet | 4228 | ARCHON_REACT_WALLET_PORT |
configurable |
| 4222 | Drawbridge | 4222 | ARCHON_DRAWBRIDGE_PORT |
public |
| 4230 | Herald | 4230 | ARCHON_HERALD_PORT |
configurable |
| 4231 | Herald Client | 4231 | ARCHON_HERALD_CLIENT_PORT |
configurable |
| 4235 | Lightning Mediator | 4235 | ARCHON_LIGHTNING_MEDIATOR_PORT |
configurable |
| 4000 | Explorer | 4000 | – | public |
| 9736 | CLN P2P | 9736 | ARCHON_CLN_PORT |
public |
| 3001 | CLN REST | 3001 | – | localhost |
| 3002 | RTL | 3002 | ARCHON_RTL_PORT |
localhost |
| 5000 | LNbits | 5000 | ARCHON_LNBITS_PORT |
localhost |
| 4240 | BTC Signet Wallet API | 4240 | – | localhost |
| 4241 | BTC Signet Wallet Metrics | 4241 | – | localhost |
| 27017 | MongoDB | 27017 | – | localhost |
| 6379 | Redis | 6379 | – | localhost |
| 5001 | IPFS API | 5001 | – | localhost |
| 4001 | IPFS Swarm | 4001 | – | public |
| 9090 | Prometheus | 9090 | – | localhost |
| 3000 | Grafana | 3000 | – | localhost |
| 4232 | Hyperswarm Metrics | 4232 | – | localhost |
| 4234 | BTC Mainnet Metrics | 4234 | – | localhost |
| 4236 | BTC Signet Metrics | 4236 | – | localhost |
Check Bitcoin RPC connectivity:
docker compose logs cln-mainnet-node | grep -i error
Verify your ARCHON_BTC_HOST, ARCHON_BTC_USER, and ARCHON_BTC_PASS are correct and that the Bitcoin node is reachable from inside the Docker network.
This is expected when running in tor network mode — the node is hidden and doesn’t announce a public address. If you need a visible address, switch to hybrid or clearnet mode and set ARCHON_CLN_ANNOUNCE_ADDR.
Rune init containers wait up to 10 minutes for CLN to be ready. Check their logs:
docker compose logs drawbridge-init
docker compose logs rtl-init
docker compose logs lnbits-init
If CLN is taking too long to start (e.g., first-time Tor setup), the init containers will time out. Restart them after CLN is running:
docker compose restart drawbridge-init
Check that the Tor container created the hostname file:
cat ./data/tor-drawbridge/hostname
If empty or missing, restart the Tor container:
docker compose restart tor
If a service fails to start with “address already in use”, check what’s bound to that port:
ss -tlnp | grep :4224
Either stop the conflicting process or change the port via the corresponding environment variable.
# All services
docker compose logs -f
# Specific service
docker compose logs -f gatekeeper
# Last 100 lines
docker compose logs --tail=100 cln-mainnet-node