Skip to content
early · pre-1.0 Latest: v0.1.0

Set-and-forget TLS
for every machine.

One static binary and a systemd timer. Every Linux host gets its own auto-renewing certificate — from Let's Encrypt, Vault, or step-ca — delivered to nginx, HAProxy, Cockpit & co. with the exact owner, mode, and SELinux context each needs.

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

Inspect the script first ↗ · verify sha256sums.txt · no host certbot required

// the chore nobody wants to own

Stop babysitting certificates.

You terminate public TLS at the edge — but the hop from there to your backends, and traffic between internal services, is often plaintext or hand-made certs that expire and page someone at 2 a.m. syscert makes every host responsible for its own cert, automatically.

Without syscert

  • Run an internal CA, then issue + copy + chmod per host
  • Cron jobs and shell scripts you hope still work
  • Reload nginx by hand; fix SELinux denials later
  • A renewal nobody owns → an outage at 2 a.m.

With syscert

  • One binary per host; it owns its own certificate
  • A systemd timer renews it forever — no cron
  • Delivered with the right owner, mode & SELinux context
  • Set it once. Walk away. It just stays valid.

// ~5 minutes, start to finish

Three steps, then forget about it.

  1. 1

    Install

    One static binary + a systemd timer. Download or build, then run install.sh.

  2. 2

    Edit two files

    Your subject & CA in syscert.toml; DNS/CA credentials in the secrets env file.

  3. 3

    Done

    The timer issues, renews and distributes — forever. No cron, no babysitting.

/etc/syscert/syscert.toml
[cert]
hostname = "host.example.com"
sans     = ["api.example.com"]

[acme]
ca        = "letsencrypt"
email     = "you@example.com"
challenge = "dns-01"

[acme.dns]
provider = "cloudflare"

[[distribute]]  # deliver to nginx
artifact = "fullchain"
path     = "/etc/nginx/tls/fullchain.pem"
owner    = "root"
group    = "nginx"
mode     = "0644"
/etc/syscert/secrets 0640
# credentials stay out of the .toml; the service
# loads this file as its environment.
CLOUDFLARE_DNS_API_TOKEN=••••••••••••••••
Then the timer takes over — syscert ensure runs on a schedule and keeps every artifact fresh.

// what you actually get

Built like infrastructure, not a script.

No cron, no scripts

A systemd timer keeps every cert fresh forever. Nothing to schedule, nothing to maintain.

Least-privilege by design

Runs as its own hardened, unprivileged service user. It touches certs — nothing else.

Exact owner, mode & SELinux

Each consumer gets its artifact with the ownership, permissions and SELinux context it needs.

certbot-compatible output

Writes cert.pem · privkey.pem · chain.pem · fullchain.pem, plus an all-in-one bundle.pem.

mTLS between services

Run it on both ends against an internal CA — each side gets its own cert and verifies the other.

Multi-CA, your choice

Public Let's Encrypt, or an internal HashiCorp Vault / Smallstep step-ca over ACME.

// plays with what you already run

Compatibility.

Certificate authorities
Let's EncryptHashiCorp VaultSmallstep step-caany ACME CA
Consumers
nginxHAProxyCockpitPostgreSQLRedissyslog / metrics
Operating systems
DebianUbuntuRHEL familyRockyAlmaFedora
Architectures
linux/amd64linux/arm64

// one binary, the whole lifecycle

A command for every stage.

syscert --help
  • $ syscert ensure default The default. Issue if missing, renew if due, then distribute.
  • $ syscert issue Force a fresh certificate now.
  • $ syscert renew Renew if inside the renewal window.
  • $ syscert distribute Copy artifacts to their consumer paths.
  • $ syscert dry-run Show exactly what would happen — change nothing.
  • $ syscert void Revoke the current certificate.
  • $ syscert destroy Revoke and remove local state.
  • $ syscert trust install Add the CA to the system trust store (and remove).

// independent & open source

Support this project.

syscert is free, AGPL-3.0, and built in the open. If it saved you a 2 a.m. page, a coffee keeps it moving.

☕ Support on Ko-fi

Give every host its own TLS.

One command. Then never think about certificate renewal again.

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