20 Commits
Author SHA1 Message Date
Roman KivalinandClaude Opus 4.6 c717da348a Add custom file permissions for key and certificate files
Support key_mode, key_owner, key_group and cert_mode, cert_owner,
cert_group per certificate. Mode is an octal string (e.g. "0640"),
owner/group are resolved by name via getpwnam/getgrnam.

Permissions are checked before applying — system calls are only made
when the current state differs from the desired state, and changes
are logged. Runs on every renew for existing files, not just when
certificates are renewed. Defaults: key 0600, cert 0644, owner/group
unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 21:03:59 +02:00
Roman KivalinandClaude Opus 4.6 aeb17eef08 Bump version to 0.7.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:56:52 +02:00
Roman KivalinandClaude Opus 4.6 b6d299300d Add configurable DNS propagation delay per solver
DNS-01 solvers now accept a propagation_delay option (default 5s).
When multiple solvers are used for a certificate, the longest delay
is used. The Solver trait method changes from needs_propagation_delay()
returning bool to propagation_delay() returning Option<Duration>.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:02:09 +02:00
Roman KivalinandClaude Opus 4.6 b2b470dd69 Implement TLSA record verification in dane-check
dane-check now queries the authoritative DNS server for published TLSA
records and compares them against expected values computed from the
current certificate. Queries are TSIG-signed using the same key as the
DNS client config (for view selection support). Reports OK, MISSING,
or MISMATCH for each name and exits with code 1 if any check fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:12:15 +02:00
Roman KivalinandClaude Opus 4.6 07384116cb Add config validation for uniqueness, missing solvers, and unused definitions
- Reject duplicate certificate names and duplicate hook names
- Reject certificates where a domain has no solver (no solver/solvers
  and no default_solver)
- Warn about DNS clients, solvers, and hooks that are defined but
  never referenced

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:02:20 +02:00
Roman KivalinandClaude Opus 4.6 ece514133d Fix dry_run flag not passed to inline hooks
Inline per-certificate hooks were always executed even in dry-run mode
because the dry_run parameter was hardcoded to false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 14:33:11 +02:00
Roman KivalinandClaude Opus 4.6 280e008ec9 Support multiple listen addresses for HTTP-01 and TLS-ALPN-01 solvers
listen now accepts a single address or a list. Certforge tries binding
all addresses and succeeds if at least one works. This supports
initial provisioning scenarios where a proxy (e.g., haproxy) may not
be running yet — certforge can bind port 80 directly as a fallback
alongside a proxy-forwarded port.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:48:16 +02:00
Roman KivalinandClaude Opus 4.6 004d93384d Add named hooks with cross-certificate deduplication
Named hooks defined in [[hook]] are referenced by certificates via
hooks = ["name"]. Triggered hooks run after all renewals complete,
in definition order.

Inline [[certificate.hook]] blocks are still supported for
per-certificate hooks that run immediately after each renewal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:41:04 +02:00
Roman KivalinandClaude Opus 4.6 252c2967fd Bump version to 0.6.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 01:24:31 +02:00
Roman KivalinandClaude Opus 4.6 f63af47487 Fix wildcard DNS-01 challenges
Per RFC 8555 §8.4, the DNS-01 challenge for *.example.com uses
_acme-challenge.example.com (strip the *. prefix), not the invalid
_acme-challenge.*.example.com.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 23:40:39 +02:00
Roman KivalinandClaude Opus 4.6 96f98352a8 Don't bind systemd-creds to a specific credential name
Omit --name= from systemd-creds encrypt so the encrypted credential
can be loaded under any name via LoadCredentialEncrypted=. Previously,
the embedded name had to match the credential name in the service
unit, causing decryption failures when services used different names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 23:29:26 +02:00
Roman KivalinandClaude Opus 4.6 3674a222a6 Bump version to 0.5.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:17:03 +02:00
Roman KivalinandClaude Opus 4.6 da8c937782 Refactor config: named DNS clients, challenge solvers, per-domain solver assignment
Breaking config change. The DNS and challenge configuration is now
structured around named, reusable components:

- [dns.*] named DNS client connections with explicit zone field
- [solver.*] challenge solvers (dns-01, http-01, tls-alpn-01)
- Certificates reference solvers by name (solver/solvers fields)
- DANE blocks reference DNS clients by name (dns field)
- Removed automatic zone detection heuristics
- Added default_solver for global fallback
- Validation: DNS-01 rejected for IP addresses, solver/solvers
  mutual exclusivity, length matching, reference integrity

HTTP-01 and TLS-ALPN-01 solver implementations to follow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 19:15:01 +02:00
Roman KivalinandClaude Opus 4.6 40d7240ef9 Bump version to 0.4.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:54:40 +02:00
Roman KivalinandClaude Opus 4.6 af8cdd3e41 Add DNS propagation delay before ACME challenge validation
Wait 5 seconds after publishing DNS-01 TXT records before notifying
the ACME server, giving the DNS server time to propagate the update.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:31:59 +02:00
Roman KivalinandClaude Opus 4.6 8ed22ca1d5 Bump version to 0.3.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:29:36 +02:00
Roman KivalinandClaude Opus 4.6 08cacff569 Build release binaries on Ubuntu 22.04 for glibc 2.35 compat
Debian 12 (bookworm) ships glibc 2.36. The previous ubuntu-latest
(24.04) produced binaries requiring glibc 2.39.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 22:43:35 +02:00
Roman KivalinandClaude Opus 4.6 1c5aa8b930 Bump version to 0.2.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:52:07 +02:00
Roman KivalinandClaude Opus 4.6 000ec410b1 Add README and CHANGELOG
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:07:20 +02:00
Roman KivalinandClaude Opus 4.6 1c517ecbab Add packaging, CI, and license
- MIT license
- Arch Linux PKGBUILD
- Debian packaging (debian/)
- GitHub Actions: CI (test + clippy) and release workflow
  builds x86_64 + aarch64 binaries, Arch and Debian packages
- Default config is now no-op (certificate blocks commented out)
- Fix clippy warnings (collapsible ifs, redundant closures)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:47:00 +02:00