Files
wgBill/backend/.env.example
T
dodox 0bab9690c6 Add Docker deployment (build- and stack-tested)
- backend/Dockerfile: gunicorn, not the dev server.
- frontend/Dockerfile: multi-stage, nginx serves the static build.
- nginx.conf proxies /api and /auth to the backend so both services
  share one origin - keeps the session cookie simple first-party,
  no SameSite=None/CORS complexity in production.
- docker-compose.yml: bind-mounts ./data/{instance,uploads} (not
  named volumes) so the sqlite db and uploaded photos are visible
  under the project dir; :Z flag for SELinux-enforcing hosts
  (Fedora/RHEL) - without it gunicorn fails with "unable to open
  database file".
- FRONTEND_PORT env var to pick the exposed port.
- .env.example: documents CORS_ORIGIN is moot in the compose setup
  (same-origin via nginx) and that SESSION_COOKIE_SECURE=true needs
  a TLS-terminating reverse proxy in front in real deployment.

Verified: both images build clean, full stack up via docker compose,
login flow starts for real against the actual NC instance through
the nginx proxy, sqlite db persists to the bind mount correctly.
2026-08-30 16:07:00 +02:00

56 lines
2.3 KiB
Bash

# Copy to .env and fill in. Never commit .env.
# --- Nextcloud ---
# Server address only - each user logs in themselves via Nextcloud Login
# Flow v2 (see /auth/login/start); there's no shared NC_USERNAME/APP_PASSWORD
# any more.
NC_BASE_URL=https://cloud.dominik-roth.eu
# Folder (relative to each user's own files root) receipt images get
# uploaded to. Created automatically on first upload if missing (each path
# segment).
NC_UPLOAD_FOLDER=Documents/Cospend/Assets
# --- Cospend ---
# Optional: pre-selects a project in the UI. The app lists all your Cospend
# projects via the API (GET /ocs/v2.php/apps/cospend/api/v1/projects), so
# this is just a convenience default, not required.
COSPEND_PROJECT_ID=
# --- Vision LLM (OpenAI-compatible chat completions API) ---
# OpenAI example:
# LLM_BASE_URL=https://api.openai.com/v1
# LLM_MODEL=gpt-4o-mini
# Gemini (OpenAI-compat layer) example:
# LLM_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
# LLM_MODEL=gemini-2.0-flash
LLM_BASE_URL=
LLM_API_KEY=
LLM_MODEL=
# --- Flask ---
FLASK_SECRET_KEY=dev-change-me
DATABASE_PATH=instance/wgbill.sqlite3
# Only matters when the frontend calls this backend from a different origin
# (e.g. local dev, vite on :5173). The docker-compose.yml setup puts nginx
# in front of both on one origin, so the browser never makes a cross-origin
# call and this is effectively unused there - but Flask-CORS still needs a
# concrete value, not "*", since credentials (the session cookie) are
# involved.
CORS_ORIGIN=http://localhost:5173
# --- Auth ---
# Generate with: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# Encrypts stored Nextcloud app passwords at rest. Required - the app
# refuses to store/read a token without it. Keep this secret; losing it
# means every logged-in user has to log in again.
TOKEN_ENCRYPTION_KEY=
# Idle session lifetime in days (sliding - refreshed on each use).
SESSION_TTL_DAYS=30
# Cookies need Secure (HTTPS-only) for any real deployment - browsers won't
# send/store a Secure cookie over plain HTTP. Only set to false for
# plain-http localhost dev. For docker-compose: put your own TLS-terminating
# reverse proxy (Caddy, nginx-proxy-manager, etc.) in front of the exposed
# frontend port and set this true; without that, leave it false or login
# will silently fail to persist.
SESSION_COOKIE_SECURE=true