Files
oikos/docs/docker-compose.portainer.yml
T
Ulas 3f387b616e fix: default TRUST_PROXY to 1 for Docker+reverse-proxy setups (#46)
With the previous default of 'loopback', Express ignored X-Forwarded-Proto
headers from Caddy/nginx when running in Docker (bridge IP, not loopback).
This caused req.secure=false, which made express-session silently drop the
session cookie on login - resulting in a 401 on every subsequent request.

Changing the default to 1 (trust one proxy hop) fixes this for all standard
Docker+reverse-proxy deployments without requiring manual configuration.
2026-04-14 09:04:06 +02:00

68 lines
2.6 KiB
YAML

# Oikos - Standalone Docker Compose for Portainer / remote deployment
# Pulls the pre-built image from GitHub Container Registry.
# No git clone required.
#
# Usage:
# 1. Copy this file and the .env section below to your server
# 2. Create a .env file next to this compose file (see below)
# 3. docker compose -f docker-compose.portainer.yml up -d
# 4. docker compose -f docker-compose.portainer.yml exec oikos node setup.js
# 5. Open http://<your-host>:3000
#
# Required .env variables:
# SESSION_SECRET=<random-string-min-32-chars>
# DB_ENCRYPTION_KEY=<random-string-min-32-chars>
#
# Generate secrets:
# openssl rand -base64 32
services:
oikos:
image: ghcr.io/ulsklyc/oikos:latest
container_name: oikos
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- oikos_data:/data
environment:
- NODE_ENV=production
- PORT=3000
- DB_PATH=/data/oikos.db
- SESSION_SECRET=${SESSION_SECRET:?Set SESSION_SECRET in .env}
- DB_ENCRYPTION_KEY=${DB_ENCRYPTION_KEY:?Set DB_ENCRYPTION_KEY in .env}
# Set to true when behind a reverse proxy with HTTPS (Caddy, nginx, Traefik)
- SESSION_SECURE=${SESSION_SECURE:-false}
# Trust proxy hops (default: 1 for Docker+reverse-proxy setups)
# Set to 'loopback' if running without a reverse proxy
- TRUST_PROXY=${TRUST_PROXY:-1}
# Weather (optional)
- OPENWEATHER_API_KEY=${OPENWEATHER_API_KEY:-}
- OPENWEATHER_CITY=${OPENWEATHER_CITY:-Berlin}
- OPENWEATHER_UNITS=${OPENWEATHER_UNITS:-metric}
- OPENWEATHER_LANG=${OPENWEATHER_LANG:-de}
# Google Calendar (optional)
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
- GOOGLE_REDIRECT_URI=${GOOGLE_REDIRECT_URI:-}
# Apple Calendar CalDAV (optional)
- APPLE_CALDAV_URL=${APPLE_CALDAV_URL:-https://caldav.icloud.com}
- APPLE_USERNAME=${APPLE_USERNAME:-}
- APPLE_APP_SPECIFIC_PASSWORD=${APPLE_APP_SPECIFIC_PASSWORD:-}
# Sync interval in minutes
- SYNC_INTERVAL_MINUTES=${SYNC_INTERVAL_MINUTES:-15}
# Rate limiting
- RATE_LIMIT_WINDOW_MS=${RATE_LIMIT_WINDOW_MS:-60000}
- RATE_LIMIT_MAX_ATTEMPTS=${RATE_LIMIT_MAX_ATTEMPTS:-5}
- RATE_LIMIT_BLOCK_DURATION_MS=${RATE_LIMIT_BLOCK_DURATION_MS:-900000}
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
volumes:
oikos_data:
driver: local