// release history
Changelog
Notable changes per release, newest first. Follows Keep a Changelog and Semantic Versioning.
[v0.4.0] — 2026-07-19
Features
feat(cli): add —interval scheduler mode for non-systemd contexts (7a19f00) feat(web): build a procedures download zip in CI; slot Procedures in the menu (43f6a19)
Bug Fixes
fix(ci): exclude web/site/ci-scoped commits from the binary version bump (ac667de) fix(ci): backward-parity gate falsely flagged real multi-word commands (6194e77) fix(acme): drop unbuildable dns-persist-01; reject it at config validation (93aa669) fix(web): serve CSP frame-ancestors as an HTTP header (48439c4) fix(web): self-host fonts and add a Content-Security-Policy (75673d9)
Documentation
docs: add Comparison page (syscert vs certbot; when to use which) (#4) (a34adb7) docs: human-rewrite all public docs + site copy (voice only) (010ca37) docs: add Comparison page (syscert vs certbot; when to use which) (a8c4138) docs: add Containerisation section + container reference examples (d9085b3) docs(spec): containerising syscert — design (5f336c0) docs: roadmap — add “reissue on config drift” to Next (69e3821) docs: fix accuracy issues found in the documentation audit (c1fb2e6) docs: add formal Procedures section (index + 11 SOPs) (0384883) docs: note self-hosted fonts and CSP in tech-stack page (883f80c) docs: add an upgrading guide under advanced install (b9416aa) docs(compliance): add Tech stack and AI-assisted development pages (d0edbef) docs(compliance): nest the security assessment under a Compliance section (6700cc7) docs(security): publish the security assessment + risk register (0912953)
Other
Docs comparison (#6) (912efdf) ci+pkg: backward command↔docs parity gate; correct secrets log string (87438bd) Merge branch ‘web-surface-headers’ (9426efd)
Risk & Security
Low risk. The only new runtime surface is the opt-in --interval scheduler; certificate
issuance, key handling, the privilege model, and secret/trust handling are otherwise
unchanged. A /security-review of v0.3.1..HEAD found no vulnerabilities.
- Go 1.26.5 is the headline fix. It patches two reachable standard-library advisories
that
govulncheckflagged on the previous toolchain — GO-2026-5856 (crypto/tls) and GO-2026-4970 (os). The release build now reports zero affecting vulnerabilities. --intervalis a scheduler, not a daemon. It’s opt-in (bare one-shot stays the default), runs no external commands, and reads only a flag/env duration, floored at 1m so it can’t hammer the CA.SIGTERM/SIGINTcancel at a cycle boundary, so an in-flight issuance or key/store write always finishes before exit — no partial or corrupt key material. A failed cycle logs at error level and retries on the next tick; a bad config still exits non-zero before the loop even starts. ADR-0046 scopes it as a container/appliance scheduler, not a host service — the systemd timer path is unchanged (ADR-0033).- Dropping
dns-persist-01only tightens validation. The unbuildable challenge is now rejected up front atdry-runwith a clear message instead of failing mid-issuance; no code path is widened. - Nothing changed in secrets, keys, permissions, or trust. Secrets stay env- or
0640-file-only and unlogged, private keys0600, and the internal-CAtrustcommands are untouched. - Supply chain unchanged. The release is a CGO-free static binary published with sha256
checksums and SLSA build provenance.
npm auditreports one high advisory in the website’s build-time toolchain (adm-zip, used only to write the procedures zip from our own docs) — it affects the site build, not the tool binary, and is tracked for a separate web dependency bump.
[v0.3.1] — 2026-06-18
Fixes
- security (RHEL):
install.shnow relabels the installed binary tobin_tso systemd can execute it on an SELinux-enforcing host — no permissive policy module needed. (#1) - security (RHEL): the write commands (
ensure/issue/renew/void/distribute) refuse early, with an actionable message, when the store can’t be safely written: as root over asyscert-owned store (which would create root-owned files the timer can’t renew, #2), or as a user who doesn’t own the store (replacing the rawmkdir … permission denied, #3). Read-only commands are unaffected. - security (RHEL): the starter
syscert.tomlis installed0640 root:syscert(was world-readable0644), so the internaldirectory_url, ACME email, and EABkidaren’t readable by every local user. (#3) - web: the site bakes the correct tool version again. The version was resolved inside
a buildx-cached Docker layer, so a rebuild on an unchanged source commit reused a stale
layer and kept showing the previous release. It’s now passed as a
SITE_VERSIONbuild-arg (deterministic + cache-busting), and the site auto-rebuilds after a release via aworkflow_runchain (therelease: publishedevent never fired forGITHUB_TOKEN-created releases). - web: docs menu reordered; Advanced install split into Manually / Compile from source / As a cron job (for appliances without systemd, e.g. Asustor) sub-pages; the sidebar submenu now indents correctly under its parent.
Risk & Security
Low risk — bug fixes and hardening only; no change to certificate issuance, key handling,
or the privilege model’s defaults. A /security-review of v0.3.0..HEAD found no
vulnerabilities.
- The store-ownership preflight is purely restrictive — it can only refuse a write (exit 1), never proceed where it previously wouldn’t, and never elevates privilege. It reads only the store path, owner uid, and username — no secret material.
- Permissions only tighten.
syscert.tomlmoves0644 → 0640; secrets stay0640, private keys0600, and the EAB HMAC is still never logged or printed. - SELinux: the installer relabels the binary to
bin_t(a label re-derived from policy, not an arbitrary grant); no permissive module is shipped. - Behaviour to note: running a write command as a user that doesn’t own the store —
including bare
sudo syscert(root) over asyscert-owned store — now refuses with guidance instead of silently mis-owning files. Run as the store owner (sudo -u syscert syscert …); the systemd timer already does.
[v0.3.0] — 2026-06-18
Features
- cli:
syscert status— a read-only, offline snapshot of the resolved config, the stored certificate’s subject/SANs/issuer/key and its issue, expiry, and renewal dates, the ACME account(s), archived snapshots, and distribution targets. No network, no credentials; it never prints the EAB HMAC.ensurenow logs a one-line cert summary on completion, so the cert’s expiry/renewal surface insystemctl status syscert/journalctl -u syscert. - cli:
destroy --keep-accountremoves only the certificate (and any archived snapshots) while keeping the ACME account, so the next run reissues reusing the existing account — no fresh EAB token needed. It also skips the internal-CA trust-anchor removal (you’re reissuing, not tearing down trust). - store: optional certificate history —
[store].archive_keep = Nsnapshots the previous artifacts underarchive/<UTC>/before each renewal (default0, disabled) — and configurable store-directory permissions,[store].dir_modeand[store].group, to grant a consumer group access. Key-bearing files stay0600regardless; only the directory mode/group are configurable. - web: a collapsible docs submenu with dedicated per-config Sample Config pages, and a mobile hamburger menu for the top nav.
Fixes
- acme: resolve the existing ACME account instead of re-registering on every run.
A persisted account is now re-established with
ResolveAccountByKey(no EAB), so a single-use External Account Binding token is validated only on first registration and never replayed — which makes a Vaulteab_policy = "always-required"safe.
Documentation
- New EAB page with a Vault subpage (request/list/revoke an EAB token, the
vault-eab-0-format, single-use semantics) and a Reloading services guide for thesystemd.pathwatch-and-reload pattern; documented the newstatusanddestroy --keep-accountcommands and the[store]options.
Risk & Security
Low risk. Certificate issuance and the privilege model are unchanged, and the
defaults preserve the existing 0700, syscert-owned store with history disabled.
A /security-review of v0.2.0..HEAD found no vulnerabilities.
- EAB handling is improved, not widened. Resolving (rather than re-registering)
the account means a single-use EAB token is sent only on first registration and
never replayed; a non-
accountDoesNotExistresolve error fails closed rather than re-registering. - Private keys stay
0600. The configurable[store].dir_mode/grouptouch only the store directory and group ownership — never per-file modes. Key-bearing artifacts remain0600(chgrp on a0600file grants the group nothing), and archived snapshots preserve each file’s original mode, so keys stay locked in the archive.statusreads only public material and never prints the EAB HMAC. - New at-rest consideration: with
archive_keep > 0, historical private keys are retained (0600) under the locked store and stay valid until their certs expire — keep the value modest and protect store backups. History is off by default. destroy --keep-accountnarrows an already-confirmed destructive operation; it keeps the account and skips system-trust removal.
[v0.2.0] — 2026-06-16
Features
- cli:
--env-file <path>loads DNS/CA credentials from a systemd EnvironmentFile for a manual run, so you no longer have to export every variable by hand. Repeatable; an existing environment variable always wins; secrets are never logged. - packaging: the network installer now uninstalls —
curl … | sudo sh -s -- --uninstall(add--purgeto also remove the store, config, and thesyscertuser), no clone needed. It delegates toinstall.sh, the single source of truth. - web: a
/healthzendpoint plus Docker and Traefik healthchecks for the website container.
Fixes
- security: use the
#nosecdirective so gosec honours the baseline suppressions. - ci: keep
web/scriptsin the Docker build context so the vendor prebuild runs.
Documentation
- Vault PKI ACME supports
dns-01— corrected the stale “Vault has no dns-01” claim across the docs and added an annotatedvault-dns-01.tomlexample (role-scoped directory + EAB). - Documented
--env-fileacross the README, FAQ, configuration reference, quick start, and troubleshooting; documented the uninstall paths on the install page and in advanced-install. - Slimmed the README to a quick-start hub with CI status badges.
Risk & Security
Low risk — no changes to certificate issuance, key handling, or the privilege model.
--purgeis now gated. The destructive uninstall (store, config, secrets, and thesyscertuser) prompts for confirmation on the controlling terminal — working even undercurl … | sh, where stdin is the pipe — and refuses to proceed without a terminal unlessSYSCERT_ASSUME_YES=1is set. This makes an already-existing operation safer.--env-filedoes not widen secret exposure. It is opt-in (nothing is read without the flag), loads the same/etc/syscert/secretsthe systemd unit already uses, never overrides a variable already in the environment, and never logs values (parse errors cite only the line number).- Network uninstall fetches
packaging/install.shover TLS from the pinned tag (ormain) and delegates to it — the same trust model as install; the release binary remains checksum-verified. - Known issue:
npm auditreports 5 high advisories in the website’s build-time dependencies (Astro toolchain). They affect the build, not the published static site or the tool binary, and are tracked for a separate web dependency bump.
[v0.1.0] — 2026-06-14
First feature release with full documentation, a one-line installer, and a repeatable release process.
Highlights
- Adopted Semantic Versioning + Conventional Commits.
Commit subjects now drive the version bump (
feat→minor,fix→patch, breaking→major) and the changelog;scripts/prerelease.shaudits readiness andscripts/release.shpublishes — see RELEASING.md.
Features
- acme: External Account Binding (EAB) — set
[acme.eab].kidin the config and supply the HMAC viaSYSCERT_EAB_HMAC, for CAs that require it (Vaulteab_policy, step-carequireEAB, ZeroSSL / Google / SSL.com). - web: a full documentation site — quick start, configuration, sample configs,
distributing, troubleshooting, FAQ, roadmap, and changelog — single-sourced from
Markdown in
docs/and rendered on GitHub and the website. - packaging: a one-line network installer (
net-install.sh, served at/install.sh) that downloads the matching release binary, verifies its checksum, and delegates toinstall.sh. The site shows the real release version + checksums.
Fixes
- packaging: the installer enables the systemd timer but no longer starts it until the config is in place.
Changed
- cli: shared flag parsing across subcommands, with
--flag-style usage output. - Docs are now canonical Markdown under
docs/; the README is a lean overview.
Continuous integration
- Added
govulncheck+gosecscanning on every push/PR; the site rebuilds when the docs, changelog, or installer change, and on each published release.
Risk & Security
Reviewed with a simplify pass and a security review (no findings). EAB adds an opt-in account-registration path only: the HMAC is read from the environment, validated before any network call, and never logged — no change to certificate validation or the default issuance path. The one-line installer checksum-verifies the downloaded binary before use. The remaining changes are docs, CI, and tooling.