Enable Keycloak auth in dev environment (docker-compose + terraform redirect URI) #164

Closed
opened 2026-06-07 17:52:14 +00:00 by ldraney · 3 comments
Owner

Type

Feature

Lineage

Standalone — discovered during auth strategy spike (#159). Dev environment lacks auth parity with prod.

Repo

ldraney/landscaping-assistant

User Story

As a developer
I want the dev environment to authenticate via Keycloak identically to prod
So that auth bugs are caught before reaching production and the dev experience matches what users see

Context

The dev environment (landscaping-dev.tail5b443a.ts.net) currently runs with graceful auth degradation — KEYCLOAK_URL is unset, so no login is required. This was fine during early development but now that auth is live in prod (OmniAuth + Auth Code + PKCE), dev should mirror it.

The dev setup is: internet → k8s nginx reverse proxy → MacBook docker-compose (port 7143) → Rails on :3000. The nginx proxy already sets X-Forwarded-Proto: https so assume_ssl works correctly.

The Keycloak client (landscaping-assistant in realm landscaping) currently only has the prod redirect URI configured. Adding the dev URI enables the same client to serve both environments.

File Targets

Files the agent should modify or create:

  • docker-compose.yml — add env_file: .env directive to web service (see Implementation mechanism below)
  • .env.example — create with all Keycloak vars as placeholders (developer copies to .env and fills in secret)

Files the agent should NOT touch:

  • config/database.yml — already correct
  • app/controllers/application_controller.rb — graceful degradation logic unchanged
  • .gitignore — already ignores .env (verify, add if missing)

Cross-repo (pal-e-services):

  • terraform/k3s.tfvars — add dev redirect URI to landscaping-assistant client
  • terraform/k3s.tfvars.example — mirror the change (without secrets)

Implementation Mechanism: env_file pattern

Use env_file: .env in docker-compose (NOT inline ${VAR} interpolation). This is the standard docker-compose secrets pattern:

  1. Add to docker-compose.yml web service:
services:
  web:
    env_file: .env
    # ... existing config unchanged
  1. Create .env.example (committed):
# Keycloak auth (copy to .env and fill in values)
# When these are set, app requires Keycloak login.
# When unset/removed, app runs with graceful degradation (no auth).
KEYCLOAK_URL=https://keycloak.tail5b443a.ts.net
KEYCLOAK_REALM=landscaping
KEYCLOAK_CLIENT_ID=landscaping-assistant
KEYCLOAK_CLIENT_SECRET=<get from k8s secret or Lucas>
  1. Verify .env is in .gitignore (add if missing)

This approach:

  • Keeps secrets out of version control
  • Makes auth opt-in (no .env file = no auth = graceful degradation preserved)
  • Single file to manage for developers
  • Standard docker-compose pattern

Feature Flag

none — this is infrastructure/environment config, not a user-facing feature

Acceptance Criteria

  • docker compose up starts app with Keycloak auth enabled (when .env has secret)
  • Visiting https://landscaping-dev.tail5b443a.ts.net redirects to Keycloak login
  • After login, callback returns to https://landscaping-dev.tail5b443a.ts.net/auth/keycloak/callback and sets session
  • Roles extracted correctly from JWT (admin sees Crew tab, member does not)
  • Graceful degradation preserved: removing .env file (or unsetting KEYCLOAK_URL) still allows auth-free local dev
  • .env file is gitignored (client secret never committed)
  • terraform apply succeeds with updated client config

Test Expectations

  • Existing auth specs pass unchanged (227 examples, 0 failures)
  • Manual test: full login flow via landscaping-dev.tail5b443a.ts.net
  • Run command: docker compose exec web bundle exec rspec

Constraints

  • Client secret must NOT be in docker-compose.yml — use .env file with env_file: directive
  • Same Keycloak realm and client as prod (just additional redirect URI)
  • Terraform change requires terraform apply on infra host after merge
  • Architecture labels (arch:rails-app, arch:platform) are board categorization — no dedicated architecture notes required for this ticket

Checklist

  • PR opened (this repo: docker-compose + .env.example)
  • PR opened (pal-e-services: terraform client config)
  • terraform apply run on infra host
  • Tests pass
  • No unrelated changes
  • Manual login verified on dev URL
  • project-landscaping-assistant — project this affects
  • #159 — auth strategy spike (documents Auth Code + PKCE architecture)
  • docs/auth-strategy.md — definitive auth decision record
  • pal-e-services PR #103 — original Keycloak client terraform setup
### Type Feature ### Lineage Standalone — discovered during auth strategy spike (#159). Dev environment lacks auth parity with prod. ### Repo `ldraney/landscaping-assistant` ### User Story As a developer I want the dev environment to authenticate via Keycloak identically to prod So that auth bugs are caught before reaching production and the dev experience matches what users see ### Context The dev environment (`landscaping-dev.tail5b443a.ts.net`) currently runs with graceful auth degradation — `KEYCLOAK_URL` is unset, so no login is required. This was fine during early development but now that auth is live in prod (OmniAuth + Auth Code + PKCE), dev should mirror it. The dev setup is: internet → k8s nginx reverse proxy → MacBook docker-compose (port 7143) → Rails on :3000. The nginx proxy already sets `X-Forwarded-Proto: https` so `assume_ssl` works correctly. The Keycloak client (`landscaping-assistant` in realm `landscaping`) currently only has the prod redirect URI configured. Adding the dev URI enables the same client to serve both environments. ### File Targets Files the agent should modify or create: - `docker-compose.yml` — add `env_file: .env` directive to `web` service (see Implementation mechanism below) - `.env.example` — create with all Keycloak vars as placeholders (developer copies to `.env` and fills in secret) Files the agent should NOT touch: - `config/database.yml` — already correct - `app/controllers/application_controller.rb` — graceful degradation logic unchanged - `.gitignore` — already ignores `.env` (verify, add if missing) Cross-repo (pal-e-services): - `terraform/k3s.tfvars` — add dev redirect URI to `landscaping-assistant` client - `terraform/k3s.tfvars.example` — mirror the change (without secrets) ### Implementation Mechanism: env_file pattern Use `env_file: .env` in docker-compose (NOT inline `${VAR}` interpolation). This is the standard docker-compose secrets pattern: 1. Add to `docker-compose.yml` web service: ```yaml services: web: env_file: .env # ... existing config unchanged ``` 2. Create `.env.example` (committed): ```env # Keycloak auth (copy to .env and fill in values) # When these are set, app requires Keycloak login. # When unset/removed, app runs with graceful degradation (no auth). KEYCLOAK_URL=https://keycloak.tail5b443a.ts.net KEYCLOAK_REALM=landscaping KEYCLOAK_CLIENT_ID=landscaping-assistant KEYCLOAK_CLIENT_SECRET=<get from k8s secret or Lucas> ``` 3. Verify `.env` is in `.gitignore` (add if missing) This approach: - Keeps secrets out of version control - Makes auth opt-in (no `.env` file = no auth = graceful degradation preserved) - Single file to manage for developers - Standard docker-compose pattern ### Feature Flag none — this is infrastructure/environment config, not a user-facing feature ### Acceptance Criteria - [ ] `docker compose up` starts app with Keycloak auth enabled (when `.env` has secret) - [ ] Visiting `https://landscaping-dev.tail5b443a.ts.net` redirects to Keycloak login - [ ] After login, callback returns to `https://landscaping-dev.tail5b443a.ts.net/auth/keycloak/callback` and sets session - [ ] Roles extracted correctly from JWT (admin sees Crew tab, member does not) - [ ] Graceful degradation preserved: removing `.env` file (or unsetting `KEYCLOAK_URL`) still allows auth-free local dev - [ ] `.env` file is gitignored (client secret never committed) - [ ] `terraform apply` succeeds with updated client config ### Test Expectations - [ ] Existing auth specs pass unchanged (227 examples, 0 failures) - [ ] Manual test: full login flow via `landscaping-dev.tail5b443a.ts.net` - Run command: `docker compose exec web bundle exec rspec` ### Constraints - Client secret must NOT be in docker-compose.yml — use `.env` file with `env_file:` directive - Same Keycloak realm and client as prod (just additional redirect URI) - Terraform change requires `terraform apply` on infra host after merge - Architecture labels (`arch:rails-app`, `arch:platform`) are board categorization — no dedicated architecture notes required for this ticket ### Checklist - [ ] PR opened (this repo: docker-compose + .env.example) - [ ] PR opened (pal-e-services: terraform client config) - [ ] `terraform apply` run on infra host - [ ] Tests pass - [ ] No unrelated changes - [ ] Manual login verified on dev URL ### Related - `project-landscaping-assistant` — project this affects - #159 — auth strategy spike (documents Auth Code + PKCE architecture) - `docs/auth-strategy.md` — definitive auth decision record - pal-e-services PR #103 — original Keycloak client terraform setup
Author
Owner

Scope Review: NEEDS_REFINEMENT

Review note: review-1383-2026-06-07

Well-structured ticket with verified file targets and clear acceptance criteria. Three refinement items found:

  • [SCOPE] Architecture note arch-rails-app does not exist in pal-e-docs — create it for traceability
  • [SCOPE] Architecture note arch-platform does not exist in pal-e-docs — create it for traceability
  • [BODY] docker-compose.yml has no env_file directive — ticket should clarify whether to add env_file: .env or use environment entries with ${KEYCLOAK_*} variable interpolation. Without this, the .env file won't inject variables into the container environment automatically.
## Scope Review: NEEDS_REFINEMENT Review note: `review-1383-2026-06-07` Well-structured ticket with verified file targets and clear acceptance criteria. Three refinement items found: - **[SCOPE]** Architecture note `arch-rails-app` does not exist in pal-e-docs — create it for traceability - **[SCOPE]** Architecture note `arch-platform` does not exist in pal-e-docs — create it for traceability - **[BODY]** docker-compose.yml has no `env_file` directive — ticket should clarify whether to add `env_file: .env` or use `environment` entries with `${KEYCLOAK_*}` variable interpolation. Without this, the `.env` file won't inject variables into the container environment automatically.
Author
Owner

Scope Review: APPROVED

Review note: review-1383-2026-06-07-r2

RE-REVIEW passed. All three issues from the previous review have been addressed:

  1. arch:rails-app / arch:platform notes — Constraints section clarifies these are board categorization labels, not arch note requirements. Accepted.
  2. Docker-compose mechanism — New "Implementation Mechanism" section provides full code examples for env_file pattern. Clear and unambiguous.

Ticket is ready for implementation. No further action needed.

## Scope Review: APPROVED Review note: `review-1383-2026-06-07-r2` RE-REVIEW passed. All three issues from the previous review have been addressed: 1. arch:rails-app / arch:platform notes — Constraints section clarifies these are board categorization labels, not arch note requirements. Accepted. 2. Docker-compose mechanism — New "Implementation Mechanism" section provides full code examples for env_file pattern. Clear and unambiguous. Ticket is ready for implementation. No further action needed.
Author
Owner

Validation: PASS

Tiers executed: Tier 1 (Local), Tier 3 (Production/Dev live)
Validation note: validation-164-2026-06-07
7 checks: 7 PASS, 0 FAIL

All acceptance criteria verified:

  • docker-compose running with Keycloak auth (4h uptime)
  • Dev URL redirects to Keycloak login (HTTP 302 confirmed)
  • Login callback works end-to-end (user-confirmed via Chrome DevTools)
  • Role extraction working (super_admin sees all 5 tabs + Platform)
  • Graceful degradation implemented (required: false + ENV guard)
  • .env gitignored, secrets never committed
  • Terraform applied, Keycloak client configured with both redirect URIs
  • Pipeline #362 green (all steps passed)
  • No regressions: prod + dev pods healthy, 0 restarts
## Validation: PASS Tiers executed: Tier 1 (Local), Tier 3 (Production/Dev live) Validation note: `validation-164-2026-06-07` 7 checks: 7 PASS, 0 FAIL All acceptance criteria verified: - docker-compose running with Keycloak auth (4h uptime) - Dev URL redirects to Keycloak login (HTTP 302 confirmed) - Login callback works end-to-end (user-confirmed via Chrome DevTools) - Role extraction working (super_admin sees all 5 tabs + Platform) - Graceful degradation implemented (`required: false` + ENV guard) - .env gitignored, secrets never committed - Terraform applied, Keycloak client configured with both redirect URIs - Pipeline #362 green (all steps passed) - No regressions: prod + dev pods healthy, 0 restarts
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/landscaping-assistant#164
No description provided.