5 min read Grounded in README.md Why CertMate? / Key Features

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:

  1. 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.
  2. 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-challenge records.
  3. Scoped API keys with per-domain allowlists. A token can be scoped to role=operator and allowed_domains=[*.api.example.com, ops.example.com]. Out-of-scope requests return 403 DOMAIN_OUT_OF_SCOPE and are written to the audit log. Useful when the certificate manager has to live next to a CI runner or a small ops team.
  4. 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.