Skip to content

feat: parameterize all ports and pod name for parallel prod/dev deployments#248

Closed
sheepdestroyer wants to merge 12 commits into
masterfrom
chore/learn-deployment-guidelines
Closed

feat: parameterize all ports and pod name for parallel prod/dev deployments#248
sheepdestroyer wants to merge 12 commits into
masterfrom
chore/learn-deployment-guidelines

Conversation

@sheepdestroyer

@sheepdestroyer sheepdestroyer commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Summary

Replaces all hardcoded port values and the pod name in pod.yaml, start-stack.sh, litellm/config.yaml and litellm/entrypoint.py with environment-variable-driven placeholders. A single pod.yaml now serves both the production agent-router-pod and a development dev-router-pod running concurrently on offset ports (+10), with data isolated to a separate dev-data/ directory.

Changes

Infrastructure

  • pod.yaml: Rewrite with *_PLACEHOLDER vars for pod name, all 13 service ports, and DATA_ROOT. Adds clickhouse-port-config volume (dynamic XML override). LiteLLM volume now binds DATA_ROOT/litellm-rendered/ (rendered at deploy time).
  • start-stack.sh: Load optional DEV_ENV_FILE overlay after main .env; resolve port/name defaults from env; add generate_clickhouse_config() and render_litellm_config() helpers; parameterize all agent-router-pod references and hardcoded ports throughout cleanup, health-check, and MinIO helpers.

Port mappings (prod → dev)

Service Prod Dev
FastAPI Router 5000 5010
LiteLLM 4000 4010
Langfuse Web 3001 3011
Langfuse Worker 3030 3040
PostgreSQL 5432 5442
Valkey Cache 6379 6389
Valkey LF 6380 6390
ClickHouse HTTP 8123 8133
ClickHouse TCP 9000 9010
ClickHouse Interserver 9009 9019
MinIO S3 9002 9012
MinIO Console 9001 9011

Application

  • litellm/config.yaml: Replace port 6379/5000 with *_PLACEHOLDER vars (rendered by render_litellm_config())
  • litellm/entrypoint.py: Read POSTGRES_PORT/LITELLM_PORT from env; use setdefault to not clobber container-injected env vars

Dev deployment

  • .env: Append production port defaults section (POD_NAME, ROUTER_PORT, …)
  • .env.dev (new): Dev overlay with POD_NAME=dev-router-pod, +10 port offsets, dev.vendeuvre.lan URLs
  • start-dev.sh (new): Thin wrapper that sets DEV_ENV_FILE+DATA_ROOT then delegates to start-stack.sh
  • .gitignore: Exclude dev-data/ (dev-stack runtime volumes)

Summary by Sourcery

Parameterize pod name and service ports for flexible prod/dev deployments and add support for pulling router images from GHCR alongside local rebuilds.

New Features:

  • Allow starting a parallel dev stack via a new start-dev.sh wrapper and .env.dev overlay using separate data directories and port offsets.
  • Support pulling the latest router image from GHCR with a new --pull mode in start-stack.sh in addition to local full rebuilds.

Bug Fixes:

  • Prevent .env values from clobbering container-injected environment variables in litellm/entrypoint.py by using default-only assignment.
  • Ensure PostgreSQL and LiteLLM respect configurable ports in both pod configuration and entrypoint logic.

Enhancements:

  • Make all service ports, pod name, and data root environment-driven in start-stack.sh and pod.yaml to enable configurable deployments.
  • Render LiteLLM config and ClickHouse port override files at deploy time into a data-root-specific directory for each environment.
  • Derive proxy base URL from PUBLIC_BASE_URL instead of separate env vars and simplify related configuration.
  • Adjust health checks and MinIO helpers to use parameterized ports and pod names instead of hardcoded values.

Chores:

  • Ignore dev-data runtime directory in version control to avoid committing local dev volumes.

Summary by CodeRabbit

  • New Features

    • Added a development startup workflow with isolated environment settings and service data directories.
    • Added support for configurable service ports, URLs, pod names, and data locations.
    • Added options to pull the latest router image and redeploy the development stack.
  • Improvements

    • Enhanced service health checks and startup behavior for custom configurations.
    • Added automatic rendering of service configuration with environment-specific values.
    • Prevented development data from being tracked in version control.

…yments

Replaces all hardcoded port values and the pod name in pod.yaml,
start-stack.sh, litellm/config.yaml and litellm/entrypoint.py with
environment-variable-driven placeholders. A single pod.yaml now serves
both the production agent-router-pod and the development dev-router-pod.

Changes:
- pod.yaml: rewrite with *_PLACEHOLDER vars for pod name, all 13 service
  ports, and DATA_ROOT; add clickhouse-port-config volume; litellm-config
  volume now points to DATA_ROOT/litellm-rendered (rendered copy)
- start-stack.sh: load optional DEV_ENV_FILE overlay; resolve port/name
  defaults after env sourcing; add generate_clickhouse_config() and
  render_litellm_config() helpers; parameterize all agent-router-pod refs
  and hardcoded ports throughout cleanup, health-check, and minio helpers
- litellm/config.yaml: replace port 6379 / 5000 with *_PLACEHOLDER vars
  (rendered at deploy time via render_litellm_config)
- litellm/entrypoint.py: read POSTGRES_PORT / LITELLM_PORT from env
  instead of hardcoded 5432 / 4000; use setdefault to not clobber
  container-injected env vars
- .env: append production port defaults (POD_NAME, ROUTER_PORT, ...)
- .env.dev: new dev overlay (POD_NAME=dev-router-pod, +10 port offsets,
  dev.vendeuvre.lan URLs)
- start-dev.sh: thin wrapper that sets DEV_ENV_FILE + DATA_ROOT then
  delegates to start-stack.sh
- .gitignore: exclude dev-data/ (dev-stack runtime volumes)
@sourcery-ai

sourcery-ai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR parameterizes pod name, all service ports, and data paths via environment variables so a production and development router stack can run concurrently from a single pod definition, and updates scripts/configs to render environment-specific ClickHouse and LiteLLM configs at deploy time.

Sequence diagram for prod/dev stack deployment via start-stack.sh

sequenceDiagram
    actor Operator
    participant start_dev_sh
    participant start_stack_sh
    participant generate_clickhouse_config
    participant render_litellm_config
    participant render_pod_yaml
    participant podman

    Operator->>start_dev_sh: run start-dev.sh
    start_dev_sh->>start_dev_sh: set DEV_ENV_FILE
    start_dev_sh->>start_dev_sh: set DATA_ROOT=dev-data
    start_dev_sh->>start_stack_sh: exec start-stack.sh

    Operator->>start_stack_sh: run start-stack.sh (prod)

    start_stack_sh->>start_stack_sh: load .env
    start_stack_sh->>start_stack_sh: load DEV_ENV_FILE (if set)
    start_stack_sh->>start_stack_sh: export POD_NAME, ports, DATA_ROOT

    start_stack_sh->>generate_clickhouse_config: generate_clickhouse_config()
    generate_clickhouse_config-->>start_stack_sh: write port-override.xml

    start_stack_sh->>render_litellm_config: render_litellm_config()
    render_litellm_config-->>start_stack_sh: write litellm-rendered/config.yaml

    start_stack_sh->>render_pod_yaml: render_pod_yaml()
    render_pod_yaml-->>start_stack_sh: pod manifest with env ports/name

    start_stack_sh->>podman: podman play kube -
    podman-->>Operator: agent-router-pod or dev-router-pod running on configured ports
Loading

File-Level Changes

Change Details Files
Parameterize pod name, ports, and data-root in pod manifest and wire them to per-env host volumes.
  • Replace hardcoded pod name with POD_NAME_PLACEHOLDER and add POD_NAME placeholder handling in render_pod_yaml
  • Replace all hardcoded service ports (Valkey, LiteLLM, router, Langfuse, Postgres, ClickHouse, MinIO) with *_PORT_PLACEHOLDER values and add raw replacement logic in render_pod_yaml
  • Switch hostPath mounts from WORKDIR-based directories to DATA_ROOT_PLACEHOLDER-based directories and add a clickhouse-port-config volume mounting a rendered port-override.xml
pod.yaml
start-stack.sh
Make stack startup, health checks, and teardown fully environment-driven, including prod/dev overlays and ClickHouse/LiteLLM rendered configs.
  • Add DEV_ENV_FILE overlay loading and define POD_NAME, DATA_ROOT, and all service ports from env with sane defaults
  • Refactor cleanup_zombie_ports, verify_stack_health, and MinIO setup to use env-driven ports and pod name instead of hardcoded values
  • Introduce generate_clickhouse_config() to emit a config.d XML overriding ClickHouse HTTP/TCP/interserver ports and render_litellm_config() to produce an env-specific LiteLLM config/entrypoint under DATA_ROOT/litellm-rendered
  • Update deploy paths to always generate ClickHouse and LiteLLM configs before pod play, and support a new --pull mode that pulls ghcr.io/sheepdestroyer/llm-routing:latest while reusing the same image tag for local rebuilds
start-stack.sh
pod.yaml
Parameterize LiteLLM and router connections to Redis and router, and make LiteLLM entrypoint respect env-provided ports without overwriting container env.
  • Replace hardcoded Valkey and router ports in litellm/config.yaml with VALKEY_CACHE_PORT_PLACEHOLDER and ROUTER_PORT_PLACEHOLDER for rendering by render_litellm_config()
  • Change litellm/entrypoint.py dotenv loading to use os.environ.setdefault so container-injected envs win, and to wait on POSTGRES_PORT from env instead of fixed 5432
  • Make LiteLLM proxy listen on LITELLM_PORT/PORT env variable and update pod liveness/readiness probes and env wiring accordingly
litellm/config.yaml
litellm/entrypoint.py
pod.yaml
Add a dedicated dev stack wrapper and environment overlay to run a dev router pod on offset ports with isolated data directories.
  • Extend .env with defaults for POD_NAME, DATA_ROOT, and all service ports used by prod, and introduce .env.dev overlay with dev-router-pod name, +10 port offsets, and dev-specific URLs
  • Add start-dev.sh wrapper that sets DEV_ENV_FILE and DATA_ROOT to dev-data/, pre-creates needed dev-data subdirectories, and delegates to start-stack.sh
  • Ignore dev-data/ runtime volumes via .gitignore to avoid committing dev artifacts
.env
.env.dev
start-dev.sh
.gitignore

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@sheepdestroyer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e87dff5d-a2f8-4760-b6aa-7ceb490d4215

📥 Commits

Reviewing files that changed from the base of the PR and between 3084c68 and 1afa7c1.

📒 Files selected for processing (9)
  • .env.dev
  • .gitignore
  • litellm/entrypoint.py
  • pod.yaml
  • router/config.yaml
  • router/main.py
  • scripts/backup.sh
  • start-dev.sh
  • start-stack.sh
📝 Walkthrough

Walkthrough

The stack adds a development environment overlay, configurable service ports and URLs, rendered service configuration, isolated dev data directories, dynamic health checks, and pull/rebuild deployment modes.

Changes

Development stack configuration

Layer / File(s) Summary
Environment overlay and bootstrap
.env.dev, .gitignore, start-dev.sh, start-stack.sh
Development startup defines pod identity, URLs, ports, data paths, optional environment loading, and --pull deployment handling.
Rendered service configuration
litellm/config.yaml, pod.yaml, start-stack.sh
Service manifests and rendered LiteLLM/ClickHouse configuration use substituted ports, URLs, storage paths, pod names, mounts, and probes.
Runtime checks and deployment lifecycle
litellm/entrypoint.py, start-stack.sh
Runtime startup, readiness checks, MinIO setup, teardown, backups, image selection, and deployment flows use configured ports and pod identity.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: parameterizing ports and pod name to support parallel prod/dev deployments.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/learn-deployment-guidelines

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.

@sourcery-ai sourcery-ai Bot left a comment

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.

Hey - I've found 1 issue, and left some high level feedback:

  • The image reference ghcr.io/sheepdestroyer/llm-routing:latest is now duplicated in both start-stack.sh and pod.yaml; consider centralizing this into an environment variable or a single config location to avoid drift.
  • In render_litellm_config(), the sed-based placeholder replacement is tightly coupled to the current config.yaml structure; adding a brief sanity check (e.g., verifying the placeholders exist before writing) would make failures from future config changes easier to detect.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The image reference `ghcr.io/sheepdestroyer/llm-routing:latest` is now duplicated in both `start-stack.sh` and `pod.yaml`; consider centralizing this into an environment variable or a single config location to avoid drift.
- In `render_litellm_config()`, the `sed`-based placeholder replacement is tightly coupled to the current `config.yaml` structure; adding a brief sanity check (e.g., verifying the placeholders exist before writing) would make failures from future config changes easier to detect.

## Individual Comments

### Comment 1
<location path="litellm/entrypoint.py" line_range="19" />
<code_context>
             line = line.strip()
             if line and not line.startswith("#") and "=" in line:
                 key, _, val = line.partition("=")
-                val = val.strip().strip('"').strip("'")
-                os.environ[key] = val
+                os.environ.setdefault(key, val)

 # Load Gemini OAuth token from credentials JSON
</code_context>
<issue_to_address>
**issue (bug_risk):** Preserving quotes/whitespace in .env values can break numeric parsing (e.g. POSTGRES_PORT).

With the updated logic, a line like `POSTGRES_PORT="5432"` now sets `os.environ['POSTGRES_PORT']` to the literal string `"5432"`, so `int(os.environ.get("POSTGRES_PORT", "5432"))` will raise `ValueError`. Leading/trailing spaces cause the same issue. Please restore at least `val.strip()` (and optionally quote stripping) while keeping the new `setdefault` behavior.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread litellm/entrypoint.py
line = line.strip()
if line and not line.startswith("#") and "=" in line:
key, _, val = line.partition("=")
val = val.strip().strip('"').strip("'")

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.

issue (bug_risk): Preserving quotes/whitespace in .env values can break numeric parsing (e.g. POSTGRES_PORT).

With the updated logic, a line like POSTGRES_PORT="5432" now sets os.environ['POSTGRES_PORT'] to the literal string "5432", so int(os.environ.get("POSTGRES_PORT", "5432")) will raise ValueError. Leading/trailing spaces cause the same issue. Please restore at least val.strip() (and optionally quote stripping) while keeping the new setdefault behavior.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces a development environment overlay (.env.dev), a start-dev.sh wrapper, and dynamic port configuration across the entire stack (including LiteLLM, Langfuse, Postgres, ClickHouse, Valkey, and MinIO) to allow running a development stack alongside production. The review feedback highlights several critical issues: removing quote-stripping in entrypoint.py will cause integer casting failures for quoted port variables; hardcoding NEXTAUTH_URL to localhost breaks external Langfuse authentication; and the pre-deploy backup script fails in dev mode due to hardcoded container names. Additionally, local volume directories should be created under the resolved DATA_ROOT to prevent repository pollution, and generated configuration files must be explicitly set to world-readable (chmod 644) to ensure non-root containers can access them.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread litellm/entrypoint.py
Comment on lines 18 to +19
key, _, val = line.partition("=")
val = val.strip().strip('"').strip("'")
os.environ[key] = val
os.environ.setdefault(key, val)

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.

critical

Without stripping quotes from the environment variable values parsed from the .env file, any quoted values (e.g., POSTGRES_PORT="5442") will retain their literal quotes (e.g., '"5442"'). This will cause a ValueError when attempting to cast them to integers later in the script (e.g., int(os.environ.get("POSTGRES_PORT", "5432"))).

We should restore the quote-stripping logic before calling os.environ.setdefault().

Suggested change
key, _, val = line.partition("=")
val = val.strip().strip('"').strip("'")
os.environ[key] = val
os.environ.setdefault(key, val)
key, _, val = line.partition("=")
val = val.strip().strip('"').strip("'")
os.environ.setdefault(key, val)

Comment thread pod.yaml
Comment on lines 304 to +305
- name: NEXTAUTH_URL
value: NEXTAUTH_URL_PLACEHOLDER
value: http://localhost:LANGFUSE_WEB_PORT_PLACEHOLDER

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.

high

Hardcoding NEXTAUTH_URL to http://localhost:LANGFUSE_WEB_PORT_PLACEHOLDER will break authentication (login, logout, and session cookies) when accessing the Langfuse dashboard externally via the reverse proxy (e.g., https://dev.vendeuvre.lan/llm-routing/langfuse). NextAuth requires NEXTAUTH_URL to match the actual public-facing URL used by the client's browser.

Instead, we should re-introduce NEXTAUTH_URL_PLACEHOLDER and replace it with the public Langfuse URL (e.g., ${PUBLIC_BASE_URL}/langfuse) during the rendering phase in start-stack.sh.

    - name: NEXTAUTH_URL
      value: NEXTAUTH_URL_PLACEHOLDER

Comment thread start-stack.sh Outdated
Comment on lines 40 to 41
# Ensure local volume directories exist on the host for Podman mounts
mkdir -p valkey-data postgres-data langfuse-data clickhouse-data redis-lf-data minio-data

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.

medium

Creating the local volume directories at the very beginning of start-stack.sh using relative paths always pollutes the repository root with empty production directories (e.g., valkey-data, postgres-data, etc.) even when running in dev mode (via start-dev.sh).

We should move this directory creation to after DATA_ROOT is resolved (around line 98) and use "$DATA_ROOT" to ensure the directories are created in the correct isolated location.

Suggested change
# Ensure local volume directories exist on the host for Podman mounts
mkdir -p valkey-data postgres-data langfuse-data clickhouse-data redis-lf-data minio-data
# Ensure local volume directories exist on the host for Podman mounts
# Note: Directory creation has been moved to after DATA_ROOT is resolved to support dev/prod isolation.

Comment thread start-stack.sh Outdated
Comment on lines +97 to +98
DATA_ROOT="${DATA_ROOT:-${WORKDIR}}"
export POD_NAME ROUTER_PORT LITELLM_PORT LANGFUSE_WEB_PORT LANGFUSE_WORKER_PORT POSTGRES_PORT VALKEY_CACHE_PORT VALKEY_LF_PORT CLICKHOUSE_HTTP_PORT CLICKHOUSE_TCP_PORT CLICKHOUSE_INTERSERVER_PORT MINIO_S3_PORT MINIO_CONSOLE_PORT DATA_ROOT

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.

medium

To support the moved directory creation, we should create the directories under "$DATA_ROOT" here, right after DATA_ROOT is resolved and exported. This also makes the duplicate mkdir -p in start-dev.sh redundant.

Suggested change
DATA_ROOT="${DATA_ROOT:-${WORKDIR}}"
export POD_NAME ROUTER_PORT LITELLM_PORT LANGFUSE_WEB_PORT LANGFUSE_WORKER_PORT POSTGRES_PORT VALKEY_CACHE_PORT VALKEY_LF_PORT CLICKHOUSE_HTTP_PORT CLICKHOUSE_TCP_PORT CLICKHOUSE_INTERSERVER_PORT MINIO_S3_PORT MINIO_CONSOLE_PORT DATA_ROOT
DATA_ROOT="${DATA_ROOT:-${WORKDIR}}"
export POD_NAME ROUTER_PORT LITELLM_PORT LANGFUSE_WEB_PORT LANGFUSE_WORKER_PORT POSTGRES_PORT VALKEY_CACHE_PORT VALKEY_LF_PORT CLICKHOUSE_HTTP_PORT CLICKHOUSE_TCP_PORT CLICKHOUSE_INTERSERVER_PORT MINIO_S3_PORT MINIO_CONSOLE_PORT DATA_ROOT
mkdir -p "$DATA_ROOT/valkey-data" "$DATA_ROOT/postgres-data" "$DATA_ROOT/clickhouse-data" "$DATA_ROOT/redis-lf-data" "$DATA_ROOT/minio-data" "$DATA_ROOT/clickhouse-config" "$DATA_ROOT/litellm-rendered"

Comment thread start-stack.sh
Comment on lines +570 to +572
</clickhouse>
EOF
echo "✓ ClickHouse port config written to ${config_dir}/port-override.xml"

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.

medium

When generating port-override.xml, the file is created with the default umask of the user running the script. If the umask is restrictive (e.g., 0077 or 0027), the ClickHouse container (which runs as UID 101) will fail to read this file, causing ClickHouse to fail to start.

We should explicitly set the file permissions to be world-readable (e.g., 644) to ensure the container can read it.

Suggested change
</clickhouse>
EOF
echo "✓ ClickHouse port config written to ${config_dir}/port-override.xml"
</clickhouse>
EOF
chmod 644 "${config_dir}/port-override.xml"
echo "✓ ClickHouse port config written to ${config_dir}/port-override.xml"

Comment thread start-stack.sh
Comment on lines +584 to +586
# Copy entrypoint.py unchanged
cp "${WORKDIR}/litellm/entrypoint.py" "${rendered_dir}/entrypoint.py"
echo "✓ LiteLLM config rendered to ${rendered_dir}/config.yaml"

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.

medium

Similarly, we should ensure that the rendered config.yaml and copied entrypoint.py are readable by the LiteLLM container.

Suggested change
# Copy entrypoint.py unchanged
cp "${WORKDIR}/litellm/entrypoint.py" "${rendered_dir}/entrypoint.py"
echo "✓ LiteLLM config rendered to ${rendered_dir}/config.yaml"
# Copy entrypoint.py unchanged
cp "${WORKDIR}/litellm/entrypoint.py" "${rendered_dir}/entrypoint.py"
chmod 644 "${rendered_dir}/config.yaml" "${rendered_dir}/entrypoint.py"
echo "✓ LiteLLM config rendered to ${rendered_dir}/config.yaml"

Comment thread start-stack.sh
Comment on lines 555 to 556
echo "💾 Taking pre-deploy database backup..."
bash scripts/backup.sh && echo "✓ Pre-deploy backup saved" || echo "⚠️ Pre-deploy backup skipped"

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.

medium

The pre-deploy database backup script scripts/backup.sh has hardcoded container names (e.g., agent-router-pod-postgres-db). When running in dev mode with POD_NAME="dev-router-pod", the backup script will fail to find the container and skip the backup.

We should update scripts/backup.sh to use the exported POD_NAME environment variable (which is already exported on line 98) instead of the hardcoded pod name.

Suggested change
echo "💾 Taking pre-deploy database backup..."
bash scripts/backup.sh && echo "✓ Pre-deploy backup saved" || echo "⚠️ Pre-deploy backup skipped"
echo "💾 Taking pre-deploy database backup..."
# Note: Ensure scripts/backup.sh is updated to use the exported $POD_NAME variable for container names.
bash scripts/backup.sh && echo "✓ Pre-deploy backup saved" || echo "⚠️ Pre-deploy backup skipped"

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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 `@start-stack.sh`:
- Around line 575-587: Update render_litellm_config to validate the generated
rendered_dir/config.yaml after sed substitution, matching the
unresolved-placeholder check used by render_pod_yaml. Detect any remaining
VALKEY_CACHE_PORT_PLACEHOLDER or ROUTER_PORT_PLACEHOLDER tokens, emit an error,
and exit before copying or reporting success; preserve normal rendering when no
placeholders remain.
🪄 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: db2a8e19-4e90-4d9c-a103-e6142aedbd65

📥 Commits

Reviewing files that changed from the base of the PR and between 3c2296e and 3084c68.

📒 Files selected for processing (7)
  • .env.dev
  • .gitignore
  • litellm/config.yaml
  • litellm/entrypoint.py
  • pod.yaml
  • start-dev.sh
  • start-stack.sh

Comment thread start-stack.sh
sheepdestroyer and others added 11 commits July 11, 2026 17:45
…non-alpine valkey image

Root cause: podman play kube converts tcpSocket liveness probes into
'nc -z -v localhost <port> || exit 1' healthchecks. Alpine's BusyBox nc
does not support -z, so the healthcheck always fails. With
HealthcheckOnFailureAction=restart, this causes an infinite SIGTERM
restart loop (~every 30s).

Changes:
- valkey-cache: tcpSocket -> exec valkey-cli ping (liveness + readiness)
- valkey-lf: tcpSocket -> exec valkey-cli -a <pass> ping (liveness)
- Image: valkey:9.1.0-alpine -> valkey:9.1.0 (non-alpine has no nc,
  so no broken built-in healthcheck to conflict with)

Verified in dev: 0 SIGTERMs, 0 ECONNREFUSED, both valkey instances
healthy, Langfuse web/worker stable, chat completions 200 OK.
Sourcery review: valkey-cli ping without -p targets default 6379,
causing false negatives when VALKEY_CACHE_PORT is customized (e.g. dev=6389).
Now matches the port-aware pattern already used by valkey-lf probes.
- litellm/entrypoint.py: restore quote stripping before setdefault
  (prevents literal '"5432"' from breaking int() parsing)
- start-stack.sh: use ROUTER_IMAGE var instead of hardcoded
  ghcr.io/sheepdestroyer/llm-routing:latest in build/pull paths
- start-stack.sh: create volume dirs under DATA_ROOT instead of
  WORKDIR (fixes pod creation when DATA_ROOT != WORKDIR)
- start-stack.sh: add placeholder validation to render_litellm_config
  and chmod 644 on rendered configs for non-root container access
- scripts/backup.sh: use POD_NAME from .env instead of hardcoded
  agent-router-pod-postgres-db (fixes dev backup failures)
- router/main.py: extract _valkey_port() helper to DRY the
  VALKEY_CACHE_PORT/VALKEY_PORT fallback (3 call sites)
- router/main.py: replace hardcoded :3001 with LANGFUSE_WEB_PORT
  env var in dashboard Infrastructure Nodes display
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