Skip to content

Conversation

@adrgs
Copy link
Owner

@adrgs adrgs commented Feb 9, 2026

Summary

  • Add HTTPS certificate support for direct IP access (https://SERVER_IP) using Let's Encrypt short-lived IP certificates (6-day validity, HTTP-01 challenge)
  • Upgrade instant-acme 0.7 → 0.8 for Identifier::Ip, ACME profiles, and new async API (Account builder, ChallengeHandle, RetryPolicy)
  • Add SNI-based DualCertResolver: serves domain cert when SNI present, IP cert when absent (per RFC 6066)

Key changes

New: IP certificate lifecycle

  • HttpChallengeHandler — in-memory token store shared between HTTP server and CertManager
  • IpCertValidator — hours-level precision validation for short-lived certs
  • Separate renewal tasks: domain (DNS-01, 12h checks) and IP (HTTP-01, 6h checks, 96h renewal threshold)
  • /.well-known/acme-challenge/:token route on HTTP server for ACME validation

Refactored: TLS architecture

  • DualCertResolver implements ResolvesServerCert with ArcSwap for hot-reload
  • TlsManager gains reload_domain() / reload_ip() (replaces single reload())
  • HTTP server starts before CertManager to ensure challenge endpoint readiness

Config (env vars)

  • IP_CERT_ENABLED (default: false) — enable/disable IP certs
  • IP_CERT_CHECK_HOURS (default: 6) — check interval
  • IP_CERT_RENEWAL_HOURS (default: 96) — renew when <96h remaining

Test plan

  • cargo build — clean (dev + release)
  • cargo test — 79 passed, 0 failed, 1 ignored (staging)
  • cargo clippy -- -D warnings — zero warnings
  • Pre-commit and pre-push hooks pass
  • Manual staging test: set ACME_DIRECTORY to staging URL, verify domain cert (DNS-01) still works
  • Manual staging test: verify IP cert issuance (HTTP-01) with real public IP
  • Verify SNI routing: openssl s_client -connect IP:443 shows IP cert, -servername domain shows domain cert

🤖 Generated with Claude Code

@adrgs adrgs force-pushed the feat/ip-certificate-support branch from 29f5403 to 45f8221 Compare February 9, 2026 22:57
Add HTTPS certificate support for direct IP access (e.g. https://SERVER_IP)
using Let's Encrypt's short-lived IP certificates (6-day validity).

Key changes:
- Upgrade instant-acme 0.7 → 0.8 (new Account builder, async auth iterator,
  ChallengeHandle, RetryPolicy, Identifier::Ip support)
- Add HTTP-01 ACME challenge handler served at /.well-known/acme-challenge/
- Add DualCertResolver with SNI-based cert selection: domain cert when SNI
  present, IP cert when absent (per RFC 6066)
- Separate renewal cycles: domain certs (DNS-01, 12h checks) and IP certs
  (HTTP-01, 6h checks with 96h renewal threshold)
- Add IpCertValidator with hours-level precision for short-lived certs
- HTTP server starts before CertManager to ensure challenge endpoint readiness

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adrgs adrgs force-pushed the feat/ip-certificate-support branch from 45f8221 to 129b4b8 Compare February 10, 2026 00:02
adrgs and others added 2 commits February 10, 2026 02:16
- server_ip.unwrap() → .expect() with invariant explanation
- RwLock .unwrap() → .expect("challenge token lock poisoned")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adrgs adrgs merged commit 56b1e2b into main Feb 10, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant