Projects

gibcert

An awesome declarative TLS certificate manager.

gibcert is an awesome declarative TLS certificate manager. It lets you issue certificates from ACME or a local CA, automate certificate deployment, automate DANE, handle renewals and revocations, and more. It is a declarative tool, meaning you write what you want in a configuration file, review the pending changes, and then apply them. No more --issue -d example.com -d www.example.com --challenge-type dns-01 blah blah blah, we're not cavemen.

Why does this exist?

An ACME client is a pretty important tool for a sysadmin if you are doing things related to TLS, but so many ACME clients have little to no thought put into them and are taped together with hopes and dreams. I won't name them, but the ones I've tried have a number of issues like bad (or no) plugin system, bad CLI design and horrible ergonomics, absolute spaghetti unmaintainable code, and... RCE's, somehow. This is why gibcert was born, as a portable and declarative certificate management tool, inspired by OpenBSD acme-client and IaC tools like Terraform, DNSControl, and so on.

Features

ACME

  • HTTP-01, DNS-01, TLS-ALPN-01, and dns-persist-01 challenges
  • Built-in CA profiles: Let's Encrypt, ZeroSSL, Google Trust Services, Buypass, SSL.com
  • ACME Renewal Information (ARI): server-driven renewal scheduling
  • ACME profiles: request specific certificate types where supported
  • IP identifier support
  • CA failover: automatic fallback to alternate issuers during outages or rate-limits
  • DNS-01 providers: manual, RFC 2136/nsupdate, PowerDNS out of the box
  • External DNS: install a gibdns provider (Cloudflare, deSEC, Gcore, or your own) and point command at it
  • DNS alias mode: keep API tokens scoped to a separate delegated zone
  • Standalone HTTP-01 and TLS-ALPN-01 listeners when no external web server is available
  • dns-persist-01 with accounturi, issuer-domain-names, wildcard policy, and persistUntil

DANE / TLSA

  • Automatic TLSA record publication and rotation with safe pre-staging across renewals

Operations

  • Atomic deployment of cert, chain, fullchain, and key files with strict mode enforcement
  • Deploy hooks for reloading services after changed material is installed
  • Native remote deployment over SSH: install certificates on other hosts with the same staging, rollback, and hooks (docs/remote-deploy.md)
  • Certificate dependencies: sequence issuance across certs that rely on each other
  • Renewal and deploy groups: share settings and template deploy paths across certs
  • Plan mode: inspect every pending account, certificate, deploy, and hook action before committing
  • Prune: review and remove stale certificates, accounts, local CAs, and old account key archives with a dry run and per-item exceptions
  • Account deactivation: retire ACME accounts at the CA, on their own or as part of prune
  • Local CA support for private certificates

Portability

  • Single static binary, one single dependency (statically linked)
  • Runs on Linux, macOS, BSDs, Windows, Plan 9/9front, Illumos, and Solaris

Showcase

Here is a minimal example of a configuration that issues certs for example.com and www.example.com from Let's Encrypt:

challenge http-01 {
  webroot /var/www/acme-challenge
}

certificate example.com {
  account letsencrypt
  names example.com www.example.com

  deploy nginx {
    fullchain /etc/nginx/tls/example.com/fullchain.pem
    key /etc/nginx/tls/example.com/privkey.pem
    after "systemctl reload nginx"
  }
}

Before you do anything, you can check what is about to be created or changed with:

gibcert plan

If you want to be super careful, you can also check your config's syntax for errors without showing the pending changes:

gibcert check

And once you are ready to make those changes, you can run:

gibcert apply

Cool, right?