Skip to content

caddy: add api.komistore.app vhost for paid-backend#22

Merged
rainxchzed merged 2 commits into
mainfrom
feat/caddy-api-komistore
May 26, 2026
Merged

caddy: add api.komistore.app vhost for paid-backend#22
rainxchzed merged 2 commits into
mainfrom
feat/caddy-api-komistore

Conversation

@rainxchzed
Copy link
Copy Markdown
Member

@rainxchzed rainxchzed commented May 25, 2026

Routes the new api.komistore.app hostname at the paid-backend container (paid-app:8080 on the shared Docker network). Same Caddy instance, same compose stack, distinct service name.

DNS prerequisite

Before this lands, api.komistore.app must resolve to 89.167.115.83. Otherwise Caddy will loop on ACME HTTP-01 (other vhosts unaffected, but docker logs github-store-backend-caddy-1 will scream).

Cheapest setup: Cloudflare DNS → A api.komistore.app → 89.167.115.83 with the proxy OFF (grey-cloud). Caddy issues Let's Encrypt directly. Swap to proxied (orange-cloud) + Full(strict) later if traffic justifies fronting.

What this fixes

Paid backend's container has been live since the last deploy (Application -- Responding at http://0.0.0.0:8080) but unreachable from the internet because Caddyfile.prod had no vhost pointing at it. Adding the block lets https://api.komistore.app/health hit it.

CSP note

Looser default-src 'self' (vs the free-tier API's 'none') because the paid backend serves /legal HTML pages alongside JSON. frame-ancestors 'none' stays locked.

Post-merge

Auto-deploy fires → Caddy reload picks up the new block. Verify with:

curl -sS https://api.komistore.app/health
# Expect: {"status":"ok"}

Summary by CodeRabbit

  • New Features

    • New production API endpoint available: api.komistore.app.
  • Chores

    • Production configuration updated for stronger security and privacy protections, request-size limits, and improved access logging for reliability and observability.

Review Change Stack

Routes the new komistore.app hostname at the paid-backend container. Reuses the same Caddy instance as the free-tier API; service names paid-app:8080 + app:8080 stay distinct on the Docker network.

DNS prereq: api.komistore.app must resolve to the VPS IP for HTTP-01 challenge to succeed. Start with a DNS-only (grey-cloud) A record; switch to proxied + Full(strict) later once traffic justifies fronting.

CSP is looser than the free-tier API block because the paid backend serves /legal HTML pages alongside JSON. frame-ancestors stays locked to 'none' to keep clickjack closed.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e2dcd8b-643c-4ee8-8973-2fbe69c34d50

📥 Commits

Reviewing files that changed from the base of the PR and between 042b4d9 and 45ad970.

📒 Files selected for processing (1)
  • Caddyfile.prod

📝 Walkthrough

Walkthrough

A new Caddy vhost for api.komistore.app routes traffic to paid-app:8080, enforces a 1MB request body limit, overwrites X-Forwarded-For and strips CF-Connecting-IP, sets multiple security response headers including a CSP limiting frame-ancestors, and logs access to stdout.

Changes

Paid App Reverse Proxy

Layer / File(s) Summary
api.komistore.app vhost configuration
Caddyfile.prod
New api.komistore.app site block reverse-proxies to paid-app:8080, enforces a 1MB request_body limit, overwrites X-Forwarded-For, removes CF-Connecting-IP, removes Server response header, sets X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, Referrer-Policy, Permissions-Policy, and Content-Security-Policy: default-src 'self'; frame-ancestors 'none', and writes access logs to stdout.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

A rabbit hops where proxies play,
Guarding headers night and day,
One-meg cap keeps payloads neat,
CSP and HSTS stand ready to meet,
Logs to stdout — the trail's complete. 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'caddy: add api.komistore.app vhost for paid-backend' directly and specifically describes the main change: adding a new Caddy vhost configuration for api.komistore.app that routes to the paid-backend service.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/caddy-api-komistore

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 `@Caddyfile.prod`:
- Around line 109-113: The CSP header defined by Content-Security-Policy
currently uses default-src 'self' which blocks inline <style> and <script> used
by the /legal pages; update the CSP string to explicitly allow inline styles and
scripts while keeping clickjacking protection—e.g., add script-src 'self'
'unsafe-inline' and style-src 'self' 'unsafe-inline' (or use nonces if you can
modify the pages) and keep frame-ancestors 'none' so the header in
Caddyfile.prod reads with explicit script-src and style-src allowing inline
content for the legal pages.
- Around line 94-103: In the api.komistore.app vhost block (the one containing
request_body and reverse_proxy paid-app:8080) add header hardening to prevent
forged forwarding headers: on the reverse_proxy to paid-app:8080 overwrite
X-Forwarded-For with the actual client IP (use Caddy's {remote}) and
remove/strip any incoming CF-Connecting-IP header before proxying (use header_up
to delete CF-Connecting-IP). This will ensure the reverse_proxy paid-app:8080
receives a trusted X-Forwarded-For and cannot be bypassed via CF-Connecting-IP.
🪄 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

Run ID: cde81d22-db9f-452f-ae65-643afd2c761f

📥 Commits

Reviewing files that changed from the base of the PR and between 15f62a4 and 042b4d9.

📒 Files selected for processing (1)
  • Caddyfile.prod

Comment thread Caddyfile.prod
Comment thread Caddyfile.prod
Comment on lines +109 to +113
# Looser than the API-only CSP above because the paid backend
# serves the /legal HTML pages (terms, privacy) as well as JSON.
# default-src 'none' would break inline <style>/<script> the legal
# pages use. Keep frame-ancestors locked down to prevent clickjack.
Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

CSP currently contradicts the inline legal-page requirement.

Line 111-Line 112 says /legal uses inline <style>/<script>, but default-src 'self' on Line 113 blocks inline content and can break those pages.

Proposed config adjustment
-        Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
+        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Looser than the API-only CSP above because the paid backend
# serves the /legal HTML pages (terms, privacy) as well as JSON.
# default-src 'none' would break inline <style>/<script> the legal
# pages use. Keep frame-ancestors locked down to prevent clickjack.
Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
# Looser than the API-only CSP above because the paid backend
# serves the /legal HTML pages (terms, privacy) as well as JSON.
# default-src 'none' would break inline <style>/<script> the legal
# pages use. Keep frame-ancestors locked down to prevent clickjack.
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'"
🤖 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 `@Caddyfile.prod` around lines 109 - 113, The CSP header defined by
Content-Security-Policy currently uses default-src 'self' which blocks inline
<style> and <script> used by the /legal pages; update the CSP string to
explicitly allow inline styles and scripts while keeping clickjacking
protection—e.g., add script-src 'self' 'unsafe-inline' and style-src 'self'
'unsafe-inline' (or use nonces if you can modify the pages) and keep
frame-ancestors 'none' so the header in Caddyfile.prod reads with explicit
script-src and style-src allowing inline content for the legal pages.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 25, 2026

Greptile Summary

This PR adds a api.komistore.app vhost block to Caddyfile.prod, routing traffic to the paid-app:8080 container on the shared Docker network. The new block mirrors the security hardening on api-direct.github-store.org and appropriately loosens the CSP from 'none' to 'self' for the HTML legal pages the paid backend serves.

  • XFF forgery defence and CF-Connecting-IP stripping (previously flagged) are present and correctly implemented, matching the api-direct.github-store.org pattern documented in CLAUDE.md.
  • The CSP comment has been updated to clarify that 'self' does not permit inline assets, and the comment notes that legal templates are kept inline-asset-free — addressing the previous review thread on that point.
  • The 1 MB body cap, security headers, and access log are consistent with the existing vhosts.

Confidence Score: 5/5

Safe to merge — the new vhost correctly replicates the direct-access security hardening from api-direct.github-store.org and introduces no regressions to the existing blocks.

The change is a single Caddy vhost block that follows the established pattern documented in CLAUDE.md. Both previously flagged issues (XFF forgery and the CSP comment accuracy) are addressed in this revision. The XFF override and CF-Connecting-IP strip are in place, the 1 MB body cap is set, and the CSP comment explicitly notes the inline-asset constraint and that legal templates are kept inline-asset-free. No logic changes to the application, no migrations, no new code paths.

No files require special attention.

Important Files Changed

Filename Overview
Caddyfile.prod Adds api.komistore.app vhost with XFF override, CF-Connecting-IP strip, 1 MB body cap, and security headers; follows the established api-direct.github-store.org pattern with a correctly reasoned looser CSP for HTML legal pages.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Caddy
    participant paid-app

    Client->>Caddy: HTTPS api.komistore.app (TLS, Let's Encrypt)
    Note over Caddy: Override X-Forwarded-For → {remote_host}
    Note over Caddy: Strip CF-Connecting-IP
    Note over Caddy: Enforce 1 MB body cap
    Caddy->>paid-app: HTTP paid-app:8080 (Docker network)
    paid-app-->>Caddy: Response
    Note over Caddy: Set security headers<br/>(CSP self, HSTS, XFO DENY, …)
    Caddy-->>Client: HTTPS Response
Loading

Reviews (2): Last reviewed commit: "caddy: lock down api.komistore.app vhost..." | Re-trigger Greptile

Comment thread Caddyfile.prod
Comment thread Caddyfile.prod
…g-IP strip, accurate CSP comment

Direct-to-VPS path (grey-cloud DNS) was missing the X-Forwarded-For
override and CF-Connecting-IP strip that api-direct.github-store.org
already has — a client could forge XFF and rotate past paid-app's
per-IP rate limiter, or claim any CF-Connecting-IP source. Both
defences now match the established pattern.

Also corrects the CSP comment: default-src 'self' does not permit
inline <style>/<script> (those require 'unsafe-inline' in
style-src/script-src or a nonce). The /legal templates are
intentionally kept inline-asset-free so the directive holds.
@rainxchzed rainxchzed merged commit 7dad757 into main May 26, 2026
2 checks passed
@rainxchzed rainxchzed deleted the feat/caddy-api-komistore branch May 26, 2026 09:50
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