{"id":50966120,"url":"https://github.com/tfindley/syscert","last_synced_at":"2026-06-18T20:32:44.104Z","repository":{"id":363887939,"uuid":"1263342043","full_name":"tfindley/syscert","owner":"tfindley","description":"Service to request and renew a SSL certificate based on CertBot, with support for LetsEncrypt and self-host ACME cert endpoints","archived":false,"fork":false,"pushed_at":"2026-06-18T06:36:11.000Z","size":472,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T08:21:56.598Z","etag":null,"topics":["certbot","daemon","go","service","ssl","ssl-certificates","tls","tls-certificate"],"latest_commit_sha":null,"homepage":"https://syscert.tfindley.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tfindley.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-08T21:32:08.000Z","updated_at":"2026-06-18T06:36:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tfindley/syscert","commit_stats":null,"previous_names":["tfindley/syscert"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/tfindley/syscert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfindley%2Fsyscert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfindley%2Fsyscert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfindley%2Fsyscert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfindley%2Fsyscert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tfindley","download_url":"https://codeload.github.com/tfindley/syscert/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tfindley%2Fsyscert/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34507157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["certbot","daemon","go","service","ssl","ssl-certificates","tls","tls-certificate"],"created_at":"2026-06-18T20:32:43.276Z","updated_at":"2026-06-18T20:32:44.094Z","avatar_url":"https://github.com/tfindley.png","language":"Go","funding_links":["https://ko-fi.com/tfindley"],"categories":[],"sub_categories":[],"readme":"# SysCert\n\n[![CI](https://github.com/tfindley/syscert/actions/workflows/ci.yml/badge.svg)](https://github.com/tfindley/syscert/actions/workflows/ci.yml)\n[![Release](https://github.com/tfindley/syscert/actions/workflows/release.yml/badge.svg)](https://github.com/tfindley/syscert/actions/workflows/release.yml)\n[![Web](https://github.com/tfindley/syscert/actions/workflows/web.yml/badge.svg)](https://github.com/tfindley/syscert/actions/workflows/web.yml)\n\n**Set-and-forget TLS for every machine.** SysCert is a small, least-privilege Linux service that\ngives a host its own TLS certificate — from **Let's Encrypt** or an internal **HashiCorp Vault** /\n**Smallstep `step-ca`** — keeps it renewed, and delivers it to local consumers (nginx, HAProxy,\nCockpit, databases…) with the exact ownership, mode, and SELinux context each needs. A systemd timer\nkeeps it fresh forever: no cron, no scripts, no cert babysitting. It's independent of any host\n`certbot`.\n\nIt speaks ACME via [lego](https://go-acme.github.io/lego/) and writes certbot-compatible output\n(`cert.pem` / `privkey.pem` / `chain.pem` / `fullchain.pem`) plus an all-in-one `bundle.pem`.\n\n\u003e **Project status: early (pre-1.0).** Working today: the full `syscert` CLI (the default *ensure*\n\u003e plus `issue` / `renew` / `distribute` / `void` / `destroy` / `dry-run` / `trust install`/`remove`),\n\u003e the systemd units, `install.sh`, and **pre-built Linux binaries** (amd64/arm64) on the\n\u003e [releases page](https://github.com/tfindley/syscert/releases). Not built yet: the Ansible role\n\u003e (see the [roadmap](docs/roadmap.md)).\n\n## Why\n\nYou terminate public TLS at the edge (HAProxy, a load balancer). But the hop from there to your\nbackends — and traffic between internal services — is often plaintext, or relies on hand-made certs\nthat expire and page someone at 2 a.m. SysCert makes every host responsible for its own cert,\nautomatically:\n\n- **Encrypt the edge→backend hop** — the backend gets its own cert, no lifecycle to manage.\n- **mTLS between services** — run it on both ends against an internal CA; `syscert trust install`\n  adds the CA to the system store so each side verifies the other.\n- **Admin UIs \u0026 data stores** — Cockpit, Postgres, Redis, internal APIs, metrics over TLS.\n- **Any host that should just have a valid, auto-renewing cert** without someone owning the renewal.\n\n## Quick start\n\n**Supported targets:** Debian/Ubuntu and the RHEL family (others may work but aren't tested), amd64\nand arm64. One static binary and a systemd timer:\n\n```sh\ncurl -fsSL https://syscert.tfindley.dev/install.sh | sudo sh\n```\n\nThis downloads the matching release binary, **verifies its checksum**, and runs the installer —\ncreating the `syscert` user, `/var/lib/syscert`, starter config + secrets, the systemd units, and\nenabling (not starting) the timer. Then edit two files and you're done:\n\n```sh\nsudoedit /etc/syscert/syscert.toml      # subject, CA, challenge, distribute targets\nsudoedit /etc/syscert/secrets           # e.g. CLOUDFLARE_DNS_API_TOKEN=...  (never in the .toml)\n\nsudo -u syscert syscert dry-run --config-only                       # validate offline\nsudo -u syscert syscert --staging --env-file /etc/syscert/secrets   # real run; --env-file loads creds\n# happy? drop --staging, then: sudo systemctl start syscert.timer\n```\n\nThe full walkthrough — complete minimal config and what each step prints — is in the\n[Quick start guide](docs/quick-start.md). To inspect the script, verify checksums by hand, build from\nsource, or install manually, see [Advanced install](docs/advanced-install.md).\n\nUninstall the same way, no clone needed —\n`curl -fsSL https://syscert.tfindley.dev/install.sh | sudo sh -s -- --uninstall` (add `--purge` to\nalso remove certs/keys/config). Details in [Advanced install](docs/advanced-install.md#uninstall).\n\n## Commands\n\n| Command | Purpose |\n|---|---|\n| `syscert [--config \u003cpath\u003e] [--staging]` | **The default.** Issue if no cert, renew if due, then distribute (what the timer runs). |\n| `syscert issue [--staging]` | Obtain a fresh cert into the store. Does not distribute. |\n| `syscert renew [--staging] [--force]` | Renew if due (or `--force`) into the store. Does not distribute. |\n| `syscert distribute` | Copy stored artifacts to the configured targets. |\n| `syscert dry-run [--config-only]` | Validate config; without `--config-only`, also run the real ACME order/challenge and discard (LE uses staging). |\n| `syscert trust install` / `trust remove` | Add/remove the internal CA in the **system** trust store (root). |\n| `syscert void [--force]` | Revoke the current cert, then reissue + distribute. |\n| `syscert destroy [--force]` | Wipe the stored cert + ACME account (provider switch). `--keep-account` drops only the cert — reissue with no new EAB token. |\n| `syscert status` | Show config + the stored cert's dates (issued/expiry/renewal), account, and distribute targets. Offline. |\n\n`--config` defaults to `/etc/syscert/syscert.toml` (or `$SYSCERT_CONFIG`). Secrets (DNS/CA tokens)\nalways come from the **environment**, never the TOML, and are never logged. The systemd service\nloads them from `/etc/syscert/secrets`; for a manual run, pass `--env-file /etc/syscert/secrets`\ninstead of exporting each one.\n\n## Documentation\n\nFull, canonical docs live in [`docs/`](docs/) and render on the website at\n**\u003chttps://syscert.tfindley.dev/docs/\u003e**:\n\n- [Quick start](docs/quick-start.md) — install → edit two files → done\n- [Configuration reference](docs/configuration.md) — every `syscert.toml` option\n- [Sample configurations](docs/examples.md) — a starter per CA + challenge, plus annotated\n  [`examples/full.toml`](examples/full.toml)\n- [Advanced install](docs/advanced-install.md) — verify checksums, build from source, manual systemd\n- [Distributing certs](docs/distributing.md) — artifacts, ownership/mode/SELinux, no reload hooks\n- [Troubleshooting](docs/troubleshooting.md) · [FAQ](docs/faq.md) · [Roadmap](docs/roadmap.md) ·\n  [Changelog](CHANGELOG.md)\n\n## Contributing\n\nCommits follow [Conventional Commits](https://www.conventionalcommits.org/) and releases follow\n[Semantic Versioning](https://semver.org/) — see [RELEASING.md](RELEASING.md). The repo uses\n[pre-commit](https://pre-commit.com/); enable the hooks once with `pre-commit install` and\n`pre-commit install --hook-type commit-msg`.\n\n## License\n\n[AGPL-3.0](LICENSE).\n\n## Author\n\n[Tristan Findley](https://tfindley.co.uk). If you'd like to support the project:\n[☕ Ko-fi](https://ko-fi.com/tfindley).\n\u003c/content\u003e\n\u003c/invoke\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfindley%2Fsyscert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftfindley%2Fsyscert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftfindley%2Fsyscert/lists"}