DNS & Domain Management
OEC.SH provides comprehensive DNS and domain management for your environments with automatic SSL certificate provisioning, multi-provider support, and seamless integration with Traefik reverse proxy.
Overview
The platform handles all aspects of domain management:
- Multi-Provider Support: Cloudflare, Route53, Azure DNS, Google Cloud DNS, DigitalOcean
- Automatic DNS Records: System subdomain auto-configuration during deployment
- Custom Domains: Bring your own domains with DNS verification
- SSL/TLS Certificates: Automatic Let's Encrypt certificates via HTTP-01 and DNS-01 challenges
- Wildcard SSL: Optional wildcard certificates for instant SSL on all environments
- Traefik Integration: Automatic routing configuration with zero downtime
- DNS Propagation Monitoring: Real-time verification before SSL issuance
Architecture
DNS Configuration Levels
Organization
└─ DNS Configurations (1:N)
├─ Provider: Cloudflare, Route53, etc.
├─ Credentials: Encrypted API tokens
├─ Wildcard SSL: Optional *.apps.oec.sh
└─ Domains (1:N)
└─ Project Environments
├─ System Subdomain: auto-generated.apps.oec.sh
└─ Custom Domain: erp.your-company.comRouting Flow
DNS Provider → DNS Record → Traefik Labels → Container
(A/CNAME) (Zone) (Router/Service) (Port 8069)DNS Providers
Supported Providers
| Provider | Status | Features | Authentication |
|---|---|---|---|
| Cloudflare | ✅ Fully Supported | Orange cloud proxy, API v4, Zone management | API Token |
| Route53 | 🔜 Coming Soon | AWS DNS, Hosted zones | Access Key + Secret |
| Azure DNS | 🔜 Coming Soon | Azure DNS zones | Service Principal |
| Google Cloud DNS | 🔜 Coming Soon | Cloud DNS zones | Service Account |
| DigitalOcean | 🔜 Coming Soon | DO DNS | API Token |
Add DNS Configuration
Organizations can configure multiple DNS providers for different zones or use cases.
API Endpoint: POST /api/v1/dns/configs
Required Permission: org.dns.create
curl -X POST https://api.oec.sh/api/v1/dns/configs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"provider": "cloudflare",
"name": "Production Cloudflare",
"credentials": {
"api_token": "your_cloudflare_api_token"
},
"provider_config": {
"account_id": "abc123def456"
},
"is_default": true
}'Response:
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"provider": "cloudflare",
"name": "Production Cloudflare",
"is_default": true,
"is_active": true,
"last_verified_at": "2024-12-11T10:30:00Z",
"verification_error": null,
"enable_wildcard_ssl": false,
"wildcard_cert_status": "not_requested",
"created_at": "2024-12-11T10:30:00Z"
}Verify Credentials
Before saving a DNS configuration, verify the credentials are valid.
API Endpoint: POST /api/v1/dns/verify-credentials
curl -X POST https://api.oec.sh/api/v1/dns/verify-credentials \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "cloudflare",
"credentials": {
"api_token": "test_token_to_verify"
}
}'Response:
{
"valid": true,
"message": "Credentials verified. Found 3 zone(s).",
"zones": [
{
"id": "abc123",
"name": "example.com",
"status": "active",
"name_servers": [
"ns1.cloudflare.com",
"ns2.cloudflare.com"
]
},
{
"id": "def456",
"name": "myapp.io",
"status": "active",
"name_servers": [
"ns3.cloudflare.com",
"ns4.cloudflare.com"
]
}
]
}List DNS Configurations
API Endpoint: GET /api/v1/dns/configs/org/{organization_id}
Required Permission: org.dns.list
curl https://api.oec.sh/api/v1/dns/configs/org/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"Automatic System Domains
Every environment automatically receives a system subdomain during deployment.
Subdomain Generation
System subdomains follow the pattern: {project-slug}-{env-name}.apps.oec.sh
Example Subdomains:
acme-production.apps.oec.shacme-staging.apps.oec.shbigcorp-demo.apps.oec.sh
Automatic DNS Creation
When an environment is deployed, OEC.SH automatically:
- Generates Subdomain: Based on project slug and environment name
- Creates A Record: Points subdomain to the server's IP address
- Configures Traefik: Adds routing labels to the Odoo container
- Requests SSL Certificate: Let's Encrypt HTTP-01 challenge
- Enables HTTPS: Automatic redirect from HTTP to HTTPS
DNS Record Example:
acme-production.apps.oec.sh. 300 IN A 165.22.65.97System Domain Behavior
- Automatic Creation: Created during first deployment
- Automatic Update: Updated if environment moves to different server
- Automatic Cleanup: Removed when environment is destroyed
- No User Action Required: Fully automated by the platform
Custom Domains
Add your own domains to environments for branded URLs.
Add Custom Domain
API Endpoint: POST /api/v1/dns/domains
Required Permission: org.dns.create
curl -X POST https://api.oec.sh/api/v1/dns/domains \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"project_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"environment_id": "f1e2d3c4-b5a6-9807-6543-210fedcba098",
"dns_config_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"domain": "erp.acme-corp.com",
"dns_record_type": "A",
"target_ip": "165.22.65.97",
"ttl": 300,
"proxied": true,
"auto_configure": true,
"is_primary": true
}'Parameters:
auto_configure: Iftrue, automatically creates DNS record in providerproxied: Enable Cloudflare orange cloud (proxy mode)is_primary: Set as the primary domain for the environmenttarget_ip: Server IP address (auto-detected from environment if not provided)
Response:
{
"id": "d1e2f3a4-b5c6-7890-1234-567890abcdef",
"project_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"environment_id": "f1e2d3c4-b5a6-9807-6543-210fedcba098",
"dns_config_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"domain": "erp.acme-corp.com",
"root_domain": "acme-corp.com",
"dns_record_type": "A",
"target_ip": "165.22.65.97",
"ttl": 300,
"proxied": true,
"dns_record_id": "abc123",
"dns_zone_id": "def456",
"ssl_enabled": true,
"ssl_provider": "cloudflare",
"is_primary": true,
"is_verified": true,
"verified_at": "2024-12-11T10:35:00Z",
"dns_propagated": true,
"status": "active",
"ssl_status": "active",
"created_at": "2024-12-11T10:35:00Z"
}DNS Record Types
A Record (IPv4)
Points domain to IPv4 address.
{
"domain": "erp.example.com",
"dns_record_type": "A",
"target_ip": "165.22.65.97",
"ttl": 300
}DNS Record:
erp.example.com. 300 IN A 165.22.65.97AAAA Record (IPv6)
Points domain to IPv6 address.
{
"domain": "erp.example.com",
"dns_record_type": "AAAA",
"target_ip": "2001:db8::1",
"ttl": 300
}DNS Record:
erp.example.com. 300 IN AAAA 2001:db8::1CNAME Record
Points domain to another hostname.
{
"domain": "erp.example.com",
"dns_record_type": "CNAME",
"target_cname": "acme-production.apps.oec.sh",
"ttl": 300
}DNS Record:
erp.example.com. 300 IN CNAME acme-production.apps.oec.sh.Manual DNS Configuration
If not using auto_configure, you need to manually create DNS records.
For A Record:
- Log into your DNS provider
- Create A record:
erp.example.com→165.22.65.97 - Wait for DNS propagation (5-60 minutes)
- Verify domain in OEC.SH
For CNAME Record:
- Log into your DNS provider
- Create CNAME record:
erp.example.com→acme-production.apps.oec.sh - Wait for DNS propagation (5-60 minutes)
- Verify domain in OEC.SH
Verify Domain
After DNS propagation, verify the domain to enable SSL.
API Endpoint: POST /api/v1/dns/domains/{domain_id}/verify
Required Permission: org.dns.sync
curl -X POST https://api.oec.sh/api/v1/dns/domains/d1e2f3a4-b5c6-7890-1234-567890abcdef/verify \
-H "Authorization: Bearer $TOKEN"This endpoint:
- Checks DNS propagation across multiple resolvers (Google, Cloudflare, Quad9)
- Verifies DNS record exists in provider
- Marks domain as verified
- Triggers SSL certificate acquisition
List Environment Domains
API Endpoint: GET /api/v1/dns/domains/environment/{environment_id}
Required Permission: org.dns.list
curl https://api.oec.sh/api/v1/dns/domains/environment/f1e2d3c4-b5a6-9807-6543-210fedcba098 \
-H "Authorization: Bearer $TOKEN"Update Domain
API Endpoint: PATCH /api/v1/dns/domains/{domain_id}
Required Permission: org.dns.update
curl -X PATCH https://api.oec.sh/api/v1/dns/domains/d1e2f3a4-b5c6-7890-1234-567890abcdef \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"target_ip": "46.101.96.153",
"proxied": false
}'Updatable Fields:
target_ip: Change target IP addresstarget_cname: Change target hostnamettl: Change time to liveproxied: Toggle Cloudflare proxy modeis_primary: Set as primary domainis_active: Enable/disable domain
Remove Domain
API Endpoint: DELETE /api/v1/dns/domains/{domain_id}?delete_dns_record=true
Required Permission: org.dns.delete
curl -X DELETE "https://api.oec.sh/api/v1/dns/domains/d1e2f3a4-b5c6-7890-1234-567890abcdef?delete_dns_record=true" \
-H "Authorization: Bearer $TOKEN"Query Parameters:
delete_dns_record: Iftrue(default), deletes DNS record from provider
SSL/TLS Certificates
OEC.SH provides automatic SSL certificate management with Let's Encrypt.
Automatic SSL (Per-Domain)
Each domain automatically receives a Let's Encrypt SSL certificate using HTTP-01 challenge.
Process:
- Environment deployed with Traefik labels
- User accesses domain via HTTPS
- Traefik requests certificate from Let's Encrypt
- HTTP-01 challenge validation
- Certificate issued and stored
- Auto-renewal 30 days before expiry
Certificate Details:
- Issuer: Let's Encrypt
- Validity: 90 days
- Auto-Renewal: Yes
- Challenge Method: HTTP-01
- Certificate Storage: Traefik acme.json file
Cloudflare Proxy Mode
When using Cloudflare with proxied: true (orange cloud):
SSL Modes:
- Full (Strict): Recommended - Cloudflare validates origin certificate
- Full: Cloudflare encrypts to origin but doesn't validate
- Flexible: Cloudflare terminates SSL, plain HTTP to origin
Benefits:
- DDoS protection
- CDN caching
- WAF (Web Application Firewall)
- Bot mitigation
- Analytics
Limitations:
- Visitor IP addresses masked (use CF-Connecting-IP header)
- WebSocket timeouts (configure Cloudflare settings)
Wildcard SSL (Optional)
Organizations can enable wildcard SSL for instant HTTPS on all system subdomains.
Benefits:
- No per-environment certificate requests
- Instant HTTPS on deployment
- Reduced Let's Encrypt rate limits
- Faster environment provisioning
Requirements:
- DNS provider with API access (Cloudflare, Route53, etc.)
- Wildcard domain configured (e.g.,
apps.oec.sh) - DNS-01 challenge support
Enable Wildcard SSL
API Endpoint: POST /api/v1/dns/configs/{config_id}/request-wildcard-ssl
Required Permission: org.dns.update
curl -X POST https://api.oec.sh/api/v1/dns/configs/7c9e6679-7425-40de-944b-e07fc1f90ae7/request-wildcard-ssl \
-H "Authorization: Bearer $TOKEN"Process:
- DNS provider creates TXT record:
_acme-challenge.apps.oec.sh - Let's Encrypt validates domain ownership via DNS-01
- Wildcard certificate issued:
*.apps.oec.sh - Certificate installed on Traefik
- All subdomains immediately get HTTPS
Certificate Details:
Subject: *.apps.oec.sh
Issuer: Let's Encrypt Authority X3
Valid: 90 days
Covers: All subdomains (e.g., acme-prod.apps.oec.sh)Certificate Status
Domain SSL Status Values:
none: SSL not enabledpending: Certificate requested, waiting for issuanceactive: Certificate issued and validexpired: Certificate expired, renewal needed
Wildcard Cert Status Values:
not_requested: Wildcard SSL not enabledpending: Certificate request in progressactive: Certificate issued and validexpired: Certificate expirederror: Certificate request failed
Force HTTPS Redirect
All domains automatically redirect HTTP to HTTPS via Traefik middleware.
HTTP Request:
GET http://erp.example.com/ HTTP/1.1
Host: erp.example.comResponse:
HTTP/1.1 308 Permanent Redirect
Location: https://erp.example.com/Traefik Integration
OEC.SH uses Traefik v3 as the reverse proxy and load balancer for all environments.
Architecture
Internet → Traefik (Port 80/443) → Docker Containers
↓
- Routing rules (labels)
- SSL termination
- HTTP to HTTPS redirect
- Load balancingTraefik Labels
Each Odoo container receives Docker labels for automatic routing configuration.
Example Labels:
labels:
# Enable Traefik
traefik.enable: "true"
traefik.docker.network: "traefik-public"
# HTTP to HTTPS redirect middleware
traefik.http.middlewares.env-123abc-redirect.redirectscheme.scheme: "https"
traefik.http.middlewares.env-123abc-redirect.redirectscheme.permanent: "true"
# HTTP router (redirects to HTTPS)
traefik.http.routers.env-123abc-sys-http.rule: "Host(`acme-prod.apps.oec.sh`)"
traefik.http.routers.env-123abc-sys-http.entrypoints: "web"
traefik.http.routers.env-123abc-sys-http.middlewares: "env-123abc-redirect"
traefik.http.routers.env-123abc-sys-http.service: "env-123abc"
# HTTPS router (main traffic)
traefik.http.routers.env-123abc-sys.rule: "Host(`acme-prod.apps.oec.sh`)"
traefik.http.routers.env-123abc-sys.entrypoints: "websecure"
traefik.http.routers.env-123abc-sys.tls: "true"
traefik.http.routers.env-123abc-sys.tls.certresolver: "letsencrypt"
traefik.http.routers.env-123abc-sys.service: "env-123abc"
# Load balancer service
traefik.http.services.env-123abc.loadbalancer.server.port: "8069"
# WebSocket routing (Odoo 18+ longpolling)
traefik.http.services.env-123abc-ws.loadbalancer.server.port: "8072"
traefik.http.routers.env-123abc-ws-sys.rule: "Host(`acme-prod.apps.oec.sh`) && (PathPrefix(`/websocket`) || PathPrefix(`/longpolling`))"
traefik.http.routers.env-123abc-ws-sys.entrypoints: "websecure"
traefik.http.routers.env-123abc-ws-sys.tls: "true"
traefik.http.routers.env-123abc-ws-sys.tls.certresolver: "letsencrypt"
traefik.http.routers.env-123abc-ws-sys.service: "env-123abc-ws"
traefik.http.routers.env-123abc-ws-sys.priority: "100"Multi-Domain Routing
When both system and custom domains are configured:
Host Rule:
Host(`acme-prod.apps.oec.sh`) || Host(`erp.acme-corp.com`)Traefik Routing:
- Both domains route to the same container
- Separate SSL certificates for each domain
- Separate routers for HTTP and HTTPS
- Shared load balancer service
WebSocket Routing (Odoo 18+)
Odoo 18 uses gevent workers on port 8072 for WebSocket/longpolling.
Path-Based Routing:
/websocket→ Port 8072 (gevent)/longpolling→ Port 8072 (gevent)- All other paths → Port 8069 (main Odoo)
Priority: WebSocket routers have priority 100 to match before main router.
Traefik Configuration File
The platform manages Traefik via static configuration:
traefik.yml:
# Entrypoints
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
# Let's Encrypt
certificatesResolvers:
letsencrypt:
acme:
email: admin@oec.sh
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
# Docker provider
providers:
docker:
exposedByDefault: false
network: traefik-publicDNS Propagation
OEC.SH monitors DNS propagation before requesting SSL certificates to prevent Let's Encrypt rate limits.
Propagation Check
The platform checks DNS resolution across multiple public resolvers:
Resolvers:
8.8.8.8- Google DNS1.1.1.1- Cloudflare DNS9.9.9.9- Quad9 DNS
Success Criteria: At least 2 out of 3 resolvers must return the correct IP address.
Timeout: 180 seconds (3 minutes) maximum wait time.
Check DNS Propagation Manually
You can manually verify DNS propagation using command-line tools.
Using dig:
# Check A record
dig +short erp.example.com @8.8.8.8
# Expected output: 165.22.65.97
# Check with all nameservers
dig erp.example.com @8.8.8.8
dig erp.example.com @1.1.1.1
dig erp.example.com @9.9.9.9Using nslookup:
nslookup erp.example.com 8.8.8.8Using host:
host erp.example.com 8.8.8.8Online Tools:
- https://dnschecker.org (opens in a new tab) - Global DNS propagation checker
- https://www.whatsmydns.net (opens in a new tab) - Multi-location DNS lookup
Propagation Times
| DNS Provider | Typical Propagation |
|---|---|
| Cloudflare | 1-5 minutes |
| Route53 | 5-10 minutes |
| GoDaddy | 10-30 minutes |
| Namecheap | 10-30 minutes |
| Generic | Up to 48 hours |
Tips for Faster Propagation:
- Use low TTL values (300 seconds = 5 minutes)
- Use DNS providers with faster propagation (Cloudflare, Route53)
- Update DNS records before deployment
Subdomain Management
System Subdomains
Every environment automatically gets a system subdomain during deployment.
Generation Rules:
- Pattern:
{project-slug}-{environment-name}.apps.oec.sh - Lowercase alphanumeric and hyphens only
- Maximum 63 characters (DNS label limit)
- Unique across the platform
Examples:
Project: "ACME Corp", Slug: "acme"
Environment: "Production" → acme-production.apps.oec.sh
Environment: "Staging" → acme-staging.apps.oec.sh
Environment: "Demo" → acme-demo.apps.oec.shCollision Handling: If subdomain exists, a random suffix is added:
acme-production.apps.oec.sh (taken)
acme-production-a7x9.apps.oec.sh (generated)Custom Subdomains
You can use custom subdomains from your own domains.
Example Setup:
Your domain: mycompany.com
Custom subdomain: erp.mycompany.com
DNS record: erp.mycompany.com → 165.22.65.97 (A record)Multi-Level Subdomains:
app.staging.mycompany.com → 165.22.65.97
erp.client1.mycompany.com → 165.22.65.97
portal.demo.mycompany.com → 46.101.96.153Wildcard Domains
Wildcard DNS records allow all subdomains to point to the same IP.
Wildcard A Record
DNS Configuration:
*.apps.mycompany.com. 300 IN A 165.22.65.97Result: All subdomains of apps.mycompany.com resolve to 165.22.65.97:
acme-prod.apps.mycompany.com→165.22.65.97bigcorp-staging.apps.mycompany.com→165.22.65.97anything.apps.mycompany.com→165.22.65.97
Wildcard SSL Certificate
Combine wildcard DNS with wildcard SSL for instant HTTPS on all environments.
Setup:
- Configure wildcard DNS:
*.apps.mycompany.com → 165.22.65.97 - Add DNS configuration with wildcard SSL enabled
- Request wildcard certificate:
*.apps.mycompany.com - Deploy environments with subdomains:
acme-prod.apps.mycompany.com
Benefits:
- All subdomains automatically get HTTPS
- No per-environment certificate requests
- Instant SSL on deployment
- Single certificate for all environments
DNS Zones
List Zones
API Endpoint: GET /api/v1/dns/configs/{config_id}/zones
Required Permission: org.dns.zones.list
curl https://api.oec.sh/api/v1/dns/configs/7c9e6679-7425-40de-944b-e07fc1f90ae7/zones \
-H "Authorization: Bearer $TOKEN"Response:
{
"zones": [
{
"id": "abc123",
"name": "example.com",
"status": "active",
"name_servers": [
"ns1.cloudflare.com",
"ns2.cloudflare.com"
]
},
{
"id": "def456",
"name": "myapp.io",
"status": "active",
"name_servers": [
"ns3.cloudflare.com",
"ns4.cloudflare.com"
]
}
]
}Zone Information
Each zone represents a DNS domain managed by your provider.
Zone Fields:
id: Provider's zone identifiername: Domain name (e.g., "example.com")status: Zone status (active, pending, error)name_servers: Authoritative nameservers
Direct DNS Record Management
For advanced users, OEC.SH provides direct DNS record manipulation without domain tracking.
Create DNS Record
API Endpoint: POST /api/v1/dns/configs/{config_id}/records
Required Permission: org.dns.create
curl -X POST https://api.oec.sh/api/v1/dns/configs/7c9e6679-7425-40de-944b-e07fc1f90ae7/records \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"zone_id": "abc123",
"record_type": "A",
"name": "api.example.com",
"content": "165.22.65.97",
"ttl": 300,
"proxied": false
}'Supported Record Types:
A- IPv4 addressAAAA- IPv6 addressCNAME- Canonical nameTXT- Text recordMX- Mail exchange (requirespriority)NS- Name serverSRV- Service record (requirespriority)CAA- Certification authority authorization
List DNS Records
API Endpoint: GET /api/v1/dns/configs/{config_id}/zones/{zone_id}/records
Required Permission: org.dns.list
curl https://api.oec.sh/api/v1/dns/configs/7c9e6679-7425-40de-944b-e07fc1f90ae7/zones/abc123/records \
-H "Authorization: Bearer $TOKEN"Filter by Type:
curl "https://api.oec.sh/api/v1/dns/configs/7c9e6679-7425-40de-944b-e07fc1f90ae7/zones/abc123/records?record_type=A" \
-H "Authorization: Bearer $TOKEN"Permissions
DNS management requires specific organization-level permissions.
DNS Permissions
| Permission | Action | Description |
|---|---|---|
org.dns.create | Create DNS configs and domains | Add DNS providers and custom domains |
org.dns.list | View DNS configs and domains | List configurations and domains |
org.dns.update | Modify DNS configs and domains | Update settings and request SSL |
org.dns.delete | Remove DNS configs and domains | Delete configurations and domains |
org.dns.sync | Verify and sync DNS records | Trigger DNS verification |
org.dns.zones.list | List DNS zones | View available zones in provider |
Role Permissions
| Role | DNS Permissions |
|---|---|
| Portal Admin | All permissions |
| Org Owner | All permissions |
| Org Admin | All permissions |
| Org Member | List only |
| Project Admin | List only |
| Project Member | List only |
Troubleshooting
DNS Record Not Updating
Symptoms: DNS record created but not resolving.
Solutions:
- Check DNS propagation time (5-60 minutes typical)
- Verify record was created in provider dashboard
- Check DNS with multiple resolvers:
dig +short domain.com @8.8.8.8 dig +short domain.com @1.1.1.1 - Verify TTL hasn't cached old value
- Clear local DNS cache:
# Linux sudo systemd-resolve --flush-caches # macOS sudo dscacheutil -flushcache # Windows ipconfig /flushdns
SSL Certificate Errors
Error: "acme: error: 400"
Cause: Let's Encrypt HTTP-01 challenge failed.
Solutions:
- Verify DNS points to correct IP address
- Check Traefik container is running
- Ensure port 80 is open and accessible
- Verify domain resolves globally (use dnschecker.org)
- Wait for full DNS propagation before retrying
Error: "certificate has expired"
Cause: Auto-renewal failed or certificate expired.
Solutions:
- Check Traefik logs for renewal errors
- Verify Let's Encrypt rate limits not exceeded
- Manually trigger renewal (restart environment)
- Check acme.json file permissions
Error: "too many certificates"
Cause: Let's Encrypt rate limit exceeded (50 certificates per domain per week).
Solutions:
- Use wildcard SSL to reduce certificate requests
- Wait 7 days for rate limit reset
- Use staging Let's Encrypt for testing
- Consolidate domains to reduce unique certificates
DNS Verification Failed
Symptoms: Domain verification fails or times out.
Solutions:
- Verify DNS record exists and is correct:
dig +short domain.com @8.8.8.8 - Check DNS propagation across multiple resolvers
- Increase TTL to 300 seconds for faster updates
- Wait longer for global propagation (up to 48 hours)
- Check DNS provider API credentials are valid
Cloudflare Orange Cloud Issues
Symptoms: SSL errors, 522 errors, timeouts with proxied domains.
Solutions:
- Verify SSL/TLS mode is "Full (Strict)" in Cloudflare
- Ensure origin certificate is valid
- Check Cloudflare firewall rules not blocking traffic
- Verify WebSocket support enabled in Cloudflare
- Increase Cloudflare timeout for long-running requests
Wildcard SSL Not Working
Symptoms: Wildcard certificate request fails.
Solutions:
- Verify DNS provider supports API access
- Check DNS-01 challenge TXT record created:
dig +short _acme-challenge.apps.oec.sh TXT @8.8.8.8 - Ensure wildcard domain matches configured domain
- Check DNS provider credentials have correct permissions
- Review certificate request logs for specific errors
Domain Shows "Wrong" Site
Symptoms: Domain shows another environment or 404 error.
Solutions:
- Check Traefik labels on container:
docker inspect container_name | grep traefik - Verify Host() rule includes correct domain
- Check for label conflicts (duplicate router names)
- Restart Traefik to reload configuration:
docker restart traefik - Review Traefik dashboard for routing rules
Multiple Environments Same IP
Symptoms: Need multiple environments on same server with different domains.
Solution: Use host-based routing (this is automatic):
- Environment 1:
app1.example.com→ Container 1 (port 8069) - Environment 2:
app2.example.com→ Container 2 (port 8070) - Environment 3:
app3.example.com→ Container 3 (port 8071)
Traefik routes based on Host header, so all can share IP 165.22.65.97.
Best Practices
DNS Configuration
- Use Low TTL During Setup: Set TTL to 300 seconds (5 minutes) for faster updates
- Increase TTL After Stable: Raise to 3600 seconds (1 hour) after DNS is stable
- Verify Before SSL: Always verify DNS propagation before requesting certificates
- Use Wildcard for Scale: Enable wildcard SSL if managing many environments
- Monitor Expiry: Track certificate expiration dates and ensure auto-renewal works
Security
- Protect API Tokens: Store DNS provider credentials securely (platform encrypts automatically)
- Limit Token Permissions: Use minimal DNS permissions (Zone:DNS:Edit for Cloudflare)
- Rotate Tokens Regularly: Update API tokens every 90 days
- Use HTTPS Only: Always enforce HTTPS redirect (automatic in OEC.SH)
- Monitor Certificate Status: Set up alerts for SSL certificate issues
Performance
- Use Cloudflare Proxy: Enable orange cloud for DDoS protection and CDN
- Geo-Distribute: Use multiple servers in different regions with same domain
- Enable HTTP/2: Traefik enables HTTP/2 automatically with SSL
- Optimize TTL: Balance between propagation speed and DNS query load
- Cache Static Assets: Use Cloudflare page rules for caching
Operational
- Document Domains: Keep track of which domains point to which environments
- Test Before Production: Verify DNS and SSL on staging domains first
- Plan Migrations: Use low TTL before changing IPs
- Backup DNS Records: Export DNS records before major changes
- Monitor Propagation: Use DNS monitoring tools to detect issues
API Reference
DNS Configurations
| Endpoint | Method | Permission | Description |
|---|---|---|---|
/api/v1/dns/providers | GET | None | List supported DNS providers |
/api/v1/dns/verify-credentials | POST | None | Verify credentials and list zones |
/api/v1/dns/configs | POST | org.dns.create | Create DNS configuration |
/api/v1/dns/configs/org/{org_id} | GET | org.dns.list | List DNS configurations |
/api/v1/dns/configs/{id} | GET | org.dns.list | Get DNS configuration |
/api/v1/dns/configs/{id} | PATCH | org.dns.update | Update DNS configuration |
/api/v1/dns/configs/{id} | DELETE | org.dns.delete | Delete DNS configuration |
/api/v1/dns/configs/{id}/verify | POST | org.dns.list | Verify credentials |
/api/v1/dns/configs/{id}/request-wildcard-ssl | POST | org.dns.update | Request wildcard SSL |
/api/v1/dns/configs/{id}/zones | GET | org.dns.zones.list | List DNS zones |
Domains
| Endpoint | Method | Permission | Description |
|---|---|---|---|
/api/v1/dns/domains | POST | org.dns.create | Create domain |
/api/v1/dns/domains/environment/{env_id} | GET | org.dns.list | List environment domains |
/api/v1/dns/domains/{id} | GET | org.dns.list | Get domain |
/api/v1/dns/domains/{id} | PATCH | org.dns.update | Update domain |
/api/v1/dns/domains/{id} | DELETE | org.dns.delete | Delete domain |
/api/v1/dns/domains/{id}/verify | POST | org.dns.sync | Verify domain |
DNS Records
| Endpoint | Method | Permission | Description |
|---|---|---|---|
/api/v1/dns/configs/{config_id}/records | POST | org.dns.create | Create DNS record |
/api/v1/dns/configs/{config_id}/zones/{zone_id}/records | GET | org.dns.list | List DNS records |
Additional Resources
Cloudflare Setup
-
Create API Token:
- Go to: https://dash.cloudflare.com/profile/api-tokens (opens in a new tab)
- Click "Create Token"
- Use template: "Edit zone DNS"
- Select zones to manage
- Copy token (shown once)
-
Get Zone ID:
- Go to your domain in Cloudflare dashboard
- Scroll to "API" section
- Copy "Zone ID"
-
Configure in OEC.SH:
- Add DNS configuration
- Provider: Cloudflare
- API Token: Paste token
- Zone ID: Paste zone ID (optional)
DNS Record Examples
Simple Website:
example.com. 300 IN A 165.22.65.97
www.example.com. 300 IN CNAME example.com.Multiple Environments:
prod.example.com. 300 IN A 165.22.65.97
staging.example.com. 300 IN A 46.101.96.153
demo.example.com. 300 IN A 159.65.158.35Wildcard Setup:
*.apps.example.com. 300 IN A 165.22.65.97External Documentation
- Traefik Documentation (opens in a new tab)
- Let's Encrypt Documentation (opens in a new tab)
- Cloudflare API Documentation (opens in a new tab)
- DNS RFC 1035 (opens in a new tab)
Last Updated: December 11, 2024 Version: 1.0.0