Skip to content

// docs · quick start

Quick start

Install the binary, edit two files, and every renewal after that is automatic. About five minutes from nothing to a live, self-renewing certificate.

1 · Install

One static binary and a systemd timer. The one-liner downloads the release binary, verifies its checksum, and runs the installer:

curl -fsSL https://syscert.tfindley.dev/install.sh | sudo sh

It creates the dedicated syscert system user, the canonical store at /var/lib/syscert, a starter config and secrets file, installs the systemd units, and enables (does not start) the timer — so the first run can’t fire against an unconfigured config. Prefer to inspect the script, verify checksums by hand, or build from source? See Advanced install.

2 · Configure two files

The installer writes starters you edit in place. First the config — your subject, CA, challenge, and where the certificate is delivered:

# /etc/syscert/syscert.toml
[cert]
hostname = "host.example.com"     # omit to use the system FQDN
sans     = ["api.example.com"]    # optional extra DNS names

[acme]
ca        = "letsencrypt"         # public CA; use "custom" for Vault / step-ca
email     = "you@example.com"
challenge = "dns-01"              # no inbound ports needed

[acme.dns]
provider = "cloudflare"           # any lego DNS provider id

[[distribute]]
artifact = "fullchain"
path     = "/etc/nginx/tls/fullchain.pem"
owner    = "root"
group    = "nginx"
mode     = "0644"

[[distribute]]
artifact = "privkey"
path     = "/etc/nginx/tls/privkey.pem"
owner    = "root"
group    = "nginx"
mode     = "0600"                 # key-bearing → not world-readable

Then the credentials your DNS provider needs. These are read from the environment, never the TOML. Look up the exact variable names for your provider in the lego DNS provider list:

# /etc/syscert/secrets   (env file, 0640 — never put secrets in the .toml)
CLOUDFLARE_DNS_API_TOKEN=your-token-here

Internal CA? Set ca = "custom" and directory_url to your Vault or step-ca ACME endpoint — see Configuration.

3 · Validate, then test on staging

Check the config offline first, then do a real run against Let’s Encrypt staging (no rate-limit risk, certs aren’t publicly trusted):

sudo -u syscert syscert dry-run --config-only   # offline checks, no network
sudo -u syscert syscert --staging               # real issue + distribute, LE staging

A passing offline check prints the resolved subject, CA, and challenge:

config OK:
  subject:   host.example.com
  CA:        letsencrypt
  challenge: dns-01

A failing check lists every problem with an actionable message and exits non-zero — fix those before going live. The full dry-run (without --config-only) performs the real ACME order and challenge, then discards the certificate.

4 · Go live

Happy with staging? Drop --staging, then hand the job to the timer:

sudo -u syscert syscert              # issue + distribute against production
sudo systemctl start syscert.timer   # hand it over to the timer
systemctl list-timers syscert.timer  # confirm it's scheduled

That’s it. The timer runs shortly after boot and daily with jitter, renewing when due and re-delivering to your consumers every time — no cron, no scripts.


Next: Configuration reference · Distributing certs · Troubleshooting