Files
RustProxy/docs/ACME_PROVIDERS.md
T
2026-10-06 23:08:43 +02:00

7.5 KiB

0.7 update: configured managed certificates now have automatic renewal and validated hot deployment. Initial issuance/import remains explicit. Read RENEWAL.md for defaults, retained profiles and opt-out.

Certificate providers

Source implementation; real provider/DNS/CA issuance and Rust runtime have not been verified in the packaging environment. Offline tests substitute Certbot, so they cannot establish that a DNS token, zone policy or CA deployment works.

Workflow

Open Certificates -> Add certificate. Choose one provider or import mode, enter the domains and metadata, then request issuance. Production is selected by default in the panel and still requires the separate explicit production confirmation. Staging remains available for testing and its certificates are not browser-trusted. After a successful job, import its validated pair into the library, then assign the certificate to a vhost. No CA operation occurs on startup or merely opening a form.

Selection Mechanism and required configuration
HTTP-01 / domain validation Certbot webroot; domain names and a publicly reachable plaintext HTTP listener
Cloudflare DNS-01; scoped API token; certbot-dns-cloudflare installed
OVH DNS-01; ovh-eu or ovh-ca, application key/secret, consumer key; certbot-dns-ovh installed
RFC2136 DNS-01; server/port, TSIG name/secret/algorithm; certbot-dns-rfc2136 installed
PEM import Upload fullchain/certificate and corresponding private key, then validate
Existing server files Advanced: reference a PEM pair already in the certificate directory

Python 3 and Certbot must be executable by the RustProxy service user. Install plugins in that SAME Certbot environment. The application does not install packages or execute sudo. Check the CLI installation with bash dev.sh acme --doctor and certbot plugins; this does not validate provider credentials or DNS reachability. DNS uses the API/plugin appropriate to the selected provider, not a Cloudflare Tunnel integration or a hand-written replacement for ACME.

The shipped OCI image already contains Certbot plus the Cloudflare, OVH and RFC2136 plugins in one dedicated Python environment. Host/source installations remain under the operator's package-management policy and must provide the plugins they use.

HTTP-01 requirements and scope

Public TCP port 80 for every requested name must reach an active plaintext RustProxy listener. NAT from public 80 to a private/custom HTTP port is allowed; setting only port 8080 in public DNS is not sufficient. Check all published A/AAAA addresses and multi-node routing. TLS-only listeners are not enough. There is no TLS-ALPN-01 mode. This implementation accepts DNS names, not IP certificates. Wildcard certificates require one of the DNS-01 providers, not HTTP-01.

During a running HTTP-01 job, RustProxy serves only /.well-known/acme-challenge/<token> for that job's exact normalized hostnames. Only GET/HEAD and bounded regular files from certs/acme-http01 are accepted; queries, traversal, unrelated names, HTTPS requests and inactive jobs cannot read these files. The reserved path precedes application auth/cache/static pages so a CA can validate ownership without logging in. This exception does not bypass application authentication for any other path. Responses are no-store.

A CDN or upstream proxy must forward this path and the correct Host without rewriting it. There is no automatic forwarding configuration at your DNS/CDN vendor. Expired challenge jobs do not leave an open generic file server.

DNS credentials and least privilege

Cloudflare: use an API token with Zone:DNS:Edit restricted to the zones used for issuance. The adapter intentionally does not accept the account-wide Global API Key.

OVH: use a consumer key allowing GET /domain/zone/ and GET/PUT/POST/DELETE for /domain/zone/<YOUR_ZONE>/*. Repeat only for required zones, not the whole account. Choose the region matching the account. Consult the official plugin docs if API policies change. A domain registered at OVH but DNS hosted elsewhere must use the actual authoritative DNS provider; registration alone is not sufficient.

RFC2136: retain the TSIG-limited update policy described in ACME_RFC2136.md. DNS provider propagation delay is configurable. The helper rejects malformed tokens, unknown/cross-provider fields and INI injection. It does not test your DNS policy in advance. Wildcard DNS-01 issuance does not add wildcard HOST routing: vhost hostnames remain exact matches.

API input

Common fields: provider, certificate_id, domains (one or more DNS names), email, environment (staging/production), agree_tos, confirm_production. RustProxy does not impose its own domain-count ceiling; the selected CA/provider may still apply its external certificate/SAN policy. DNS providers accept propagation_seconds.

Provider-specific fields:

  • http01: none; wildcard domains are rejected.
  • cloudflare: api_token.
  • ovh: endpoint, application_key, application_secret, consumer_key.
  • rfc2136: dns_server, dns_port, key_name, key_secret, key_algorithm, sign_query.

POST /api/acme/issue is authenticated and CSRF-protected; one job runs at a time. GET /api/acme is safe status metadata only. Job status is process-local; account and credential files persist. A completed certificate has optional issuer metadata with provider/environment, not a copy of request credentials.

Secret storage, renewal and limitations

Provider secrets are sent to the private worker on stdin, not command arguments. They are not stored in exported JSON, SQLite, localStorage or audit records. Files are private (0600 credentials, 0700 directories); these permissions do NOT encrypt them. The service user/root can read them. Certbot account/lineage state and provider credential files persist for managed renewal under certs/acme/<environment>-<id>-<provider>; RFC2136 keeps its old path without a provider suffix. Issued PEM outputs use new immutable names before library import.

Back up these private profiles separately while issuance is idle: the standard SQLite/configured-PEM backup does not include every account/credential profile. Do not put real credentials into shell history or source-control examples. Restrict the admin interface and service environment. Rotate exposed API credentials.

Configured managed certificates in 0.7 renew through the shared RustProxy worker; validated changed material is published automatically while failed checks preserve the active generation. Use the certificate's toggle to disable scheduled renewal. PEM-only imports remain manual. A separate system Certbot timer may own a different, manual RustProxy certificate id and publish it with tls deploy --id ...; it must not also own a RustProxy-managed ACME profile. There is no external expiry alert, revocation or certificate garbage collector. Cancellation kills the worker group; interrupted DNS cleanup can leave TXT records an operator must remove. See renewal and recovery and test CA staging first.

Primary references

These document upstream requirements, not evidence that this RustProxy build has passed live provider or CA acceptance.