---
configs:
  caddyfile:
    content: |
      notes-old.kucharczyk.xyz {
        handle {
          root * /srv/notes
          file_server
        }
      }

include:
  - services/bazarr.yml
  - services/jellyfin.yml
  - services/komga.yml
  - services/radarr.yml
  - services/miniflux.yml
  - services/jelu.yml
  - services/sonarr.yml
  - services/postgres.yml
  - services/nextcloud.yml
  - services/sabnzbd.yml
  - services/openldap.yml
  - services/prowlarr.yml
  - services/netbootxyz.yml
  - services/registry.yml
  - services/portainer.yml
  - services/drone/drone.yml
  - services/enshrouded.yml
  - services/7dtdserver.yml
  - services/gluetun.yml
  - services/handbrake-server.yml
  - services/redlib.yml
  - services/calibre-web.yml
  - services/kavita.yml

services:
  caddy:
    image: lucaslorentz/caddy-docker-proxy:ci-alpine
    container_name: caddy
    ports:
      - "${TIMETRACKER_EXTERNAL_PORT}:${TIMETRACKER_INTERNAL_PORT}"
      - "${DENDRON_NOTES_EXTERNAL_PORT}:${DENDRON_NOTES_INTERNAL_PORT}"
      - 80:80
      - 443:443
    environment:
      - CADDY_INGRESS_NETWORKS=docker-compose-templates_public
      - CADDY_DOCKER_CADDYFILE_PATH=/Caddyfile
    configs:
      - source: caddyfile
        target: /Caddyfile
    volumes:
      - "${DOCKER_STORAGE_PATH}/caddy/etc:/etc/caddy"
      - "${DOCKER_STORAGE_PATH}/caddy/data:/data"
      - "${DOCKER_STORAGE_PATH}/caddy/config:/config"
      - "/var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock"
      - "/www/notes:/srv/notes"
      - "timetracker-static:/srv/timetracker"
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      public:
        ipv4_address: 192.168.240.2
    restart: unless-stopped
    # cap_drop:
    #   - ALL
    # cap_add:
    #   - NET_BIND_SERVICE

  timetracker:
    image: ${REGISTRY_URL}/timetracker
    container_name: timetracker
    environment:
      - TZ=${TZ}
      - "CSRF_TRUSTED_ORIGINS=https://tracker.kucharczyk.xyz"
    user: ${PUID}
    volumes:
      - "${DOCKER_STORAGE_PATH}/timetracker/db.sqlite3:/home/timetracker/app/db.sqlite3"
      - "${DOCKER_STORAGE_PATH}/timetracker/backups:/home/timetracker/app/games/fixtures/backups"
      - "timetracker-static:/var/www/django/static"
    depends_on:
      - caddy
    networks:
      public:
        ipv4_address: 192.168.240.3
    labels:
      caddy: tracker.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 8001 }}"
      caddy.handle_path: "/static/*"
      caddy.handle_path.root: "* /srv/timetracker"
      caddy.handle_path.file_server:
      caddy.handle: /robots.txt
      caddy.handle.root: "* /srv/timetracker"
      caddy.handle.file_server:
    restart: unless-stopped

  trilium:
    image: zadam/trilium
    container_name: trilium
    restart: always
    environment:
      - TRILIUM_DATA_DIR=/home/node/trilium-data
    volumes:
      - ${DOCKER_STORAGE_PATH}/trilium:/home/node/trilium-data
    ports:
      - "${TRILIUM_EXTERNAL_PORT}:${TRILIUM_INTERNAL_PORT}"
    networks:
      public:
        ipv4_address: 192.168.240.4

  ntfy:
    image: binwiederhier/ntfy
    container_name: ntfy
    command:
      - serve
    user: ${PUID}:${PGID}
    environment:
      - TZ=${TZ}
    volumes:
      - "${DOCKER_STORAGE_PATH}/ntfy/cache:/var/cache/ntfy"
      - "${DOCKER_STORAGE_PATH}/ntfy/config:/etc/ntfy"
    ports:
      - "${NTFY_EXTERNAL_PORT}:${NTFY_INTERNAL_PORT}"
    networks:
      public:
        ipv4_address: 192.168.240.5
    labels:
      caddy: "notify.${DOMAIN}, http://notify.${DOMAIN}"
      caddy.reverse_proxy: "{{ upstreams $NTFY_INTERNAL_PORT }}"
      caddy.@httpget.protocol: http
      caddy.@httpget.method: get
      caddy.@httpget.path_regexp: "^/([-_a-z0-9]{0,64}$|docs/|static/)"
      caddy.redir: "@httpget https://{host}{uri}"
    restart: unless-stopped

  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:2.20.0
    container_name: audiobookshelf
    environment:
      - AUDIOBOOKSHELF_UID=${PUID}
      - AUDIOBOOKSHELF_GID=${PGID}
      - TZ=${TZ}
    volumes:
      - "${DOCKER_STORAGE_PATH}/audiobookshelf/audiobooks:/audiobooks"
      - "${DOCKER_STORAGE_PATH}/audiobookshelf/podcasts:/podcasts"
      - "${DOCKER_STORAGE_PATH}/audiobookshelf/config:/config"
      - "${DOCKER_STORAGE_PATH}/audiobookshelf/metadata:/metadata"
    ports:
      - "${AUDIOBOOKSHELF_EXTERNAL_PORT}:${AUDIOBOOKSHELF_INTERNAL_PORT}"
    networks:
      public:
        ipv4_address: 192.168.240.6
    restart: unless-stopped

  beets:
    image: lscr.io/linuxserver/beets:2.2.0
    container_name: beets
    user: 1000:100
    environment:
      - TZ=${TZ}
    volumes:
      - "${DOCKER_STORAGE_PATH}/beets:/config"
      - "${STORAGE_PATH}/media/music2:/music"
      - "${STORAGE_PATH}/download/music:/downloads"
    ports:
      - 8337:8337
    networks:
      public:
        ipv4_address: 192.168.240.7
    restart: unless-stopped

  mealie:
    container_name: mealie
    image: hkotel/mealie:v1.9.0
    environment:
      PUID: ${PUID}
      PGID: ${PGID}
      TZ: ${TZ}
    env_file:
      - mealie.env
    volumes:
      - "${DOCKER_STORAGE_PATH}/mealie/data/:/app/data"
    networks:
      public:
        ipv4_address: 192.168.240.8
    labels:
      caddy: recipes.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 9000 }}"
    restart: unless-stopped

  rtorrent:
    image: binhex/arch-rtorrentvpn
    container_name: rtorrent
    volumes:
      - "${DOCKER_STORAGE_PATH}/rtorrent/config:/config"
      - "${DOCKER_STORAGE_PATH}/rtorrent/watch:/watch"
      - ${STORAGE_PATH}/seed:/data
      - /etc/localtime:/etc/localtime:ro
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
    env_file:
      - rtorrent.env
    ports:
      - "9080:9080"
      - "9443:9443"
      - "8118:8118"
      - "6881:6881"
    networks:
      public:
        ipv4_address: 192.168.240.9
    labels:
      caddy: torrent.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 9080 }}"
    restart: unless-stopped

  webhook:
    image: ${REGISTRY_URL}/webhook
    container_name: webhook
    build: https://git.kucharczyk.xyz/containers/webhook.git#main
    user: ${PUID}:${PGID}
    environment:
      - TZ=${TZ}
    volumes:
      - "${DOCKER_STORAGE_PATH}/webhook/config:/config"
      - "${DOCKER_STORAGE_PATH}/webhook/scripts:/var/webhook"
    ports:
      - "${WEBHOOK_EXTERNAL_PORT}:${WEBHOOK_INTERNAL_PORT}"
    networks:
      public:
        ipv4_address: 192.168.240.10
    restart: unless-stopped

  valheim:
    image: ghcr.io/lloesche/valheim-server
    container_name: valheim
    volumes:
      - ${DOCKER_STORAGE_PATH}/valheim/config:/config
      - ${DOCKER_STORAGE_PATH}/valheim/data:/opt/valheim
    env_file:
      - valheim.env
    ports:
      - ${VALHEIM_EXTERNAL_PORT}:${VALHEIM_INTERNAL_PORT}
    cap_add:
      - SYS_NICE
    networks:
      public:
        ipv4_address: 192.168.240.11
    restart: unless-stopped

  stash:
    image: stashapp/stash:v0.28.1
    container_name: stash
    ports:
      - "${STASH_EXTERNAL_PORT}:${STASH_INTERNAL_PORT}"
    ## If you intend to use stash's DLNA functionality uncomment the below network mode and comment out the above ports section
    # network_mode: host
    logging:
      driver: "json-file"
      options:
        max-file: "10"
        max-size: "2m"
    environment:
      - STASH_STASH=/data/
      - STASH_GENERATED=/generated/
      - STASH_METADATA=/metadata/
      - STASH_CACHE=/cache/
      - STASH_PORT=${STASH_INTERNAL_PORT}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      ## Adjust below paths (the left part) to your liking.
      ## E.g. you can change ./config:/root/.stash to ./stash:/root/.stash

      ## Keep configs, scrapers, and plugins here.
      - "${DOCKER_STORAGE_PATH}/stash/config:/root/.stash"
      ## Point this at your collection.
      - "${STORAGE_PATH}/xxx:/data/"
      ## This is where your stash's metadata lives
      - "${DOCKER_STORAGE_PATH}/stash/metadata:/metadata"
      ## Any other cache content.
      - "${DOCKER_STORAGE_PATH}/stash/cache:/cache"
      ## Where to store generated content (screenshots,previews,transcodes,sprites)
      - "${DOCKER_STORAGE_PATH}/stash/generated:/generated"
      ## Where to store binary blob data (scene covers, images)
      - "${DOCKER_STORAGE_PATH}/stash/blobs:/blobs"
    networks:
      public:
        ipv4_address: 192.168.240.13
    restart: unless-stopped

  navidrome:
    image: deluan/navidrome:0.55.0
    container_name: navidrome
    ports:
      - "${NAVIDROME_EXTERNAL_PORT}:${NAVIDROME_INTERNAL_PORT}"
    env_file:
      - navidrome.env
    user: "${PUID}:${PGID}"
    volumes:
      - "${DOCKER_STORAGE_PATH}/navidrome:/data"
      - "${STORAGE_PATH}/media/music2:/music"
    networks:
      public:
        ipv4_address: 192.168.240.14
    labels:
      caddy: music.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams $NAVIDROME_INTERNAL_PORT }}"
    restart: unless-stopped

  maloja:
    image: krateng/maloja
    container_name: maloja
    ports:
      - "${MALOJA_EXTERNAL_PORT}:${MALOJA_INTERNAL_PORT}"
    env_file:
      - maloja.env
    user: "${PUID}:${PGID}"
    volumes:
      - "${DOCKER_STORAGE_PATH}/maloja:/data"
    networks:
      public:
        ipv4_address: 192.168.240.15
    restart: unless-stopped

  redis:
    container_name: redis
    image: docker.io/library/redis:7
    networks:
      public:
        ipv4_address: 192.168.240.30
    restart: unless-stopped
    volumes:
      - "${DOCKER_STORAGE_PATH}/redis:/data"

  paperless-ngx:
    container_name: paperless-ngx
    image: ghcr.io/paperless-ngx/paperless-ngx:2.0.1
    restart: unless-stopped
    depends_on:
      - redis
      - gotenberg
      - tika
    ports:
      - "${PAPERLESS_EXTERNAL_PORT}:${PAPERLESS_INTERNAL_PORT}"
    networks:
      public:
        ipv4_address: 192.168.240.16
    healthcheck:
      test:
        [
          "CMD",
          "curl",
          "-fs",
          "-S",
          "--max-time",
          "2",
          "http://localhost:8000"
        ]
      interval: 30s
      timeout: 10s
      retries: 5
    volumes:
      - "${DOCKER_STORAGE_PATH}/paperless-ngx/data:/usr/src/paperless/data"
      - "${DOCKER_STORAGE_PATH}/paperless-ngx/media:/usr/src/paperless/media"
      - "${DOCKER_STORAGE_PATH}/paperless-ngx/export:/usr/src/paperless/export"
      - "${DOCKER_STORAGE_PATH}/paperless-ngx/consume:/usr/src/paperless/consume"
    env_file: paperless-ngx.env
    environment:
      PAPERLESS_REDIS: redis://redis:6379
      PAPERLESS_TIKA_ENABLED: 1
      PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
      PAPERLESS_TIKA_ENDPOINT: http://tika:9998
      PAPERLESS_URL: "https://paperless.${DOMAIN}"

  gotenberg:
    image: docker.io/gotenberg/gotenberg:7.6
    restart: unless-stopped
    networks:
      public:
        ipv4_address: 192.168.240.17
    # The gotenberg chromium route is used to convert .eml files. We do not
    # want to allow external content like tracking pixels or even javascript.
    command:
      - "gotenberg"
      - "--chromium-disable-javascript=true"
      - "--chromium-allow-list=file:///tmp/.*"

  tika:
    image: ghcr.io/paperless-ngx/tika:latest
    networks:
      public:
        ipv4_address: 192.168.240.18
    restart: unless-stopped

  homer:
    image: b4bz/homer
    container_name: homer
    ports:
      - "${HOMER_EXTERNAL_PORT}:${HOMER_INTERNAL_PORT}"
    networks:
      public:
        ipv4_address: 192.168.240.19
    volumes:
      - "${DOCKER_STORAGE_PATH}/homer:/www/assets"
    environment:
      UID: ${PUID}
      GID: ${PGID}
    restart: unless-stopped

  syncthing:
    image: lscr.io/linuxserver/syncthing:1.28.1
    container_name: syncthing
    volumes:
      - "${DOCKER_STORAGE_PATH}/syncthing:/config"
      - "${DOCKER_STORAGE_PATH}/syncthing/shares:/shares"
      - "${STORAGE_PATH}:/storage"
    ports:
      - "${SYNCTHING_EXTERNAL_PORT1}:${SYNCTHING_INTERNAL_PORT1}"
      - "${SYNCTHING_EXTERNAL_PORT2}:${SYNCTHING_INTERNAL_PORT2}"
      - "${SYNCTHING_EXTERNAL_PORT3}:${SYNCTHING_INTERNAL_PORT3}"
      - "${SYNCTHING_EXTERNAL_PORT4}:${SYNCTHING_INTERNAL_PORT4}"
    environment:
      - "PUID=${PUID}"
      - "PGID=${PGID}"
    restart: unless-stopped
    networks:
      public:
        ipv4_address: 192.168.240.20

  mediawiki:
    container_name: mediawiki
    image: mediawiki
    networks:
      public:
        ipv4_address: 192.168.240.21
    labels:
      caddy: wiki.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams $MEDIAWIKI_INTERNAL_PORT }}"
    depends_on:
      - mariadb
    ports:
      - "${MEDIAWIKI_EXTERNAL_PORT}:${MEDIAWIKI_INTERNAL_PORT}"
    volumes:
      - "${DOCKER_STORAGE_PATH}/mediawiki/images:/var/www/html/images"
      - "${DOCKER_STORAGE_PATH}/mediawiki/extensions:/var/www/html/extensions"
      - "${DOCKER_STORAGE_PATH}/mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php"
    restart: unless-stopped

  photoprism:
    container_name: photoprism
    image: docker.io/photoprism/photoprism
    networks:
      public:
        ipv4_address: 192.168.240.22
    ports:
      - "${PHOTOPRISM_EXTERNAL_PORT}:${PHOTOPRISM_INTERNAL_PORT}"
    labels:
      caddy: photos.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 2342 }}"
    depends_on:
      - mariadb
    env_file:
      - photoprism.env
    volumes:
      - "${PHOTOS_STORAGE_PATH}/import:/photoprism/import"
      - "${PHOTOS_STORAGE_PATH}/originals:/photoprism/originals"
      - "${PHOTOS_STORAGE_PATH}/storage:/photoprism/storage"
    restart: unless-stopped

  mariadb:
    container_name: mariadb
    image: linuxserver/mariadb
    networks:
      public:
        ipv4_address: 192.168.240.23
    ports:
      - "${MARIADB_EXTERNAL_PORT}:${MARIADB_INTERNAL_PORT}"
    volumes:
      - "${DOCKER_STORAGE_PATH}/mariadb:/config"
      - sockets:/run/mysqld/
    restart: unless-stopped

  baserow:
    container_name: baserow
    image: baserow/baserow:latest
    networks:
      public:
        ipv4_address: 192.168.240.24
    labels:
      caddy: baserow.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 80 }}"
    depends_on:
      - postgres
    env_file:
      - baserow.env
    volumes:
      - "${DOCKER_STORAGE_PATH}/baserow:/baserow/data"
    restart: unless-stopped

  gitea:
    container_name: gitea
    image: gitea/gitea:1.23.4
    networks:
      public:
        ipv4_address: 192.168.240.26
    depends_on:
      - postgres
    ports:
      - "${GITEA_WEBUI_EXTERNAL_PORT}:${GITEA_WEBUI_INTERNAL_PORT}"
      - "${GITEA_SSH_EXTERNAL_PORT}:${GITEA_SSH_INTERNAL_PORT}"
    labels:
      caddy: git.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams $GITEA_WEBUI_INTERNAL_PORT }}"
    volumes:
      - "${DOCKER_STORAGE_PATH}/gitea:/data"
    restart: unless-stopped

  gitearunner:
    container_name: gitearunner
    image: gitea/act_runner
    depends_on:
      - gitea
    volumes:
      - "${DOCKER_STORAGE_PATH}/gitearunner/config:/config"
      - "${DOCKER_STORAGE_PATH}/gitearunner/data:/data"
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      public:
        ipv4_address: 192.168.240.27
    environment:
      - GITEA_INSTANCE_URL=https://git.${DOMAIN}
      - CONFIG_FILE=/config/config.yaml
      # When using Docker Secrets, it's also possible to use
      # GITEA_RUNNER_REGISTRATION_TOKEN_FILE to pass the location.
      # The env var takes precedence
      - GITEA_RUNNER_REGISTRATION_TOKEN=92U7bIiADtqkILwjjj9rffjz8vyNp0zo7uaOgrIG
      - GITEA_RUNNER_LABELS="ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
      - GITEA_RUNNER_NAME="NAS_CONTAINER"
    restart: unless-stopped

  linkace:
    image: linkace/linkace:v1.15.4-simple
    container_name: linkace
    networks:
      public:
        ipv4_address: 192.168.240.28
    labels:
      caddy: bookmarks.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 80 }}"
    depends_on:
      - mariadb
      - redis
    environment:
      # these env variables are instead of .env file
      # see https://www.linkace.org/docs/v1/setup/setup-with-docker/advanced-configuration/#using-docker-environment-variables-instead-of-the-env-file
      - APP_KEY=base64:X6XDR+dfqn5PM9QdmmxJoOECSsldWhkfnyi6yvohgNM=
      - DB_HOST=${MYSQL_HOST}
      - DB_DATABASE=${LINKACE_DB}
      - DB_USERNAME=${LINKACE_DB_USERNAME}
      - DB_PASSWORD=${LINKACE_DB_PASSWORD}
      - REDIS_HOST=redis
    ports:
      - "${LINKACE_EXTERNAL_PORT}:${LINKACE_INTERNAL_PORT}"
    volumes:
      - ${DOCKER_STORAGE_PATH}/linkace/backups:/app/storage/app/backups
      - ${DOCKER_STORAGE_PATH}/linkace/logs:/app/storage/logs
    restart: unless-stopped

  # ghost:
  #   image: "ghost:latest"
  #   container_name: ghost
  #   environment:
  #     - url=http://blog.kucharczyk.xyz
  #   labels:
  #     - "traefik.enable=true"
  #     - "traefik.http.routers.ghost.rule=Host(`blog.kucharczyk.xyz`)"
  #     - "traefik.http.routers.ghost.entrypoints=https"
  #     - "traefik.http.routers.ghost.tls.certresolver=myresolver"
  #   volumes:
  #     - ${DOCKER_STORAGE_PATH}/ghost/content:/var/lib/ghost/content
  #   networks:
  #     - public

  vaultwarden:
    image: vaultwarden/server:1.32.1
    container_name: vaultwarden
    networks:
      public:
        ipv4_address: 192.168.240.29
    ports:
      - "${VAULTWARDEN_EXTERNAL_PORT}:${VAULTWARDEN_INTERNAL_PORT}"
    labels:
      caddy: bw.${DOMAIN}
      caddy.reverse_proxy: "{{ upstreams 80 }}"
    env_file:
      - ./secrets/vaultwarden.env
    environment:
      - PUSH_ENABLED=true
      # PUSH_INSTALLATION_ID=
      # PUSH_INSTALLATION_KEY=
      - PUSH_RELAY_URI=https://api.bitwarden.eu
      - PUSH_IDENTITY_URI=https://identity.bitwarden.eu
      - ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$aWJ2cVRvYUsySkM3M01TMTJJMnZqbUF0Wm1qRWhvd1B6Sk50Q1hwck96dz0$$FKjZ36E54pX2e0AE9OaDpiH43TyAyfVwr3IvracbqEA
      - SMTP_HOST=${EMAIL_HOST}
      - SMTP_FROM=${EMAIL_FROM}
      - SMTP_FROM_NAME="Bitwarden (bw.kucharczyk.xyz)"
      - SMTP_PORT=${EMAIL_PORT}
      - SMTP_USERNAME=${EMAIL_FROM}
      - SMTP_PASSWORD=${EMAIL_PASSWORD}
    volumes:
      - ${DOCKER_STORAGE_PATH}/vaultwarden:/data
    restart: unless-stopped
       

networks:
  public:
    attachable: true
    ipam:
      config:
        # 192.168.240.1 - 192.168.240.254
        - subnet: "192.168.240.0/24"

volumes:
  timetracker-static:
  sockets: