This guide outlines security best practices for deploying and operating ChainLaunch.
Access Control & Authentication
1. Strong Password Policy
Enforce:
- Minimum 12 characters
- Mix of uppercase, lowercase, numbers, and symbols
- No dictionary words or personal information
- Change password every 90 days
Configuration:
security:
password_policy:
min_length: 12
require_uppercase: true
require_lowercase: true
require_numbers: true
require_symbols: true
expiration_days: 902. Multi-Factor Authentication (MFA)
Enable MFA for:
- All admin accounts (required)
- All operator accounts (recommended)
- Users with sensitive permissions
Via UI:
- Go to Settings → Users
- Select user
- Click Enable MFA
- Follow 2FA setup (TOTP or U2F)
3. API Key Security
Best Practices:
- ✅ Rotate API keys every 90 days
- ✅ Set specific expiration dates
- ✅ Use separate keys per service
- ✅ Minimize permissions per key
- ✅ Store securely (environment variables, secrets manager)
- ❌ Never commit API keys to version control
- ❌ Never use permanent keys for automation
Create restricted API key:
chainlaunch api-keys create \
--name ci-cd-pipeline \
--role OPERATOR \
--permission NODE_READ,NETWORK_READ,SYSTEM_MONITOR \
--expires-in 365d4. OIDC/SSO Setup
Enable Single Sign-On for enterprise:
- Go to Settings → Authentication
- Select OIDC provider (Keycloak, Auth0, Okta)
- Configure provider credentials
- Map OIDC groups to ChainLaunch roles
Configuration Example:
oidc:
provider: keycloak
issuer_url: https://keycloak.example.com/auth/realms/master
client_id: chainlaunch
client_secret: "${OIDC_CLIENT_SECRET}"
group_claim: groups
group_mappings:
admins: admin
operators: operator
viewers: viewerNetwork Security
1. TLS/SSL Encryption
Enable TLS for all communications:
- API server TLS
- Node-to-node TLS
- P2P network TLS
Configuration:
tls:
enabled: true
cert_file: /etc/chainlaunch/tls.cert
key_file: /etc/chainlaunch/tls.key
min_version: "1.2"
cipher_suites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY13052. Firewall Configuration
Whitelist traffic:
Incoming:
- Port 8100 (API) - From admin networks only
- Port 8545 (JSON-RPC) - From app servers only
- Port 30303 (P2P) - From other validators/nodes only
- Port 3101 (UI) - From trusted networks only
Outgoing:
- Port 443 (HTTPS) - For external services
- Port 53 (DNS) - For DNS resolution
3. Network Segmentation
Isolate networks:
┌─────────────────┐
│ Internet │
└────────┬────────┘
│ (Firewall)
│
┌────────▼────────┐
│ Public Subnet │ (Bastion, Load Balancer)
└────────┬────────┘
│ (Internal Network)
│
┌────────▼────────────────────────┐
│ Private Subnet │
│ ┌─────────────────────────────┐ │
│ │ ChainLaunch Server │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ Validator Nodes │ │ │
│ │ │ Database │ │ │
│ │ └──────────────────────┘ │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────┘
4. DDoS Protection
Implement rate limiting:
curl -X POST http://localhost:8100/api/v1/settings/ratelimit \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"requests_per_minute": 1000,
"burst_size": 50,
"enable_ddos_protection": true
}'Monitoring & Metrics Hardening
ChainLaunch can deploy and manage an embedded Prometheus instance to scrape your nodes (see Configure Monitoring). Prometheus has no built-in authentication, so its network exposure and the admin API are the two settings you must get right.
1. Prometheus binds to loopback by default
As of the latest release, the managed Prometheus instance binds to 127.0.0.1 (loopback) by default in all three deployment modes — Docker, systemd, and launchd. Only processes on the same host (including the ChainLaunch backend, which dials http://localhost:<port> to query metrics) can reach it. Nothing is published on the network unless you explicitly opt in.
This is a change from earlier behavior, where Prometheus could be reachable on 0.0.0.0. If you previously relied on a remote scraper hitting the ChainLaunch Prometheus port directly, you must now either run that scraper on the same host or opt into external exposure (below).
Prometheus is unauthenticated
The Prometheus HTTP endpoint exposes every metric ChainLaunch collects — node topology, resource usage, internal labels — to anyone who can reach it. Never bind it to 0.0.0.0 on a host with a public IP without an authenticating reverse proxy in front of it.
2. Opting into external access safely
If an external scraper, standalone Grafana, federation peer, or external Alertmanager genuinely needs to reach Prometheus directly, set the listen address to 0.0.0.0. Do this only behind one of the following controls:
- Authenticating reverse proxy (recommended). Put nginx, Caddy, Traefik, or oauth2-proxy in front of Prometheus and keep Prometheus itself on loopback. The proxy terminates TLS and enforces auth; Prometheus never listens on a routable interface.
- Private network / firewall allowlist. If you must expose the port, restrict it to the scraper's source IPs (security group,
ufw, or the firewall rules in Network Security above). Treat the Prometheus port like the API port: admin networks only. - mTLS or a service mesh. In Kubernetes, keep Prometheus on
ClusterIPand require client certificates or mesh policy for cross-namespace scrapes.
Example nginx reverse proxy enforcing basic auth while keeping Prometheus on loopback:
server {
listen 443 ssl;
server_name prometheus.example.com;
ssl_certificate /etc/nginx/tls/fullchain.pem;
ssl_certificate_key /etc/nginx/tls/privkey.pem;
location / {
auth_basic "Prometheus";
auth_basic_user_file /etc/nginx/prometheus.htpasswd;
proxy_pass http://127.0.0.1:9090; # Prometheus stays on loopback
}
}Keep the listen address at its 127.0.0.1 default whenever the backend is the only consumer — which is the case for the in-app dashboards and per-node metrics views.
Prefer remote_write over exposing the port
If the goal is to centralize metrics in an external store (Grafana Mimir, Grafana Cloud, AWS Managed Prometheus, Datadog), you usually do not need to expose Prometheus at all. Configure outbound remote_write instead and keep the endpoint on loopback. See External Observability.
3. The --web.enable-admin-api risk
Prometheus' admin API (--web.enable-admin-api) exposes unauthenticated, destructive endpoints such as POST /api/v1/admin/tsdb/delete_series and DELETE /api/v1/data. Anyone who can reach the Prometheus port could wipe your metrics history — and it completely bypasses ChainLaunch RBAC.
ChainLaunch does not use the admin API internally, so it is now opt-in and off by default in all three deployment modes. Leave it off:
- ✅ Off (default). ChainLaunch never enables
--web.enable-admin-api. Recommended for virtually all deployments. - ⚠️ On (opt-in only). Enable it only if you have a specific operational need (e.g. deleting series during a controlled cleanup), and only when Prometheus is on loopback or behind an authenticating proxy that blocks the admin paths.
If you turn the admin API on, treat the Prometheus port as a privileged interface and restrict access exactly as you would the ChainLaunch API.
4. Notification-provider secrets are protected
SMTP passwords, webhook HMAC secrets, API tokens, and custom auth headers stored on notification providers (see Notifications) are handled as write-only secrets:
- Redacted in API responses.
GET/POSTresponses replace secret fields (password,secret,token,apikey,apitoken, and webhookcustomHeaders) with a__REDACTED__placeholder. The plaintext is never returned to a client after it is saved. Updates that resubmit the placeholder (or an empty value) keep the stored secret intact, so editing a provider in the UI does not require re-entering credentials. - Encrypted at rest. The provider
configblob is sealed with the ChainLaunch master encryption key before it touches SQLite, the same AES-256-GCM scheme used for SSO, Vault, and KMS credentials. See Encryption at Rest for how the master key is supplied and rotated. Existing rows are migrated lazily — they stay readable as plaintext until the next edit re-saves them encrypted.
This means a stolen chainlaunch.db does not leak your SMTP password or Slack/PagerDuty webhook secrets, and API consumers (including audit log subscribers) never see them.
Data Security
1. Encryption at Rest
Enable database encryption:
database:
encryption:
enabled: true
algorithm: AES-256-GCM
key_derivation: PBKDF2
iterations: 100000Encrypt sensitive fields:
- API keys
- Provider credentials
- Certificate private keys
- User passwords
2. Encryption in Transit
Use TLS 1.2+:
tls:
min_version: "1.2"
max_version: "1.3"
require_client_cert: true
client_ca: /etc/chainlaunch/ca-cert.pem3. Database Security
Secure database connection:
# Use SSL for database connections
DATABASE_URL="postgresql://user:pass@db.example.com:5432/chainlaunch?sslmode=require"Limit database access:
- Run database on private network
- Use database user with minimal privileges
- Enable database audit logging
- Regular backups to secure location
4. Key Management
Hardware Security Module (HSM):
- Store master keys in HSM
- Use AWS KMS or HashiCorp Vault for key provider
- Never store keys in plaintext
Key Rotation:
# Generate a replacement key, then update the consuming node and remove the
# old key. ChainLaunch does not expose an in-place "rotate" endpoint today.
chainlaunch keys create --name signing-key-2026 --algorithm EC --curve P-256
# (reconfigure the node to use the new key, then…)
chainlaunch keys delete <old-key-id>Monitoring & Audit
1. Enable Comprehensive Audit Logging
Configuration:
audit:
enabled: true
retention_days: 365
log_level: info
archive_after_days: 30
targets:
- type: syslog
server: syslog.example.com
- type: s3
bucket: audit-logs-bucket2. Monitor for Anomalies
Set up alerts for:
- Failed login attempts (>3 in 15 minutes)
- Permission elevation (user assigned admin role)
- Unusual API usage patterns
- Certificate expiration warnings
- Network topology changes
Example alert configuration:
alerts:
failed_logins:
threshold: 3
window_minutes: 15
action: lock_account
permission_elevation:
enabled: true
notify: security-team@example.com
certificate_expiry:
days_before: 30
notify: ops-team@example.com3. Collect Security Logs
Send logs to SIEM:
# Example: Send to Splunk
curl -X POST https://splunk.example.com:8088/services/collector \
-H "Authorization: Splunk YOUR_TOKEN" \
-d @audit-logs.json4. Regular Security Audits
Monthly:
- Review audit logs for anomalies
- Check user permissions are appropriate
- Verify API key usage
- Audit failed operations
Quarterly:
- Security assessment
- Penetration testing
- Policy review
- Compliance verification
Infrastructure Security
1. Host Hardening
Operating System:
- Apply latest security patches
- Disable unnecessary services
- Use SELinux/AppArmor
- Enable firewall
SSH Configuration:
# ~/.ssh/config
Host chainlaunch-prod
HostName prod.chainlaunch.example.com
User chainlaunch
IdentityFile ~/.ssh/id_rsa_chainlaunch
IdentitiesOnly yes
StrictHostKeyChecking yes
UserKnownHostsFile ~/.ssh/known_hosts2. Container Security (if using Docker)
Build secure images:
# Use minimal base image
FROM alpine:3.18
# Run as non-root user
RUN addgroup -g 1000 chainlaunch && \
adduser -D -u 1000 -G chainlaunch chainlaunch
USER chainlaunch
# No secrets in imageScan images:
# Scan for vulnerabilities
docker scan chainlaunch:latest
trivy image chainlaunch:latest3. Kubernetes Security (if deployed on K8s)
RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: chainlaunch-role
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list"]Network policies:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: chainlaunch-netpol
spec:
podSelector:
matchLabels:
app: chainlaunch
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress
ports:
- protocol: TCP
port: 8080Compliance & Governance
1. Document Security Policies
Create and maintain:
- Information Security Policy
- Access Control Policy
- Data Classification Policy
- Incident Response Plan
- Disaster Recovery Plan
2. Regular Training
User Training:
- Password security
- Phishing awareness
- Data handling procedures
- Incident reporting
Administrator Training:
- Secure configuration
- Backup procedures
- Incident response
- Compliance requirements
3. Compliance Reporting
Generate compliance reports:
# SOC 2 audit report
curl -X POST http://localhost:8100/api/v1/reports/soc2 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"start_date": "2024-01-01",
"end_date": "2024-12-31"
}' \
--output soc2-report.pdfIncident Response
1. Incident Response Plan
Document:
- Detection procedures
- Escalation paths
- Response procedures
- Communication templates
- Recovery procedures
2. Security Incident Workflow
1. Detection
↓
2. Analysis
↓
3. Containment
↓
4. Eradication
↓
5. Recovery
↓
6. Post-Incident Review
3. Breach Notification
In case of security incident:
- Isolate affected systems
- Collect forensic evidence
- Notify security team
- Investigate root cause
- Implement fixes
- Notify users if required
- Document lessons learned
Security Checklist
- TLS 1.2+ enabled for all communications
- All users have strong passwords (min 12 chars)
- Admin users have MFA enabled
- API keys have expiration dates
- RBAC configured with principle of least privilege
- Audit logging enabled with retention policy
- Database encrypted at rest
- Backups encrypted and stored securely
- Firewall configured to limit network access
- SSH key-based authentication only
- Regular security patches applied
- Monitoring and alerting configured
- Incident response plan documented
- Security policies documented
- Regular security audits scheduled
See Also
- RBAC & Permissions
- Audit Logging & Compliance
- Key Management
- Configure Monitoring — deploy and manage the embedded Prometheus instance
- Notifications — provider secrets are redacted and encrypted
- Encryption at Rest — how the master key seals stored secrets
- Backup & Recovery