Co-authored-by: Cursor <cursoragent@cursor.com>
8.3 KiB
Let's Encrypt Certificate for RPC-01 (VMID 2500)
Date: $(date)
Container: besu-rpc-1 (Core RPC Node)
VMID: 2500
IP: 192.168.11.250
⚠️ Important: Domain Requirements
Let's Encrypt requires a publicly accessible domain name. The current Nginx configuration uses .local domains which will not work with Let's Encrypt:
- ❌
rpc-core.besu.local- Not publicly accessible - ❌
rpc-core.chainid138.local- Not publicly accessible - ❌
rpc-core-ws.besu.local- Not publicly accessible
Required: A public domain that:
- Resolves to the server's IP (or is accessible via Cloudflare Tunnel)
- Is accessible from the internet (for HTTP-01 challenge)
- Or has DNS API access (for DNS-01 challenge)
🔧 Setup Options
Option 1: Use Public Domain (Recommended)
If you have a public domain (e.g., d-bis.org or similar):
-
Configure DNS:
- Create A record:
rpc-core.yourdomain.com→192.168.11.250 - Or use Cloudflare Tunnel (CNAME to tunnel)
- Create A record:
-
Update Nginx config to include public domain:
pct exec 2500 -- sed -i 's/server_name.*;/server_name rpc-core.yourdomain.com rpc-core.besu.local 192.168.11.250;/' /etc/nginx/sites-available/rpc-core -
Obtain certificate:
pct exec 2500 -- certbot --nginx -d rpc-core.yourdomain.com
Option 2: Use Cloudflare Tunnel (If Using Cloudflare)
If using Cloudflare Tunnel (VMID 102), you can:
- Use Cloudflare's SSL (handled by Cloudflare)
- Or use DNS-01 challenge with Cloudflare API:
pct exec 2500 -- certbot certonly --dns-cloudflare \ --dns-cloudflare-credentials /etc/cloudflare/credentials.ini \ -d rpc-core.yourdomain.com
Option 3: Keep Self-Signed (For Internal Use)
If this is internal-only and doesn't need public validation:
- ✅ Keep self-signed certificate
- ✅ Works for internal network
- ✅ No external dependencies
- ❌ Browser warnings (acceptable for internal use)
📋 Step-by-Step: Public Domain Setup
Prerequisites
- Public domain (e.g.,
yourdomain.com) - DNS access to create A record or CNAME
- Port 80 accessible from internet (for HTTP-01 challenge)
Step 1: Install Certbot
pct exec 2500 -- apt-get update
pct exec 2500 -- apt-get install -y certbot python3-certbot-nginx
Step 2: Configure DNS
Option A: Direct A Record
Type: A
Name: rpc-core
Target: 192.168.11.250
TTL: Auto
Option B: Cloudflare Tunnel (CNAME)
Type: CNAME
Name: rpc-core
Target: <tunnel-id>.cfargotunnel.com
Proxy: 🟠 Proxied
Step 3: Update Nginx Configuration
Add public domain to server_name:
pct exec 2500 -- sed -i 's/server_name.*rpc-core.besu.local.*;/server_name rpc-core.yourdomain.com rpc-core.besu.local 192.168.11.250;/' /etc/nginx/sites-available/rpc-core
Step 4: Obtain Certificate
For HTTP-01 challenge (requires port 80 accessible):
pct exec 2500 -- certbot --nginx \
--non-interactive \
--agree-tos \
--email admin@yourdomain.com \
-d rpc-core.yourdomain.com
For DNS-01 challenge (if HTTP-01 fails):
# Install DNS plugin
pct exec 2500 -- apt-get install -y python3-certbot-dns-cloudflare
# Create credentials file
pct exec 2500 -- bash -c 'cat > /etc/cloudflare/credentials.ini <<EOF
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
EOF
chmod 600 /etc/cloudflare/credentials.ini'
# Obtain certificate
pct exec 2500 -- certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/cloudflare/credentials.ini \
--non-interactive \
--agree-tos \
--email admin@yourdomain.com \
-d rpc-core.yourdomain.com
Step 5: Update Nginx to Use Certificate
Certbot should automatically update Nginx configuration. Verify:
pct exec 2500 -- cat /etc/nginx/sites-available/rpc-core | grep ssl_certificate
Should show:
ssl_certificate /etc/letsencrypt/live/rpc-core.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rpc-core.yourdomain.com/privkey.pem;
Step 6: Test Configuration
# Test Nginx config
pct exec 2500 -- nginx -t
# Reload Nginx
pct exec 2500 -- systemctl reload nginx
# Test HTTPS
curl -X POST https://rpc-core.yourdomain.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
Step 7: Verify Auto-Renewal
# Check certbot timer
pct exec 2500 -- systemctl status certbot.timer
# Test renewal
pct exec 2500 -- certbot renew --dry-run
🔄 Using the Automated Script
If you have a public domain, use the automated script:
cd /home/intlc/projects/proxmox
./scripts/setup-letsencrypt-rpc-2500.sh rpc-core.yourdomain.com
The script will:
- Install Certbot
- Verify domain accessibility
- Obtain certificate
- Update Nginx configuration
- Set up auto-renewal
- Test configuration
📋 DNS-01 Challenge Setup (Cloudflare)
If you need to use DNS-01 challenge:
1. Get Cloudflare API Token
- Go to Cloudflare Dashboard
- My Profile → API Tokens
- Create Token with:
- Zone: DNS:Edit
- Zone Resources: Include → Specific zone → yourdomain.com
2. Create Credentials File
pct exec 2500 -- bash -c 'cat > /etc/cloudflare/credentials.ini <<EOF
dns_cloudflare_api_token = YOUR_API_TOKEN_HERE
EOF
chmod 600 /etc/cloudflare/credentials.ini'
3. Install DNS Plugin
pct exec 2500 -- apt-get install -y python3-certbot-dns-cloudflare
4. Obtain Certificate
pct exec 2500 -- certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/cloudflare/credentials.ini \
--non-interactive \
--agree-tos \
--email admin@yourdomain.com \
-d rpc-core.yourdomain.com \
--preferred-challenges dns
5. Update Nginx Manually
Since DNS-01 doesn't auto-update Nginx:
pct exec 2500 -- sed -i 's|ssl_certificate /etc/nginx/ssl/rpc.crt;|ssl_certificate /etc/letsencrypt/live/rpc-core.yourdomain.com/fullchain.pem;|' /etc/nginx/sites-available/rpc-core
pct exec 2500 -- sed -i 's|ssl_certificate_key /etc/nginx/ssl/rpc.key;|ssl_certificate_key /etc/letsencrypt/live/rpc-core.yourdomain.com/privkey.pem;|' /etc/nginx/sites-available/rpc-core
pct exec 2500 -- nginx -t
pct exec 2500 -- systemctl reload nginx
🔍 Verification
Check Certificate
# List certificates
pct exec 2500 -- certbot certificates
# View certificate details
pct exec 2500 -- openssl x509 -in /etc/letsencrypt/live/rpc-core.yourdomain.com/fullchain.pem -noout -subject -issuer -dates
Test HTTPS
# Test from container
pct exec 2500 -- curl -X POST https://rpc-core.yourdomain.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Test from external
curl -X POST https://rpc-core.yourdomain.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
Check Auto-Renewal
# Check timer status
pct exec 2500 -- systemctl status certbot.timer
# Test renewal
pct exec 2500 -- certbot renew --dry-run
🐛 Troubleshooting
Domain Not Accessible
Error: Failed to obtain certificate
Solutions:
- Verify DNS:
dig rpc-core.yourdomain.com - Check port 80: Ensure accessible from internet
- Use DNS-01 challenge instead
Port 80 Not Accessible
Error: Connection refused or timeout
Solutions:
- Check firewall:
pct exec 2500 -- iptables -L -n - Check NAT/router configuration
- Use DNS-01 challenge instead
Certificate Already Exists
Error: Certificate already exists
Solutions:
# Force renewal
pct exec 2500 -- certbot --nginx --force-renewal -d rpc-core.yourdomain.com
# Or delete and recreate
pct exec 2500 -- certbot delete --cert-name rpc-core.yourdomain.com
pct exec 2500 -- certbot --nginx -d rpc-core.yourdomain.com
📚 Related Documentation
Note: For internal-only use, the self-signed certificate is sufficient and doesn't require external dependencies.
Last Updated: $(date)