Quickstart¶
The fastest path: a single host with outbound internet access getting a certificate for a name it can't serve on port 80. This is standalone mode; the other modes build on the same core.
1. Build¶
$ git clone https://github.com/amitpatole/gapcert && cd gapcert
$ make build
$ ./bin/gapcert version
0.1.0
Go 1.26+ is required to build. The result is a static binary with no runtime dependency.
2. Delegate the challenge (recommended)¶
So gapcert never needs write access to your production DNS zone, pre-create a one-time CNAME pointing the challenge name at a dedicated challenge zone (an acme-dns instance works well):
Now a credential that can only write to acme.example.com is enough to prove
control of web.internal.example.com. See configuration
for the other solvers (Route53, Cloudflare, RFC2136/TSIG).
3. Configure¶
Write ~/.config/gapcert/config.yaml:
ca: letsencrypt-staging # switch to `letsencrypt` once it works
email: ops@example.com
certificates:
- name: web
domains: ["web.internal.example.com"]
solver: challenge-zone
hook: "systemctl reload nginx" # run after a successful (re)issue
solvers:
challenge-zone:
type: acme-dns
api_base: https://acme-dns.example.com
storage_path: ~/.config/gapcert/acme-dns.json
Start on staging
Point ca at letsencrypt-staging first. Let's Encrypt's production
endpoint has strict rate limits; staging lets you iterate freely. Switch to
letsencrypt once a staging issue succeeds.
4. Issue¶
$ gapcert issue
web obtaining [web.internal.example.com] via challenge-zone ...
web stored ~/.local/share/gapcert/certs/web
web hook ok
The private key was generated locally and written 0600; only a CSR left the
host. Check what you have and when it expires:
5. Keep it renewed¶
Run gapcert renew from cron or a systemd timer. It re-issues only
certificates inside their renewal window, rotates the key, and fires the
deploy hook:
That's the whole loop for one host. If your hosts can't reach the internet directly, keep the credentials off every box with the broker; if they have no network at all, use the courier.