Skip to content

feat(docker): support generic provider env bootstrap#401

Merged
penso merged 6 commits intomainfrom
issue-125
Mar 12, 2026
Merged

feat(docker): support generic provider env bootstrap#401
penso merged 6 commits intomainfrom
issue-125

Conversation

@penso
Copy link
Copy Markdown
Collaborator

@penso penso commented Mar 11, 2026

Summary

  • Fixes Request: Docker image with environment variable support for API key and provider #125.
  • Add shared generic Docker bootstrap env handling for MOLTIS_PROVIDER/MOLTIS_API_KEY and the short aliases PROVIDER/API_KEY.
  • Wire that fallback into provider registration plus provider-setup auto-detect/configured-state paths so runtime and UI agree.
  • Document unattended Docker and Docker Compose setup with MOLTIS_PASSWORD, MOLTIS_PROVIDER, and MOLTIS_API_KEY.

Validation

Completed

  • just format
  • cargo +nightly-2025-11-30 test -p moltis-config provider_env --lib
  • cargo +nightly-2025-11-30 test -p moltis-providers openai_registers_with_generic_provider_env_override --lib
  • cargo +nightly-2025-11-30 test -p moltis-provider-setup generic_provider_env --lib
  • just build-css
  • cargo +nightly-2025-11-30 clippy -Z unstable-options --workspace --all-targets --timings -- -D warnings

Remaining

  • just lint (cargo +nightly-2025-11-30 clippy -Z unstable-options --workspace --all-features --all-targets --timings -- -D warnings) on this macOS host, blocked by llama-cpp-sys requiring CUDA/NVCC when --all-features enables the CUDA local-llm path.

Manual QA

  • Run Moltis in Docker with MOLTIS_PASSWORD, MOLTIS_PROVIDER=openai, and MOLTIS_API_KEY=sk-....
  • Open the web UI and confirm onboarding is skipped and the selected provider is already configured.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq bot commented Mar 11, 2026

Merging this PR will not alter performance

✅ 39 untouched benchmarks
⏩ 5 skipped benchmarks1


Comparing issue-125 (30f806d) with main (742bce9)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 11, 2026

Greptile Summary

This PR introduces a shared provider_env module in moltis-config that reads MOLTIS_PROVIDER/MOLTIS_API_KEY (and short aliases PROVIDER/API_KEY) from the environment, centralising logic that was previously duplicated in both moltis-providers and moltis-provider-setup. It wires the resolved provider identity and API key into the provider-registration path (resolve_api_key), the auto-detect source list (detect_auto_provider_sources_with_overrides), and the configured-state check (is_provider_configured), so Docker users can skip the browser setup wizard by setting three env vars before first boot.

Key changes:

  • New crates/config/src/provider_env.rs with generic_provider_env, generic_provider_api_key_from_env, and generic_provider_env_source_for_provider, plus a normalize_provider_name that maps common aliases (claude → anthropic, google → gemini, etc.)
  • crates/providers/src/lib.rs: removes duplicate env_value implementation and adds the generic env as a last-resort fallback in resolve_api_key (after config and provider-specific env key)
  • crates/provider-setup/src/lib.rs: removes duplicate env_value_with_overrides and wires both new functions into auto-detect and configured-state paths
  • docs/src/docker.md and README.md: documents the three-tier env var strategy and the new unattended bootstrap path
  • examples/docker-compose.yml: adds commented-out unattended-setup environment block

Notable concerns:

  • Test isolation: env_value_with_overrides checks std::env::var before falling back to the env_overrides map, so tests can be silently affected by ambient env vars (MOLTIS_PROVIDER, API_KEY, etc.) present in the test runner — consider using a crate like temp-env to unset these vars during tests, or inverting the lookup priority so env_overrides genuinely overrides the real environment.
  • Dual normalize_provider_name: moltis-provider-setup still has its own lowercase-only version alongside the new alias-aware one in moltis-config, creating a risk of drift if new aliases are added later.

Confidence Score: 4/5

  • Safe to merge with minor follow-up work on test isolation and the divergent normalize_provider_name implementations.
  • The core logic is correct — priority ordering (config > specific env key > generic env) is sensible, alias normalisation is symmetric, and the feature is well-tested with unit tests covering the major paths. The main risk is test flakiness from ambient env vars in certain CI environments due to env_value_with_overrides checking real env first, and the dual normalize_provider_name implementations could silently diverge over time, but neither is a blocking production bug today.
  • crates/config/src/provider_env.rs (test isolation), crates/provider-setup/src/lib.rs (divergent normalize_provider_name)

Important Files Changed

Filename Overview
crates/config/src/provider_env.rs New module centralising generic MOLTIS_PROVIDER/API_KEY env lookup. Core logic is sound, but env_value_with_overrides gives real env vars precedence over env_overrides, making the new unit tests susceptible to interference from ambient env vars; and the independent resolution of provider vs key candidates allows mismatched namespacing silently.
crates/config/src/lib.rs Adds provider_env module and re-exports its public symbols. Straightforward plumbing change, no issues.
crates/provider-setup/src/lib.rs Delegates env_value_with_overrides to the config crate and wires generic_provider_env_source_for_provider / generic_provider_api_key_from_env into auto-detect and is_configured paths. A divergent local normalize_provider_name (lowercase-only vs config's alias-aware version) remains and could cause offered-list mismatches with aliases.
crates/providers/src/lib.rs Delegates env_value to the config crate and adds generic_provider_api_key_from_env as a last-resort fallback in resolve_api_key. Priority order (config > specific env > generic env) is correct.
docs/src/docker.md Documents the three-tier env var strategy clearly. Warns about API_KEY collision risk. No issues.
examples/docker-compose.yml Adds commented-out unattended-setup environment block. Comments make intent clear and variables are all commented out by default. No issues.
README.md Minor prose addition pointing users to the unattended Docker setup path. No issues.

Sequence Diagram

sequenceDiagram
    participant Env as OS Environment
    participant Cfg as moltis-config<br/>provider_env
    participant Providers as moltis-providers<br/>resolve_api_key
    participant Setup as moltis-provider-setup<br/>is_configured / auto_detect

    Note over Env: MOLTIS_PROVIDER and<br/>MOLTIS_API_KEY are set

    Providers->>Cfg: env_value_with_overrides(overrides, "OPENAI_API_KEY")
    Cfg->>Env: std::env::var("OPENAI_API_KEY")
    Env-->>Cfg: None (not set)
    Cfg-->>Providers: None — fall through

    Providers->>Cfg: generic_provider_api_key_from_env("openai", overrides)
    Cfg->>Env: std::env::var("MOLTIS_PROVIDER") returns "openai"
    Cfg->>Env: std::env::var("MOLTIS_API_KEY") returns secret value
    Cfg-->>Providers: Some(Secret)
    Providers-->>Providers: API key resolved

    Setup->>Cfg: generic_provider_env_source_for_provider("openai", overrides)
    Cfg-->>Setup: Some("env:MOLTIS_PROVIDER+MOLTIS_API_KEY")
    Setup-->>Setup: source appended to auto-detect list

    Setup->>Cfg: generic_provider_api_key_from_env("openai", overrides)
    Cfg-->>Setup: Some(_)
    Setup-->>Setup: is_configured returns true
Loading

Comments Outside Diff (1)

  1. crates/provider-setup/src/lib.rs, line 1038-1040 (link)

    Divergent normalize_provider_name implementations still coexist

    The local normalize_provider_name here only trims + lowercases:

    fn normalize_provider_name(value: &str) -> String {
        value.trim().to_ascii_lowercase()
    }

    The newly added normalize_provider_name in moltis_config::provider_env also strips underscores, maps "claude" → "anthropic", "google" → "gemini", etc.

    Both functions exist with the same logical role. If config.offered contains an alias like "claude", ui_offered_provider_order will produce "claude", while every other internal comparison canonicalises it to "anthropic". The provider would then fail to appear in the offered UI list despite being genuinely configured.

    Since the PR already centralises env_value_with_overrides, it would be a natural follow-up to also expose moltis_config::provider_env::normalize_provider_name (or a thin public wrapper) and have this function delegate to it, eliminating the risk of future alias drift.

Last reviewed commit: e0cf823

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 97.66355% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/config/src/provider_env.rs 96.09% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@penso
Copy link
Copy Markdown
Collaborator Author

penso commented Mar 11, 2026

Addressed the Greptile review items in 29897c23: env_overrides now take precedence over ambient env, generic_provider_env documents and tests mixed MOLTIS_*/bare-key pairing, and provider-setup now delegates provider-name normalization to the shared alias-aware helper so offered aliases like claude map correctly to anthropic.

@penso penso merged commit 5ce59d2 into main Mar 12, 2026
49 of 54 checks passed
@penso penso deleted the issue-125 branch March 12, 2026 22:31
penso added a commit that referenced this pull request Mar 23, 2026
* feat(docker): support generic provider env bootstrap

* test(onboarding): stabilize import step e2e flow

* fix(config): address provider env review comments

* test(tools): fix sandbox off coverage
jmikedupont2 pushed a commit to meta-introspector/moltis that referenced this pull request Mar 23, 2026
* feat(docker): support generic provider env bootstrap

* test(onboarding): stabilize import step e2e flow

* fix(config): address provider env review comments

* test(tools): fix sandbox off coverage
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.

Request: Docker image with environment variable support for API key and provider

1 participant