GoDoxy
Advanced Topics

Certificates

Configure certificates for GoDoxy

TL;DR

  • Main certificate covers all domains in autocert.domains
  • Extra certificates can be configured for additional domains
  • SNI selection: exact match > wildcard match, main cert > extra cert
  • Managed by lego (ACME) with DNS-01; auto-issued and auto-renewed
  • Bring your own certificate with provider: local
  • Short alias vs FQDN determines how domains match
  • match_domains restricts which base domains are valid
  • TCP on HTTPS: stream routes listening on the configured HTTPS_ADDR are matched by TLS SNI (same rules as HTTP). Without tls_termination, bytes are forwarded unchanged; with tls_termination: true and autocert, Godoxy terminates TLS and proxies plaintext to the upstream TCP port. Registration rejects TLS termination when no autocert provider is configured

Certificates

  • Main certificate covers every domain in autocert.domains

  • Extra certificates can be added via the extra field for additional domains

  • Based on SNI (Server Name Indication) from the client's TLS handshake

    • Exact match > wildcard match (e.g., app.example.com exact beats *.example.com wildcard)
    • Main cert > extra certificates when both match
    • Falls back to main cert if no match
  • Issued/managed by lego using ACME, typically Let's Encrypt via DNS-01

  • Auto-issue/renew with 1-hour cooldown after failures. Renewal happens when:

    • autocert is enabled but no certs are present
    • The set of autocert.domains no longer matches the loaded certificate
    • The certificate will expire within 30 days

TCP stream routes on the HTTPS listener

TCP routes whose listen address is the HTTPS entrypoint share the same TLS socket as the web UI and reverse proxies. GoDoxy inspects the ClientHello SNI to pick the stream route, using the same naming rules as HTTP routes:

  • Short alias: if SNI is mqtt.example.com and the route key is mqtt, the first label (mqtt) can select that route when it is registered under that name.
  • FQDN: the full normalized hostname can match the route when that is how the route is keyed.

Passthrough (default) — After SNI matching, the encrypted stream is forwarded as-is to host:port. Use this when the upstream speaks TLS (for example the upstream terminates HTTPS).

Termination — Set tls_termination: true only on a TCP route listening on the configured shared HTTPS_ADDR. Route validation rejects other listeners, and SNI route registration rejects TLS termination unless an operational autocert provider exists. GoDoxy matches ClientHello SNI, completes the TLS handshake using autocert, then proxies a plaintext TCP connection to the configured upstream. Leave tls_termination disabled for SNI passthrough when autocert is absent or when the upstream should serve its own certificate.

Extra Certificates

  • Must specify unique cert_path and key_path (no duplicates)

  • Inherit all configuration from the main config (except extra)

  • Participate in ACME cycles independently

  • Selected via SNI when the client's requested domain matches (exact or wildcard)

  • Main certificate takes precedence when both match

Autocert Configuration

FieldTypeDefaultRequiredDescription
providerstringlocalYesCertificate / DNS-01 provider
emailstring-YesACME email
domainsarray-YesCertificate domains
optionsobject-provider != localProvider-specific options
resolversarray-NoDNS resolvers
cert_pathstringcerts/cert.crtNoCertificate file path
key_pathstringcerts/priv.keyNoPrivate key file path
extraarray-NoAdditional certificates
ca_dir_urlstring-NoCA directory URL
ca_certsarray-NoCA certificates to use
eab_kidstring-NoEAB Key ID
eab_hmacstring-NoBase64 encoded EAB¹ HMAC
certificate_key_typestringEC256NoPrivate key algorithm for ACME-issued leaf certs (lego Certificate.KeyType)
  1. EAB refers to External Account Binding.

certificate_key_type applies only when GoDoxy obtains or renews the certificate via ACME (not for provider: local static files). Default is elliptic curve P-256 (EC256). Allowed values: EC256, EC384, RSA2048, RSA3072, RSA4096, RSA8192 (case-insensitive). Aliases: P256 / P384 for EC, and bare sizes 2048, 3072, 4096, 8192 for RSA. Invalid values are rejected during config validation. On an extra entry, a non-empty certificate_key_type overrides the main autocert setting for that certificate’s lego config.

Using Existing SSL Certificate

autocert:
  provider: local
  # path relative to /app
  cert_path: certs/cert.crt
  key_path: certs/priv.key

Autocert with Cloudflare

Use certificate_key_type when you need an RSA leaf (for example clients without ECDSA, such as some IoT TLS stacks). See the table above for all allowed values.

autocert:
  provider: cloudflare
  email: your-email@example.com
  domains:
    - "*.yourdomain.com"
  # certificate_key_type: RSA2048
  options:
    auth_token: your-zone-api-token

Autocert with a Custom Internal CA

You may use internal CA like step-ca for issuing certificates.

Use step-ca as an example:

export ACME_URL=https://acme.internal
# get root certs and save to `certs/roots.pem`
# assume that `certs/` is mounted to `/app/certs` (by default)
curl -k https://${ACME_URL}/roots.pem > certs/roots.pem
autocert:
  provider: custom
  email: your-email@example.com
  domains:
    - "*.yourdomain.com"
  ca_dir_url: https://acme.internal/acme/acme/directory
  ca_certs:
    - certs/roots.pem

EAB

If using EAB (External Account Binding), set eab_kid and eab_hmac in autocert. Also works with custom ACME CAs.

autocert:
  provider: custom
  email: your-email@example.com
  domains:
    - "*.yourdomain.com"
  eab_kid: your-eab-kid
  eab_hmac: base64-encoded-hmac

Multiple Certificates with SNI

Configure multiple certificates for different domains. GoDoxy uses SNI to select the appropriate certificate during TLS handshake.

domains is ignored for local provider.

Example: Multiple certificates with different providers

autocert:
  provider: cloudflare
  email: your-email@example.com
  domains:
    - "*.example.com"
  options:
    auth_token: your-zone-api-token
  extra:
    # Extra cert 1: Same provider, different domain
    - cert_path: certs/other.crt
      key_path: certs/other.key
      domains:
        - "*.other.com"
      # Inherits provider, email, options from main config

    # Extra cert 2: Different provider (custom CA)
    - cert_path: certs/internal.crt
      key_path: certs/internal.key
      provider: custom
      # certificate_key_type: RSA2048  # optional; overrides main autocert when set
      domains:
        - "*.internal.local"
      ca_dir_url: https://ca.internal/acme/directory

    # Extra cert 3: Local/static certificate
    - cert_path: certs/static.crt
      key_path: certs/static.key
      provider: local
      domains:
        - "*.services.internal"
      # Static certificate, no ACME obtain/renew

SNI Selection Behavior:

Based on the example above, certificate selection works as follows:

HostnameSelected CertificateMatch Type
app.example.comMain certExact match (*.example.com)
sub.example.comMain certWildcard match (*.example.com)
api.other.comExtra cert 1Wildcard match (*.other.com)
service.internal.localExtra cert 2Wildcard match (*.internal.local)
db.services.internalExtra cert 3Wildcard match (*.services.internal)
unknown.comMain cert (fallback)No match

Selection Precedence:

  1. Exact match > wildcard match
  2. Main cert > extra certificates when both match
  3. Falls back to main cert if no match

Other DNS providers

Check DNS-01 Providers

Troubleshooting

If you encounter issues:

  • Set LEGO_DISABLE_CNAME_SUPPORT=1 if your domain has a CNAME record
  • Try different DNS resolvers via autocert.resolvers

On this page