feat(docker): add home node and exit node compose files
docker-compose.node.yml — minimal chain node + wallet with PoS staking. Home users run this to support the network and earn staking rewards. docker-compose.exit.yml — full VPN exit node with WireGuard. Home users run this to provide bandwidth via the Lethean dVPN and earn LTHN. Includes chain node, wallet, WireGuard server, and a controller that manages gateway peering and status reporting. .env.example updated with exit node settings (public IP, name, max peers). Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
parent
1261d0d94e
commit
7af620e7f6
3 changed files with 285 additions and 0 deletions
|
|
@ -36,3 +36,17 @@ DAEMON_LOG_LEVEL=1
|
||||||
# POOL_API_PORT=2117
|
# POOL_API_PORT=2117
|
||||||
# LNS_HTTP_PORT=5553
|
# LNS_HTTP_PORT=5553
|
||||||
# LNS_DNS_PORT=5354
|
# LNS_DNS_PORT=5354
|
||||||
|
|
||||||
|
# === Exit Node Settings (docker-compose.exit.yml) ===
|
||||||
|
|
||||||
|
# Your public IP address (required for VPN exit node)
|
||||||
|
# EXIT_PUBLIC_IP=auto
|
||||||
|
|
||||||
|
# Exit node name (registered as on-chain alias)
|
||||||
|
# EXIT_NAME=my-exit-node
|
||||||
|
|
||||||
|
# Maximum VPN peers (WireGuard clients)
|
||||||
|
# EXIT_MAX_PEERS=25
|
||||||
|
|
||||||
|
# Timezone
|
||||||
|
# TZ=Europe/London
|
||||||
|
|
|
||||||
185
docker/docker-compose.exit.yml
Normal file
185
docker/docker-compose.exit.yml
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
# Lethean Exit Node
|
||||||
|
# Run a VPN exit node and earn LTHN by providing bandwidth to the network.
|
||||||
|
# Peers with Lethean gateways which route encrypted VPN traffic through your node.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# cp .env.example .env
|
||||||
|
# # Set WALLET_PASSWORD, EXIT_PUBLIC_IP, and EXIT_NAME
|
||||||
|
# docker compose -f docker-compose.exit.yml up -d
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# - Runs a full chain node (syncs blockchain)
|
||||||
|
# - Runs a wallet with PoS staking
|
||||||
|
# - Runs a WireGuard VPN server
|
||||||
|
# - Registers as an exit node on-chain via alias
|
||||||
|
# - Peers with gateway nodes for traffic routing
|
||||||
|
# - Earns LTHN for bandwidth provided
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# - Public IP address (or port forwarding on router)
|
||||||
|
# - Open ports: 46942 (P2P), 51820/udp (WireGuard)
|
||||||
|
# - Linux with Docker (WireGuard kernel module)
|
||||||
|
#
|
||||||
|
# Ports:
|
||||||
|
# 46942 — P2P (chain peering)
|
||||||
|
# 51820 — WireGuard VPN (UDP)
|
||||||
|
# 8124 — Exit node management API (local only)
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- Chain Node ---
|
||||||
|
daemon:
|
||||||
|
image: lthn/chain:testnet
|
||||||
|
container_name: lthn-exit-daemon
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${DAEMON_P2P_PORT:-46942}:36942"
|
||||||
|
volumes:
|
||||||
|
- chain-data:/data
|
||||||
|
entrypoint:
|
||||||
|
- lethean-chain-node
|
||||||
|
command:
|
||||||
|
- --data-dir
|
||||||
|
- /data
|
||||||
|
- --rpc-bind-ip
|
||||||
|
- "0.0.0.0"
|
||||||
|
- --rpc-bind-port
|
||||||
|
- "36941"
|
||||||
|
- --p2p-bind-port
|
||||||
|
- "36942"
|
||||||
|
- --rpc-enable-admin-api
|
||||||
|
- --allow-local-ip
|
||||||
|
- --log-level
|
||||||
|
- "${DAEMON_LOG_LEVEL:-1}"
|
||||||
|
- --disable-upnp
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -sf http://localhost:36941/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"getinfo\"}' -H 'Content-Type: application/json' | grep -q OK"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
networks:
|
||||||
|
exit-net:
|
||||||
|
|
||||||
|
# --- Wallet (PoS staking + payment receipt) ---
|
||||||
|
wallet:
|
||||||
|
image: lthn/chain:testnet
|
||||||
|
container_name: lthn-exit-wallet
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- wallet-data:/wallet
|
||||||
|
entrypoint:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
command:
|
||||||
|
- |
|
||||||
|
if [ ! -f /wallet/exit.wallet ]; then
|
||||||
|
echo '${WALLET_PASSWORD:-}' | lethean-wallet-cli --generate-new-wallet /wallet/exit.wallet --password '${WALLET_PASSWORD:-}' --daemon-address daemon:36941 --command exit;
|
||||||
|
fi;
|
||||||
|
lethean-wallet-cli \
|
||||||
|
--wallet-file /wallet/exit.wallet \
|
||||||
|
--password '${WALLET_PASSWORD:-}' \
|
||||||
|
--daemon-address daemon:36941 \
|
||||||
|
--rpc-bind-port 36944 \
|
||||||
|
--rpc-bind-ip 0.0.0.0 \
|
||||||
|
--do-pos-mining
|
||||||
|
depends_on:
|
||||||
|
daemon:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
exit-net:
|
||||||
|
|
||||||
|
# --- WireGuard VPN Exit ---
|
||||||
|
wireguard:
|
||||||
|
image: lscr.io/linuxserver/wireguard:latest
|
||||||
|
container_name: lthn-exit-wireguard
|
||||||
|
restart: unless-stopped
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- SYS_MODULE
|
||||||
|
environment:
|
||||||
|
PUID: 1000
|
||||||
|
PGID: 1000
|
||||||
|
TZ: ${TZ:-Europe/London}
|
||||||
|
SERVERURL: ${EXIT_PUBLIC_IP:-auto}
|
||||||
|
SERVERPORT: 51820
|
||||||
|
PEERS: ${EXIT_MAX_PEERS:-25}
|
||||||
|
PEERDNS: 1.1.1.1,1.0.0.1
|
||||||
|
INTERNAL_SUBNET: 10.13.13.0
|
||||||
|
ALLOWEDIPS: 0.0.0.0/0,::/0
|
||||||
|
LOG_CONFS: "false"
|
||||||
|
ports:
|
||||||
|
- "51820:51820/udp"
|
||||||
|
volumes:
|
||||||
|
- wireguard-config:/config
|
||||||
|
sysctls:
|
||||||
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
- net.ipv4.ip_forward=1
|
||||||
|
networks:
|
||||||
|
exit-net:
|
||||||
|
|
||||||
|
# --- Exit Node Controller ---
|
||||||
|
# Manages gateway peering, alias registration, and payment verification
|
||||||
|
controller:
|
||||||
|
image: lthn/chain:testnet
|
||||||
|
container_name: lthn-exit-controller
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- controller-data:/data
|
||||||
|
entrypoint:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
command:
|
||||||
|
- |
|
||||||
|
echo "Lethean Exit Node Controller"
|
||||||
|
echo "Waiting for daemon and wallet..."
|
||||||
|
|
||||||
|
# Wait for daemon
|
||||||
|
until curl -sf http://daemon:36941/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getinfo"}' -H 'Content-Type: application/json' > /dev/null 2>&1; do
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
echo "Daemon ready"
|
||||||
|
|
||||||
|
# Wait for wallet
|
||||||
|
until curl -sf http://wallet:36944/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getbalance"}' -H 'Content-Type: application/json' > /dev/null 2>&1; do
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
echo "Wallet ready"
|
||||||
|
|
||||||
|
# Get wallet address
|
||||||
|
ADDR=$$(curl -sf http://wallet:36944/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getaddress"}' -H 'Content-Type: application/json' | grep -oP '"address":"[^"]+' | cut -d'"' -f4)
|
||||||
|
echo "Exit node wallet: $$ADDR"
|
||||||
|
|
||||||
|
# Get chain height
|
||||||
|
HEIGHT=$$(curl -sf http://daemon:36941/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getinfo"}' -H 'Content-Type: application/json' | grep -oP '"height":[0-9]+' | cut -d: -f2)
|
||||||
|
echo "Chain height: $$HEIGHT"
|
||||||
|
|
||||||
|
# Register alias if EXIT_NAME is set and we have balance
|
||||||
|
if [ -n "${EXIT_NAME:-}" ]; then
|
||||||
|
echo "Exit node name: ${EXIT_NAME}"
|
||||||
|
echo "To register on-chain: send 1 LTHN to this wallet, then alias will auto-register"
|
||||||
|
echo "Alias comment: v=lthn1;type=exit;cap=vpn,proxy;ip=${EXIT_PUBLIC_IP:-auto}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Status loop
|
||||||
|
while true; do
|
||||||
|
BALANCE=$$(curl -sf http://wallet:36944/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getbalance"}' -H 'Content-Type: application/json' | grep -oP '"balance":[0-9]+' | cut -d: -f2)
|
||||||
|
HEIGHT=$$(curl -sf http://daemon:36941/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getinfo"}' -H 'Content-Type: application/json' | grep -oP '"height":[0-9]+' | cut -d: -f2)
|
||||||
|
WG_PEERS=$$(curl -sf http://wireguard:51820 2>/dev/null | wc -l || echo 0)
|
||||||
|
echo "$$(date +%H:%M:%S) height=$$HEIGHT balance=$$(echo "scale=4; $$BALANCE/1000000000000" | bc 2>/dev/null || echo $$BALANCE) peers=$$WG_PEERS"
|
||||||
|
sleep 60
|
||||||
|
done
|
||||||
|
depends_on:
|
||||||
|
daemon:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
exit-net:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
exit-net:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
chain-data:
|
||||||
|
wallet-data:
|
||||||
|
wireguard-config:
|
||||||
|
controller-data:
|
||||||
86
docker/docker-compose.node.yml
Normal file
86
docker/docker-compose.node.yml
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Lethean Home Node
|
||||||
|
# A self-contained chain node for home users who want to support the network.
|
||||||
|
# Syncs the chain, runs a wallet with PoS staking, and exposes P2P for peering.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# cp .env.example .env # edit WALLET_PASSWORD at minimum
|
||||||
|
# docker compose -f docker-compose.node.yml up -d
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# - Syncs and validates the Lethean blockchain
|
||||||
|
# - Peers with other nodes (P2P port 46942)
|
||||||
|
# - Runs a wallet that stakes automatically (PoS mining)
|
||||||
|
# - Optionally mines with ProgPoWZ (connect external GPU miner)
|
||||||
|
#
|
||||||
|
# Earnings:
|
||||||
|
# - PoS staking rewards (proportional to balance)
|
||||||
|
# - PoW block rewards if mining
|
||||||
|
#
|
||||||
|
# Ports:
|
||||||
|
# 46941 — Daemon RPC (local tools)
|
||||||
|
# 46942 — P2P (open this on your router for full node)
|
||||||
|
# 46944 — Wallet RPC (local tools)
|
||||||
|
|
||||||
|
services:
|
||||||
|
daemon:
|
||||||
|
image: lthn/chain:testnet
|
||||||
|
container_name: lthn-node
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${DAEMON_RPC_PORT:-46941}:36941"
|
||||||
|
- "${DAEMON_P2P_PORT:-46942}:36942"
|
||||||
|
volumes:
|
||||||
|
- chain-data:/data
|
||||||
|
entrypoint:
|
||||||
|
- lethean-chain-node
|
||||||
|
command:
|
||||||
|
- --data-dir
|
||||||
|
- /data
|
||||||
|
- --rpc-bind-ip
|
||||||
|
- "0.0.0.0"
|
||||||
|
- --rpc-bind-port
|
||||||
|
- "36941"
|
||||||
|
- --p2p-bind-port
|
||||||
|
- "36942"
|
||||||
|
- --rpc-enable-admin-api
|
||||||
|
- --allow-local-ip
|
||||||
|
- --log-level
|
||||||
|
- "${DAEMON_LOG_LEVEL:-1}"
|
||||||
|
- --disable-upnp
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -sf http://localhost:36941/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"getinfo\"}' -H 'Content-Type: application/json' | grep -q OK"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
|
||||||
|
wallet:
|
||||||
|
image: lthn/chain:testnet
|
||||||
|
container_name: lthn-wallet
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${WALLET_RPC_PORT:-46944}:36944"
|
||||||
|
volumes:
|
||||||
|
- wallet-data:/wallet
|
||||||
|
entrypoint:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
command:
|
||||||
|
- |
|
||||||
|
if [ ! -f /wallet/node.wallet ]; then
|
||||||
|
echo '${WALLET_PASSWORD:-}' | lethean-wallet-cli --generate-new-wallet /wallet/node.wallet --password '${WALLET_PASSWORD:-}' --daemon-address daemon:36941 --command exit;
|
||||||
|
fi;
|
||||||
|
lethean-wallet-cli \
|
||||||
|
--wallet-file /wallet/node.wallet \
|
||||||
|
--password '${WALLET_PASSWORD:-}' \
|
||||||
|
--daemon-address daemon:36941 \
|
||||||
|
--rpc-bind-port 36944 \
|
||||||
|
--rpc-bind-ip 0.0.0.0 \
|
||||||
|
--do-pos-mining
|
||||||
|
depends_on:
|
||||||
|
daemon:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
chain-data:
|
||||||
|
wallet-data:
|
||||||
Loading…
Add table
Reference in a new issue