Skip to content

// docs · compliance · tech stack

Tech stack

Everything SysCert is made of — the binary, its dependencies, the runtime model, the docs site, and the build pipeline — in one place.

A deliberately small, boring stack: a single static Go binary, a tiny systemd footprint, and a short dependency list. Nothing to babysit, little to attack.

The tool

AreaChoice
Language / toolchainGo ≥ 1.26, CGO_ENABLED=0 → a single static binary (linux amd64 + arm64)
TLS & cryptoGo standard library crypto/tls, crypto/ecdsa (P-256 default), crypto/rand
ACME & DNSlego v5 — the ACME client and DNS-01 providers
ConfigBurntSushi/toml
Loggingstandard-library structured logging (log/slog) to stderr/journal
Direct dependenciestwo (lego, toml); the large transitive tree is lego’s per-provider DNS SDKs

Architecture. A CLI (bare syscert = ensure, plus issue|renew|void|destroy|distribute|status|trust|dry-run) over small internal packages: config load + fail-fast validation, an ACME client wrapper (lego), an atomic certificate store (/var/lib/syscert), distribution to consumer paths with per-target owner/mode/SELinux context, renewal decisioning, and system trust management. The default model is no long-running daemon: a systemd oneshot + timer runs the binary on a schedule. --interval <duration> (env SYSCERT_INTERVAL) adds an in-process renewal loop for non-systemd contexts (containers, appliances) without changing the host model. One-shot (no flag) stays the default.

Runtime model. Runs as a dedicated, non-root syscert system user under a hardened systemd unit (NoNewPrivileges, ProtectSystem=strict, MemoryDenyWriteExecute, a single CAP_CHOWN). Outputs are certbot-compatible (cert/privkey/chain/fullchain/bundle). See the Security assessment for the full control set.

The documentation site

AreaChoice
GeneratorAstro static site (docs are the canonical docs/*.md, vendored at build)
Fontsself-hosted (IBM Plex Sans/Mono + Martian Mono via @fontsource, latin subset) — no third-party font origins
Content-Security-Policyserved on every page via Astro’s security.csp — per-page auto-generated script-src/style-src hashes plus default-src/font-src/connect-src/base-uri 'self', img-src 'self' data:, object-src 'none' (<meta>-delivered; frame-ancestors covered by the X-Frame-Options: SAMEORIGIN header in nginx)
Runtime imagenginx:alpine-slim serving static files (TLS terminated upstream by Traefik)
Registry / hostingimage published to GHCR (ghcr.io/tfindley/syscert-web), pulled by a self-managed host behind Traefik

The website is a hosting artifact, not the product. It documents the binary, which is the thing you install. Self-hosted fonts and the per-page CSP keep its origin self-contained; see the Security assessment for the site’s full header set.

Build, release & CI

StageWhat runs
CI (GitHub Actions)go build · go test · go vet · gofmt · gosec
Release gating (scripts/prerelease.sh)the above plus govulncheck, command/flag↔docs parity, example-config validation, version-stamp checks — all blocking
Releasecross-compiled amd64/arm64 with -trimpath -ldflags "-s -w", sha256sums.txt, and a SLSA build-provenance attestation (GitHub OIDC)
Sitecontainer image built and pushed to GHCR on docs/site changes and after each release

Releases are reproducible (-trimpath, pinned go.sum, embedded VCS revision) and verifiable (sha256sum --check + gh attestation verify).

Licensing

SysCert is released under the AGPL-3.0 license.


Next: Security assessment · AI-assisted development