docker-compose.yml

# homelab-compose/docker-compose.yml
# See mercemay.top/src/homelab-compose/ for the full README.

networks:
  edge:
    driver: bridge
  internal:
    driver: bridge
    internal: true

volumes:
  immich_pg:
  paperless_data:
  paperless_media:
  paperless_pg:
  gitea_data:
  gitea_pg:
  grafana_data:
  prometheus_data:

services:
  caddy:
    image: caddy:2.8-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy/data:/data
      - ./caddy/config:/config
    networks: [edge, internal]
    depends_on:
      - jellyfin
      - immich-server
      - paperless
      - gitea
      - grafana

  jellyfin:
    image: jellyfin/jellyfin:10.9
    restart: unless-stopped
    environment:
      - TZ=${TZ}
    devices:
      - /dev/dri:/dev/dri
    volumes:
      - ./jellyfin/config:/config
      - ./jellyfin/cache:/cache
      - ${MEDIA_ROOT}:/media:ro
    networks: [internal]

  immich-server:
    image: ghcr.io/immich-app/immich-server:v1.119.1
    restart: unless-stopped
    env_file: .env
    volumes:
      - ${PHOTOS_ROOT}:/usr/src/app/upload
    depends_on:
      - immich-redis
      - immich-postgres
      - immich-machine-learning
    networks: [internal]

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:v1.119.1
    restart: unless-stopped
    env_file: .env
    volumes:
      - ./immich/ml-cache:/cache
    networks: [internal]

  immich-redis:
    image: redis:7-alpine
    restart: unless-stopped
    networks: [internal]

  immich-postgres:
    image: tensorchord/pgvecto-rs:pg14-v0.2.0
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${IMMICH_DB_USER}
      POSTGRES_PASSWORD: ${IMMICH_DB_PASSWORD}
      POSTGRES_DB: immich
    volumes:
      - immich_pg:/var/lib/postgresql/data
    networks: [internal]

  paperless:
    image: ghcr.io/paperless-ngx/paperless-ngx:2.11
    restart: unless-stopped
    env_file: .env
    depends_on:
      - paperless-db
      - paperless-redis
    volumes:
      - paperless_data:/usr/src/paperless/data
      - paperless_media:/usr/src/paperless/media
      - ./paperless/consume:/usr/src/paperless/consume
    networks: [internal]

  paperless-db:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${PAPERLESS_DB_USER}
      POSTGRES_PASSWORD: ${PAPERLESS_DB_PASSWORD}
      POSTGRES_DB: paperless
    volumes:
      - paperless_pg:/var/lib/postgresql/data
    networks: [internal]

  paperless-redis:
    image: redis:7-alpine
    restart: unless-stopped
    networks: [internal]

  gitea:
    image: gitea/gitea:1.22
    restart: unless-stopped
    environment:
      USER_UID: "1000"
      USER_GID: "1000"
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: gitea-db:5432
      GITEA__database__NAME: gitea
      GITEA__database__USER: ${GITEA_DB_USER}
      GITEA__database__PASSWD: ${GITEA_DB_PASSWORD}
    volumes:
      - gitea_data:/data
    depends_on:
      - gitea-db
    networks: [internal]
    ports:
      - "2222:22"

  gitea-db:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${GITEA_DB_USER}
      POSTGRES_PASSWORD: ${GITEA_DB_PASSWORD}
      POSTGRES_DB: gitea
    volumes:
      - gitea_pg:/var/lib/postgresql/data
    networks: [internal]

  syncthing:
    image: syncthing/syncthing:1.27
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000
    volumes:
      - ./syncthing/config:/var/syncthing/config
      - ${SYNC_ROOT}:/var/syncthing/data
    ports:
      - "22000:22000/tcp"
      - "22000:22000/udp"
      - "21027:21027/udp"
    networks: [edge]

  pihole:
    image: pihole/pihole:2024.07
    restart: unless-stopped
    cap_add: [NET_ADMIN]
    environment:
      TZ: ${TZ}
      WEBPASSWORD: ${PIHOLE_PASSWORD}
    volumes:
      - ./pihole/etc-pihole:/etc/pihole
      - ./pihole/dnsmasq.d:/etc/dnsmasq.d
    ports:
      - "53:53/tcp"
      - "53:53/udp"
    networks: [edge]

  prometheus:
    image: prom/prometheus:v2.54.1
    restart: unless-stopped
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.retention.time=90d
    networks: [internal]

  grafana:
    image: grafana/grafana:11.1.4
    restart: unless-stopped
    environment:
      GF_SECURITY_ADMIN_USER: ${GRAFANA_USER}
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
      GF_INSTALL_PLUGINS: ""
    volumes:
      - grafana_data:/var/lib/grafana
    depends_on:
      - prometheus
    networks: [internal]