diff --git a/Dockerfile b/Dockerfile index 098aaef..c3c2a85 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,4 +24,4 @@ RUN uv build --wheel --out-dir /app/dist RUN uv pip install --system --no-cache . EXPOSE 8000 -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers", "--forwarded-allow-ips", "*"] diff --git a/app/auth/providers/google.py b/app/auth/providers/google.py index 9d5b86e..b91249b 100644 --- a/app/auth/providers/google.py +++ b/app/auth/providers/google.py @@ -111,13 +111,15 @@ async def google_callback(request: Request): request.session.pop("login_next", None), default="/dashboard" ) - # Redirect to target with token in cookie - is_production = os.environ.get("TESTING", "").lower() not in ("1", "true") + # Redirect to target with token in cookie. Match password/email providers: + # Secure only when DOMAIN is set (production with TLS), so the cookie is + # actually sent over plain HTTP in dev. + use_secure = os.environ.get("DOMAIN", "") != "" response = RedirectResponse(url=target, status_code=302) response.set_cookie( key="access_token", value=jwt_token, httponly=True, max_age=86400, samesite="lax", - secure=is_production, + secure=use_secure, ) return response diff --git a/config/.env.template b/config/.env.template index 66122e0..7f0f52d 100644 --- a/config/.env.template +++ b/config/.env.template @@ -44,4 +44,22 @@ SESSION_SECRET= # python -c "import secrets; print(secrets.token_he # DATA_DIR=/data # Default: /data in Docker, ./data locally # LOG_LEVEL=info # debug, info, warning, error # CORS_ORIGINS=http://localhost:3000,http://localhost:8000 -# DOMAIN=data.yourcompany.com # For Caddy TLS (production profile) + +# ── HTTPS / REVERSE PROXY ─────────────────────────── +# Set these when the app runs behind a TLS terminator (Caddy, Cloudflare +# Tunnel, nginx, GCP LB, etc.). The app itself speaks plain HTTP on :8000; +# the terminator is responsible for TLS. +# +# DOMAIN: public hostname. When set, session cookies get the `Secure` flag +# (browser only sends them over HTTPS). Also used by the Caddy +# profile to auto-provision Let's Encrypt certs. +# DOMAIN=data.yourcompany.com +# +# SERVER_URL: absolute base URL used to build OAuth callback URLs and other +# external links. Set this to avoid relying on the incoming +# request's Host header (which a misconfigured proxy can get +# wrong). Must match the redirect URI registered in OAuth apps. +# SERVER_URL=https://data.yourcompany.com +# +# Uvicorn is started with `--proxy-headers --forwarded-allow-ips='*'` so it +# trusts X-Forwarded-Proto / X-Forwarded-For from the reverse proxy. diff --git a/config/deploy.yml b/config/deploy.yml index 444c8b6..68220c8 100644 --- a/config/deploy.yml +++ b/config/deploy.yml @@ -16,7 +16,7 @@ servers: web: hosts: - YOUR_SERVER_IP - cmd: uvicorn app.main:app --host 0.0.0.0 --port 8000 + cmd: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' options: volume: - /data:/data diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 6f911e5..c3ce141 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -2,7 +2,7 @@ # This file is auto-loaded by `docker compose up` when present services: app: - command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload + command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --proxy-headers --forwarded-allow-ips='*' volumes: - .:/app - data:/data diff --git a/docker-compose.test.yml b/docker-compose.test.yml index d916a75..317fb6f 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -1,7 +1,7 @@ services: app: build: . - command: uvicorn app.main:app --host 0.0.0.0 --port 8000 + command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' ports: - "8000:8000" environment: diff --git a/docker-compose.yml b/docker-compose.yml index 94d4932..0b408eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: app: build: . - command: uvicorn app.main:app --host 0.0.0.0 --port 8000 + command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips='*' ports: - "8000:8000" volumes: