name: studio-einszwovier

services:
  web:
    build: .
    container_name: 124_webapp
    ports:
      - "80:8000"
    volumes:
      - ./data:/cost-assistant/data
      - ./templates:/cost-assistant/templates:ro
      - ./static:/cost-assistant/static:ro
    env_file:
      - .env
    restart: unless-stopped
    mem_limit: 1g
    cpus: 1.0
    mem_reservation: 256m
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8000/ || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    depends_on:
      synapse:
        condition: service_started
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=Studio EinsZwoVier PDF Cost Calculator"
      - "maintainer=Studio EinsZwoVier"

  synapse:
    image: matrixdotorg/synapse:latest
    container_name: matrix_server
    ports:
      - "${SYNAPSE_PORT:-8008}:8008"
    volumes:
      - ./matrix/data:/data
    environment:
      - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
    restart: unless-stopped
    mem_limit: 2g
    cpus: 2.0
    mem_reservation: 512m
    healthcheck:
      test:
        ["CMD-SHELL", "curl -f http://localhost:8008/_matrix/static/ || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=Matrix homeserver for print orders"
      - "maintainer=Studio EinsZwoVier"

  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    ports:
      - "${OLLAMA_PORT:-11434}:11434"
    volumes:
      - ./ollama:/root/.ollama
    restart: unless-stopped
    mem_limit: 16g
    cpus: 6.0
    mem_reservation: 4g
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:11434/ || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 60s
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=Local LLM inference engine"
      - "maintainer=Studio EinsZwoVier"

  open-webui:
    image: ghcr.io/open-webui/open-webui:latest
    container_name: open-webui
    ports:
      - "${OPENWEBUI_PORT:-8080}:8080"
    volumes:
      - ./open-webui:/app/backend/data
    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
      - WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY:-secret_key_change_me}
    restart: unless-stopped
    mem_limit: 2g
    cpus: 2.0
    mem_reservation: 512m
    depends_on:
      - ollama
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8080/ || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=Web UI for Ollama LLM"
      - "maintainer=Studio EinsZwoVier"

  bookstack:
    image: lscr.io/linuxserver/bookstack:latest
    container_name: bookstack
    environment:
      - MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_PASSWORD}
      - MYSQL_DATABASE=${BOOKSTACK_DB_DATABASE}
      - MYSQL_USER=${BOOKSTACK_DB_USERNAME}
      - MYSQL_PASSWORD=${BOOKSTACK_DB_PASSWORD}
    volumes:
      - ./bookstack/bookstack_app_data:/config
    ports:
      - "${BOOKSTACK_PORT}:80"
    restart: unless-stopped
    depends_on:
      bookstack-mariadb:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "mariadb -u${BOOKSTACK_DB_USERNAME} -p${BOOKSTACK_DB_PASSWORD} -e 'SELECT 1' || exit 1",
        ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=BookStack Documentation Wiki"
      - "maintainer=Studio EinsZwoVier"

  bookstack-mariadb:
    image: lscr.io/linuxserver/mariadb:latest
    container_name: bookstack-mariadb
    environment:
      - MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_PASSWORD}
      - MYSQL_DATABASE=${BOOKSTACK_DB_DATABASE}
      - MYSQL_USER=${BOOKSTACK_DB_USERNAME}
      - MYSQL_PASSWORD=${BOOKSTACK_DB_PASSWORD}
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Berlin
    env_file:
      - .env
    volumes:
      - ./bookstack/bookstack_db_data:/config
    restart: unless-stopped
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "mariadb -u${BOOKSTACK_DB_USERNAME} -p${BOOKSTACK_DB_PASSWORD} -e 'SELECT 1' || exit 1",
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=MariaDB Database for BookStack"
      - "maintainer=Studio EinsZwoVier"

  watchtower:
    image: containrrr/watchtower:latest
    container_name: watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_POLL_INTERVAL=86400
      - WATCHTOWER_INCLUDE_RESTARTING=true
      - WATCHTOWER_LABEL_ENABLE=true
    command: --cleanup --interval 86400 --label-enable
    healthcheck:
      test: ["CMD-SHELL", "pgrep watchtower || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
    labels:
      - "description=Watchtower Auto-Update Service"
      - "maintainer=Studio EinsZwoVier"

  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "${PORTAINER_PORT}:9000"
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -f http://localhost:9000/api/system/status || exit 1",
        ]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    labels:
      - "description=Portainer Container Management UI"
      - "maintainer=Studio EinsZwoVier"

  jupyterhub:
    build: ./jupyterhub
    container_name: jupyterhub
    ports:
      - "8001:8001"
      - "8081:8081"
    volumes:
      - ./data:/home
      - ./jupyterhub/jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro
      - ./static/images/logo.png:/srv/jupyterhub/logo.png:ro
      - /var/run/docker.sock:/var/run/docker.sock # Docker socket for spawning containers
    env_file:
      - .env
    environment:
      - JUPYTERHUB_SINGLEUSER_APP=jupyterlab
    restart: unless-stopped
    mem_limit: 2g
    cpus: 1.0
    depends_on:
      - web
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=JupyterHub for interactive notebooks"
      - "maintainer=Studio EinsZwoVier"

  forgejo:
    image: codeberg.org/forgejo/forgejo:11
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - TZ=Europe/Berlin
      - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true
    restart: unless-stopped
    ports:
      - "${FORGEJO_PORT:-3003}:3000"
      - "222:22"
    volumes:
      - ./forgejo/data:/data
    mem_limit: 2g
    cpus: 2.0
    mem_reservation: 512m
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/ || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=Forgejo Git Server"
      - "maintainer=Studio EinsZwoVier"

  element-web:
    image: vectorim/element-web:latest
    container_name: element-web
    restart: unless-stopped
    ports:
      - "${ELEMENT_PORT:-8082}:80"
    volumes:
      - ./element-web/config.json:/app/config.json:ro
    mem_limit: 512m
    cpus: 0.5
    mem_reservation: 128m
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 20s
    depends_on:
      synapse:
        condition: service_started
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "description=Element Web Matrix Client"
      - "maintainer=studio einszwovier"

volumes:
  portainer_data:
    driver: local
    labels:
      - "description=Portainer persistent data"

networks:
  default:
    name: einszwovier_network
    labels:
      - "description=Studio EinsZwoVier network"
      - "maintainer=Studio EinsZwoVier"
