What CertMate is (and isn't)
CertMate is a self-hosted certificate manager: a web UI and REST API around certbot, with first-class DNS-01 across 23 DNS providers, role-scoped API keys, and a deploy-hook system that pushes renewals to your edge. Here's where it fits.
Most operators already have a way to get TLS certificates. They have a
cron, a certbot renew, and a memory of the time the cron
silently broke and a cert expired on a Friday afternoon. The question
isn't "how do I get a cert" — it's "how do I run cert
issuance so I don't have to think about it again".
CertMate answers that question. It's a service, not a script: a Flask app with a web UI, a REST API, persistent state, role-based access control, an audit log, and DNS-01 plugins for 23 DNS providers. You point it at a domain, pick a provider, and it issues the certificate and keeps it renewed. When a renewal lands it fires a configurable shell command per domain so nginx / HAProxy / your edge cluster gets the new bundle without manual intervention.
The four things that make CertMate distinct
Reading the repo in order, four design choices stand out:
- DNS-01 first. Every certificate flows through the DNS-01 challenge. HTTP-01 isn't even an option in the UI. That sounds restrictive but it's deliberate: DNS-01 is the only path to wildcard certificates, it works for hosts that aren't on the public internet, and it doesn't need port 80 open anywhere. The cost is that you need API credentials for your DNS provider; CertMate ships 23 first-class adapters so most operators already have one.
- Multi-account, multi-provider DNS. You can have
Cloudflare-production, Cloudflare-staging, Route53-archive, and a
PowerDNS for an internal subzone — all configured at once, each
certificate pinned to the account that should manage its
_acme-challengerecords. - Scoped API keys with per-domain allowlists. A
token can be scoped to
role=operatorandallowed_domains=[*.api.example.com, ops.example.com]. Out-of-scope requests return403 DOMAIN_OUT_OF_SCOPEand are written to the audit log. Useful when the certificate manager has to live next to a CI runner or a small ops team. - Deploy hooks as a first-class contract. When a cert is created, renewed, or revoked, CertMate runs configured shell commands with the new file paths exposed as environment variables. No symlink-shuffling, no "where did the new cert go" — see the deploy hooks topic for the exact contract.
Where it fits vs the alternatives
vs certbot
Certbot is the tool CertMate runs internally. The difference is the envelope: certbot is a CLI you invoke; CertMate is a service that invokes certbot, stores the result, talks HTTP to your other systems, and survives a restart. If your fleet is one VPS with two domains, certbot + a cron is the right answer. If your fleet has 30 domains, three DNS providers, and you'd like someone to be able to request a certificate without ssh-ing into anything, CertMate is the right answer.
vs Caddy
Caddy is a reverse proxy that does automatic HTTPS as a feature of serving traffic. It's brilliant when your TLS lives at the same process that terminates HTTPS. It's not the answer when your TLS needs to live somewhere else — a sibling cluster, an S3 bucket consumed by mTLS clients, a hardware load balancer, an edge service you don't run. CertMate is the cert factory; what you feed the cert to is your decision.
vs Traefik
Same shape as Caddy. Traefik's ACME integration is excellent when Traefik is the only consumer of the certificate. The moment a second consumer exists — even a backup nginx that just needs the same cert — you end up either duplicating issuance or syncing certs around. CertMate solves the "one cert, many consumers" problem by being the single source and pushing via deploy hooks.
vs an internal PKI (Vault, Smallstep, cert-manager)
Different problem. Internal PKIs issue certificates from your own
CA for service-to-service mTLS. CertMate issues certificates from a
public CA (Let's Encrypt, ZeroSSL, Google Public CA — see
docs/ca-providers.md) for the public hostnames your
users hit. Run both if you need both; CertMate's
client-certs subsystem also issues internal mTLS certs from
a local CA, but that's a complementary path, not a replacement for
Vault.
When CertMate is overkill
Be honest: if your domain count is one, your host count is one, and your renewal contract is "let certbot handle it on the host that serves the traffic," CertMate is more service than you need. The inflection points where it pays for itself are:
- You need wildcard certificates (the answer is always DNS-01).
- Your cert lives on a host that doesn't speak port 80 to the public internet.
- You have more than one consumer for the same cert.
- You have a compliance requirement to audit who renewed what.
- You want a non-technical operator to be able to request a cert without shell access.
Reading the source
The pieces worth knowing about, in order:
modules/core/— the issuance, renewal, and deploy logic.modules/web/— Flask routes, RBAC, audit.docs/— operator-facing docs, hand-written.- The conversational sidecar lives in a sibling repo: certmate-agent. Not required for CertMate itself; useful if you want to talk to CertMate in natural language instead of clicking around.