
TLS Certificate Configuration
All peer connections in Muti Metroo use TLS for encryption and authentication. This guide covers certificate generation and configuration.
Overview
Muti Metroo uses a PKI (Public Key Infrastructure) model with centralized TLS configuration:
- Certificate Authority (CA): Signs all certificates, configured once globally
- Agent Certificate: Used for both server and client authentication
- Global mTLS Setting: Enable/disable mutual TLS with a simple boolean
Global TLS Configuration
TLS settings are configured once in the global tls: section:
tls:
# CA certificate for verifying peers and clients
ca: "./certs/ca.crt"
# Agent's identity certificate (used by listeners and peer connections)
cert: "./certs/agent.crt"
key: "./certs/agent.key"
# Enable mutual TLS on listeners (require client certificates)
mtls: true
This single configuration is used by:
- All listeners (for server TLS and optional mTLS)
- All peer connections (for client certificate presentation)
Certificate Requirements
Important: Muti Metroo only accepts EC (Elliptic Curve) certificates. RSA certificates are not supported for the mesh CA and agent certificates.
The only exception is when connecting through a WebSocket proxy to an external server - in this case, the external server may use any certificate type since mTLS is not available through proxies.
Generating Certificates
Using the CLI
# Generate CA (do once, share across mesh)
muti-metroo cert ca -n "My Mesh CA" -o ./certs
# Generate agent certificate (signed by the CA)
muti-metroo cert agent -n "agent-1" \
--ca ./certs/ca.crt \
--ca-key ./certs/ca.key \
--dns "agent1.example.com" \
--ip "192.168.1.10" \
-o ./certs
# View certificate info
muti-metroo cert info ./certs/agent-1.crt
If you use -o ./certs for the CA, the --ca and --ca-key flags default to ./certs/ca.crt and ./certs/ca.key, so you can omit them.
All certificates generated by the CLI use P-256 ECDSA keys.
Using OpenSSL
# Generate EC CA key and certificate
openssl ecparam -name prime256v1 -genkey -noout -out ca.key
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 \
-out ca.crt -subj "/CN=My Mesh CA"
# Generate EC agent key and CSR
openssl ecparam -name prime256v1 -genkey -noout -out agent.key
openssl req -new -key agent.key -out agent.csr \
-subj "/CN=agent-1"
# Sign agent certificate
openssl x509 -req -in agent.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out agent.crt -days 365 -sha256
Configuration Options
File-Based Certificates
Standard approach using file paths:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true
Inline PEM Certificates
Embed certificates directly in config (useful for Kubernetes secrets):
tls:
ca_pem: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAKi...
-----END CERTIFICATE-----
cert_pem: |
-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAKi...
-----END CERTIFICATE-----
key_pem: |
-----BEGIN EC PRIVATE KEY-----
MIIEvQIBADANBg...
-----END EC PRIVATE KEY-----
mtls: true
Inline PEM takes precedence over file paths.
Environment Variables
Use environment variables for secrets:
tls:
ca_pem: "${TLS_CA}"
cert_pem: "${TLS_CERT}"
key_pem: "${TLS_KEY}"
mtls: true
Mutual TLS (mTLS)
mTLS requires both sides to present certificates. With the global configuration, enabling mTLS is simple:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true # Enable mTLS on all listeners
When mtls: true:
- Listeners require connecting peers to present valid client certificates
- The global CA is used to verify client certificates
- The global agent certificate is automatically used by peers as their client certificate
Benefits of mTLS
- Mutual authentication (both sides verified)
- Prevents unauthorized connections
- Defense against man-in-the-middle attacks
- Required for zero-trust environments
Per-Listener Overrides
Individual listeners can override global settings:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true
listeners:
# Uses global settings
- transport: quic
address: "0.0.0.0:4433"
# Override: disable mTLS for this listener
- transport: h2
address: "0.0.0.0:8443"
tls:
mtls: false
# Override: use different certificate
- transport: ws
address: "0.0.0.0:443"
tls:
cert: "./certs/public-facing.crt"
key: "./certs/public-facing.key"
mtls: false
# No TLS: plaintext for reverse proxy
- transport: ws
address: "127.0.0.1:8080"
plaintext: true
Per-Peer Overrides
Individual peer connections can override global settings:
tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true
peers:
# Uses global CA and cert
- id: "abc123..."
transport: quic
address: "192.168.1.50:4433"
# Override: different CA for this peer
- id: "def456..."
transport: quic
address: "external.example.com:4433"
tls:
ca: "./certs/external-ca.crt"
# Certificate pinning
- id: "ghi789..."
transport: quic
address: "pinned.example.com:4433"
tls:
fingerprint: "sha256:ab12cd34..."
Certificate Validity
Validity Period
Default validity periods:
- CA certificates: 365 days
- Agent/client certificates: 90 days
Specify custom validity:
muti-metroo cert ca --days 730 # 2 years
muti-metroo cert agent --days 180 # 6 months
Subject Alternative Names (SANs)
Always include SANs for agent certificates:
muti-metroo cert agent -n "agent-1" \
--ca ./certs/ca.crt \
--ca-key ./certs/ca.key \
--dns "agent1.example.com" \
--dns "agent1.internal" \
--ip "192.168.1.10" \
--ip "10.0.0.10" \
-o ./certs
Certificate Rotation
Planned Rotation
- Generate new certificates before expiration
- Deploy new certificates alongside old ones
- Update configuration to use new certificates
- Restart agents
- Remove old certificates
Emergency Rotation
If CA is compromised:
- Generate new CA
- Generate new certificates for all agents
- Deploy and restart all agents simultaneously
- Revoke trust in old CA
Monitoring Expiration
CLI Check
muti-metroo cert info ./certs/agent.crt
Output includes expiration date.
OpenSSL Check
openssl x509 -enddate -noout -in ./certs/agent.crt
Automated Monitoring
Add to your monitoring:
#!/bin/bash
# Check if cert expires in next 30 days
openssl x509 -checkend 2592000 -noout -in ./certs/agent.crt
if [ $? -eq 1 ]; then
echo "Certificate expires soon!"
fi
Troubleshooting
Certificate Not Trusted
Error: x509: certificate signed by unknown authority
- Verify CA certificate is correct
- Check CA was used to sign agent certificate
Certificate Expired
Error: x509: certificate has expired
- Generate new certificate
- Check system time is correct
Name Mismatch
Error: x509: certificate is valid for agent1.example.com, not agent2.example.com
- Use correct hostname/IP
- Add SANs when generating certificate
Private Key Mismatch
Error: tls: private key does not match public key
- Verify key matches certificate:
openssl x509 -noout -pubkey -in agent.crt | openssl md5
openssl ec -in agent.key -pubout 2>/dev/null | openssl md5
# Must match
RSA Certificate Rejected
Error: certificate must use ECDSA, got RSA
- Muti Metroo only accepts EC certificates
- Regenerate certificates using ECDSA (P-256)
Best Practices
- Use EC certificates: RSA is not supported
- Protect CA private key: Use hardware security module or secure vault
- Use short validity: 90-365 days for agent certs
- Use SANs: Include all hostnames and IPs
- Enable mTLS: Especially in production
- Automate rotation: Before certificates expire
- Monitor expiration: Alert before expiry
Examples
Development
tls:
ca: "./dev-certs/ca.crt"
cert: "./dev-certs/agent.crt"
key: "./dev-certs/agent.key"
mtls: false # Relax for development
listeners:
- transport: quic
address: "0.0.0.0:4433"
Production with mTLS
tls:
ca: "/etc/muti-metroo/certs/ca.crt"
cert: "/etc/muti-metroo/certs/agent.crt"
key: "/etc/muti-metroo/certs/agent.key"
mtls: true
listeners:
- transport: quic
address: "0.0.0.0:4433"
peers:
- id: "abc123..."
transport: quic
address: "peer.example.com:4433"
Kubernetes
tls:
ca_pem: "${CA_CRT}"
cert_pem: "${TLS_CRT}"
key_pem: "${TLS_KEY}"
mtls: true
listeners:
- transport: quic
address: "0.0.0.0:4433"
Related
- CLI: cert - Certificate CLI commands
- Security: TLS/mTLS - Security considerations
- Deployment - Production deployment