Files
web_server/docker-compose.yml
Adam French aa6de883be
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 34s
Move Open-WebUI to chat.${DOMAIN} subdomain
Open-WebUI's SvelteKit frontend hardcodes asset/API paths at build time,
so subpath hosting under /openwebui/ produced 404s on /_app/... assets.
Move it to its own subdomain so it can run at root.

- certbot: request cert with chat.${DOMAIN} as a third SAN via --expand
- nginx (prod): drop /openwebui blocks; add chat.${DOMAIN} HTTP redirect
  + HTTPS server with the existing admin auth gate
- nginx (dev): drop /openwebui blocks (no chat.localhost in dev)
- compose: WEBUI_URL points to https://chat.${DOMAIN}

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 17:29:29 +01:00

220 lines
5.1 KiB
YAML

networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
volumes:
# Postgres database
dbdata:
# File upload
uploads:
# Vue build
vue_dist:
# Searxng data
searxng_data:
# Open-WebUI data
openwebui_data:
services:
vue:
build:
context: ./vue
dockerfile: Dockerfile
container_name: vue
volumes:
- vue_dist:/output
networks:
- app-network
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
container_name: nginx
env_file: ./.env
restart: always
depends_on:
- vue
- backend
- icecast2
- gitea
- hasura
- quartz
- searxng
- open-webui
networks:
- app-network
ports:
- 80:80
- 443:443
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
- uploads:/uploads
- vue_dist:/etc/nginx/html
certbot:
image: certbot/certbot:v3.1.0
container_name: certbot
volumes:
- ./certbot/entrypoint.sh:/entrypoint.sh
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: ["/entrypoint.sh"]
env_file:
- .env
networks:
- app-network
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: "${BACKEND_HOST}"
restart: always
depends_on:
- db
networks:
- app-network
env_file:
- ./.env
volumes:
- ./backend/token/:/backend/token
- ${OBSIDIAN_DIR}:/backend/notes
- ./logs:/backend/logs
- uploads:/backend/uploads
- ./icecast2/fallback_music:/backend/fallback_music
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
autoheal:
image: willfarrell/autoheal:latest
container_name: autoheal
restart: always
environment:
- AUTOHEAL_CONTAINER_LABEL=all
- AUTOHEAL_INTERVAL=30
- AUTOHEAL_START_PERIOD=60
volumes:
- /var/run/docker.sock:/var/run/docker.sock
db:
image: postgres:16
container_name: "${POSTGRES_HOST}"
restart: always
env_file:
- ./.env
networks:
- app-network
volumes:
- dbdata:/var/lib/postgresql/data
hasura:
image: hasura/graphql-engine:v2.44.0
container_name: "${HASURA_HOST}"
restart: always
depends_on:
- db
networks:
- app-network
environment:
HASURA_GRAPHQL_DATABASE_URL: "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
HASURA_GRAPHQL_ADMIN_SECRET: "${HASURA_GRAPHQL_ADMIN_SECRET}"
HASURA_GRAPHQL_ENABLE_CONSOLE: "false"
HASURA_GRAPHQL_DEV_MODE: "false"
HASURA_GRAPHQL_ENABLED_LOG_TYPES: "startup, http-log, webhook-log, websocket-log, query-log"
icecast2:
build:
context: ./icecast2
dockerfile: Dockerfile
container_name: "${ICECAST_HOST}"
restart: always
networks:
- app-network
env_file:
- ./.env
volumes:
- ./icecast2/fallback_music:/music:ro
ports:
- "${LIQUIDSOAP_HARBOR_PORT:-8001}:${LIQUIDSOAP_HARBOR_PORT:-8001}"
quartz:
build:
context: ./quartz
dockerfile: Dockerfile
container_name: "${QUARTZ_HOST}"
restart: always
networks:
- app-network
env_file:
- ./.env
volumes:
- ${OBSIDIAN_DIR}:/quartz/content:ro
searxng:
build:
context: ./searxng
dockerfile: Dockerfile
container_name: "${SEARXNG_HOST}"
restart: unless-stopped
networks:
- app-network
environment:
- BASE_URL=https://www.${DOMAIN}/searxng/
- INSTANCE_NAME=searxng
- SEARXNG_SECRET_KEY=${SEARXNG_SECRET_KEY}
volumes:
- searxng_data:/etc/searxng
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: "${OPENWEBUI_HOST}"
restart: always
networks:
- app-network
env_file:
- ./.env
environment:
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL}
- WEBUI_AUTH=False
- WEBUI_URL=https://chat.${DOMAIN}
volumes:
- openwebui_data:/app/backend/data
gitea:
image: docker.gitea.com/gitea:1.25.4-rootless
container_name: "${GITEA_HOST}"
entrypoint: ["/usr/bin/dumb-init", "--", "/etc/gitea/entrypoint.sh"]
networks:
- app-network
environment:
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=${POSTGRES_HOST}
- GITEA__database__NAME=${POSTGRES_GITEA_DB}
- GITEA__database__USER=${POSTGRES_USER}
- GITEA__database__PASSWD=${POSTGRES_PASSWORD}
- GITEA__server__LFS_JWT_SECRET=${GITEA_LFS_JWT_SECRET}
- GITEA__security__INTERNAL_TOKEN=${GITEA_INTERNAL_TOKEN}
- GITEA__oauth2__JWT_SECRET=${GITEA_OAUTH2_JWT_SECRET}
- USER_UID=1000
- USER_GID=1000
restart: always
volumes:
- ./gitea/data:/var/lib/gitea
- ./gitea/config:/etc/gitea
- ./gitea/entrypoint.sh:/etc/gitea/entrypoint.sh:ro
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "2222:2222"
- "3000:3000"
depends_on:
- db