# Please email lab@seedno.de with any questions about this file, or setting up any services therein

# The following variables should be set in a file named .env in the same directory as docker-compose.yml (alter as needed):
# - CLOUDFLARE_API_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# - TIMEZONE=America/Chicago
# - UID=1000
# - GID=1000

version: "3.8"

services:

  traefik:
    image: traefik:latest
    container_name: traefik
    restart: always
    environment:
      - "CF_DNS_API_TOKEN=${CLOUDFLARE_API_TOKEN}"
    command:
      - "--api"
      - "--providers.docker=true"
      - "--providers.file.directory=/conf"
      - "--providers.file.watch=true"
      - "--entrypoints.http.address=:80"
      - "--entrypoints.https.address=:443"
      - "--entrypoints.metrics.address=:8082"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.letsencrypt.acme.storage=/certs/acme.json"
      - "--accesslog=true"
      - "--log.level=ERROR"
      - "--log.filePath=/var/log/traefik.log"
      - "--metrics.prometheus=true"
      - "--metrics.prometheus.entrypoint=metrics"
      - "--metrics.prometheus.addentrypointslabels=true"
      - "--metrics.prometheus.addserviceslabels=true"
      - "--serverstransport.insecureskipverify=true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`seedno.de`) && (PathPrefix(`/dashboard/`) || PathPrefix(`/api`))"
      - "traefik.http.routers.traefik.entrypoints=https"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik.middlewares=adminauth,whitelist@file"
      - "traefik.http.middlewares.compress.compress=true"
      - "traefik.http.middlewares.adminauth.basicauth.usersfile=/conf/admin.auth"
      - "traefik.http.middlewares.familyauth.basicauth.usersfile=/conf/family.auth"
      - "traefik.http.middlewares.friendsauth.basicauth.usersfile=/conf/friends.auth"
      - "traefik.http.middlewares.secure.headers.browserxssfilter=true"
      - "traefik.http.middlewares.secure.headers.contenttypenosniff=true"
      - "traefik.http.middlewares.secure.headers.customresponseheaders.Permissions-Policy=geolocation=(), midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(), payment=()"
      - "traefik.http.middlewares.secure.headers.framedeny=true"
      - "traefik.http.middlewares.secure.headers.customframeoptionsvalue=SAMEORIGIN"
      - "traefik.http.middlewares.secure.headers.sslredirect=true"
      - "traefik.http.middlewares.secure.headers.referrerpolicy=strict-origin"
      - "traefik.http.middlewares.secure.headers.forcestsheader=true"
      - "traefik.http.middlewares.secure.headers.stspreload=true"
      - "traefik.http.middlewares.secure.headers.stsincludesubdomains=true"
      - "traefik.http.middlewares.secure.headers.stsseconds=63072000"
      - "traefik.http.middlewares.secure.headers.customresponseheaders.Server=GNU-Netcat/0.7.1"
      - "traefik.http.middlewares.secure.headers.customresponseheaders.X-Clacks-Overhead=GNU Terry Pratchett"
      - "traefik.http.middlewares.secure.headers.customresponseheaders.Expect-CT=enforce,max-age=86400"
      - "traefik.http.middlewares.secure.headers.customrequestheaders.X-Forwarded-Proto=https"
    ports:
      - "80:80"
      - "443:443"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
        read_only: true
      - type: bind
        source: /docker/traefik/certs
        target: /certs
      - type: bind
        source: /docker/traefik/config
        target: /conf
        read_only: true

  muse:
    image: codetheweb/muse:latest
    container_name: muse
    restart: always
    environment:
      - "DISCORD_TOKEN=${MUSE_DISCORD_TOKEN}"
      - "YOUTUBE_API_KEY=${MUSE_YOUTUBE_API_KEY}"
      - "SPOTIFY_CLIENT_ID=${MUSE_SPOTIFY_CLIENT_ID}"
      - "SPOTIFY_CLIENT_SECRET=${MUSE_SPOTIFY_CLIENT_SECRET}"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/muse/data
        target: /data

  7d2d:
    image: vinanrra/7dtd-server:latest
    container_name: 7d2d
    restart: always
    environment:
      - "ALLOC_FIXES=YES"
      - "BACKUP=YES"
      - "MONITOR=YES"
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "START_MODE=1"
      - "TEST_ALERT=NO"
      - "TimeZone=${TIMEZONE}"
      - "VERSION=stable"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.7d2d-admin.rule=Host(`admin.7d2d.seedno.de`)"
      - "traefik.http.routers.7d2d-admin.entrypoints=https"
      - "traefik.http.routers.7d2d-admin.service=7d2d-admin"
      - "traefik.http.routers.7d2d-admin.tls=true"
      - "traefik.http.routers.7d2d-admin.tls.certresolver=letsencrypt"
      - "traefik.http.routers.7d2d-admin.middlewares=adminauth,compress,secure"
      - "traefik.http.services.7d2d-admin.loadbalancer.server.port=8080"
      - "traefik.http.routers.7d2d-map.rule=Host(`map.7d2d.seedno.de`)"
      - "traefik.http.routers.7d2d-map.entrypoints=https"
      - "traefik.http.routers.7d2d-map.service=7d2d-map"
      - "traefik.http.routers.7d2d-map.tls=true"
      - "traefik.http.routers.7d2d-map.tls.certresolver=letsencrypt"
      - "traefik.http.routers.7d2d-map.middlewares=adminauth,compress,secure"
      - "traefik.http.services.7d2d-map.loadbalancer.server.port=8082"
    networks:
      - traefik
    ports:
      - "26900:26900"
      - "26900:26900/udp"
      - "26901:26901/udp"
      - "26902:26902/udp"
    volumes:
      - type: bind
        source: /docker/7d2d/7DaysToDie
        target: /home/sdtdserver/.local/share/7DaysToDie
      - type: bind
        source: /docker/7d2d/ServerFiles
        target: /home/sdtdserver/serverfiles
      - type: bind
        source: /docker/7d2d/LogFolder
        target: /home/sdtdserver/log
      - type: bind
        source: /docker/7d2d/BackupFolder
        target: /home/sdtdserver/lgsm/backup
      - type: bind
        source: /docker/7d2d/LGSM-Config
        target: /home/sdtdserver/lgsm/config-lgsm/sdtdserver

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - GOTIFY_CONNECTION
  gotify:
    image: gotify/server:latest
    container_name: gotify
    restart: always
    depends_on:
      - gotify-db
    environment:
      - "GOTIFY_DATABASE_CONNECTION=${GOTIFY_CONNECTION}"
      - "GOTIFY_DATABASE_DIALECT=postgres"
      - "GOTIFY_REGISTRATION=false"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.gotify.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'"
      - "traefik.http.middlewares.gotify-prefix.stripprefix.prefixes=/notify"
      - "traefik.http.routers.gotify.rule=Host(`seedno.de`) && PathPrefix(`/notify/`)"
      - "traefik.http.routers.gotify.entrypoints=https"
      - "traefik.http.routers.gotify.service=gotify"
      - "traefik.http.routers.gotify.tls=true"
      - "traefik.http.routers.gotify.tls.certresolver=letsencrypt"
      - "traefik.http.routers.gotify.middlewares=compress,secure,gotify,gotify-prefix"
      - "traefik.http.services.gotify.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/gotify/data
        target: /var/gotify/data

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - GOTIFY_DATABASE_NAME
  # - GOTIFY_DATABASE_USER
  # - GOTIFY_DATABASE_PASS
  gotify-db:
    image: postgres:13-alpine
    container_name: gotify-db
    restart: always
    environment:
      - "POSTGRES_DB=${GOTIFY_DATABASE_NAME}"
      - "POSTGRES_USER=${GOTIFY_DATABASE_USER}"
      - "POSTGRES_PASSWORD=${GOTIFY_DATABASE_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/gotify/database
        target: /var/lib/postgresql/data

  polaris:
    image: ogarcia/polaris:latest
    container_name: polaris
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.polaris.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data: https://*.swagger.io"
      - "traefik.http.routers.polaris.rule=Host(`music.seedno.de`)"
      - "traefik.http.routers.polaris.entrypoints=https"
      - "traefik.http.routers.polaris.service=polaris"
      - "traefik.http.routers.polaris.tls=true"
      - "traefik.http.routers.polaris.tls.certresolver=letsencrypt"
      - "traefik.http.routers.polaris.middlewares=compress,secure,polaris"
      - "traefik.http.services.polaris.loadbalancer.server.port=5050"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/polaris/data
        target: /var/lib/polaris
      - type: bind
        source: /storage/audio
        target: /music
        read_only: true

  terraria:
    image: beardedio/terraria:tshock-dev-latest
    container_name: terraria
    restart: always
    tty: true
    stdin_open: true
    environment:
      - "world=IG.wld"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    ports:
      - "7777:7777"
    volumes:
      - type: bind
        source: /docker/terraria/config
        target: /config

  netdata:
    image: netdata/netdata:latest
    container_name: netdata
    hostname: netdata.crimson.seedno.de
    restart: always
    cap_add:
      - "SYS_PTRACE"
    security_opt:
      - "apparmor:unconfined"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.netdata.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; img-src 'self' data:; connect-src 'self' https://registry.my-netdata.io https://www.googleapis.com; frame-src 'self' https://app.netdata.cloud"
      - "traefik.http.routers.netdata.rule=Host(`netdata.crimson.seedno.de`)"
      - "traefik.http.routers.netdata.entrypoints=https"
      - "traefik.http.routers.netdata.service=netdata"
      - "traefik.http.routers.netdata.tls=true"
      - "traefik.http.routers.netdata.tls.certresolver=letsencrypt"
      - "traefik.http.routers.netdata.middlewares=compress,secure,netdata,whitelist@file"
      - "traefik.http.services.netdata.loadbalancer.server.port=19999"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /proc
        target: /host/proc
        read_only: true
      - type: bind
        source: /sys
        target: /host/sys
        read_only: true

  pwndrop:
    image: ghcr.io/linuxserver/pwndrop:latest
    container_name: pwndrop
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "SECRET_PATH=${PWNDROP_SECRET_PATH}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.pwndrop.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; font-src 'self' data: https://fonts.gstatic.com/"
      - "traefik.http.routers.pwndrop-admin.rule=Host(`files.seedno.de`) && PathPrefix(`${PWNDROP_SECRET_PATH}`)"
      - "traefik.http.routers.pwndrop-admin.entrypoints=https"
      - "traefik.http.routers.pwndrop-admin.service=pwndrop"
      - "traefik.http.routers.pwndrop-admin.tls=true"
      - "traefik.http.routers.pwndrop-admin.tls.certresolver=letsencrypt"
      - "traefik.http.routers.pwndrop-admin.middlewares=compress,secure,pwndrop,whitelist@file"
      - "traefik.http.routers.pwndrop.rule=Host(`files.seedno.de`)"
      - "traefik.http.routers.pwndrop.entrypoints=https"
      - "traefik.http.routers.pwndrop.service=pwndrop"
      - "traefik.http.routers.pwndrop.tls=true"
      - "traefik.http.routers.pwndrop.tls.certresolver=letsencrypt"
      - "traefik.http.routers.pwndrop.middlewares=compress,secure,pwndrop"
      - "traefik.http.services.pwndrop.loadbalancer.server.port=8080"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/pwndrop/config
        target: /config

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - BOOKSTACK_DATABASE_NAME
  # - BOOKSTACK_DATABASE_USER
  # - BOOKSTACK_DATABASE_PASS
  bookstack:
    image: ghcr.io/linuxserver/bookstack:latest
    container_name: bookstack
    restart: always
    depends_on:
      - bookstack-db
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "APP_URL=https://bookstack.seedno.de"
      - "DB_HOST=bookstack-db"
      - "DB_USER=${BOOKSTACK_DATABASE_USER}"
      - "DB_PASS=${BOOKSTACK_DATABASE_PASS}"
      - "DB_DATABASE=${BOOKSTACK_DATABASE_NAME}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.bookstack.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'"
      - "traefik.http.routers.bookstack.rule=Host(`bookstack.seedno.de`)"
      - "traefik.http.routers.bookstack.entrypoints=https"
      - "traefik.http.routers.bookstack.service=bookstack"
      - "traefik.http.routers.bookstack.tls=true"
      - "traefik.http.routers.bookstack.tls.certresolver=letsencrypt"
      - "traefik.http.routers.bookstack.middlewares=compress,secure,bookstack"
      - "traefik.http.services.bookstack.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/bookstack/config
        target: /config

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - BOOKSTACK_DATABASE_ROOT_PASS
  # - BOOKSTACK_DATABASE_NAME
  # - BOOKSTACK_DATABASE_USER
  # - BOOKSTACK_DATABASE_PASS
  bookstack-db:
    image: ghcr.io/linuxserver/mariadb
    container_name: bookstack-db
    restart: always
    environment:
      - "MYSQL_ROOT_PASSWORD=${BOOKSTACK_DATABASE_ROOT_PASS}"
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "MYSQL_DATABASE=${BOOKSTACK_DATABASE_NAME}"
      - "MYSQL_USER=${BOOKSTACK_DATABASE_USER}"
      - "MYSQL_PASSWORD=${BOOKSTACK_DATABASE_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/bookstack/database
        target: /config

  paperless-ng:
    image: ghcr.io/linuxserver/paperless-ng:latest
    container_name: paperless-ng
    restart: always
    depends_on:
      - paperless-ng-redis
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "REDIS_URL=paperless-ng-redis:6379"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.paperless-ng.headers.contentSecurityPolicy=default-src 'self'; img-src 'self' data:"
      - "traefik.http.routers.paperless-ng.rule=Host(`paperless.seedno.de`)"
      - "traefik.http.routers.paperless-ng.entrypoints=https"
      - "traefik.http.routers.paperless-ng.service=paperless-ng"
      - "traefik.http.routers.paperless-ng.tls=true"
      - "traefik.http.routers.paperless-ng.tls.certresolver=letsencrypt"
      - "traefik.http.routers.paperless-ng.middlewares=compress,secure,paperless-ng"
      - "traefik.http.services.paperless-ng.loadbalancer.server.port=8000"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/paperless-ng/config
        target: /config
      - type: bind
        source: /docker/paperless-ng/data
        target: /data

  paperless-ng-redis:
    image: redis
    container_name: paperless-ng-redis
    restart: always
    labels:
      - "traefik.enable=false"
    networks:
      - traefik

  endlessh:
    image: ghcr.io/linuxserver/endlessh
    container_name: endlessh
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "MSDELAY=10000"
      - "MAXLINES=32"
      - "MAXCLIENTS=4096"
      - "LOGFILE=true"
      - "BINDFAMILY=4"
    labels:
      - "traefik.enable=false"
    ports:
      - "22:2222"
    volumes:
      - type: bind
        source: /docker/endlessh/config
        target: /config

  code-server:
    image: ghcr.io/linuxserver/code-server:latest
    container_name: code-server
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "SUDO_PASSWORD=${CODE_SUDO_PASSWORD}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.code-server.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:"
      - "traefik.http.routers.code-server.rule=Host(`code.seedno.de`)"
      - "traefik.http.routers.code-server.entrypoints=https"
      - "traefik.http.routers.code-server.service=code-server"
      - "traefik.http.routers.code-server.tls=true"
      - "traefik.http.routers.code-server.tls.certresolver=letsencrypt"
      - "traefik.http.routers.code-server.middlewares=adminauth,compress,secure,code-server"
      - "traefik.http.services.code-server.loadbalancer.server.port=8443"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/code-server/config
        target: /config

  registry:
    image: registry:2
    container_name: registry
    restart: always
    environment:
      - "REGISTRY_HTTP_ADDR=0.0.0.0:5000"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.registry.rule=Host(`docker.seedno.de`)"
      - "traefik.http.routers.registry.entrypoints=https"
      - "traefik.http.routers.registry.service=registry"
      - "traefik.http.routers.registry.tls=true"
      - "traefik.http.routers.registry.tls.certresolver=letsencrypt"
      - "traefik.http.routers.registry.middlewares=compress,secure"
      - "traefik.http.services.registry.loadbalancer.server.port=5000"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/registry/data
        target: /var/lib/registry

  minecraft:
    image: itzg/minecraft-server:latest
    container_name: minecraft
    restart: always
    environment:
      - "VERSION=1.17.1"
      - "ONLINE_MODE=true"
      - "OVERRIDE_SERVER_PROPERTIES=true"
      - "SERVER_NAME=Seednode's Safe Space"
      - "SERVER_PORT=25565"
      - "MEMORY=4G"
      - "MAX_PLAYERS=32"
      - "ENABLE_COMMAND_BLOCK=false"
      - "FORCE_GAMEMODE=true"
      - "MODE=survival"
      - "MOTD=Welcome to Hell."
      - "EULA=TRUE"
      - "TYPE=PAPER"
      - "UID=${UID}"
      - "GID=${GID}"
      - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=false"
    ports:
      - "25565:25565"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/minecraft/1.17.1
        target: /data

  dokuwiki:
    image: ghcr.io/linuxserver/dokuwiki
    container_name: dokuwiki
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=America/Chicago"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.dokuwiki.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' https: data:; media-src 'self' https: data:"
      - "traefik.http.routers.dokuwiki.rule=Host(`dokuwiki.seedno.de`)"
      - "traefik.http.routers.dokuwiki.entrypoints=https"
      - "traefik.http.routers.dokuwiki.service=dokuwiki"
      - "traefik.http.routers.dokuwiki.tls=true"
      - "traefik.http.routers.dokuwiki.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dokuwiki.middlewares=compress,secure,dokuwiki"
      - "traefik.http.services.dokuwiki.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/dokuwiki/config
        target: /config

  mediawiki:
    image: mediawiki
    container_name: mediawiki
    restart: always
    depends_on:
      - mediawiki-db
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.mediawiki.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' https: data:; media-src 'self' https: data:"
      - "traefik.http.routers.mediawiki.rule=Host(`mediawiki.seedno.de`)"
      - "traefik.http.routers.mediawiki.entrypoints=https"
      - "traefik.http.routers.mediawiki.service=mediawiki"
      - "traefik.http.routers.mediawiki.tls=true"
      - "traefik.http.routers.mediawiki.tls.certresolver=letsencrypt"
      - "traefik.http.routers.mediawiki.middlewares=compress,secure,mediawiki,whitelist@file"
      - "traefik.http.services.mediawiki.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/mediawiki/config/LocalSettings.php
        target: /var/www/html/LocalSettings.php
      - type: bind
        source: /docker/mediawiki/images
        target: /var/www/html/images

  # MEDIAWIKI_DB_USER and MEDIAWIKI_DB_PASS should be set in a file named .env in the same directory as docker-compose.yml
  mediawiki-db:
    image: ghcr.io/linuxserver/mariadb
    container_name: mediawiki-db
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=America/Chicago"
      - "MYSQL_DATABASE=mediawiki"
      - "MYSQL_USER=${MEDIAWIKI_DB_USER}"
      - "MYSQL_PASSWORD=${MEDIAWIKI_DB_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/mediawiki/database
        target: /config

  keycloak:
    image: quay.io/keycloak/keycloak:14.0.0
    container_name: keycloak
    restart: always
    depends_on:
      - keycloak-db
    environment:
      - "KEYCLOAK_USER=${KEYCLOAK_USER}"
      - "KEYCLOAK_PASSWORD=${KEYCLOAK_PASS}"
      - "DB_VENDOR=postgres"
      - "DB_ADDR=keycloak-db"
      - "DB_PORT=5432"
      - "DB_DATABASE=${KEYCLOAK_DATABASE_NAME}"
      - "DB_USER=${KEYCLOAK_DATABASE_USER}"
      - "DB_PASSWORD=${KEYCLOAK_DATABASE_PASS}"
      - "PROXY_ADDRESS_FORWARDING=true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.keycloak.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'"
      - "traefik.http.routers.keycloak.rule=Host(`keycloak.seedno.de`)"
      - "traefik.http.routers.keycloak.entrypoints=https"
      - "traefik.http.routers.keycloak.service=keycloak"
      - "traefik.http.routers.keycloak.tls=true"
      - "traefik.http.routers.keycloak.tls.certresolver=letsencrypt"
      - "traefik.http.routers.keycloak.middlewares=compress,secure,keycloak"
      - "traefik.http.services.keycloak.loadbalancer.server.port=8080"
    networks:
      - traefik

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - KEYCLOAK_DATABASE_NAME
  # - KEYCLOAK_DATABASE_USER
  # - KEYCLOAK_DATABASE_PASS
  keycloak-db:
    image: postgres:13-alpine
    container_name: keycloak-db
    restart: always
    environment:
      - "POSTGRES_DB=${KEYCLOAK_DATABASE_NAME}"
      - "POSTGRES_USER=${KEYCLOAK_DATABASE_USER}"
      - "POSTGRES_PASSWORD=${KEYCLOAK_DATABASE_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/keycloak/database
        target: /var/lib/postgresql/data

  owncast:
    image: gabekangas/owncast:latest
    container_name: owncast
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.owncast.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' blob:; img-src 'self' data:; font-src 'self' data:; media-src 'self' blob:"
      - "traefik.http.routers.owncast.rule=Host(`stream.seedno.de`)"
      - "traefik.http.routers.owncast.entrypoints=https"
      - "traefik.http.routers.owncast.service=owncast"
      - "traefik.http.routers.owncast.tls=true"
      - "traefik.http.routers.owncast.tls.certresolver=letsencrypt"
      - "traefik.http.routers.owncast.middlewares=compress,secure,owncast"
      - "traefik.http.services.owncast.loadbalancer.server.port=8080"
    ports:
      - "1935:1935"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/owncast/data
        target: /app/data

  archiveteam:
    image: atdr.meo.ws/archiveteam/warrior-dockerfile
    container_name: archiveteam
    restart: always
    depends_on:
      - watchtower
    environment:
      - "CONCURRENT_ITEMS=6"
      - "DOWNLOADER=Seednode"
      - "HTTP_USERNAME=${ARCHIVETEAM_USERNAME}"
      - "HTTP_PASSWORD=${ARCHIVETEAM_PASSWORD}"
      - "SELECTED_PROJECT=auto"
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "traefik.enable=true"
      - "traefik.http.routers.archiveteam.rule=Host(`warrior.crimson.seedno.de`)"
      - "traefik.http.routers.archiveteam.entrypoints=https"
      - "traefik.http.routers.archiveteam.service=archiveteam"
      - "traefik.http.routers.archiveteam.tls=true"
      - "traefik.http.routers.archiveteam.tls.certresolver=letsencrypt"
      - "traefik.http.routers.archiveteam.middlewares=compress,secure,whitelist@file"
      - "traefik.http.services.archiveteam.loadbalancer.server.port=8001"
    networks:
      - traefik

  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: always
    command:
      - "--label-enable"
      - "--cleanup"
      - "--interval=3600"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - INVIDIOUS_DATABASE_NAME
  # - INVIDIOUS_DATABASE_USER
  # - INVIDIOUS_DATABASE_PASS
  invidious:
    image: quay.io/invidious/invidious:latest
    container_name: invidious
    restart: always
    depends_on:
      - invidious-db
    environment:
      INVIDIOUS_CONFIG: |
        channel_threads: 1
        check_tables: true
        feed_threads: 1
        db:
          user: ${INVIDIOUS_DATABASE_USER}
          password: ${INVIDIOUS_DATABASE_PASS}
          host: invidious-db
          port: 5432
          dbname: ${INVIDIOUS_DATABASE_NAME}
        full_refresh: false
        https_only: false
        domain: invidious.seedno.de
    labels:
      - "traefik.http.routers.invidious.rule=Host(`invidious.seedno.de`)"
      - "traefik.http.routers.invidious.entrypoints=https"
      - "traefik.http.routers.invidious.service=invidious"
      - "traefik.http.routers.invidious.tls=true"
      - "traefik.http.routers.invidious.tls.certresolver=letsencrypt"
      - "traefik.http.routers.invidious.middlewares=adminauth,compress,secure"
      - "traefik.http.services.invidious.loadbalancer.server.port=3000"
    networks:
      - traefik

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - INVIDIOUS_DATABASE_NAME
  # - INVIDIOUS_DATABASE_USER
  # - INVIDIOUS_DATABASE_PASS
  invidious-db:
    image: postgres:13-alpine
    container_name: invidious-db
    restart: always
    environment:
      - "POSTGRES_DB=${INVIDIOUS_DATABASE_NAME}"
      - "POSTGRES_USER=${INVIDIOUS_DATABASE_USER}"
      - "POSTGRES_PASSWORD=${INVIDIOUS_DATABASE_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/invidious/database
        target: /var/lib/postgresql/data
      - type: bind
        source: /docker/invidious/sql
        target: /config/sql
      - type: bind
        source: /docker/invidious/scripts/init-invidious-db.sh
        target: /docker-entrypoint-initdb.d/init-invidious-db.sh
        read_only: true

  smokeping:
    image: ghcr.io/linuxserver/smokeping:latest
    container_name: smokeping
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.smokeping.headers.contentSecurityPolicy=default-src 'self'; img-src 'self' data:"
      - "traefik.http.routers.smokeping.rule=Host(`ping.seedno.de`)"
      - "traefik.http.routers.smokeping.entrypoints=https"
      - "traefik.http.routers.smokeping.service=smokeping"
      - "traefik.http.routers.smokeping.tls=true"
      - "traefik.http.routers.smokeping.tls.certresolver=letsencrypt"
      - "traefik.http.routers.smokeping.middlewares=compress,secure,smokeping"
      - "traefik.http.services.smokeping.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/smokeping/config
        target: /config
        read_only: true
      - type: bind
        source: /docker/smokeping/data
        target: /data

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - DRAWIO_KEYSTORE_PASSS
  # - DRAWIO_KEY_PASS
  drawio:
    image: jgraph/drawio:latest
    container_name: drawio
    restart: always
    environment:
      - "KEYSTORE_PASS=${DRAWIO_KEYSTORE_PASS}"
      - "KEY_PASS=${DRAWIO_KEY_PASS}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.drawio.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://www.draw.io/notifications"
      - "traefik.http.routers.drawio.rule=Host(`draw.seedno.de`)"
      - "traefik.http.routers.drawio.entrypoints=https"
      - "traefik.http.routers.drawio.service=drawio"
      - "traefik.http.routers.drawio.tls=true"
      - "traefik.http.routers.drawio.tls.certresolver=letsencrypt"
      - "traefik.http.routers.drawio.middlewares=compress,secure,drawio"
      - "traefik.http.services.drawio.loadbalancer.server.port=8080"
    networks:
      - traefik

  # Note: "proxy_set_header X-Forwarded-for $remote_addr;" must be commented out in /config/nginx/site-confs/default, due to how traefik handles the header value
  snapdrop:
    image: ghcr.io/linuxserver/snapdrop
    container_name: snapdrop
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.snapdrop.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'sha256-biLFinpqYMtWHmXfkA1BPeCY0/fNt46SAZ+BBk5YUog='; style-src-attr 'self' 'unsafe-inline'"
      - "traefik.http.routers.snapdrop.rule=Host(`drop.seedno.de`)"
      - "traefik.http.routers.snapdrop.entrypoints=https"
      - "traefik.http.routers.snapdrop.service=snapdrop"
      - "traefik.http.routers.snapdrop.tls=true"
      - "traefik.http.routers.snapdrop.tls.certresolver=letsencrypt"
      - "traefik.http.routers.snapdrop.middlewares=compress,secure,snapdrop"
      - "traefik.http.services.snapdrop.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/snapdrop/config
        target: /config

  sflow-exporter:
    image: sflow/host-sflow:latest
    container_name: sflow-exporter
    restart: always
    environment:
      - "COLLECTOR=flows.seedno.de"
      - "DROPMON=enable"
      - "NET=host"
      - "POLLING=20"
      - "PORT=6343"
      - "SAMPLING=1000"
    labels:
      - "traefik.enable=false"
    network_mode: host
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
        read_only: true

  sflow-collector:
    image: sflow/prometheus:latest
    container_name: sflow-collector
    restart: always
    environment:
      - "RTMEM=2G"
    command:
      - "-Dsnmp.ifname=yes"
      - "-Dgeo.country=resources/config/GeoLite2-Country.mmdb"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.sflow.headers.contentSecurityPolicy=default-src 'self'"
      - "traefik.http.routers.sflow.rule=Host(`flows.seedno.de`)"
      - "traefik.http.routers.sflow.entrypoints=https"
      - "traefik.http.routers.sflow.service=sflow"
      - "traefik.http.routers.sflow.tls=true"
      - "traefik.http.routers.sflow.tls.certresolver=letsencrypt"
      - "traefik.http.routers.sflow.middlewares=adminauth,compress,secure,sflow,whitelist@file"
      - "traefik.http.services.sflow.loadbalancer.server.port=8008"
    ports:
      - "10.25.0.1:6343:6343/udp"
    networks:
      - traefik

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: always
    environment:
      - "GF_ALERTING_ENABLED=false"
      - "GF_AUTH_ANONYMOUS_ENABLED=false"
      - "GF_DEFAULT_INSTANCE_NAME=grafana.seedno.de"
      - "GF_INSTALL_PLUGINS=grafana-piechart-panel,grafana-clock-panel"
      - "GF_METRICS_ENABLED=true"
      - "GF_SECURITY_COOKIE_SECURE=true"
      - "GF_SECURITY_DISABLE_GRAVATAR=true"
      - "GF_SECURITY_ALLOW_EMBEDDING=false"
      - "GF_SERVER_DOMAIN=grafana.seedno.de"
      - "GF_SERVER_ENFORCE_DOMAIN=true"
      - "GF_SERVER_HTTP_PORT=3000"
      - "GF_SERVER_HTTP_PROTOCOL=https"
      - "GF_SERVER_ROOT_URL=https://grafana.seedno.de/"
      - "GF_SERVER_SERVE_FROM_SUB_PATH=false"
      - "GF_SNAPSHOTS_EXTERNAL_ENABLED=false"
      - "GF_USERS_ALLOW_SIGN_UP=false"
      - "GF_USERS_VIEWERS_CAN_EDIT=false"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.grafana.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:"
      - "traefik.http.routers.grafana.rule=Host(`grafana.seedno.de`)"
      - "traefik.http.routers.grafana.entrypoints=https"
      - "traefik.http.routers.grafana.service=grafana"
      - "traefik.http.routers.grafana.tls=true"
      - "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
      - "traefik.http.routers.grafana.middlewares=grafana,compress,secure,whitelist@file"
      - "traefik.http.services.grafana.loadbalancer.server.port=3000"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/grafana/data
        target: /var/lib/grafana

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: always
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=30d"
      - "--web.console.libraries=/usr/share/prometheus/console_libraries"
      - "--web.console.templates=/usr/share/prometheus/consoles"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/prometheus/config/prometheus.yml
        target: /etc/prometheus/prometheus.yml
        read_only: true
      - type: bind
        source: /docker/prometheus/data
        target: /prometheus

  irc:
    image: ghcr.io/linuxserver/thelounge:latest
    container_name: irc
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.irc.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='"
      - "traefik.http.routers.irc.rule=Host(`chat.seedno.de`)"
      - "traefik.http.routers.irc.entrypoints=https"
      - "traefik.http.routers.irc.service=irc"
      - "traefik.http.routers.irc.tls=true"
      - "traefik.http.routers.irc.tls.certresolver=letsencrypt"
      - "traefik.http.routers.irc.middlewares=compress,secure,irc"
      - "traefik.http.services.irc.loadbalancer.server.port=9000"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/thelounge/config
        target: /config

  # The config file is located inside the container at /config/www/nextcloud/config/config.php
  nextcloud:
    image: ghcr.io/linuxserver/nextcloud
    container_name: nextcloud
    restart: always
    depends_on:
      - nextcloud-db
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nextcloud.rule=Host(`cloud.seedno.de`)"
      - "traefik.http.routers.nextcloud.entrypoints=https"
      - "traefik.http.routers.nextcloud.service=nextcloud"
      - "traefik.http.routers.nextcloud.tls=true"
      - "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
      - "traefik.http.routers.nextcloud.middlewares=compress,secure,nextcloud@file"
      - "traefik.http.services.nextcloud.loadbalancer.server.port=443"
      - "traefik.http.services.nextcloud.loadbalancer.server.scheme=https"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/nextcloud/config
        target: /config
      - type: bind
        source: /docker/nextcloud/data
        target: /data

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - NEXTCLOUD_DATABASE_NAME
  # - NEXTCLOUD_DATABASE_USER
  # - NEXTCLOUD_DATABASE_PASS
  nextcloud-db:
    image: postgres:13-alpine
    container_name: nextcloud-db
    restart: always
    environment:
      - "POSTGRES_DB=${NEXTCLOUD_DATABASE_NAME}"
      - "POSTGRES_USER=${NEXTCLOUD_DATABASE_USER}"
      - "POSTGRES_PASSWORD=${NEXTCLOUD_DATABASE_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/nextcloud/database
        target: /var/lib/postgresql/data

  jellyfin:
    image: ghcr.io/linuxserver/jellyfin
    container_name: jellyfin
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "JELLYFIN_PublishedServerUrl=watch.seedno.de"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.jellyfin.rule=Host(`watch.seedno.de`)"
      - "traefik.http.routers.jellyfin.entrypoints=https"
      - "traefik.http.routers.jellyfin.service=jellyfin"
      - "traefik.http.routers.jellyfin.tls=true"
      - "traefik.http.routers.jellyfin.tls.certresolver=letsencrypt"
      - "traefik.http.routers.jellyfin.middlewares=compress,secure"
      - "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
      - /dev/dri/card0:/dev/dri/card0
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/jellyfin/config
        target: /config
      - type: bind
        source: /storage/hevc
        target: /data/miscellaneous
        read_only: true
      - type: bind
        source: /storage/media/movies
        target: /data/movies
        read_only: true
      - type: bind
        source: /storage/media/screencasts
        target: /data/screencasts
        read_only: true
      - type: bind
        source: /storage/media/streams
        target: /data/streams
        read_only: true
      - type: bind
        source: /storage/media/tvshows
        target: /data/tvshows
        read_only: true
      - type: bind
        source: /storage/media/videos
        target: /data/videos
        read_only: true
      - type: bind
        source: /storage/youtube
        target: /data/youtube
        read_only: true

  cyberchef:
    image: mpepping/cyberchef:latest
    container_name: cyberchef
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.cyberchef.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; object-src 'self' data:; frame-src 'self' data:; worker-src 'self' blob: data:"
      - "traefik.http.routers.cyberchef.rule=Host(`tools.seedno.de`)"
      - "traefik.http.routers.cyberchef.entrypoints=https"
      - "traefik.http.routers.cyberchef.service=cyberchef"
      - "traefik.http.routers.cyberchef.tls=true"
      - "traefik.http.routers.cyberchef.tls.certresolver=letsencrypt"
      - "traefik.http.routers.cyberchef.middlewares=compress,secure,cyberchef"
      - "traefik.http.services.cyberchef.loadbalancer.server.port=8000"
    networks:
      - traefik

  element:
    image: vectorim/element-web
    container_name: element
    restart: always
    depends_on:
      - synapse
      - synapse-db
    environment:
      - "VIRTUAL_PORT=80"
      - "VIRTUAL_HOST=element.seedno.de"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.element.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https:; img-src 'self' data: https:; media-src 'self' https:"
      - "traefik.http.routers.element.rule=Host(`element.seedno.de`)"
      - "traefik.http.routers.element.entrypoints=https"
      - "traefik.http.routers.element.service=element"
      - "traefik.http.routers.element.tls=true"
      - "traefik.http.routers.element.tls.certresolver=letsencrypt"
      - "traefik.http.routers.element.middlewares=compress,secure,element"
      - "traefik.http.services.element.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/element/config/config.json
        target: /usr/share/nginx/html/config.element.seedno.de.json
        read_only: true
 
  synapse:
    image: matrixdotorg/synapse:latest
    container_name: synapse
    restart: always
    depends_on:
      - synapse-db
    environment:
      - "SYNAPSE_CONFIG_DIR=/data"
      - "SYNAPSE_CONFIG_PATH=/data/homeserver.yaml"
      - "UID=${UID}"
      - "GID=${GID}"
      - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.synapse.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'"
      - "traefik.http.routers.synapse.rule=Host(`matrix.seedno.de`)"
      - "traefik.http.routers.synapse.entrypoints=https"
      - "traefik.http.routers.synapse.service=synapse"
      - "traefik.http.routers.synapse.tls=true"
      - "traefik.http.routers.synapse.tls.certresolver=letsencrypt"
      - "traefik.http.routers.synapse.middlewares=compress,secure,synapse"
      - "traefik.http.services.synapse.loadbalancer.server.port=8008"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/synapse/data
        target: /data
      - type: bind
        source: /docker/synapse/media
        target: /data/media
      - type: bind
        source: /docker/synapse/uploads
        target: /data/uploads

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - SYNAPSE_DB_USER
  # - SYNAPSE_DB_PASS
  synapse-db:
    image: postgres:12-alpine
    container_name: synapse-db
    restart: always
    environment:
      - "POSTGRES_DB=synapse"
      - "POSTGRES_USER=${SYNAPSE_DB_USER}"
      - "POSTGRES_PASSWORD=${SYNAPSE_DB_PASS}"
      - "POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/synapse/database
        target: /var/lib/postgresql/data

  pastebin:
    image: mkaczanowski/pastebin
    container_name: pastebin
    restart: always
    command:
      - "--address=0.0.0.0"
      - "--port=8000"
      - "--db=/data/pastebin.db"
      - "--uri=https://paste.seedno.de"
      - "--slug-len=12"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.pastebin.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' https://cdnjs.cloudflare.com; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self' data:"
      - "traefik.http.routers.pastebin.rule=Host(`paste.seedno.de`)"
      - "traefik.http.routers.pastebin.entrypoints=https"
      - "traefik.http.routers.pastebin.service=pastebin"
      - "traefik.http.routers.pastebin.tls=true"
      - "traefik.http.routers.pastebin.tls.certresolver=letsencrypt"
      - "traefik.http.routers.pastebin.middlewares=compress,secure,pastebin"
      - "traefik.http.services.pastebin.loadbalancer.server.port=8000"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/pastebin/data
        target: /data

  hastebin:
    image: angristan/hastebin:latest
    container_name: hastebin
    restart: always
    environment:
      - "UID=${UID}"
      - "GID=${GID}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.hastebin.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' ajax.googleapis.com"
      - "traefik.http.routers.hastebin.rule=Host(`haste.seedno.de`)"
      - "traefik.http.routers.hastebin.entrypoints=https"
      - "traefik.http.routers.hastebin.service=hastebin"
      - "traefik.http.routers.hastebin.tls=true"
      - "traefik.http.routers.hastebin.tls.certresolver=letsencrypt"
      - "traefik.http.routers.hastebin.middlewares=compress,secure,hastebin"
      - "traefik.http.services.hastebin.loadbalancer.server.port=7777"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/hastebin/data
        target: /app/data

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - VAULTWARDEN_DB_USER
  # - VAULTWARDEN_DB_PASS
  vaultwarden:
    image: vaultwarden/server:alpine
    container_name: vaultwarden
    restart: always
    depends_on:
      - vaultwarden-db
    environment:
      - "DATABASE_URL=postgresql://${VAULTWARDEN_DB_USER}:${VAULTWARDEN_DB_PASS}@vaultwarden-db:5432/bitwarden"
      - "DOMAIN=https://vault.seedno.de"
      - "WEBSOCKET_ENABLED=false"
      - "SIGNUPS_ALLOWED=false"
      - "INVITATIONS_ALLOWED=false"
      - "SHOW_PASSWORD_HINT=false"
      - "TRASH_AUTO_DELETE_DAYS=30"
      - "LOG_FILE=/data/vaultwarden.log"
      - "ROCKET_PORT=80"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.vaultwarden.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; img-src 'self' data:"
      - "traefik.http.routers.vaultwarden.rule=Host(`vault.seedno.de`)"
      - "traefik.http.routers.vaultwarden.entrypoints=https"
      - "traefik.http.routers.vaultwarden.service=vaultwarden"
      - "traefik.http.routers.vaultwarden.tls=true"
      - "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
      - "traefik.http.routers.vaultwarden.middlewares=compress,secure,vaultwarden"
      - "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/vaultwarden/data
        target: /data

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - VAULTWARDEN_DB_USER
  # - VAULTWARDEN_DB_PASS
  vaultwarden-db:
    image: postgres:13-alpine
    container_name: vaultwarden-db
    restart: always
    environment:
      - "POSTGRES_DB=bitwarden"
      - "POSTGRES_USER=${VAULTWARDEN_DB_USER}"
      - "POSTGRES_PASSWORD=${VAULTWARDEN_DB_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/vaultwarden/database
        target: /var/lib/postgresql/data

  nginx:
    image: docker.seedno.de/seednode/nginx-php:latest
    container_name: nginx
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.accessseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' data:"
      - "traefik.http.routers.accessseednode.rule=Host(`access.seedno.de`)"
      - "traefik.http.routers.accessseednode.entrypoints=https"
      - "traefik.http.routers.accessseednode.service=nginx"
      - "traefik.http.routers.accessseednode.tls=true"
      - "traefik.http.routers.accessseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.accessseednode.middlewares=adminauth,compress,secure,accessseednode,whitelist@file"
      - "traefik.http.middlewares.cdnseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline' https://seedno.de; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net blob:; img-src 'self' https://seedno.de; media-src 'self' blob:"
      - "traefik.http.routers.cdnseednode.rule=Host(`cdn.seedno.de`)"
      - "traefik.http.routers.cdnseednode.entrypoints=https"
      - "traefik.http.routers.cdnseednode.service=nginx"
      - "traefik.http.routers.cdnseednode.tls=true"
      - "traefik.http.routers.cdnseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.cdnseednode.middlewares=compress,secure,cdnseednode"
      - "traefik.http.middlewares.decoseednode.headers.contentSecurityPolicy=default-src 'self'"
      - "traefik.http.routers.decoseednode.rule=Host(`deco.seedno.de`)"
      - "traefik.http.routers.decoseednode.entrypoints=https"
      - "traefik.http.routers.decoseednode.service=nginx"
      - "traefik.http.routers.decoseednode.tls=true"
      - "traefik.http.routers.decoseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.decoseednode.middlewares=compress,secure,decoseednode"
      - "traefik.http.routers.devseednode.rule=Host(`dev.seedno.de`)"
      - "traefik.http.routers.devseednode.entrypoints=https"
      - "traefik.http.routers.devseednode.service=nginx"
      - "traefik.http.routers.devseednode.tls=true"
      - "traefik.http.routers.devseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.devseednode.middlewares=compress,secure"
      - "traefik.http.routers.flashseednode.rule=Host(`flash.seedno.de`)"
      - "traefik.http.routers.flashseednode.entrypoints=https"
      - "traefik.http.routers.flashseednode.service=nginx"
      - "traefik.http.routers.flashseednode.tls=true"
      - "traefik.http.routers.flashseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.flashseednode.middlewares=compress,secure"
      - "traefik.http.middlewares.frozenbutthangcom.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' https://seedno.de; img-src 'self' https://seedno.de"
      - "traefik.http.routers.frozenbutthangcom.rule=Host(`frozenbutthang.com`) || Host(`www.frozenbutthang.com`)"
      - "traefik.http.routers.frozenbutthangcom.entrypoints=https"
      - "traefik.http.routers.frozenbutthangcom.service=nginx"
      - "traefik.http.routers.frozenbutthangcom.tls=true"
      - "traefik.http.routers.frozenbutthangcom.tls.certresolver=letsencrypt"
      - "traefik.http.routers.frozenbutthangcom.middlewares=compress,secure,frozenbutthangcom"
      - "traefik.http.middlewares.gpgseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'"
      - "traefik.http.routers.gpgseednode.rule=Host(`gpg.seedno.de`)"
      - "traefik.http.routers.gpgseednode.entrypoints=https"
      - "traefik.http.routers.gpgseednode.service=nginx"
      - "traefik.http.routers.gpgseednode.tls=true"
      - "traefik.http.routers.gpgseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.gpgseednode.middlewares=compress,secure,gpgseednode"
      - "traefik.http.middlewares.indexseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline' https://seedno.de; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net blob:; img-src 'self' https://seedno.de; media-src 'self' blob:"
      - "traefik.http.routers.indexseednode.rule=Host(`index.seedno.de`)"
      - "traefik.http.routers.indexseednode.entrypoints=https"
      - "traefik.http.routers.indexseednode.service=nginx"
      - "traefik.http.routers.indexseednode.tls=true"
      - "traefik.http.routers.indexseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.indexseednode.middlewares=adminauth,compress,secure,indexseednode,whitelist@file"
      - "traefik.http.middlewares.jaegerseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' data:"
      - "traefik.http.routers.jaegerseednode.rule=Host(`jaeger.seedno.de`)"
      - "traefik.http.routers.jaegerseednode.entrypoints=https"
      - "traefik.http.routers.jaegerseednode.service=nginx"
      - "traefik.http.routers.jaegerseednode.tls=true"
      - "traefik.http.routers.jaegerseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.jaegerseednode.middlewares=compress,secure,jaegerseednode"
      - "traefik.http.middlewares.localhostseednode.headers.contentSecurityPolicy=default-src 'self'"
      - "traefik.http.routers.localhostseednode.rule=Host(`localhost.seedno.de`)"
      - "traefik.http.routers.localhostseednode.entrypoints=https"
      - "traefik.http.routers.localhostseednode.service=nginx"
      - "traefik.http.routers.localhostseednode.tls=true"
      - "traefik.http.routers.localhostseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.localhostseednode.middlewares=compress,secure,localhostseednode"
      - "traefik.http.middlewares.matrixseednode.headers.contentSecurityPolicy=default-src 'self'"
      - "traefik.http.routers.matrixseednode.rule=Host(`matrix.seedno.de`) && PathPrefix(`/.well-known/matrix/`)"
      - "traefik.http.routers.matrixseednode.entrypoints=https"
      - "traefik.http.routers.matrixseednode.service=nginx"
      - "traefik.http.routers.matrixseednode.tls=true"
      - "traefik.http.routers.matrixseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.matrixseednode.middlewares=compress,secure,matrixseednode"
      - "traefik.http.middlewares.mirrorseednode.headers.contentSecurityPolicy=default-src 'self' 'unsafe-inline' https:"
      - "traefik.http.routers.mirrorseednode.rule=Host(`mirror.seedno.de`)"
      - "traefik.http.routers.mirrorseednode.entrypoints=https"
      - "traefik.http.routers.mirrorseednode.service=nginx"
      - "traefik.http.routers.mirrorseednode.tls=true"
      - "traefik.http.routers.mirrorseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.mirrorseednode.middlewares=adminauth,compress,secure,mirrorseednode"
      - "traefik.http.middlewares.picsseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' data:"
      - "traefik.http.routers.picsseednode.rule=Host(`pics.seedno.de`)"
      - "traefik.http.routers.picsseednode.entrypoints=https"
      - "traefik.http.routers.picsseednode.service=nginx"
      - "traefik.http.routers.picsseednode.tls=true"
      - "traefik.http.routers.picsseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.picsseednode.middlewares=compress,secure,picsseednode"
      - "traefik.http.middlewares.seednode.headers.contentSecurityPolicy=default-src 'self'; script-src 'self' 'sha256-CrLg5HEtxiJtWQPNGCzTFSY0zEk6/BoA7pa7TdC2KzQ='"
      - "traefik.http.middlewares.seednode.headers.customresponseheaders.Cross-Origin-Embedder-Policy=require-corp; report-to=default"
      - "traefik.http.middlewares.seednode.headers.customresponseheaders.Cross-Origin-Opener-Policy=same-origin; report-to=default"
      - "traefik.http.middlewares.seednode.headers.customresponseheaders.Cross-Origin-Resource-Policy=same-origin"
      - "traefik.http.routers.seednode.rule=Host(`seedno.de`) || Host(`www.seedno.de`)"
      - "traefik.http.routers.seednode.priority=1"
      - "traefik.http.routers.seednode.entrypoints=https"
      - "traefik.http.routers.seednode.service=nginx"
      - "traefik.http.routers.seednode.tls=true"
      - "traefik.http.routers.seednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.seednode.middlewares=compress,secure,seednode"
      - "traefik.http.middlewares.streammods.headers.contentSecurityPolicy=default-src 'self' 'unsafe-inline' https:"
      - "traefik.http.routers.streammods.rule=Host(`stream.seedno.de`) && (PathPrefix(`/mods/`) || Path(`/{mods:mods.*html}`))"
      - "traefik.http.routers.streammods.entrypoints=https"
      - "traefik.http.routers.streammods.service=nginx"
      - "traefik.http.routers.streammods.tls=true"
      - "traefik.http.routers.streammods.tls.certresolver=letsencrypt"
      - "traefik.http.routers.streammods.middlewares=friendsauth,compress,secure,streammods"
      - "traefik.http.middlewares.streamseednode.headers.contentSecurityPolicy=default-src 'self' 'unsafe-inline' https:"
      - "traefik.http.routers.streamseednode.rule=Host(`stream.seedno.de`) && PathPrefix(`/vods/`)"
      - "traefik.http.routers.streamseednode.entrypoints=https"
      - "traefik.http.routers.streamseednode.service=nginx"
      - "traefik.http.routers.streamseednode.tls=true"
      - "traefik.http.routers.streamseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.streamseednode.middlewares=compress,secure,streamseednode"
      - "traefik.http.middlewares.ttyseednode.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'sha256-k8Gt4ydPyZBh2YfRzVWrh7031fvz/VI3cHeGzcyXNR0=' 'sha256-VwEY7val4b+j8yqYQs9EMxGA1WRNoWDizHNeHzHCjAU=' 'sha256-ZjbbycUVTww9AXSPtpbF6WEV6bbCMIwMXlb/vq8bQRI=' https://seedno.de; img-src 'self' https://seedno.de; media-src 'self' data:"
      - "traefik.http.routers.ttyseednode.rule=Host(`tty.seedno.de`)"
      - "traefik.http.routers.ttyseednode.entrypoints=https"
      - "traefik.http.routers.ttyseednode.service=nginx"
      - "traefik.http.routers.ttyseednode.tls=true"
      - "traefik.http.routers.ttyseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.ttyseednode.middlewares=compress,secure,ttyseednode"
      - "traefik.http.middlewares.youtubeseednode.headers.contentSecurityPolicy=default-src 'self' 'unsafe-inline' https:"
      - "traefik.http.routers.youtubeseednode.rule=Host(`youtube.seedno.de`)"
      - "traefik.http.routers.youtubeseednode.entrypoints=https"
      - "traefik.http.routers.youtubeseednode.service=nginx"
      - "traefik.http.routers.youtubeseednode.tls=true"
      - "traefik.http.routers.youtubeseednode.tls.certresolver=letsencrypt"
      - "traefik.http.routers.youtubeseednode.middlewares=adminauth,compress,secure,youtubeseednode"
      - "traefik.http.services.nginx.loadbalancer.server.port=80"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/nginx/config
        target: /etc/nginx
        read_only: true
      - type: bind
        source: /docker/nginx/logs
        target: /var/log/nginx
      - type: bind
        source: /storage
        target: /storage
        read_only: true
      - type: bind
        source: /var/www/html
        target: /var/www/html
        read_only: true

  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: always
    depends_on:
      - gitea-db
    environment:
      - "TMPDIR=/data/backups"
      - "USER_UID=${UID}"
      - "USER_GID=${GID}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.gitea.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' https: data:; manifest-src 'self' data:"
      - "traefik.http.routers.gitea.rule=Host(`git.seedno.de`)"
      - "traefik.http.routers.gitea.entrypoints=https"
      - "traefik.http.routers.gitea.service=gitea"
      - "traefik.http.routers.gitea.tls=true"
      - "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
      - "traefik.http.routers.gitea.middlewares=compress,secure,gitea"
      - "traefik.http.services.gitea.loadbalancer.server.port=3000"
    ports:
      - "9023:22"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/gitea/data
        target: /data
      - type: bind
        source: /etc/localtime
        target: /etc/localtime
        read_only: true
      - type: bind
        source: /docker/gitea/conf/sshd_config
        target: /etc/ssh/sshd_config
        read_only: true

  # The following variables should be set in a file named .env in the same directory as docker-compose.yml:
  # - GITEA_DB_USER
  # - GITEA_DB_PASS
  gitea-db:
    image: postgres:13-alpine
    container_name: gitea-db
    restart: always
    environment:
      - "POSTGRES_DB=gitea"
      - "POSTGRES_USER=${GITEA_DB_USER}"
      - "POSTGRES_PASSWORD=${GITEA_DB_PASS}"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/gitea/database
        target: /var/lib/postgresql/data

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
    container_name: elasticsearch
    restart: always
    environment:
      - "discovery.type=single-node"
      - "ES_JAVA_OPTS=-Xms1G -Xmx8G"
    labels:
      - "traefik.enable=false"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/elasticsearch/data
        target: /usr/share/elasticsearch/data

  qbittorrent:
    image: ghcr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "UMASK_SET=022"
      - "WEBUI_PORT=8080"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.qbittorrent.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'"
      - "traefik.http.routers.qbittorrent.rule=Host(`torrent.seedno.de`)"
      - "traefik.http.routers.qbittorrent.entrypoints=https"
      - "traefik.http.routers.qbittorrent.service=qbittorrent"
      - "traefik.http.routers.qbittorrent.tls=true"
      - "traefik.http.routers.qbittorrent.tls.certresolver=letsencrypt"
      - "traefik.http.routers.qbittorrent.middlewares=compress,secure,qbittorrent"
      - "traefik.http.services.qbittorrent.loadbalancer.server.port=8080"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/qbittorrent/config
        target: /config
      - type: bind
        source: /storage/media/torrents
        target: /downloads

  unifi:
    image: jacobalberty/unifi:latest
    container_name: unifi
    restart: always
    environment:
    - "BIND_PRIV=false"
    - "RUNAS_UID0=false"
    - "UNIFI_UID=${UID}"
    - "UNIFI_GID=${GID}"
    - "TZ=${TIMEZONE}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.unifi-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.unifi-redirect.redirectscheme.permanent=true"
      - "traefik.http.middlewares.unifi.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; img-src 'self' data: static.ubnt.com"
      - "traefik.http.routers.unifi.rule=Host(`unifi.seedno.de`)"
      - "traefik.http.routers.unifi.entrypoints=https"
      - "traefik.http.routers.unifi.tls=true"
      - "traefik.http.routers.unifi.tls.certresolver=letsencrypt"
      - "traefik.http.routers.unifi.middlewares=compress,secure,unifi-redirect,unifi,whitelist@file"
      - "traefik.http.services.unifi.loadbalancer.server.port=8443"
      - "traefik.http.services.unifi.loadbalancer.server.scheme=https"
    networks:
      - traefik
    ports:
      - "3478:3478/udp"
      - "8080:8080"
    volumes:
      - type: bind
        source: /docker/unifi/data
        target: /unifi

  syncthing:
    image: ghcr.io/linuxserver/syncthing:amd64-latest
    container_name: syncthing
    restart: always
    environment:
      - "PUID=${UID}"
      - "PGID=${GID}"
      - "TZ=${TIMEZONE}"
      - "UMASK_SET=022"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.syncthing.replacepathregex.regex=^/sync/(.*)"
      - "traefik.http.middlewares.syncthing.replacepathregex.replacement=/$$1"
      - "traefik.http.routers.syncthing.rule=Host(`seedno.de`) && PathPrefix(`/sync/`)"
      - "traefik.http.routers.syncthing.entrypoints=https"
      - "traefik.http.routers.syncthing.service=syncthing"
      - "traefik.http.routers.syncthing.tls=true"
      - "traefik.http.routers.syncthing.tls.certresolver=letsencrypt"
      - "traefik.http.routers.syncthing.middlewares=adminauth,compress,secure,syncthing,whitelist@file"
      - "traefik.http.services.syncthing.loadbalancer.server.port=8384"
    ports:
      - "22000:22000"
    networks:
      - traefik
    volumes:
      - type: bind
        source: /docker/syncthing/config
        target: /config
      - type: bind
        source: /home/sinc/Dropbox
        target: /home/sinc/Dropbox
      - type: bind
        source: /storage
        target: /storage
      - type: bind
        source: /var/www/html
        target: /var/www/html

networks:
  traefik:
    name: traefik
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br_traefik
    ipam:
      driver: default
      config:
        - subnet: 10.160.0.0/22