TLS/HTTPS
Nylon provides comprehensive TLS support with automatic certificate management through ACME (Let's Encrypt).
Quick HTTPS Setup
Automatic Certificates (Let's Encrypt)
# Runtime config
https:
- 0.0.0.0:443
config_dir: "./config"
acme: "./acme" # Certificate storage directory# Proxy config
tls:
- type: acme
provider: letsencrypt
domains:
- example.com
- www.example.com
acme:
email: [email protected]
routes:
- route:
type: host
value: example.com|www.example.com
name: main
tls:
enabled: true
paths:
- path:
- /
- /{*path}
service:
name: backendThat's it! Nylon will:
- Automatically request certificates
- Handle ACME HTTP-01 challenge
- Renew certificates before expiry
- Serve HTTPS traffic
Manual Certificates
Using Your Own Certificates
tls:
- type: custom
domains:
- example.com
- www.example.com
cert: /path/to/cert.pem
key: /path/to/key.pemCertificate Formats
Nylon accepts standard PEM-encoded certificates:
# Certificate file (cert.pem)
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
# Private key file (key.pem)
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----ACME Configuration
Let's Encrypt Production
tls:
- type: acme
provider: letsencrypt
domains:
- example.com
acme:
email: [email protected]Let's Encrypt Staging (Testing)
tls:
- type: acme
provider: letsencrypt
domains:
- example.com
acme:
email: [email protected]Use staging for testing to avoid rate limits!
ACME HTTP-01 Challenge
Nylon automatically handles HTTP-01 challenge:
- ACME server requests validation at:
http://example.com/.well-known/acme-challenge/{token} - Nylon responds with challenge response
- Certificate issued after validation
Requirements:
- Domain must point to your Nylon server
- Port 80 must be accessible from internet
- HTTP listener must be configured
Multi-Domain Certificates
Separate Certificates
tls:
# Certificate for api.example.com
- type: acme
provider: letsencrypt
domains:
- api.example.com
acme:
email: [email protected]
# Certificate for admin.example.com
- type: acme
provider: letsencrypt
domains:
- admin.example.com
acme:
email: [email protected]Wildcard Certificates
Wildcard certificates require DNS-01 challenge (not yet supported). Use separate certificates or SAN certificates instead.
# NOT YET SUPPORTED
tls:
- domains:
- "*.example.com" # Wildcard not supported yetWorkaround: List all subdomains:
tls:
- type: acme
provider: letsencrypt
domains:
- api.example.com
- admin.example.com
- app.example.com
acme:
email: [email protected]HTTP to HTTPS Redirect
Automatically redirect HTTP requests to HTTPS:
routes:
- route:
type: host
value: example.com|api.example.com|admin.example.com
name: main
tls:
enabled: true
redirect: ${host} # Redirect HTTP to HTTPS
paths:
- path:
- /
- /{*path}
service:
name: backendRequests to http://example.com/* → https://example.com/*
Certificate Renewal
Automatic Renewal
Nylon automatically renews certificates:
- Checks expiry daily
- Renews certificates 30 days before expiry
- No downtime during renewal
Manual Renewal
Force certificate renewal:
# Reload configuration (triggers renewal check)
sudo nylon service reload
# Or send SIGHUP
kill -HUP $(cat /var/run/nylon.pid)Certificate Storage
Certificates are stored in the ACME directory:
acme/
├── example.com.cert
├── example.com.key
├── api.example.com.cert
├── api.example.com.key
└── account.jsonKeep these files safe!
- Back up regularly
- Set appropriate permissions:
chmod 600 *.key - Don't commit to version control
SNI (Server Name Indication)
Nylon supports SNI for serving multiple domains on one IP:
tls:
- domains:
- example.com
cert: /path/to/example.com.pem
key: /path/to/example.com.key
- domains:
- another.com
cert: /path/to/another.com.pem
key: /path/to/another.com.keyNylon automatically selects the correct certificate based on the requested hostname.
TLS Versions and Ciphers
Nylon uses secure defaults from Pingora:
- TLS 1.2 and TLS 1.3 enabled
- Modern cipher suites
- Forward secrecy
- No support for insecure protocols (SSLv3, TLS 1.0, TLS 1.1)
Examples
Production Setup
# config.yaml
http:
- 0.0.0.0:80
https:
- 0.0.0.0:443
config_dir: "/etc/nylon/config"
acme: "/etc/nylon/acme"
pingora:
threads: 4# config/proxy.yaml
tls:
- domains:
- example.com
- www.example.com
acme:
email: [email protected]
services:
- name: backend
service_type: http
endpoints:
- ip: 10.0.0.1
port: 3000
routes:
- route:
type: host
value: example.com
name: main
tls:
enabled: true
redirect: ${host}
paths:
- path:
- /
- /{*path}
service:
name: backendMultiple Domains
tls:
- domains:
- api.example.com
acme:
email: [email protected]
- domains:
- admin.example.com
acme:
email: [email protected]
routes:
- route:
type: host
value: api.example.com
name: api
tls:
enabled: true
paths:
- path:
- /
- /{*path}
service:
name: api-service
- route:
type: host
value: admin.example.com
name: admin
tls:
enabled: true
paths:
- path:
- /
- /{*path}
service:
name: admin-serviceMixed HTTP/HTTPS
routes:
# HTTPS only
- route:
type: host
value: secure.example.com
name: secure
tls:
enabled: true
paths:
- path:
- /
- /{*path}
service:
name: secure-service
# HTTP only (internal service)
- route:
type: host
value: internal.example.com
name: internal
paths:
- path:
- /
- /{*path}
service:
name: internal-serviceTroubleshooting
Certificate Not Issued
Check domain DNS:
dig example.com
nslookup example.comCheck port 80 accessibility:
curl -I http://example.com/.well-known/acme-challenge/testCheck logs:
sudo journalctl -u nylon -fRate Limiting
Let's Encrypt has rate limits:
- 50 certificates per domain per week
- 5 duplicate certificates per week
Solution: Use staging for testing:
directory_url: https://acme-staging-v02.api.letsencrypt.org/directoryCertificate Expired
If auto-renewal fails:
# Remove old certificate
rm acme/example.com.cert acme/example.com.key
# Reload to trigger new request
sudo nylon service reloadSNI Not Working
Ensure:
- Client supports SNI (all modern browsers do)
- Hostname in request matches configured domain
- Certificate includes the requested domain
Security Best Practices
1. Use Production ACME URL
# ✅ Good
directory_url: https://acme-v02.api.letsencrypt.org/directory
# ❌ Bad (staging certificates not trusted)
directory_url: https://acme-staging-v02.api.letsencrypt.org/directory2. Protect Private Keys
chmod 600 acme/*.key
chown root:root acme/*.key3. Enable HTTPS Redirect
tls:
enabled: true
redirect: ${host} # Force HTTPS4. Use HSTS Header
middleware:
- plugin: ResponseHeaderModifier
payload:
set:
- name: strict-transport-security
value: "max-age=31536000; includeSubDomains"5. Monitor Certificate Expiry
Set up monitoring for certificates expiring soon:
# Check certificate expiry
openssl x509 -in acme/example.com.cert -noout -datesSee Also
- Configuration - TLS configuration reference
- Routing - Configure routes with TLS
- Examples - TLS examples