feat: automate TLS cert issuance via certbot (#87) - #95
Conversation
Replace the self-signed prod cert with a real Let's Encrypt cert issued and renewed by an on-demand certbot container. certbot writes into the deploy-owned nginx/certs mount, so issuance needs no root or /etc/letsencrypt access. - nginx :80 serves /.well-known/acme-challenge/ from a webroot shared with certbot, ahead of the HTTPS redirect (http-01 challenge) - add certbot service + certbot_webroot volume to the prod compose - document first-issue + weekly renewal (deploy crontab) in nginx/README.md
|
Warning Review limit reached
Next review available in: 52 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughProduction Compose now provisions an on-demand Certbot service with shared ACME webroot storage. Nginx serves HTTP-01 challenge files before redirecting other HTTP traffic, and the README documents certificate issuance, configuration, reloads, and renewal. ChangesLet’s Encrypt TLS integration
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Certbot as Certbot service
participant Webroot as certbot_webroot
participant LetsEncrypt as Let's Encrypt
participant Nginx
Certbot->>Webroot: write HTTP-01 challenge file
LetsEncrypt->>Nginx: request ACME challenge over HTTP
Nginx->>Webroot: read challenge file
Nginx-->>LetsEncrypt: return challenge response
Certbot->>Certbot: write certificates to /etc/letsencrypt
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
deploy/docker-compose.prod.yml (1)
54-54: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winPin the Certbot image.
certbot/certbot:latestis mutable; use a versioned tag or digest so issuance/renewal runs don't pick up an unexpected upstream build.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@deploy/docker-compose.prod.yml` at line 54, Update the Certbot service image reference from the mutable certbot/certbot:latest tag to a specific versioned tag or immutable digest, preserving the existing Certbot service configuration.Source: MCP tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@deploy/docker-compose.prod.yml`:
- Around line 60-61: Restore the Certbot image entrypoint in
deploy/docker-compose.prod.yml by removing the empty entrypoint override, while
preserving the existing command only if needed for normal service behavior. The
certonly and renew command sites in nginx/README.md at lines 59-68 and 88-89
require no direct changes; they must continue relying on the restored image
entrypoint.
---
Nitpick comments:
In `@deploy/docker-compose.prod.yml`:
- Line 54: Update the Certbot service image reference from the mutable
certbot/certbot:latest tag to a specific versioned tag or immutable digest,
preserving the existing Certbot service configuration.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1ee1b53e-d7ae-4035-bab2-f68efab29623
📒 Files selected for processing (3)
deploy/docker-compose.prod.ymlnginx/README.mdnginx/templates/default.conf.template
) The empty entrypoint override broke the documented 'run --rm certbot certonly' and 'renew' commands — with entrypoint cleared, Compose execs 'certonly' as the binary instead of 'certbot certonly'. Restore the image's default entrypoint and instead use a 'certbot' profile to keep the service out of a bare 'compose up' (explicitly named services in 'run' start regardless of profile).
What
Prod (
getsynxor.com) still serves the self-signed IP cert (CN=209.97.172.226), so browsers warn and wss only works after a click-through. This wires up a real Let's Encrypt cert issued and renewed by an on-demandcertbotcontainer, terminating the last blocker on Tier 2 TLS of #87.The design avoids root entirely: certbot writes into the deploy-owned
nginx/certsmount (thedeployuser is in thedockergroup), so nosudoand no/etc/letsencryptaccess is needed — which matters given root on the droplet is only reachable via the DO recovery console.Changes
:80server block serves/.well-known/acme-challenge/from a webroot shared with certbot, ahead of the HTTPS redirect, so the http-01 challenge resolves over plain HTTP. In dev the webroot is unmounted and the path just 404s — harmless.certbotservice (no daemon —command: true, driven on demand) plus acertbot_webrootvolume mounted into both nginx (:ro) and certbot. certbot's config dir maps ontonginx/certs, so issued certs land atlive/getsynxor.com/{fullchain,privkey}.pemexactly whereTLS_CERT_PATH/TLS_KEY_PATHexpect them.nginx/README.mdProduction section rewritten with the real first-issue commands (staging dry-run → real issue), the.envcert paths, and a weeklydeploy-crontab renewal line.Deploy steps (operator, after merge + CD ships the files)
Run from
$DEPLOY_PATHon the droplet asdeploy, no sudo:Then set in the host
.envand reload:Weekly renewal via
deploycrontab — seenginx/README.md.Verification
nginx -tnot run locally (no Docker on the dev box) — the challenge location is a standardlocation { root … }and validates when the stack comes up on the droplet.getsynxor.comandwww.getsynxor.comboth resolve to the droplet, ports 80/443 open — http-01 will validate for both names.Part of #87 (Tier 2 — real TLS cert + auto-renew). HSTS header left as a follow-up so it can be env-gated without affecting local dev.
Summary by CodeRabbit
New Features
Documentation