Features
DNS & Domains
Domain Management

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.com

Routing Flow

DNS Provider → DNS Record → Traefik Labels → Container
   (A/CNAME)      (Zone)     (Router/Service)   (Port 8069)

DNS Providers

Supported Providers

ProviderStatusFeaturesAuthentication
Cloudflare✅ Fully SupportedOrange cloud proxy, API v4, Zone managementAPI Token
Route53🔜 Coming SoonAWS DNS, Hosted zonesAccess Key + Secret
Azure DNS🔜 Coming SoonAzure DNS zonesService Principal
Google Cloud DNS🔜 Coming SoonCloud DNS zonesService Account
DigitalOcean🔜 Coming SoonDO DNSAPI 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.sh
  • acme-staging.apps.oec.sh
  • bigcorp-demo.apps.oec.sh

Automatic DNS Creation

When an environment is deployed, OEC.SH automatically:

  1. Generates Subdomain: Based on project slug and environment name
  2. Creates A Record: Points subdomain to the server's IP address
  3. Configures Traefik: Adds routing labels to the Odoo container
  4. Requests SSL Certificate: Let's Encrypt HTTP-01 challenge
  5. Enables HTTPS: Automatic redirect from HTTP to HTTPS

DNS Record Example:

acme-production.apps.oec.sh.  300  IN  A  165.22.65.97

System 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: If true, automatically creates DNS record in provider
  • proxied: Enable Cloudflare orange cloud (proxy mode)
  • is_primary: Set as the primary domain for the environment
  • target_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.97

AAAA 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::1

CNAME 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:

  1. Log into your DNS provider
  2. Create A record: erp.example.com165.22.65.97
  3. Wait for DNS propagation (5-60 minutes)
  4. Verify domain in OEC.SH

For CNAME Record:

  1. Log into your DNS provider
  2. Create CNAME record: erp.example.comacme-production.apps.oec.sh
  3. Wait for DNS propagation (5-60 minutes)
  4. 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:

  1. Checks DNS propagation across multiple resolvers (Google, Cloudflare, Quad9)
  2. Verifies DNS record exists in provider
  3. Marks domain as verified
  4. 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 address
  • target_cname: Change target hostname
  • ttl: Change time to live
  • proxied: Toggle Cloudflare proxy mode
  • is_primary: Set as primary domain
  • is_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: If true (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:

  1. Environment deployed with Traefik labels
  2. User accesses domain via HTTPS
  3. Traefik requests certificate from Let's Encrypt
  4. HTTP-01 challenge validation
  5. Certificate issued and stored
  6. 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:

  1. DNS provider creates TXT record: _acme-challenge.apps.oec.sh
  2. Let's Encrypt validates domain ownership via DNS-01
  3. Wildcard certificate issued: *.apps.oec.sh
  4. Certificate installed on Traefik
  5. 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 enabled
  • pending: Certificate requested, waiting for issuance
  • active: Certificate issued and valid
  • expired: Certificate expired, renewal needed

Wildcard Cert Status Values:

  • not_requested: Wildcard SSL not enabled
  • pending: Certificate request in progress
  • active: Certificate issued and valid
  • expired: Certificate expired
  • error: 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.com

Response:

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 balancing

Traefik 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-public

DNS 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 DNS
  • 1.1.1.1 - Cloudflare DNS
  • 9.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.9

Using nslookup:

nslookup erp.example.com 8.8.8.8

Using host:

host erp.example.com 8.8.8.8

Online Tools:

Propagation Times

DNS ProviderTypical Propagation
Cloudflare1-5 minutes
Route535-10 minutes
GoDaddy10-30 minutes
Namecheap10-30 minutes
GenericUp 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.sh

Collision 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.153

Wildcard 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.97

Result: All subdomains of apps.mycompany.com resolve to 165.22.65.97:

  • acme-prod.apps.mycompany.com165.22.65.97
  • bigcorp-staging.apps.mycompany.com165.22.65.97
  • anything.apps.mycompany.com165.22.65.97

Wildcard SSL Certificate

Combine wildcard DNS with wildcard SSL for instant HTTPS on all environments.

Setup:

  1. Configure wildcard DNS: *.apps.mycompany.com → 165.22.65.97
  2. Add DNS configuration with wildcard SSL enabled
  3. Request wildcard certificate: *.apps.mycompany.com
  4. 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 identifier
  • name: 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 address
  • AAAA - IPv6 address
  • CNAME - Canonical name
  • TXT - Text record
  • MX - Mail exchange (requires priority)
  • NS - Name server
  • SRV - Service record (requires priority)
  • 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

PermissionActionDescription
org.dns.createCreate DNS configs and domainsAdd DNS providers and custom domains
org.dns.listView DNS configs and domainsList configurations and domains
org.dns.updateModify DNS configs and domainsUpdate settings and request SSL
org.dns.deleteRemove DNS configs and domainsDelete configurations and domains
org.dns.syncVerify and sync DNS recordsTrigger DNS verification
org.dns.zones.listList DNS zonesView available zones in provider

Role Permissions

RoleDNS Permissions
Portal AdminAll permissions
Org OwnerAll permissions
Org AdminAll permissions
Org MemberList only
Project AdminList only
Project MemberList only

Troubleshooting

DNS Record Not Updating

Symptoms: DNS record created but not resolving.

Solutions:

  1. Check DNS propagation time (5-60 minutes typical)
  2. Verify record was created in provider dashboard
  3. Check DNS with multiple resolvers:
    dig +short domain.com @8.8.8.8
    dig +short domain.com @1.1.1.1
  4. Verify TTL hasn't cached old value
  5. 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:

  1. Verify DNS points to correct IP address
  2. Check Traefik container is running
  3. Ensure port 80 is open and accessible
  4. Verify domain resolves globally (use dnschecker.org)
  5. Wait for full DNS propagation before retrying

Error: "certificate has expired"

Cause: Auto-renewal failed or certificate expired.

Solutions:

  1. Check Traefik logs for renewal errors
  2. Verify Let's Encrypt rate limits not exceeded
  3. Manually trigger renewal (restart environment)
  4. Check acme.json file permissions

Error: "too many certificates"

Cause: Let's Encrypt rate limit exceeded (50 certificates per domain per week).

Solutions:

  1. Use wildcard SSL to reduce certificate requests
  2. Wait 7 days for rate limit reset
  3. Use staging Let's Encrypt for testing
  4. Consolidate domains to reduce unique certificates

DNS Verification Failed

Symptoms: Domain verification fails or times out.

Solutions:

  1. Verify DNS record exists and is correct:
    dig +short domain.com @8.8.8.8
  2. Check DNS propagation across multiple resolvers
  3. Increase TTL to 300 seconds for faster updates
  4. Wait longer for global propagation (up to 48 hours)
  5. Check DNS provider API credentials are valid

Cloudflare Orange Cloud Issues

Symptoms: SSL errors, 522 errors, timeouts with proxied domains.

Solutions:

  1. Verify SSL/TLS mode is "Full (Strict)" in Cloudflare
  2. Ensure origin certificate is valid
  3. Check Cloudflare firewall rules not blocking traffic
  4. Verify WebSocket support enabled in Cloudflare
  5. Increase Cloudflare timeout for long-running requests

Wildcard SSL Not Working

Symptoms: Wildcard certificate request fails.

Solutions:

  1. Verify DNS provider supports API access
  2. Check DNS-01 challenge TXT record created:
    dig +short _acme-challenge.apps.oec.sh TXT @8.8.8.8
  3. Ensure wildcard domain matches configured domain
  4. Check DNS provider credentials have correct permissions
  5. Review certificate request logs for specific errors

Domain Shows "Wrong" Site

Symptoms: Domain shows another environment or 404 error.

Solutions:

  1. Check Traefik labels on container:
    docker inspect container_name | grep traefik
  2. Verify Host() rule includes correct domain
  3. Check for label conflicts (duplicate router names)
  4. Restart Traefik to reload configuration:
    docker restart traefik
  5. 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

  1. Use Low TTL During Setup: Set TTL to 300 seconds (5 minutes) for faster updates
  2. Increase TTL After Stable: Raise to 3600 seconds (1 hour) after DNS is stable
  3. Verify Before SSL: Always verify DNS propagation before requesting certificates
  4. Use Wildcard for Scale: Enable wildcard SSL if managing many environments
  5. Monitor Expiry: Track certificate expiration dates and ensure auto-renewal works

Security

  1. Protect API Tokens: Store DNS provider credentials securely (platform encrypts automatically)
  2. Limit Token Permissions: Use minimal DNS permissions (Zone:DNS:Edit for Cloudflare)
  3. Rotate Tokens Regularly: Update API tokens every 90 days
  4. Use HTTPS Only: Always enforce HTTPS redirect (automatic in OEC.SH)
  5. Monitor Certificate Status: Set up alerts for SSL certificate issues

Performance

  1. Use Cloudflare Proxy: Enable orange cloud for DDoS protection and CDN
  2. Geo-Distribute: Use multiple servers in different regions with same domain
  3. Enable HTTP/2: Traefik enables HTTP/2 automatically with SSL
  4. Optimize TTL: Balance between propagation speed and DNS query load
  5. Cache Static Assets: Use Cloudflare page rules for caching

Operational

  1. Document Domains: Keep track of which domains point to which environments
  2. Test Before Production: Verify DNS and SSL on staging domains first
  3. Plan Migrations: Use low TTL before changing IPs
  4. Backup DNS Records: Export DNS records before major changes
  5. Monitor Propagation: Use DNS monitoring tools to detect issues

API Reference

DNS Configurations

EndpointMethodPermissionDescription
/api/v1/dns/providersGETNoneList supported DNS providers
/api/v1/dns/verify-credentialsPOSTNoneVerify credentials and list zones
/api/v1/dns/configsPOSTorg.dns.createCreate DNS configuration
/api/v1/dns/configs/org/{org_id}GETorg.dns.listList DNS configurations
/api/v1/dns/configs/{id}GETorg.dns.listGet DNS configuration
/api/v1/dns/configs/{id}PATCHorg.dns.updateUpdate DNS configuration
/api/v1/dns/configs/{id}DELETEorg.dns.deleteDelete DNS configuration
/api/v1/dns/configs/{id}/verifyPOSTorg.dns.listVerify credentials
/api/v1/dns/configs/{id}/request-wildcard-sslPOSTorg.dns.updateRequest wildcard SSL
/api/v1/dns/configs/{id}/zonesGETorg.dns.zones.listList DNS zones

Domains

EndpointMethodPermissionDescription
/api/v1/dns/domainsPOSTorg.dns.createCreate domain
/api/v1/dns/domains/environment/{env_id}GETorg.dns.listList environment domains
/api/v1/dns/domains/{id}GETorg.dns.listGet domain
/api/v1/dns/domains/{id}PATCHorg.dns.updateUpdate domain
/api/v1/dns/domains/{id}DELETEorg.dns.deleteDelete domain
/api/v1/dns/domains/{id}/verifyPOSTorg.dns.syncVerify domain

DNS Records

EndpointMethodPermissionDescription
/api/v1/dns/configs/{config_id}/recordsPOSTorg.dns.createCreate DNS record
/api/v1/dns/configs/{config_id}/zones/{zone_id}/recordsGETorg.dns.listList DNS records

Additional Resources

Cloudflare Setup

  1. Create API Token:

  2. Get Zone ID:

    • Go to your domain in Cloudflare dashboard
    • Scroll to "API" section
    • Copy "Zone ID"
  3. 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.35

Wildcard Setup:

*.apps.example.com.  300  IN  A  165.22.65.97

External Documentation


Last Updated: December 11, 2024 Version: 1.0.0