From ce169a751248d11e90d919706809a20af1d0203f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Domr=C3=B6as?= Date: Thu, 29 Jan 2026 07:12:47 +0100 Subject: [PATCH] recent changes --- beszel-agent/docker-compose.yaml | 16 ++ caddy/Caddyfile | 13 +- caddy/Caddyfile.bak | 30 +++- journiv/.env | 297 +++++++++++++++++++++++++++++++ journiv/Caddyfilepart | 5 + journiv/docker-compose.yml | 181 +++++++++++++++++++ restartall.sh | 1 + 7 files changed, 532 insertions(+), 11 deletions(-) create mode 100644 beszel-agent/docker-compose.yaml create mode 100644 journiv/.env create mode 100644 journiv/Caddyfilepart create mode 100644 journiv/docker-compose.yml diff --git a/beszel-agent/docker-compose.yaml b/beszel-agent/docker-compose.yaml new file mode 100644 index 0000000..074d9ae --- /dev/null +++ b/beszel-agent/docker-compose.yaml @@ -0,0 +1,16 @@ +services: + beszel-agent: + image: henrygd/beszel-agent + container_name: beszel-agent + restart: unless-stopped + network_mode: host + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - /home/soenke/docker-data/beszel-agent/beszel_agent_data:/var/lib/beszel-agent + # monitor other disks / partitions by mounting a folder in /extra-filesystems + # - /mnt/disk/.beszel:/extra-filesystems/sda1:ro + environment: + LISTEN: 45876 + KEY: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVA2+hStjbFgCmiZl80+JFDZZxePZ4fRV8hEwLj3/o5' + TOKEN: b608d327-43be-4a2c-a4fb-7e6606639fab + HUB_URL: https://beszel.domr.ovh diff --git a/caddy/Caddyfile b/caddy/Caddyfile index de4173b..cd58555 100644 --- a/caddy/Caddyfile +++ b/caddy/Caddyfile @@ -143,12 +143,6 @@ haus.home.domroese.eu { reverse_proxy 192.168.1.65:8472 } -homarr.domr.ovh, -homarr.home.domroese.eu:443 { - tls soenke@domroese.eu - reverse_proxy 192.168.1.65:7575 -} - homebox.domr.ovh, homebox.home.domroese.eu:443 { tls soenke@domroese.eu @@ -182,6 +176,12 @@ jenkins.home.domroese.eu { reverse_proxy 192.168.1.65:8040 } +journal.domr.ovh, +journiv.domr.ovh { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:8198 +} + kopia.domr.ovh, kopia.home.domroese.eu { tls soenke@domroese.eu @@ -189,6 +189,7 @@ kopia.home.domroese.eu { } + mealie.domr.ovh, mealie.home.domroese.eu:443 { tls soenke@domroese.eu diff --git a/caddy/Caddyfile.bak b/caddy/Caddyfile.bak index b932c86..967fc25 100644 --- a/caddy/Caddyfile.bak +++ b/caddy/Caddyfile.bak @@ -9,7 +9,17 @@ auth.home.domroese.eu { +beszel.domr.ovh, +beszel.home.domroese.eu { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:7090 +} +bit.domr.ovh, +bit.home.domroese.eu { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:4489 +} bookstack.domr.ovh, bookstack.home.domroese.eu { @@ -127,11 +137,10 @@ guac.home.domroese.eu { reverse_proxy 192.168.1.65:6080 } - -homarr.domr.ovh, -homarr.home.domroese.eu:443 { - tls soenke@domroese.eu - reverse_proxy 192.168.1.65:7575 +haus.domr.ovh, +haus.home.domroese.eu { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:8472 } homebox.domr.ovh, @@ -147,6 +156,11 @@ homepage.home.domroese.eu:443 { reverse_proxy 192.168.1.65:3891 } +huly.domr.ovh, +huly.home.domroese.eu { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:8087 +} ittools.domr.ovh:443, ittools.home.domroese.eu:443, @@ -169,6 +183,7 @@ kopia.home.domroese.eu { } + mealie.domr.ovh, mealie.home.domroese.eu:443 { tls soenke@domroese.eu @@ -243,6 +258,11 @@ api.plantit.home.domroese.eu:443 { reverse_proxy 192.168.1.65:8632 } +portracker.domr.ovh, +portracker.home.domroese.eu:443 { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:4999 +} diff --git a/journiv/.env b/journiv/.env new file mode 100644 index 0000000..7702262 --- /dev/null +++ b/journiv/.env @@ -0,0 +1,297 @@ +# ============================================================================ +# Journiv Environment Configuration Template +# Copy this file to .env and customize for your deployment. +# +# Usage: +# cp env.template .env +# nano .env +# Required settings: +# - SECRET_KEY +# - DOMAIN_NAME +# +# If using PostgreSQL (DB_DRIVER=postgres), also set: +# - Either POSTGRES_PASSWORD (with optional components), OR +# - DATABASE_URL with a PostgreSQL URL (postgresql:// or postgres://) +# NOT BOTH - specifying both will cause startup to fail +# +# All other settings are optional. +# ============================================================================ + + +# ============================================================================ +# REQUIRED SETTINGS +# ============================================================================ + +# Secret key for JWT token signing and encryption +# Generate with: +# python -c "import secrets; print(secrets.token_urlsafe(32))" +# Or: +# openssl rand -base64 32 +SECRET_KEY=gjQ/6282Fdf3p4hK61nx/OHmLJCluIQauz/mm5idPls + + +# ============================================================================ +# DOMAIN CONFIGURATION +# ============================================================================ + +# Public domain name where Journiv is accessible. +# DO NOT include http:// or https://. +# DO NOT include trailing slashes. +# +# Examples: +DOMAIN_NAME=journiv.domr.ovh +DOMAIN_NAME=journal.domr.ovh +# DOMAIN_NAME=192.168.1.10 +# +# WRONG: +# DOMAIN_NAME=https://journiv.example.com +# DOMAIN_NAME=journiv.example.com/ + +# Protocol scheme for public URLs: http or https +# IMPORTANT: Set to "https" for production deployments, especially when behind a reverse proxy (Traefik, Caddy, Nginx, etc.). +# - Default: "http" (for local development only) +# - Production: "https" (REQUIRED when behind reverse proxy or using SSL/TLS) +# +# Journiv uses this to generate correct public redirect URLs: +# {DOMAIN_SCHEME}://{DOMAIN_NAME}/#/oidc-finish +# {DOMAIN_SCHEME}://{DOMAIN_NAME}/#/login?logout=success +# +DOMAIN_SCHEME=https + + +# ============================================================================ +# DATABASE CONFIGURATION +# ============================================================================ + +# Database driver selection: "sqlite" (default) or "postgres" +DB_DRIVER=sqlite + +# Primary database URL (defaults to SQLite) +# For SQLite: sqlite:////data/journiv.db +# For PostgreSQL: postgresql://user:password@host:5432/dbname +DATABASE_URL=sqlite:////data/journiv.db + +# When DB_DRIVER=postgres, you must specify EITHER: +# Option 1: POSTGRES_PASSWORD (with optional components below) +# Option 2: DATABASE_URL with a PostgreSQL URL (postgresql:// or postgres://) +# NOT BOTH - specifying both will cause startup to fail + +# PostgreSQL password (required when DB_DRIVER=postgres and using Option 1) +POSTGRES_PASSWORD=oUPnKDY3stjREg7ctUYWrbnn4wNs0Yy3 + +# (Optional) PostgreSQL components for Docker deployments (used with POSTGRES_PASSWORD) +# Defaults are used if not specified: +# POSTGRES_HOST=postgres +# POSTGRES_USER=journiv +# POSTGRES_DB=journiv_prod (production) or journiv_dev (development) +# POSTGRES_PORT=5432 +# POSTGRES_HOST= +#POSTGRES_USER=journiv +#POSTGRES_DB=journiv_prod +#POSTGRES_PORT=5432 + + + +# ============================================================================ +# APPLICATION SETTINGS +# ============================================================================ + +APP_NAME=Journiv +# APP_VERSION=latest # Pin to a specific version for production if needed +# DEBUG=false +ENVIRONMENT=production +APP_PORT=8198 + + +# ============================================================================ +# API CONFIGURATION +# ============================================================================ + +# API_V1_PREFIX=/api/v1 + +# Enable CORS only when the frontend runs on a different origin. +# ENABLE_CORS=false + +# Required when ENABLE_CORS=true. +# Example: +# CORS_ORIGINS=https://journiv.example.com,https://myapp.example.net +# CORS_ORIGINS= + + +# ============================================================================ +# SECURITY SETTINGS +# ============================================================================ + +# ALGORITHM=HS256 +# ACCESS_TOKEN_EXPIRE_MINUTES=15 +# REFRESH_TOKEN_EXPIRE_DAYS=7 + +# Disable user signup +# DISABLE_SIGNUP=false + + +# ============================================================================ +# OIDC CONFIGURATION +# ============================================================================ + +# Enable OIDC login (Pocket-ID, Keycloak, Authentik, etc.) +OIDC_ENABLED=true + +# OIDC provider issuer +# Example: https://id.example.com or https://auth.example.com/realms/default +OIDC_ISSUER=https://auth.domr.ovh/application/o/journiv + +# OIDC client credentials +OIDC_CLIENT_ID="L1wmsh8BqoGlQRO6ZULMkTCRGOhu9M0L3Im7tiGd" +OIDC_CLIENT_SECRET=MPhUBLM8p4soNCfpfbp0pgAxoaqRHj36EvTzALVicoVy7Tf1UrVh2ckXJtciGYNscuQpQ78c8j8MXb1a1pn3bvOcnGERSYC2uT9s4AXhchD5yTKBBfFEz4l15OMZNqvG + +# OIDC redirect URI +# Must match provider configuration EXACTLY. +# Example: +# OIDC_REDIRECT_URI=https://journiv.example.com/api/v1/auth/oidc/callback +OIDC_REDIRECT_URI=https://journal.domr.ovh/api/v1/auth/oidc/callback + +# OIDC scopes to request +# OIDC_SCOPES="openid email profile" + +# Automatically create users from OIDC claims +# OIDC_AUTO_PROVISION=true + +# Disable SSL verification (ONLY for local development with self-signed certs) +# OIDC_DISABLE_SSL_VERIFY=false + +# Allow OIDC over HTTP (INSECURE). Recommended only for advanced users in isolated homelabs. +# Default: false +# OIDC_ALLOW_INSECURE_PROD=false + + +# ============================================================================ +# REDIS CONFIGURATION (Optional) +# ============================================================================ + +# Optional Redis URL for OIDC state caching, rate-limit persistence, and Celery +# Example: redis://localhost:6379/0 +# REDIS_URL= + + +# ============================================================================ +# CELERY CONFIGURATION (For Import/Export) +# ============================================================================ + +# Celery broker and result backend +# If not set, defaults to REDIS_URL +# Examples: +# CELERY_BROKER_URL=redis://localhost:6379/0 +# CELERY_RESULT_BACKEND=redis://localhost:6379/0 +# CELERY_BROKER_URL= +# CELERY_RESULT_BACKEND= + +# Celery task serialization (default: json) +# CELERY_TASK_SERIALIZER=json +# CELERY_RESULT_SERIALIZER=json +# CELERY_TIMEZONE=UTC +# CELERY_ENABLE_UTC=true + + +# ============================================================================ +# IMPORT/EXPORT CONFIGURATION +# ============================================================================ + +# Maximum file size for import/export operations (in MB) +# IMPORT_EXPORT_MAX_FILE_SIZE_MB=500 + +# Days to keep export files before automatic cleanup +# Set to -1 to disable automatic cleanup. +# EXPORT_CLEANUP_DAYS=7 + +# Directories for import/export operations +# IMPORT_TEMP_DIR=/data/imports/temp +# EXPORT_DIR=/data/exports + + +# ============================================================================ +# INTEGRATIONS (IMMICH) +# ============================================================================ + +# Default Immich base URL for all users on the instance. +# If set, users can leave the Immich URL field empty in the UI. +# Immich URL specified per user level in settting screens can be used to override this. +# Example: IMMICH_BASE_URL=https://immich.example.com +# Example: IMMICH_BASE_URL=http://192.168.1.1:2283 +# IMMICH_BASE_URL= + + +# ============================================================================ +# CONTENT SECURITY POLICY (CSP) +# ============================================================================ + +# ENABLE_CSP=true +# ENABLE_HSTS=true +# ENABLE_CSP_REPORTING=true + +# Where browsers should POST CSP violation reports +# CSP_REPORT_URI=/api/v1/security/csp-report + + +# ============================================================================ +# FILE STORAGE +# ============================================================================ + +# Directory for user-uploaded files and media +# MEDIA_ROOT=/data/media + +# Maximum allowed upload size in MB +# MAX_FILE_SIZE_MB=50 + +# Allowed media MIME types (comma-separated) +# ALLOWED_MEDIA_TYPES=image/jpeg,image/png,image/gif,image/webp,image/heic,video/mp4,video/avi,video/mov,video/webm,video/x-m4v,audio/mpeg,audio/wav,audio/ogg,audio/m4a,audio/aac + +# Allowed file extensions (comma-separated) +# ALLOWED_FILE_EXTENSIONS=.jpg,.jpeg,.png,.gif,.webp,.heic,.mp4,.avi,.mov,.webm,.m4v,.mp3,.wav,.ogg,.m4a,.aac + +# Signed media URL TTL in seconds (for images and general media) +# Default 5 minutes +# MEDIA_SIGNED_URL_TTL_SECONDS=300 + +# Signed video URL TTL in seconds (for video streaming, longer to support playback of large files) +# Default 20 mins +# MEDIA_SIGNED_URL_VIDEO_TTL_SECONDS=1200 + +# Signed thumbnail URL TTL in seconds (used for caching thumbnails) +# Default 24 hours +# MEDIA_THUMBNAIL_SIGNED_URL_TTL_SECONDS=86400 + +# Grace period in seconds for signed media URL expiration checks +# MEDIA_SIGNED_URL_GRACE_SECONDS=60 + + +# ============================================================================ +# LOGGING +# ============================================================================ + +# LOG_LEVEL=INFO +# LOG_FILE= +# LOG_DIR=/data/logs + + +# ============================================================================ +# EXTERNAL API CONFIGURATION +# ============================================================================ + +# OpenWeather API keys for weather data fetching +# Get your free API key at: https://openweathermap.org/api +# Weather service is optional - if not configured, weather features will be disabled +# OPEN_WEATHER_API_KEY_25=your-openweather-2-5-api-key-here +# OPEN_WEATHER_API_KEY_30=your-openweather-3-0-api-key-here + + +# ============================================================================ +# RATE LIMITING +# ============================================================================ + +# Enable rate limiting (protects login endpoints) +# RATE_LIMITING_ENABLED=true + +# Backend for rate-limit storage (default: in-memory) +# Example for Redis: redis://localhost:6379/1 +# RATE_LIMIT_STORAGE_URI=memory:// diff --git a/journiv/Caddyfilepart b/journiv/Caddyfilepart new file mode 100644 index 0000000..a883649 --- /dev/null +++ b/journiv/Caddyfilepart @@ -0,0 +1,5 @@ +journal.domr.ovh, +journiv.domr.ovh { + tls soenke@domroese.eu + reverse_proxy 192.168.1.65:8198 +} diff --git a/journiv/docker-compose.yml b/journiv/docker-compose.yml new file mode 100644 index 0000000..faa6cfe --- /dev/null +++ b/journiv/docker-compose.yml @@ -0,0 +1,181 @@ +# Journiv Production Docker Compose (PostgreSQL). +# Journiv recommends using PostgreSQL based deployment over SQLite. +# +# Usage: +# docker compose up -d +# +# Required Environment Variables: +# SECRET_KEY - Generate with: python -c "import secrets; print(secrets.token_urlsafe(32))" +# DOMAIN_NAME - Needed when running in same-origin SPA mode (ENABLE_CORS=false). +# POSTGRES_PASSWORD - Must be provided in .env file. + +x-base-env: &base-env + REDIS_URL: redis://valkey:6379/0 + CELERY_BROKER_URL: redis://valkey:6379/0 + CELERY_RESULT_BACKEND: redis://valkey:6379/0 + DB_DRIVER: sqlite + # POSTGRES_HOST: postgres + +x-celery-common: &celery-common + image: swalabtech/journiv-app:${APP_VERSION:-latest} + env_file: .env + volumes: + - /home/soenke/docker-data/journiv/app_data:/data + depends_on: + postgres: + condition: service_healthy + valkey: + condition: service_healthy + networks: + - backend + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "50m" + max-file: "5" + deploy: + resources: + limits: + cpus: "1.0" + memory: 1g + reservations: + memory: 256m + +x-app-common: &app-common + image: swalabtech/journiv-app:${APP_VERSION:-latest} + env_file: .env + volumes: + - /home/soenke/docker-data/journiv/app_data:/data + depends_on: + postgres: + condition: service_healthy + valkey: + condition: service_healthy + networks: + - backend + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "50m" + max-file: "5" + +x-celery-healthcheck: &celery-healthcheck + interval: 30s + timeout: 10s + retries: 5 + start_period: 40s + +services: + postgres: + image: postgres:18.1 + container_name: journiv-postgres-db + environment: + - POSTGRES_USER=${POSTGRES_USER:-journiv} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # must provide a password in .env file + - POSTGRES_DB=${POSTGRES_DB:-journiv_prod} + volumes: + - /home/soenke/docker-data/journiv/postgres_data:/var/lib/postgresql + networks: + - backend + restart: unless-stopped + deploy: + resources: + limits: + cpus: "1.0" + memory: 1g + reservations: + memory: 256m + logging: + driver: "json-file" + options: + max-size: "50m" + max-file: "5" + healthcheck: + test: + [ + "CMD-SHELL", + "pg_isready -U ${POSTGRES_USER:-journiv} -d ${POSTGRES_DB:-journiv_prod}", + ] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + + valkey: + # Journiv uses Valkey which is similar to Redis for cache. + image: valkey/valkey:9.0-alpine + container_name: journiv-valkey-cache + restart: unless-stopped + volumes: + - /home/soenke/docker-data/journiv/valkey_data:/data + networks: + - backend + healthcheck: + test: ["CMD", "valkey-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + + celery-worker: + <<: *celery-common + container_name: journiv-celery-worker + command: celery -A app.core.celery_app worker --loglevel=info + environment: + <<: *base-env + SERVICE_ROLE: celery-worker + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + healthcheck: + <<: *celery-healthcheck + + celery-beat: + <<: *celery-common + container_name: journiv-celery-beat + command: celery -A app.core.celery_app beat --loglevel=info --scheduler redbeat.RedBeatScheduler --pidfile=/tmp/celerybeat.pid + environment: + <<: *base-env + SERVICE_ROLE: celery-beat + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + REDBEAT_REDIS_URL: redis://valkey:6379/2 + healthcheck: + <<: *celery-healthcheck + + app: + <<: *app-common + container_name: journiv-postgres-app + ports: + - "${APP_PORT:-8000}:8000" + environment: + <<: *base-env + SERVICE_ROLE: app + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + ENVIRONMENT: production + RATE_LIMIT_STORAGE_URI: redis://valkey:6379/1 + networks: + - backend + - frontend + healthcheck: + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + deploy: + resources: + limits: + cpus: "2.0" + memory: 2g + reservations: + memory: 512m + +#volumes: +# app_data: +# postgres_data: +# valkey_data: + +networks: + backend: + driver: bridge + frontend: + driver: bridge diff --git a/restartall.sh b/restartall.sh index cb7b710..570243e 100755 --- a/restartall.sh +++ b/restartall.sh @@ -3,6 +3,7 @@ for dir in *; do if [[ "$dir" != "caddy" ]]; then if [[ "$dir" != "pihole" ]]; then ( cd "$dir" && docker compose pull && docker compose down && docker compose up -d ) + sleep 2s fi fi fi