feat(ssl): move certificate generation to runtime with persistent volume
Self-signed SSL certificates are now generated at first startup instead of being baked into the Docker image. Certificates persist in ./certs/ and are reused on subsequent runs. Users can provide their own certs
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
# SSL certificates (auto-generated or user-provided)
|
||||||
|
/certs/
|
||||||
|
|
||||||
# ElectrumX server data
|
# ElectrumX server data
|
||||||
/electrumx-data/
|
/electrumx-data/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM lukechilds/electrumx
|
FROM lukechilds/electrumx
|
||||||
|
|
||||||
# Install curl (needed by entrypoint for RPC calls and IP detection)
|
# Install curl (needed by entrypoint for RPC calls and IP detection)
|
||||||
RUN apk add --no-cache curl || apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
RUN apk add --no-cache curl openssl || apt-get update && apt-get install -y --no-install-recommends curl openssl && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy Palladium coin definition and patch ElectrumX
|
# Copy Palladium coin definition and patch ElectrumX
|
||||||
COPY electrumx-patch/coins_plm.py /tmp/coins_plm.py
|
COPY electrumx-patch/coins_plm.py /tmp/coins_plm.py
|
||||||
@@ -28,34 +28,6 @@ for target in [
|
|||||||
print('>> Patched ElectrumX with Palladium coin classes')
|
print('>> Patched ElectrumX with Palladium coin classes')
|
||||||
PATCH
|
PATCH
|
||||||
|
|
||||||
RUN mkdir -p /certs && \
|
|
||||||
cat >/certs/openssl.cnf <<'EOF' && \
|
|
||||||
openssl req -x509 -nodes -newkey rsa:4096 -days 3650 \
|
|
||||||
-keyout /certs/server.key -out /certs/server.crt \
|
|
||||||
-config /certs/openssl.cnf && \
|
|
||||||
chmod 600 /certs/server.key && chmod 644 /certs/server.crt
|
|
||||||
[req]
|
|
||||||
distinguished_name = dn
|
|
||||||
x509_extensions = v3_req
|
|
||||||
prompt = no
|
|
||||||
|
|
||||||
[dn]
|
|
||||||
C = IT
|
|
||||||
ST = -
|
|
||||||
L = -
|
|
||||||
O = ElectrumX
|
|
||||||
CN = plm.local
|
|
||||||
|
|
||||||
[v3_req]
|
|
||||||
keyUsage = keyEncipherment, dataEncipherment, digitalSignature
|
|
||||||
extendedKeyUsage = serverAuth
|
|
||||||
subjectAltName = @alt_names
|
|
||||||
|
|
||||||
[alt_names]
|
|
||||||
DNS.1 = plm.local
|
|
||||||
IP.1 = 127.0.0.1
|
|
||||||
EOF
|
|
||||||
|
|
||||||
ENV SSL_CERTFILE=/certs/server.crt
|
ENV SSL_CERTFILE=/certs/server.crt
|
||||||
ENV SSL_KEYFILE=/certs/server.key
|
ENV SSL_KEYFILE=/certs/server.key
|
||||||
|
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -46,6 +46,9 @@ palladium-stack/
|
|||||||
│ ├── blocks/ # Blockchain blocks (auto-generated)
|
│ ├── blocks/ # Blockchain blocks (auto-generated)
|
||||||
│ ├── chainstate/ # Blockchain state (auto-generated)
|
│ ├── chainstate/ # Blockchain state (auto-generated)
|
||||||
│ └── ... # Other runtime data (auto-generated)
|
│ └── ... # Other runtime data (auto-generated)
|
||||||
|
├── certs/ # SSL certificates (auto-generated on first run)
|
||||||
|
│ ├── server.crt # Self-signed certificate
|
||||||
|
│ └── server.key # Private key
|
||||||
├── electrumx-data/ # ElectrumX database (auto-generated)
|
├── electrumx-data/ # ElectrumX database (auto-generated)
|
||||||
├── web-dashboard/ # Web monitoring dashboard
|
├── web-dashboard/ # Web monitoring dashboard
|
||||||
│ ├── app.py # Flask backend API
|
│ ├── app.py # Flask backend API
|
||||||
@@ -271,7 +274,7 @@ docker compose up -d
|
|||||||
**What happens:**
|
**What happens:**
|
||||||
1. Builds three Docker images: `palladium-node`, `electrumx-server`, and `palladium-dashboard`
|
1. Builds three Docker images: `palladium-node`, `electrumx-server`, and `palladium-dashboard`
|
||||||
2. Starts Palladium node first
|
2. Starts Palladium node first
|
||||||
3. Starts ElectrumX (waits for node to be ready)
|
3. Starts ElectrumX (waits for node to be ready, auto-generates SSL certificates in `./certs/` if not present)
|
||||||
4. Starts Web Dashboard (connects to both services)
|
4. Starts Web Dashboard (connects to both services)
|
||||||
|
|
||||||
**First build takes 5-10 minutes.**
|
**First build takes 5-10 minutes.**
|
||||||
@@ -455,8 +458,6 @@ Key settings in `.palladium/palladium.conf`:
|
|||||||
| `port=2333` | Default | P2P network port (mainnet) |
|
| `port=2333` | Default | P2P network port (mainnet) |
|
||||||
| `rpcport=2332` | Default | RPC port (mainnet) |
|
| `rpcport=2332` | Default | RPC port (mainnet) |
|
||||||
|
|
||||||
**Important:** current `docker-compose.yml` starts `palladiumd` with command-line `-rpcallowip=0.0.0.0/0`, which overrides `rpcallowip` values in `palladium.conf`. Keep this in mind for security hardening.
|
|
||||||
|
|
||||||
**ZeroMQ Ports (optional):**
|
**ZeroMQ Ports (optional):**
|
||||||
- `28332` - Block hash notifications
|
- `28332` - Block hash notifications
|
||||||
- `28333` - Transaction hash notifications
|
- `28333` - Transaction hash notifications
|
||||||
@@ -680,8 +681,9 @@ docker compose build --no-cache
|
|||||||
```
|
```
|
||||||
|
|
||||||
3. **SSL Certificates:**
|
3. **SSL Certificates:**
|
||||||
- Default uses self-signed certificates
|
- Self-signed certificates are auto-generated on first startup in `./certs/`
|
||||||
- For production, use valid SSL certificates (Let's Encrypt)
|
- The certificate includes localhost and the auto-detected public IP in its SAN
|
||||||
|
- To use your own certificates (e.g. Let's Encrypt), place `server.crt` and `server.key` in `./certs/` before starting
|
||||||
|
|
||||||
4. **Dashboard Access:**
|
4. **Dashboard Access:**
|
||||||
- Consider adding authentication
|
- Consider adding authentication
|
||||||
@@ -744,7 +746,7 @@ environment:
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
* **Data Persistence:** All data stored in `./.palladium/` and `./electrumx-data/`
|
* **Data Persistence:** All data stored in `./.palladium/`, `./electrumx-data/`, and `./certs/`
|
||||||
* **Backup:** Regularly backup `.palladium/wallet.dat` if you store funds
|
* **Backup:** Regularly backup `.palladium/wallet.dat` if you store funds
|
||||||
* **Network Switch:** Always clear ElectrumX database when switching networks
|
* **Network Switch:** Always clear ElectrumX database when switching networks
|
||||||
* **Updates:** Check for Palladium Core updates regularly
|
* **Updates:** Check for Palladium Core updates regularly
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./electrumx-data:/data
|
- ./electrumx-data:/data
|
||||||
- ./.palladium/palladium.conf:/palladium-config/palladium.conf:ro
|
- ./.palladium/palladium.conf:/palladium-config/palladium.conf:ro
|
||||||
|
- ./certs:/certs
|
||||||
|
|
||||||
dashboard:
|
dashboard:
|
||||||
build:
|
build:
|
||||||
|
|||||||
@@ -70,6 +70,61 @@ echo "DAEMON_URL: http://${RPC_USER}:***@palladiumd:${RPC_PORT}/"
|
|||||||
echo "REPORT_SERVICES: ${REPORT_SERVICES:-not set}"
|
echo "REPORT_SERVICES: ${REPORT_SERVICES:-not set}"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
|
|
||||||
|
# ── SSL certificate generation (skip if certs already exist) ──
|
||||||
|
if [ ! -f /certs/server.crt ] || [ ! -f /certs/server.key ]; then
|
||||||
|
echo "SSL certificates not found, generating self-signed certificate..."
|
||||||
|
|
||||||
|
# Collect SAN entries
|
||||||
|
SAN="DNS.1 = localhost"
|
||||||
|
SAN_IDX=1
|
||||||
|
IP_IDX=1
|
||||||
|
SAN="${SAN}\nIP.${IP_IDX} = 127.0.0.1"
|
||||||
|
|
||||||
|
# Try to detect public IP for SAN
|
||||||
|
for url in https://icanhazip.com https://ifconfig.me https://api.ipify.org; do
|
||||||
|
DETECTED_IP=$(curl -sf --max-time 5 "$url" 2>/dev/null | tr -d '[:space:]')
|
||||||
|
if [ -n "$DETECTED_IP" ]; then
|
||||||
|
IP_IDX=$((IP_IDX + 1))
|
||||||
|
SAN="${SAN}\nIP.${IP_IDX} = ${DETECTED_IP}"
|
||||||
|
echo ">> Including public IP in certificate SAN: ${DETECTED_IP}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
cat >/tmp/openssl.cnf <<SSLEOF
|
||||||
|
[req]
|
||||||
|
distinguished_name = dn
|
||||||
|
x509_extensions = v3_req
|
||||||
|
prompt = no
|
||||||
|
|
||||||
|
[dn]
|
||||||
|
C = IT
|
||||||
|
ST = -
|
||||||
|
L = -
|
||||||
|
O = PalladiumStack
|
||||||
|
CN = localhost
|
||||||
|
|
||||||
|
[v3_req]
|
||||||
|
keyUsage = keyEncipherment, dataEncipherment, digitalSignature
|
||||||
|
extendedKeyUsage = serverAuth
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[alt_names]
|
||||||
|
$(echo -e "$SAN")
|
||||||
|
SSLEOF
|
||||||
|
|
||||||
|
openssl req -x509 -nodes -newkey rsa:4096 -days 3650 \
|
||||||
|
-keyout /certs/server.key -out /certs/server.crt \
|
||||||
|
-config /tmp/openssl.cnf 2>/dev/null
|
||||||
|
|
||||||
|
chmod 600 /certs/server.key
|
||||||
|
chmod 644 /certs/server.crt
|
||||||
|
rm -f /tmp/openssl.cnf
|
||||||
|
echo ">> SSL certificate generated successfully"
|
||||||
|
else
|
||||||
|
echo ">> Using existing SSL certificates from /certs/"
|
||||||
|
fi
|
||||||
|
|
||||||
# Update TX_COUNT / TX_COUNT_HEIGHT in coins.py from the live node
|
# Update TX_COUNT / TX_COUNT_HEIGHT in coins.py from the live node
|
||||||
echo "Fetching chain tx stats from palladiumd..."
|
echo "Fetching chain tx stats from palladiumd..."
|
||||||
TX_STATS=$(curl -sf --user "${RPC_USER}:${RPC_PASSWORD}" \
|
TX_STATS=$(curl -sf --user "${RPC_USER}:${RPC_PASSWORD}" \
|
||||||
|
|||||||
Reference in New Issue
Block a user