feat: automatic ACME certificate rotation and integration tests - #13
Open
phaus wants to merge 15 commits into
Open
feat: automatic ACME certificate rotation and integration tests#13phaus wants to merge 15 commits into
phaus wants to merge 15 commits into
Conversation
added 15 commits
September 5, 2026 00:57
Adds a new pkg/autocert package that orchestrates Let's Encrypt certificate provisioning and renewal via go-acme/lego v4.35.2. - Config (HTTP-01/DNS-01 challenge selection, email, CA URL) - Account creation/persistence interface - HTTP-01 challenge handler (/.well-known/acme-challenge/) - DNS-01 wiring for lego's built-in autodns provider - Obtain/Renew certificate flow with PostgreSQL storage interface - Background renewal loop Also vendors lego and its transitive dependencies. Because lego v4 requires newer x/net, x/crypto, grpc, protobuf etc., the whole graph is upgraded; go.mod now declares go 1.25.0 (required by the dep graph). The legacy Azure SDK used by blobstore/backend/azure.go is pinned back to the previously-vendored version via a replace directive so that backend continues to compile unchanged.
The CI runner installs Go 1.22.12. With go 1.25.0 in go.mod it downloaded the Go 1.25 toolchain, which then failed to find the covdata tool when running -race -cover tests for pkg/rpcplus/comborpc and fdrpc. Revert to go 1.23 so the downloaded toolchain matches the project baseline and coverage works.
The project now depends on packages (e.g. cloud.google.com/go/auth) that require Go >= 1.25.0. The CI runner was installing Go 1.22.12, causing toolchain downloads and missing the covdata coverage tool. Install Go 1.25.0 directly in both build and test jobs.
Adds a self-contained integration test (TestManagerObtainWithPebble) that starts a local Pebble ACME test server, runs the autocert HTTP-01 challenge flow, and verifies the issued certificate chains back to the Pebble root CA. Test is gated by the ACME_PEBBLE_TEST environment variable because it downloads and runs the letsencrypt/pebble module. Also adds an optional HTTPClient field to autocert.Config so tests can inject a TLS client that trusts the test CA. Includes the pebbletest helper as a separate Go module to keep Pebble out of the main module's vendor tree.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #12 (continuation).
This PR finishes the remaining data-layer and rotation work for Let's Encrypt ACME certificate management:
acme_domaincolumn tohttp_routes. When an ACME certificate is provisioned or renewed,controller/data/route.gonow syncs the new certificate to all bound routes and fires route events so the router hot-swaps without requiringflynn route update --acme <domain>to be re-run.flynn route update <id> --acme <domain>persistsacme_domainon the route while still snapshotting the current cert; the field is cleared when the route is switched back to manual-c/-k.controller/data/acme_test.gocoversACMEStoreaccount/certificate CRUD, upsert, domain normalization, deletion, andRouteRepo.SyncACMECertroute binding + renewal rotation (requires PostgreSQL to run).acme_domain; the route JSON schema is updated.Test Results
go build ./...cleango test -vet=off ./pkg/autocert/...→ 7 passedgo test -vet=off ./controller/ -run TestACME→ 7 passedcontroller/data/acme_test.gointegration tests compile (require Postgres).Commits
router: add acme_domain field to Route and HTTPRoutecontroller/data: add acme_domain column and ACME cert route synccontroller: wire ACME store to sync route certs on renewalcli: persist acme_domain on route update --acmecontroller/data: add ACMEStore integration tests