Skip to content

Comments

Feature/self hosting guide#698

Closed
sla-te wants to merge 4 commits intoelie222:mainfrom
sla-te:feature/self-hosting-guide
Closed

Feature/self hosting guide#698
sla-te wants to merge 4 commits intoelie222:mainfrom
sla-te:feature/self-hosting-guide

Conversation

@sla-te
Copy link

@sla-te sla-te commented Aug 19, 2025

As discussed in Discord a little writeup to make self hosting work with dedicated instances of redis/postgres.

Summary by CodeRabbit

  • Documentation

    • Added a comprehensive self-hosting guide with Docker Compose, TLS reverse proxy, environment templates, setup/verification steps, optional integrations, upgrades, and troubleshooting.
  • Chores

    • Made production image more configurable by accepting database connection values at build time with runtime overrides and cleaned up the start command; retained public URL handling.
  • Bug Fixes

    • Fixed a production container instruction to restore reliable builds.

sla-te added 2 commits August 19, 2025 23:50
Signed-off-by: sla-te <22568014+sla-te@users.noreply.github.com>
…to run the migrations

Signed-off-by: sla-te <22568014+sla-te@users.noreply.github.com>
@vercel
Copy link

vercel bot commented Aug 19, 2025

@sla-te is attempting to deploy a commit to the Inbox Zero OSS Program Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 19, 2025

Walkthrough

Adds a new Self-hosting README describing a Docker Compose + host-native services deployment with Caddy TLS proxy, and updates docker/Dockerfile.prod to use build-time ARGs for DATABASE_URL and DIRECT_URL with corresponding ENV passthrough; retains NEXT_PUBLIC_BASE_URL handling and cleans up CMD whitespace.

Changes

Cohort / File(s) Summary
Self-hosting docs
SELFHOSTING_README.md
New documentation for self-hosted deployment: topology, prerequisites, host service preparation, .env template, docker-compose.override.yml, Caddyfile example, build/migrate/run steps, verification, security/networking notes, optional integrations, upgrade/rebuild guidance, troubleshooting.
Docker build/runtime env wiring
docker/Dockerfile.prod
Replaces static runtime ENVs for DATABASE_URL and DIRECT_URL with build-time ARGs and sets ENV DATABASE_URL=${DATABASE_URL} / ENV DIRECT_URL=${DIRECT_URL} to wire them through; preserves NEXT_PUBLIC_BASE_URL passthrough and removes trailing whitespace from CMD.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Admin as Admin (host)
    participant Caddy as Caddy (host)
    participant Web as Web App (container)
    participant DB as PostgreSQL (host)
    participant Redis as Redis (host)

    Note over Admin,Caddy: Setup & config (Caddyfile, .env, docker-compose.override)
    Admin->>Caddy: Configure TLS & reverse proxy
    Admin->>Web: Build image with ARGs (DATABASE_URL, DIRECT_URL, NEXT_PUBLIC_BASE_URL)
    Admin->>Web: Start container (connects to host services via host.docker.internal)

    Caddy->>Web: HTTPS request -> reverse proxy
    Web->>DB: SQL queries using DATABASE_URL (host-native)
    Web->>Redis: Cache ops using REDIS_URL (host-native)
    Web-->>Caddy: Response
    Caddy-->>Admin: Serve TLS response to client
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

A rabbit nibbles lines of config bright,
ARGs hop in place of ENVs at night.
Caddy hums TLS, containers align,
Host and web whisper: "connect just fine."
Compose the burrow, migrate, and sigh—Inbox Zero leaps high. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@CLAassistant
Copy link

CLAassistant commented Aug 19, 2025

CLA assistant check
All committers have signed the CLA.

@jit-ci
Copy link

jit-ci bot commented Aug 19, 2025

Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset.

In case there are security findings, they will be communicated to you as a comment inside the PR.

Hope you’ll enjoy using Jit.

Questions? Comments? Want to learn more? Get in touch with us.

Signed-off-by: sla-te <22568014+sla-te@users.noreply.github.com>
Copy link
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docker/Dockerfile.prod (1)

28-31: Ensure Prisma generate sees DATABASE_URL/DIRECT_URL: move ARG/ENV before generate

pnpm … prisma generate (Line 29) currently runs before ARG DATABASE_URL, ARG DIRECT_URL and the corresponding ENV are declared (Lines 37–38, 60–63). Some Prisma setups read env vars during generate; running without them can break builds.

Apply this diff to declare ARGs and set ENVs before the generate step:

@@
-# Run Prisma generate with build-time variables (cached)
-RUN pnpm --filter inbox-zero-ai exec -- prisma generate
+# Accept build-time arguments for NEXT_PUBLIC and DB URLs
+# Users can override any of these during build
+ARG NEXT_PUBLIC_BASE_URL="http://localhost:3000"
+ARG DATABASE_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
+ARG DIRECT_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
+
+# Provide dummy build-time ENV VARS (Still needed for build)
+ENV AUTH_SECRET="dummy_secret_for_build_only"
+ENV GOOGLE_CLIENT_ID="dummy_id_for_build_only"
+ENV GOOGLE_CLIENT_SECRET="dummy_secret_for_build_only"
+ENV EMAIL_ENCRYPT_SECRET="dummy_encrypt_secret_for_build_only"
+ENV EMAIL_ENCRYPT_SALT="dummy_encrypt_salt_for_build_only"
+ENV GOOGLE_PUBSUB_TOPIC_NAME="dummy_topic_for_build_only"
+ENV GOOGLE_PUBSUB_VERIFICATION_TOKEN="dummy_pubsub_token_for_build"
+ENV INTERNAL_API_KEY="dummy_apikey_for_build_only"
+ENV API_KEY_SALT="dummy_salt_for_build_only"
+ENV UPSTASH_REDIS_URL="http://dummy-redis-for-build:6379"
+ENV UPSTASH_REDIS_TOKEN="dummy_redis_token_for_build"
+ENV REDIS_URL="redis://dummy:dummy@dummy:6379"
+ENV QSTASH_TOKEN="dummy_qstash_token_for_build"
+ENV QSTASH_CURRENT_SIGNING_KEY="dummy_qstash_curr_key_for_build"
+ENV QSTASH_NEXT_SIGNING_KEY="dummy_qstash_next_key_for_build"
+
+# Set NEXT_PUBLIC env vars from ARGs (users can override these)
+ENV NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
+
+# Set DATABASE_URL, DIRECT_URL from ARGs (users can override these)
+ENV DATABASE_URL=${DATABASE_URL}
+ENV DIRECT_URL=${DIRECT_URL}
+
+# Run Prisma generate now that env vars are present
+RUN pnpm --filter inbox-zero-ai exec -- prisma generate
@@
-# Accept build-time arguments for all NEXT_PUBLIC variables
-# Users can override any of these during build
-ARG NEXT_PUBLIC_BASE_URL="http://localhost:3000"
-ARG DATABASE_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
-ARG DIRECT_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
@@
-# Set NEXT_PUBLIC env vars from ARGs (users can override these)
-ENV NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
-
-# Set DATABASE_URL, DIRECT_URL from ARGs (users can override these)
-ENV DATABASE_URL=${DATABASE_URL}
-ENV DIRECT_URL=${DIRECT_URL}

If you’d prefer not to expose DB envs during build, you can keep dummy values for ARG/ENV and ensure your Prisma generate doesn’t require connectivity.

Also applies to: 34-38, 60-63, 65-65

🧹 Nitpick comments (9)
SELFHOSTING_README.md (7)

40-44: Remove the /etc/hosts requirement for host.docker.internal on Linux

On Linux, you don’t need to add “127.0.0.1 host.docker.internal” to the host’s /etc/hosts. Inside containers, mapping is correctly handled via extra_hosts: ["host.docker.internal:host-gateway"]. The host OS itself doesn’t need this entry, and adding it can be misleading.

Apply this diff to drop the misleading bullet:

 Note on host.docker.internal:
 - On macOS and Windows, Docker provides it automatically.
 - On Linux, the override below maps host.docker.internal to the host gateway via extra_hosts.
-- Make sure you have `127.0.0.1 host.docker.internal` in your /etc/hosts file.

69-126: Add code fence languages and fix LLM model placeholders

  • Specify a language for fenced blocks to satisfy MD040 and improve readability. Use env here.
  • “gpt-5” is likely not a valid model identifier. Use a currently available model or a neutral placeholder to avoid confusion and setup failures.

Apply this diff:

-```
+```env
 # App and Web
 WEB_PORT=3105
 NEXT_PUBLIC_BASE_URL="https://example.com"  # This is baked into the build
@@
 # Optional but commonly used (LLM config)
 DEFAULT_LLM_PROVIDER="openai"
-DEFAULT_LLM_MODEL="gpt-5"           # Choose a current model you have access to (gpt-5 is quite accurate)
+DEFAULT_LLM_MODEL="gpt-4.1"         # Choose a current model you have access to
 ECONOMY_LLM_PROVIDER="openai"
-ECONOMY_LLM_MODEL="gpt-4.1-nano"
+ECONOMY_LLM_MODEL="gpt-4.1-mini"
 OPENAI_API_KEY="<your_openai_api_key>"

141-180: Compose override: add YAML fence and confirm custom tags support (!reset, !override)

  • Label the code block as YAML (MD040).
  • The !reset and !override tags are not standard Docker Compose. If you rely on project-specific tooling, great—otherwise these will fail with vanilla docker compose.

Apply this diff to add the language:

-```
+```yaml
 services:
   db: !reset []
   redis: !reset []
@@
 volumes: !reset []

If the tags require internal tooling, please confirm they are supported in your CI/CD and local dev workflows; otherwise, replace with standard compose semantics and document any manual steps.

---

`193-250`: **Caddyfile fixes: specify fence language and align routes (/twitter vs /x)**

- Add a code fence language (`caddyfile` or `txt`) for MD040.
- The preflight matcher uses `/twitter` while the proxy matcher uses `/x`. Pick one for consistency (assuming `/x`).


Apply this diff:

```diff
-```
+```caddyfile
 example.com {
@@
   @preflight {
     method OPTIONS
-    path /game /github /discord /twitter
+    path /game /github /discord /x
   }
@@
   @ext {
-    path /game /github /discord /x
+    path /game /github /discord /x
   }
@@
 }
-```
+```

263-276: Add shell language to command blocks

Use bash for command snippets to satisfy MD040 and improve syntax highlighting.

Apply this diff:

-```
+```bash
 docker compose build web

@@
- +bash
docker compose run --rm migrate

@@
-```
+```bash
docker compose up -d

---

`277-279`: **Avoid bare URLs in text**

Wrap raw URLs/hosts in backticks or markdown links to satisfy MD034 and improve readability.


Apply this diff:

```diff
-    - Or test locally: curl -I http://127.0.0.1:3105 (without TLS, from the host).
+    - Or test locally: `curl -I http://127.0.0.1:3105` (without TLS, from the host).

13-21: Standardize unordered list indentation to 2 spaces (MD007)

Several lists use 4-space subitem indentation; markdownlint expects 2. Not a blocker, but easy polish.

Examples of affected sections:

  • Topology overview (Lines 13–21)
  • Prerequisites (Lines 30–38)
  • Prepare Postgres/PgBouncer/Redis (Lines 50–61)
  • Verifications (Lines 285–295)
  • Upgrades/Rebuilds (Lines 324–327)
  • Troubleshooting (Lines 334–341)

Would you like me to push a quick formatting pass?

Also applies to: 30-38, 50-61, 285-295, 324-327, 334-341

docker/Dockerfile.prod (2)

20-23: Comment vs command mismatch: “ignore-scripts” disables postinstall

The comment says postinstall scripts will run, but --ignore-scripts prevents them. Either remove the flag or update the comment.

Two options:

  • To allow scripts:
-RUN pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
+RUN pnpm install --frozen-lockfile --prefer-offline
  • Or adjust the comment to reflect that scripts are intentionally skipped.

37-38: Dummy credentials trigger secret scanners; consider neutral placeholders or skip annotation

Tools like Checkov flag postgresql://dummy:dummy@... as basic auth credentials. These aren’t real secrets, but to reduce noise:

  • Use more neutral placeholders, or
  • Add a scanner skip annotation (if your pipeline supports it).

Example:

-ARG DATABASE_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
-ARG DIRECT_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
+# checkov:skip=CKV_SECRET_4 reason=Dummy credentials for build-time only; overridden at runtime
+ARG DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/DB?schema=public"
+ARG DIRECT_URL="postgresql://USER:PASSWORD@HOST:5432/DB?schema=public"
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dd7e1a3 and bf64070.

📒 Files selected for processing (2)
  • SELFHOSTING_README.md (1 hunks)
  • docker/Dockerfile.prod (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
!{.cursor/rules/*.mdc}

📄 CodeRabbit Inference Engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • SELFHOSTING_README.md
  • docker/Dockerfile.prod
*{TASKS,ASSISTANT_CHAT,*.md}

📄 CodeRabbit Inference Engine (.cursor/rules/task-list.mdc)

*{TASKS,ASSISTANT_CHAT,*.md}: Create task lists in a markdown file in the project root, using TASKS.md or a descriptive name relevant to the feature (e.g., ASSISTANT_CHAT.md), and include a clear title and description of the feature being implemented.
Structure the task list markdown file with sections: Completed Tasks, In Progress Tasks, Future Tasks, Implementation Plan, and Relevant Files.
Update the task list as you progress: mark tasks as completed by changing [ ] to [x], add new tasks as identified, and move tasks between sections as appropriate.
Keep the 'Relevant Files' section updated with file paths, brief descriptions of each file's purpose, and status indicators (e.g., ✅) for completed components.
Add implementation details to the task list markdown file, including architecture decisions, data flow descriptions, technical components needed, and environment configuration.
When working with task lists, regularly update the task list file after implementing significant components, mark completed tasks with [x], add new tasks discovered during implementation, maintain the 'Relevant Files' section, and document implementation details.
When implementing tasks one by one, first check which task to implement next, and after implementing a task, update the file to reflect progress.

Files:

  • SELFHOSTING_README.md
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • SELFHOSTING_README.md
  • docker/Dockerfile.prod
🧠 Learnings (1)
📚 Learning: 2025-07-18T15:04:30.467Z
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.467Z
Learning: Applies to apps/web/**/{.env.example,env.ts} : Client-side environment variables: Prefix with `NEXT_PUBLIC_`

Applied to files:

  • docker/Dockerfile.prod
🪛 LanguageTool
SELFHOSTING_README.md

[grammar] ~13-~13: There might be a mistake here.
Context: ...ogy Overview - Native services on host: - PostgreSQL (5432) - PgBouncer (e.g.,...

(QB_NEW_EN)


[grammar] ~14-~14: There might be a mistake here.
Context: ...ervices on host: - PostgreSQL (5432) - PgBouncer (e.g., 6432 for Prisma) - ...

(QB_NEW_EN)


[grammar] ~15-~15: There might be a mistake here.
Context: ... - PgBouncer (e.g., 6432 for Prisma) - Redis (6379) - Reverse proxy (Caddy)...

(QB_NEW_EN)


[grammar] ~16-~16: There might be a mistake here.
Context: ....g., 6432 for Prisma) - Redis (6379) - Reverse proxy (Caddy), serving your publ...

(QB_NEW_EN)


[grammar] ~17-~17: There might be a mistake here.
Context: ...Caddy), serving your public domain (TLS) - Docker containers: - web (Next.js ap...

(QB_NEW_EN)


[grammar] ~18-~18: There might be a mistake here.
Context: ...public domain (TLS) - Docker containers: - web (Next.js app) - serverless-redis...

(QB_NEW_EN)


[grammar] ~19-~19: There might be a mistake here.
Context: ...cker containers: - web (Next.js app) - serverless-redis-http helper (talks to R...

(QB_NEW_EN)


[grammar] ~22-~22: There might be a mistake here.
Context: ...lks to Redis on the host) Ingress flow: Internet → Caddy (TLS termination, on ho...

(QB_NEW_EN)


[grammar] ~25-~25: There might be a mistake here.
Context: ...ntainer Database/Cache from containers: web → host.docker.internal → PgBouncer/P...

(QB_NEW_EN)


[grammar] ~32-~32: There might be a mistake here.
Context: ...sites - Docker and Docker Compose (v2+) - A Linux host where: - Postgres, PgBo...

(QB_NEW_EN)


[grammar] ~33-~33: There might be a mistake here.
Context: ...cker Compose (v2+) - A Linux host where: - Postgres, PgBouncer, and Redis run nativ...

(QB_NEW_EN)


[grammar] ~37-~37: There might be a mistake here.
Context: ...dled by Caddy (or another reverse proxy) - Git and basic shell access Note on host...

(QB_NEW_EN)


[grammar] ~293-~293: There might be a mistake here.
Context: ... correct and uses https. - Admin access: - Confirm the ADMINS email has the expecte...

(QB_NEW_EN)


[grammar] ~314-~314: There might be a mistake here.
Context: ...our public domain. If enabling Outlook: - Set MICROSOFT_CLIENT_ID, MICROSOFT_CLIEN...

(QB_NEW_EN)


[grammar] ~323-~323: There might be a mistake here.
Context: ...(notably NEXT_PUBLIC_BASE_URL), rebuild: - docker compose build web - docker co...

(QB_NEW_EN)


[grammar] ~324-~324: There might be a mistake here.
Context: ... rebuild: - docker compose build web - docker compose up -d web - For database ...

(QB_NEW_EN)


[grammar] ~325-~325: There might be a mistake here.
Context: ...build web - docker compose up -d web - For database schema changes in new versi...

(QB_NEW_EN)


[grammar] ~326-~326: There might be a mistake here.
Context: ...database schema changes in new versions: - docker compose run --rm migrate --- ##...

(QB_NEW_EN)


[grammar] ~340-~340: There might be a mistake here.
Context: ...m the container. - host.docker.internal: - Ensure the override includes extra_hosts...

(QB_NEW_EN)


[grammar] ~406-~406: There might be a mistake here.
Context: ... - Build the image (after setting .env): - docker compose build web - Run migration...

(QB_NEW_EN)


[grammar] ~407-~407: There might be a mistake here.
Context: ...ng .env): - docker compose build web - Run migrations: - docker compose run...

(QB_NEW_EN)


[grammar] ~408-~408: There might be a mistake here.
Context: ...cker compose build web - Run migrations: - docker compose run --rm migrate - Start ...

(QB_NEW_EN)


[grammar] ~409-~409: There might be a mistake here.
Context: ...s: - docker compose run --rm migrate - Start services: - docker compose up ...

(QB_NEW_EN)


[grammar] ~410-~410: There might be a mistake here.
Context: ...mpose run --rm migrate - Start services: - docker compose up -d That’s it! Your In...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.17.2)
SELFHOSTING_README.md

14-14: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


15-15: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


16-16: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


17-17: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


19-19: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


20-20: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


23-23: Bare URL used

(MD034, no-bare-urls)


34-34: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


35-35: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


36-36: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


50-50: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


51-51: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


52-52: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


55-55: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


56-56: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


57-57: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


60-60: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


61-61: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


69-69: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


130-130: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


130-130: Bare URL used

(MD034, no-bare-urls)


131-131: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


131-131: Bare URL used

(MD034, no-bare-urls)


141-141: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


193-193: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


263-263: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


268-268: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


273-273: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


277-277: Bare URL used

(MD034, no-bare-urls)


278-278: Bare URL used

(MD034, no-bare-urls)


285-285: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


287-287: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


288-288: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


290-290: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


292-292: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


294-294: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


324-324: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


325-325: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


327-327: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


334-334: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


335-335: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


337-337: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


339-339: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


341-341: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


349-349: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


407-407: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


409-409: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


411-411: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

🪛 Hadolint (2.12.0)
docker/Dockerfile.prod

[error] 1-1: unexpected 'R'
expecting '#', ADD, ARG, CMD, COPY, ENTRYPOINT, ENV, EXPOSE, FROM, HEALTHCHECK, LABEL, MAINTAINER, ONBUILD, RUN, SHELL, STOPSIGNAL, USER, VOLUME, WORKDIR, a pragma, end of input, or whitespaces

(DL1000)

🪛 Checkov (3.2.334)
docker/Dockerfile.prod

[MEDIUM] 37-38: Basic Auth Credentials

(CKV_SECRET_4)

🔇 Additional comments (1)
docker/Dockerfile.prod (1)

60-63: Runtime env wiring looks good

ENV DATABASE_URL=${DATABASE_URL} and ENV DIRECT_URL=${DIRECT_URL} will be overridden by compose-time environment: values as documented in the README. CMD pnpm --filter inbox-zero-ai start is appropriate for production start.

Also applies to: 71-71

Comment on lines +349 to +400
```
WEB_PORT=3105
ADMINS="your.email@example.com"
NEXT_PUBLIC_BASE_URL="https://example.com"

EMAIL_ENCRYPT_SALT=""
EMAIL_ENCRYPT_SECRET=""

DATABASE_URL="postgresql://<user>:<password>@host.docker.internal:6432/inboxzero?pgbouncer=true"
DIRECT_URL="postgresql://<puser>:<password>@host.docker.internal:5432/inboxzero?schema=public"

# LLM config (optional)
DEFAULT_LLM_PROVIDER="openai"
DEFAULT_LLM_MODEL="gpt-4.1-mini"
ECONOMY_LLM_MODEL="gpt-4o-mini"
ECONOMY_LLM_PROVIDER="openai"
OPENAI_API_KEY="sk-<your_openai_api_key>"

INTERNAL_API_KEY=""
API_KEY_SALT=""

UPSTASH_REDIS_TOKEN=""
REDIS_URL="redis://:<password>@host.docker.internal:6379/1"
SRH_CONNECTION_STRING="redis://:<password>@host.docker.internal:6379/1"
QSTASH_TOKEN="dummy_qstash_token_for_build"
QSTASH_CURRENT_SIGNING_KEY="dummy_qstash_curr_key_for_build"
QSTASH_NEXT_SIGNING_KEY="dummy_qstash_next_key_for_build"

LOG_ZOD_ERRORS=true
CRON_SECRET=""

# Gmail (optional)
GOOGLE_CLIENT_ID="<your_google_client_id>"
GOOGLE_CLIENT_SECRET="<your_google_client_secret>"
GOOGLE_ENCRYPT_SECRET=""
GOOGLE_ENCRYPT_SALT=""
GOOGLE_PUBSUB_TOPIC_NAME="projects/<your-gcp-project-id>/topics/<your-topic-name>"
GOOGLE_PUBSUB_VERIFICATION_TOKEN=""

# Outlook (optional)
# MICROSOFT_CLIENT_ID=
# MICROSOFT_CLIENT_SECRET=
# MICROSOFT_ENCRYPT_SECRET=
# MICROSOFT_ENCRYPT_SALT=

# Optional analytics/logging/SaaS (set if you use them)
# NEXT_PUBLIC_SENTRY_DSN=
# NEXT_PUBLIC_POSTHOG_KEY=
# RESEND_API_KEY=
# LOOPS_API_SECRET=
# NEXT_PUBLIC_CRISP_WEBSITE_ID=
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Redacted .env template: fix DIRECT_URL typo, add fence language, and normalize model placeholders

  • Correct DIRECT_URL user placeholder (<puser><user>).
  • Specify env for the code block.
  • Keep model placeholders consistent with earlier section.

Apply this diff:

-```
+```env
 WEB_PORT=3105
 ADMINS="your.email@example.com"
 NEXT_PUBLIC_BASE_URL="https://example.com"
@@
-DIRECT_URL="postgresql://<puser>:<password>@host.docker.internal:5432/inboxzero?schema=public"
+DIRECT_URL="postgresql://<user>:<password>@host.docker.internal:5432/inboxzero?schema=public"
@@
-DEFAULT_LLM_MODEL="gpt-4.1-mini"
-ECONOMY_LLM_MODEL="gpt-4o-mini"
+DEFAULT_LLM_MODEL="gpt-4.1"
+ECONOMY_LLM_MODEL="gpt-4.1-mini"
 ECONOMY_LLM_PROVIDER="openai"
 OPENAI_API_KEY="sk-<your_openai_api_key>"
@@
-```
+```
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

349-349: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In SELFHOSTING_README.md around lines 349 to 400, the .env snippet needs three
edits: change the opening and closing triple backticks to specify the language
by replacing ``` with ```env, fix the DIRECT_URL user placeholder from <puser>
to <user>, and normalize the LLM model placeholders by setting
DEFAULT_LLM_MODEL="gpt-4.1" and ECONOMY_LLM_MODEL="gpt-4.1-mini"; update the
snippet accordingly so the fenced block starts with ```env and contains the
corrected DIRECT_URL and model values.

Signed-off-by: sla-te <22568014+sla-te@users.noreply.github.com>
Copy link
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: 1

🧹 Nitpick comments (2)
docker/Dockerfile.prod (2)

37-38: Avoid credential-like defaults in build ARGs (trips scanners, unnecessary).

Checkov flags these as Basic Auth credentials (CKV_SECRET_4). Since these are only placeholders, prefer removing the defaults entirely (or set to empty) to avoid false positives and accidental propagation.

Apply this diff:

-ARG DATABASE_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
-ARG DIRECT_URL="postgresql://dummy:dummy@dummy:5432/dummy?schema=public"
+ARG DATABASE_URL
+ARG DIRECT_URL

20-26: Optional: Use a multi-stage build to avoid carrying dev deps and any build-only envs.

Right now everything (node_modules, source, dummy envs) lands in the runtime image. A builder stage can run pnpm install, prisma generate, and next build with safe placeholders; then copy the built app into a minimal runtime stage, improving security and image size.

Example outline (non-diff, for clarity):

FROM node:22-alpine AS builder
WORKDIR /app
RUN apk add --no-cache openssl && npm i -g pnpm
# copy manifests, install, copy source...
# set only dummy envs needed for build, NOT real DB URLs
ENV NODE_ENV=production
ENV NEXT_PUBLIC_BASE_URL=http://localhost:3000
RUN pnpm --filter inbox-zero-ai exec -- prisma generate
RUN pnpm --filter inbox-zero-ai exec -- next build

FROM node:22-alpine AS runner
WORKDIR /app
RUN npm i -g pnpm
ENV NODE_ENV=production
# DO NOT set DATABASE_URL/DIRECT_URL here; provide at runtime
COPY --from=builder /app/apps/web/.next ./apps/web/.next
# copy only runtime artifacts and necessary package.json files
EXPOSE 3000
CMD pnpm --filter inbox-zero-ai start

This prevents build-time placeholders or user-provided args from leaking into the runtime image.

Also applies to: 65-69

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bf64070 and 8cf10df.

📒 Files selected for processing (1)
  • docker/Dockerfile.prod (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
!{.cursor/rules/*.mdc}

📄 CodeRabbit Inference Engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • docker/Dockerfile.prod
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • docker/Dockerfile.prod
🧠 Learnings (1)
📚 Learning: 2025-07-18T15:04:30.467Z
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.467Z
Learning: Applies to apps/web/**/{.env.example,env.ts} : Client-side environment variables: Prefix with `NEXT_PUBLIC_`

Applied to files:

  • docker/Dockerfile.prod
🪛 Checkov (3.2.334)
docker/Dockerfile.prod

[MEDIUM] 37-38: Basic Auth Credentials

(CKV_SECRET_4)

🔇 Additional comments (1)
docker/Dockerfile.prod (1)

71-71: LGTM: Cleaned up CMD.

Removing trailing whitespace and using pnpm filter directly is fine.

Comment on lines +60 to +63
# Set DATABASE_URL, DIRECT_URL from ARGs (users can override these)
ENV DATABASE_URL=${DATABASE_URL}
ENV DIRECT_URL=${DIRECT_URL}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical: Don’t bake DATABASE_URL/DIRECT_URL into the image.

Mapping build-time ARGs to runtime ENV will persist secrets into the final image if passed via --build-arg. These values become visible via docker history/inspect and are stored in the registry. Pass DB URLs at runtime (compose/k8s env/secrets) instead.

Apply this diff to prevent secret persistence:

-# Set DATABASE_URL, DIRECT_URL from ARGs (users can override these)
-ENV DATABASE_URL=${DATABASE_URL}
-ENV DIRECT_URL=${DIRECT_URL}
+## Intentionally do not set DATABASE_URL/DIRECT_URL at build-time.
+## Provide them at runtime via environment variables or secrets.

If Prisma/Next build requires placeholders, keep dummy ENV limited to the builder stage only (see multi-stage suggestion below), but avoid propagating real values to the final image.

🤖 Prompt for AI Agents
In docker/Dockerfile.prod around lines 60-63, remove the lines that map
build-time args DATABASE_URL and DIRECT_URL into runtime ENV to avoid baking
secrets into the image; instead only accept ARGs in the build stage (or populate
dummy placeholders in the builder stage if Prisma/Next needs them) and ensure
the final stage does not set ENV DATABASE_URL or DIRECT_URL — supply the real DB
URLs at runtime via docker-compose/k8s secrets or environment variables; if
using multi-stage builds, move any placeholder ENV usage to the intermediate
builder stage and do not propagate those ENV values into the final image, and
update docs/compose manifests to document runtime secret injection.

@elie222
Copy link
Owner

elie222 commented Aug 28, 2025

@sla-te see the coderabbit comments which are important

@elie222 elie222 closed this Aug 29, 2025
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.

3 participants