Files
ethereum-rpc-docker/README.md
rob dd8ce689e4 Add VIBE.md debugging guide and update README.md
- Add VIBE.md as primary debugging reference for automated tools
- Rewrite README.md as human-focused operator guide
- Fix README.md inaccuracies (remove show-networks.sh references, fix typo)
- Split content: README for humans, VIBE for agents

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-22 08:37:38 +00:00

848 lines
21 KiB
Markdown

# ethereum-rpc-docker — Blockchain RPC Node Configurations
**ethereum-rpc-docker** provides production-ready Docker Compose configurations for running
blockchain RPC nodes. Whether you're running a single Ethereum node or a fleet of L2s,
this repository has everything you need to get started quickly.
For **debugging and troubleshooting**, see [VIBE.md](VIBE.md) — the automated operations guide.
---
## 1. What This Repository Is
This is a collection of Docker Compose files and supporting scripts for operating blockchain
RPC nodes. Each compose file defines a complete node configuration including:
- **Client** (execution layer): Geth, Erigon, Reth, Nethermind, Besu, etc.
- **Node** (consensus layer): op-node, lighthouse, prysm, nitro, etc.
- **Relay** (data availability): eigenda-proxy, op-alt, celestia, etc.
- **Proxy** (access layer): nginx for HTTP/WS unification
- **Monitoring**: Prometheus metrics, Grafana dashboards
You can run a single node or combine multiple compose files to create a full fleet.
---
## 2. Quick Start
### Prerequisites
- Docker and Docker Compose installed
- Docker daemon running
- Public IP address (for P2P connectivity)
- At least 500GB free disk for Ethereum mainnet pruned nodes
### Step 1: Create Your Environment File
Create a `.env` file in this directory. Here's a complete example:
```bash
# === REQUIRED: Network Settings ===
# Your public IP address (required for P2P on most chains)
IP=203.0.113.42
# Docker internal subnet for chain containers
CHAINS_SUBNET=192.168.0.0/26
# === REQUIRED: SSL Settings ===
# Domain for Traefik SSL certificates (use traefik.me for testing)
DOMAIN=203-0-113-42.traefik.me
# Email for Let's Encrypt notifications
MAIL=your-email@example.com
# IP whitelist (CIDR notation, 0.0.0.0/0 allows all)
WHITELIST=0.0.0.0/0
# === OPTIONAL: SSL ===
# Disable SSL for local testing (remove for production)
# NO_SSL=true
# === OPTIONAL: Fallback RPC Endpoints ===
# These are used by nodes for initial sync and as fallbacks
ETHEREUM_MAINNET_EXECUTION_RPC=https://ethereum-rpc.publicnode.com
ETHEREUM_MAINNET_EXECUTION_WS=wss://ethereum-rpc.publicnode.com
ETHEREUM_MAINNET_BEACON_REST=https://ethereum-beacon-api.publicnode.com
ETHEREUM_SEPOLIA_EXECUTION_RPC=https://ethereum-sepolia-rpc.publicnode.com
ETHEREUM_SEPOLIA_EXECUTION_WS=wss://ethereum-sepolia-rpc.publicnode.com
ARBITRUM_SEPOLIA_EXECUTION_RPC=https://arbitrum-sepolia-rpc.publicnode.com
```
**To get your public IP:**
```bash
curl ipinfo.io/ip
```
**For traefik.me domain:** Replace dots with hyphens in your IP:
```bash
IP=203.0.113.42
DOMAIN=203-0-113-42.traefik.me
```
### Step 2: Select Which Nodes to Run
Add compose files to the `COMPOSE_FILE` variable in your `.env`. Always include
`base.yml` and `rpc.yml` first, then add your node configurations:
```bash
# Example: Run Ethereum mainnet with Geth (pruned)
COMPOSE_FILE=base.yml:rpc.yml:ethereum-mainnet-geth-pruned.yml
# Example: Run multiple nodes
COMPOSE_FILE=base.yml:rpc.yml:ethereum-mainnet-geth-pruned.yml:arbitrum-one.yml:optimism-mainnet.yml
# Example: Include monitoring
COMPOSE_FILE=base.yml:rpc.yml:monitoring.yml:ethereum-mainnet-geth-pruned.yml
```
### Step 3: Start Your Nodes
```bash
# Start all configured nodes
docker compose up -d
# Check status of all nodes
./show-status.sh
# View logs for a specific node
./logs.sh ethereum-mainnet-geth-pruned
```
### Step 4: Access Your RPC Endpoints
Once your nodes are running, access them at:
```
# HTTPS (via Traefik)
https://<your-domain>/ethereum-mainnet-geth-pruned
# HTTP (if NO_SSL=true)
http://<your-domain>/ethereum-mainnet-geth-pruned
# WebSocket
wss://<your-domain>/ethereum-mainnet-geth-pruned
```
---
## 3. Configuration Guide
### Environment Variables Reference
#### Required Variables
| Variable | Description | Example |
|---|---|---|
| `IP` | Your public IP address | `203.0.113.42` |
| `DOMAIN` | Your domain for SSL | `203-0-113-42.traefik.me` |
| `MAIL` | Email for Let's Encrypt | `admin@example.com` |
| `COMPOSE_FILE` | Which compose files to load | `base.yml:rpc.yml:ethereum-mainnet.yml` |
#### Optional Variables
| Variable | Description | Default |
|---|---|---|
| `WHITELIST` | IP whitelist (CIDR) | `0.0.0.0/0` (all) |
| `CHAINS_SUBNET` | Docker network subnet | `192.168.0.0/26` |
| `NO_SSL` | Disable SSL | Not set (SSL enabled) |
#### Chain-Specific Variables
These are automatically used by nodes that support them:
| Variable | Description |
|---|---|
| `ETHEREUM_*_EXECUTION_RPC` | Fallback JSON-RPC endpoint |
| `ETHEREUM_*_EXECUTION_WS` | Fallback WebSocket endpoint |
| `ETHEREUM_*_BEACON_REST` | Fallback Beacon API endpoint |
| `OP_NODE_NETWORK` | OP Stack network identifier |
| `OP_NODE_L1_RPC_URL` | L1 RPC endpoint for OP Stack |
### Static Compose Files
These files provide infrastructure and should always be included:
| File | Purpose | Required? |
|---|---|---|
| `base.yml` | Base Docker networking | ✅ Yes |
| `rpc.yml` | RPC gateway configuration | ✅ Yes |
| `monitoring.yml` | Prometheus + Grafana stack | ❌ No |
| `prometheus.yml` | Prometheus configuration | ❌ No |
| `nodeexporter.yml` | Node metrics exporter | ❌ No |
| `cadvisor.yml` | Container metrics | ❌ No |
| `drpc.yml` | DRPC gateway | ❌ No |
| `drpc-free.yml` | DRPC free tier | ❌ No |
| `backup-http.yml` | Backup HTTP server | ❌ No |
| `logging-proxy.yml` | Logging infrastructure | ❌ No |
| `portainer.yml` | Portainer UI | ❌ No |
| `benchmark-proxy.yml` | Latency testing | ❌ No |
---
## 4. Available Networks
### Layer 1 Networks
#### Major Networks
- **Ethereum**: Mainnet, Sepolia, Holesky
- **BSC** (Binance Smart Chain): Mainnet
- **Polygon**: Mainnet, Amoy
- **Avalanche**: C-Chain Mainnet
- **Gnosis**: Mainnet, Chiado
#### Alternative L1s
- **Fantom**: Mainnet, Testnet
- **Core**: Mainnet
- **Berachain**: Mainnet, Testnet
- **Ronin**: Mainnet
- **Viction**: Mainnet
- **Fuse**: Mainnet
- **Tron**: Mainnet
- **ThunderCore**: Mainnet
#### Emerging L1s
- **Goat**: Mainnet, Testnet
- **AlephZero**: Mainnet
- **Haqq**: Mainnet, Testnet
- **Taiko**: Mainnet
- **Rootstock**: Mainnet
### Layer 2 Networks
#### OP Stack
- Optimism: Mainnet, Sepolia
- Base: Mainnet, Sepolia
- Zora: Mainnet
- Mode: Mainnet
- Blast: Mainnet
- Fraxtal: Mainnet
- Bob: Mainnet
- Boba: Mainnet, Testnet
- Worldchain: Mainnet
- Metal: Mainnet
- Ink: Mainnet
- Lisk: Mainnet, Sepolia
- SNAX: Mainnet
- Celo: Mainnet
#### Arbitrum Ecosystem
- Arbitrum One: Mainnet
- Arbitrum Nova: Mainnet
- Everclear: Mainnet
- Playblock: Mainnet
- Real: Mainnet
- Connext: Mainnet
- OpenCampusCodex: Mainnet
#### Other L2s
- Linea: Mainnet
- Scroll: Mainnet, Sepolia
- zkSync Era: Mainnet
- Metis: Mainnet
- Moonbeam: Mainnet
- Starknet: Mainnet
- zkEVM: Mainnet
- Immutable zkEVM: Mainnet
- Polygon zkEVM: Mainnet
### Node Types Available
For most networks, you can choose from:
| Sync Mode | Database | Client | Use Case |
|---|---|---|---|
| Pruned | Various | Geth, Erigon, Reth | Standard production |
| Archive | Various | Geth, Erigon, Reth | Full history, analytics |
| Archive-Trace | Various | Reth, Erigon | Full history + transaction tracing |
---
## 5. Accessing Your Nodes
### URL Patterns
Each node is accessible via Traefik reverse proxy at:
```
https://<your-domain>/<config-name>
```
Where `<config-name>` is the compose filename without `.yml`, e.g.:
- `ethereum-mainnet-geth-pruned`
- `op-base-sepolia-op-reth-pruned-trace`
- `arbitrum-one-arbnode-archive`
### Ports
| Service | Port | Protocol | Notes |
|---|---|---|---|
| Traefik HTTP | 80 | TCP | Redirects to HTTPS |
| Traefik HTTPS | 443 | TCP | SSL termination |
| Docker internal | Various | TCP/UDP | P2P and internal communications |
**Note:** P2P ports are randomized to avoid conflicts. Check your compose file
for specific port mappings.
### Local Access (Without SSL)
For local development/testing, set `NO_SSL=true` in your `.env`:
```bash
# Access locally without SSL
echo "NO_SSL=true" >> .env
docker compose up -d
# Then access at:
http://localhost:<port>
```
Find the port in your compose file or use:
```bash
./get-local-url.sh <config-name>
```
---
## 6. Resource Requirements
### Hardware Recommendations
| Node Type | Disk | RAM | CPU | Notes |
|---|---|---|---|---|
| Ethereum Pruned | 500GB - 1TB | 8GB | 2+ cores | Standard production |
| Ethereum Archive | 2TB - 4TB | 16GB+ | 4+ cores | Full history |
| Ethereum Archive-Trace | 4TB - 8TB | 32GB+ | 8+ cores | Full + tracing |
| BSC Pruned | 500GB - 800GB | 8GB | 2+ cores | |
| BSC Archive | 2TB - 3TB | 16GB | 4+ cores | |
| Polygon Pruned | 300GB - 500GB | 8GB | 2+ cores | |
| Polygon Archive | 1TB - 2TB | 16GB | 4+ cores | |
| L2 Pruned (OP Stack) | 100GB - 300GB | 4-8GB | 2+ cores | Base, Optimism, etc. |
| L2 Archive (OP Stack) | 500GB - 1TB | 8-16GB | 4+ cores | |
| L2 Pruned (Arbitrum) | 200GB - 500GB | 4-8GB | 2+ cores | |
| L2 Archive (Arbitrum) | 1TB - 2TB | 8-16GB | 4+ cores | |
### Storage Recommendations
- **Use SSD or NVMe**: HDDs are too slow for blockchain nodes
- **Separate volumes**: Consider separating chain data from OS
- **Monitor usage**: Use `./show-db-size.sh` to track growth
- **Plan for growth**: Archive nodes grow ~1-2GB/day for Ethereum
### Performance Tips
- **CPU**: More cores = faster sync, but diminishing returns after 8 cores
- **RAM**: Archive nodes need sufficient RAM for state
- **Disk I/O**: NVMe > SSD > HDD. RAID 0 can help for multiple nodes
- **Network**: 1Gbps+ recommended for multiple nodes
---
## 7. SSL Certificates and Domain Setup
### Traefik.me (Testing/Development)
For quick testing, use the free traefik.me service:
```bash
# Get your IP
IP=$(curl -s ipinfo.io/ip)
# Create domain by replacing dots with hyphens
DOMAIN=$(echo $IP | tr . -).traefik.me
# Add to .env
echo "DOMAIN=$DOMAIN" >> .env
echo "MAIL=your-email@example.com" >> .env
```
Traefik.me automatically provides valid SSL certificates. No additional setup needed.
### Let's Encrypt (Production)
For production, use your own domain with Let's Encrypt:
```bash
# Set your domain
DOMAIN=yourdomain.com
# Set your email for notifications
MAIL=admin@yourdomain.com
# Add to .env
echo "DOMAIN=$DOMAIN" >> .env
echo "MAIL=$MAIL" >> .env
```
Traefik will automatically obtain and renew certificates from Let's Encrypt.
### Disabling SSL
For local development, you can disable SSL:
```bash
# In .env
echo "NO_SSL=true" >> .env
# Then restart
docker compose up -d
```
---
## 8. DRPC Integration — Monetize Your RPC
[DRPC](https://drpc.org/) allows you to sell excess RPC capacity and earn revenue.
### Quick Setup
1. **Enable DRPC in your `.env`:**
```bash
# Add to .env
GW_DOMAIN=your-gateway-domain.com
GW_REDIS_RAM=2gb
DRPC_VERSION=0.64.16
```
2. **Add DRPC to COMPOSE_FILE:**
```bash
COMPOSE_FILE=base.yml:rpc.yml:drpc.yml:ethereum-mainnet-geth-pruned.yml
```
3. **Generate upstreams configuration:**
```bash
./upstreams.sh
```
The `upstreams.sh` script automatically detects all running nodes on your machine and
generates the configuration for the dshackle load balancer.
### Configuration Options
| Variable | Description | Default |
|---|---|---|
| `GW_DOMAIN` | Your gateway domain | Required |
| `GW_REDIS_RAM` | Redis memory limit | `2gb` |
| `DRPC_VERSION` | DRPC version to use | Latest |
### Multi-Server Setup
For running DRPC across multiple servers:
1. On each server, run nodes with DRPC enabled
2. On your gateway server, run `./upstreams.sh` to generate combined config
3. Deploy the dshackle configuration to your gateway
For more information, visit [drpc.org](https://drpc.org/).
---
## 9. Backup and Restore System
### Why Backups Matter
- **Database corruption**: Power loss or bugs can corrupt your chain data
- **Quick recovery**: Restore from backup instead of re-syncing from scratch
- **Migration**: Move nodes between servers efficiently
- **Cloning**: Create identical nodes for redundancy
### Local Backups
```bash
# Create a backup of a node
./backup-node.sh ethereum-mainnet-geth-pruned
# Backup is stored in /backup directory
# List available backups
./list-backups.sh
# Restore from latest backup
./restore-volumes.sh ethereum-mainnet-geth-pruned
```
### Remote Backups (WebDAV)
For multi-server setups, use WebDAV for remote backups:
```bash
# Backup to remote WebDAV
./backup-node.sh ethereum-mainnet https://backup-server.tld/dav
# Restore from remote WebDAV
./restore-volumes.sh ethereum-mainnet https://backup-server.tld/backup/
```
### HTTP Backup Server
Expose your backups via HTTP for easy access:
```bash
# Add to COMPOSE_FILE
COMPOSE_FILE=base.yml:rpc.yml:backup-http.yml:ethereum-mainnet.yml
# Access backups at:
# - HTTP: https://yourdomain.tld/backup
# - WebDAV: https://yourdomain.tld/dav
```
### Cross-Server Transfers
Transfer node data between servers without SSH:
```bash
# On Server A (source):
./backup-node.sh ethereum-mainnet https://server-a.domain.tld/dav
# On Server B (destination):
./restore-volumes.sh ethereum-mainnet https://server-a.domain.tld/backup/
```
### Cloning Nodes
Clone a running node to create a replica:
```bash
# Clone node state
./clone-node.sh ethereum-mainnet-geth-pruned
# Clone peer connections (faster sync)
./clone-peers.sh ethereum-mainnet-geth-pruned
```
---
## 10. Security and Network Configuration
### Firewall Configuration
Many chains require specific ports for P2P discovery. Docker will bind to these
ports on all interfaces (0.0.0.0).
**Critical:** You must configure your firewall to:
1. Allow inbound connections to P2P ports (UDP/TCP)
2. Allow outbound connections from containers
3. Block containers from reaching local networks (security)
### iptables Rules
Here's a systemd service and script for managing Docker firewall rules:
**`/etc/systemd/system/iptables-firewall.service`:**
```ini
[Unit]
Description= iptables firewall docker fix
After=docker.service
[Service]
ExecStart=/usr/local/bin/iptables-firewall.sh start
RemainAfterExit=true
StandardOutput=journal
[Install]
WantedBy=multi-user.target
```
**`/usr/local/bin/iptables-firewall.sh`:**
```bash
#!/bin/bash
PATH="/sbin:/usr/sbin:/bin:/usr/bin"
# Flush existing rules
iptables -F DOCKER-USER
# Block local networks from containers
# (prevents containers from reaching your LAN)
iptables -I DOCKER-USER -s {{ chains_subnet }} -d 192.168.0.0/16 -j REJECT
iptables -I DOCKER-USER -s {{ chains_subnet }} -d 172.16.0.0/12 -j REJECT
iptables -I DOCKER-USER -s {{ chains_subnet }} -d 10.0.0.0/8 -j REJECT
# Allow containers to reach each other
iptables -I DOCKER-USER -s {{ chains_subnet }} -d {{ chains_subnet }} -j ACCEPT
# Allow specific external networks if needed
iptables -I DOCKER-USER -s {{ chains_subnet }} -d 10.13.13.0/24 -j ACCEPT
```
Replace `{{ chains_subnet }}` with your `CHAINS_SUBNET` value (default: `192.168.0.0/26`).
### IP Whitelist
Control which IPs can access your RPC endpoints:
```bash
# In .env - allow all
WHITELIST=0.0.0.0/0
# Allow specific IPs
WHITELIST=192.0.2.0/24,203.0.113.0/24
# Update whitelist without restart
./update-whitelist.sh
```
---
## 11. Daily Operations
### Starting and Stopping Nodes
```bash
# Start a specific node
./start.sh ethereum-mainnet-geth-pruned
# Stop a specific node
./stop.sh ethereum-mainnet-geth-pruned
# Restart a node (keeps volumes)
./force-recreate.sh ethereum-mainnet-geth-pruned
```
### Monitoring Node Health
```bash
# Check all nodes
./show-status.sh
# Check specific node
./sync-status.sh ethereum-mainnet-geth-pruned
# Get latest block
./latest.sh ethereum-mainnet-geth-pruned
# Check disk usage
./show-db-size.sh
# Check memory usage
./show-ram.sh ethereum-mainnet-geth-pruned
```
### Viewing Logs
```bash
# View logs for a node
./logs.sh ethereum-mainnet-geth-pruned
# View logs with follow
./logs.sh ethereum-mainnet-geth-pruned -f
# View all container logs
docker compose logs -f
```
### Checking Peers
```bash
# Check peer count for all nodes
./peer-count.sh
# Check specific node peers
./peer-count.sh | grep ethereum-mainnet
```
---
## 12. Node Structure and Naming
### Understanding Node Components
A typical node consists of one or more of these components:
| Component | Purpose | Example Implementations |
|---|---|---|
| **Client** | Execution layer (handles transactions) | Geth, Erigon, Reth, Nethermind, Besu |
| **Node** | Consensus/derivation layer | op-node, lighthouse, prysm, nitro, beacon-kit |
| **Relay** | Data availability | eigenda-proxy, op-alt, celestia |
| **Proxy** | HTTP/WS unification | nginx |
| **Database** | External database | Postgres |
### Naming Conventions
**Config names** (compose filenames) follow this pattern:
```
{network}-{chain}-{client}-{syncmode}-{dbtype}.yml
```
Examples:
- `ethereum-mainnet-geth-pruned.yml` — Ethereum mainnet, Geth client, pruned
- `op-base-sepolia-op-reth-archive-trace.yml` — Base sepolia, op-reth, archive with tracing
- `arb-arbitrum-one-arbnode-archive.yml` — Arbitrum One, arbnode, archive
**Short names** (used in URLs and container labels):
```
{network}-{chain}[-{client}][-{syncmode}][-{dbtype}]
```
**Volume names**:
```
<config-name>_<service>_<type>
```
Example: `ethereum-mainnet-geth-pruned_client_data`
### Defaults
- **Default client**: geth (Ethereum), op-geth (OP Stack), arbnode (Arbitrum)
- **Default sync mode**: pruned
- **Default database**: Depends on client (leveldb, pebble, etc.)
- **Default node**: op-node (OP Stack), prysm (Ethereum beacon), etc.
---
## 13. Syncing and Initial Setup
### Sync Modes
| Mode | Description | Speed | Storage |
|---|---|---|---|
| **Snap Sync** | Download recent state, verify | Fast | Medium |
| **Fast Sync** | Download blocks, verify headers | Medium | Medium |
| **Full Sync** | Verify all blocks from genesis | Slow | Full |
| **Archive** | Full sync + keep all state | Slowest | Largest |
Most nodes use **snap sync** or **fast sync** by default for pruned nodes.
### Using Checkpoints
Some nodes support checkpoint sync for faster startup:
```bash
# Check if checkpoint is configured
grep checkpoint <config-file>.yml
```
Checkpoints are typically provided by trusted community members or node operators.
### Snapshots
For even faster sync, some nodes support snapshot downloads:
```bash
# Check snapshot configuration
grep snapshot <config-file>.yml
```
Snapshots are large files containing the entire chain state at a point in time.
### Initial Sync Time
| Network | Pruned | Archive |
|---|---|---|
| Ethereum Mainnet | 1-3 days | 1-2 weeks |
| BSC Mainnet | 1-2 days | 3-5 days |
| Polygon Mainnet | 6-12 hours | 1-2 days |
| L2 Networks | Minutes - hours | Hours - 1 day |
Times vary based on hardware, network connection, and chain state.
---
## 14. Common Issues and Solutions
### Container Won't Start
**Symptom:** Container exits immediately or fails to start.
**Check:**
```bash
./logs.sh <config-name>
docker ps -a | grep <config-name>
```
**Common fixes:**
- Check `.env` file has all required variables
- Validate compose syntax: `docker compose -f <file>.yml config`
- Ensure ports aren't conflicting
- Pull images: `docker compose pull`
### Not Syncing / Stuck
**Symptom:** Node shows 0 peers or stuck at low block.
**Check:**
```bash
./sync-status.sh <config-name>
./peer-count.sh | grep <config-name>
./logs.sh <config-name> | grep -i error
```
**Common fixes:**
- Set `IP=` in `.env` (required for P2P)
- Check firewall allows P2P ports
- Verify checkpoint/snapshot URLs are reachable
- Restart with fresh volumes
### RPC Endpoint Not Accessible
**Symptom:** Can't connect to RPC endpoint.
**Check:**
```bash
./show-status.sh
curl http://localhost:<port>
docker ps | grep traefik
```
**Common fixes:**
- Check Traefik is running
- Verify DOMAIN is set correctly
- Check SSL configuration
- Test with NO_SSL=true for debugging
### High Resource Usage
**Symptom:** Node using too much CPU, memory, or disk.
**Check:**
```bash
./show-ram.sh <config-name>
./show-db-size.sh
./show-cpu.sh
```
**Common fixes:**
- Reduce max peers
- Upgrade hardware
- Switch to pruned mode
- Limit specific resources in compose file
### For More Debugging
For detailed debugging workflows, error patterns, and advanced troubleshooting,
see [VIBE.md](VIBE.md).
---
## 15. Utility Scripts Overview
This repository includes many scripts for managing your nodes. For the complete
debugging reference, see [VIBE.md](VIBE.md).
### Most Useful for Daily Operations
| Script | What It Does |
|---|---|
| `show-status.sh` | Show health of all running nodes |
| `show-running.sh` | List running containers |
| `logs.sh <name>` | View node logs |
| `sync-status.sh <name>` | Check sync progress |
| `latest.sh <name>` | Get latest block |
| `stop.sh <name>` | Stop a node |
| `start.sh <name>` | Start a node |
| `force-recreate.sh <name>` | Restart a node |
| `backup-node.sh <name>` | Create backup |
| `restore-volumes.sh <name>` | Restore from backup |
---
## 16. Learning More
- **[VIBE.md](VIBE.md)** — Complete debugging and operations guide for automated tools
- **[DRPC Documentation](https://drpc.org/)** — For monetization setup
- **[Traefik Documentation](https://doc.traefik.io/traefik/)** — For SSL and reverse proxy
- **[Docker Compose Documentation](https://docs.docker.com/compose/)** — For compose file reference
---
*For debugging and troubleshooting, see [VIBE.md](VIBE.md).*
*For the complete script reference and advanced operations, see [VIBE.md](VIBE.md).*