This place is not a place of honor... no highly esteemed deed is commemorated here... nothing valued is here.
What is here was dangerous and repulsive to us. This message is a warning about danger.
The danger is still present, in your time, as it was in ours.
The danger is unleashed only if you substantially disturb this place. This place is best shunned and left uninhabited.

## Please email lab@seedno.de with any questions about this file, or setting up any services therein
## The actual files are not a monolith like this one; this page is generated as a convenient reference

## 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

services:

  ### https://github.com/traefik/traefik
  ## Files for basicauth middleware should be generated with the following:
  # $ htpasswd -c "${filename}" "${username}"
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    environment:
      - "CF_DNS_API_TOKEN=${CLOUDFLARE_API_TOKEN:?not set}"
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--accesslog=true"
      - "--accesslog.bufferingsize=100"
      - "--accesslog.fields.names.StartUTC=drop"
      - "--accesslog.filepath=/var/log/access.log"
      - "--api"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53"
      - "--certificatesresolvers.letsencrypt.acme.storage=/certs/acme.json"
      - "--entrypoints.http.address=:80"
      - "--entrypoints.http.http.redirections.entrypoint.to=https"
      - "--entrypoints.http.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.https.address=:443"
      - "--entrypoints.https.http3"
      - "--entrypoints.metrics.address=:8082"
      - "--experimental.http3=true"
      - "--log.filePath=/var/log/traefik.log"
      - "--log.level=ERROR"
      - "--metrics.prometheus=true"
      - "--metrics.prometheus.addentrypointslabels=true"
      - "--metrics.prometheus.addserviceslabels=true"
      - "--metrics.prometheus.entrypoint=metrics"
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--providers.docker.network=traefik"
      - "--providers.file.directory=/conf"
      - "--providers.file.watch=true"
      - "--serverstransport.insecureskipverify=true"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.compress.compress=true"
      - "traefik.http.middlewares.compress.compress.excludedcontenttypes=video/mp4,video/mp2t,video/mpeg,video/quicktime,video/webm,video/x-m4v"
      - "traefik.http.middlewares.errors.errors.status=404,502,504"
      - "traefik.http.middlewares.errors.errors.service=errors"
      - "traefik.http.middlewares.errors.errors.query=/{status}.html"
      - "traefik.http.middlewares.adminauth.basicauth.usersfile=/conf/auth/admin"
      - "traefik.http.middlewares.familyauth.basicauth.usersfile=/conf/auth/family"
      - "traefik.http.middlewares.friendsauth.basicauth.usersfile=/conf/auth/friends"
      - "traefik.http.middlewares.ratelimit.ratelimit.average=25"
      - "traefik.http.middlewares.ratelimit.ratelimit.burst=1"
      - "traefik.http.middlewares.ratelimit.ratelimit.period=1"
      - "traefik.http.middlewares.ratelimit.ratelimit.sourcecriterion.requestheadername=X-Forwarded-For"
      - "traefik.http.middlewares.secure.headers.browserxssfilter=true"
      - "traefik.http.middlewares.secure.headers.contenttypenosniff=true"
      - "traefik.http.middlewares.secure.headers.customframeoptionsvalue=SAMEORIGIN"
      - "traefik.http.middlewares.secure.headers.customresponseheaders.Permissions-Policy=geolocation=(), midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(), payment=()"
      - "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.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.middlewares.secure.headers.customrequestheaders.X-Scheme=https"
      - "traefik.http.middlewares.secure.headers.forcestsheader=true"
      - "traefik.http.middlewares.secure.headers.framedeny=true"
      - "traefik.http.middlewares.secure.headers.referrerpolicy=strict-origin-when-cross-origin"
      - "traefik.http.middlewares.secure.headers.sslredirect=true"
      - "traefik.http.middlewares.secure.headers.stsincludesubdomains=true"
      - "traefik.http.middlewares.secure.headers.stspreload=true"
      - "traefik.http.middlewares.secure.headers.stsseconds=63072000"
      - "traefik.http.routers.traefik.rule=Host(`dashboard.crimson.seedno.de`)"
      - "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=errors,whitelist-vpn@file"
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    networks:
      - traefik
      - audio
      - code-server
      - commands
      - cyberchef
      - drawio
      - errors
      - gitea
      - grafana
      - hellpot
      - nature
      - naughty
      - nginx
      - prometheus
      - query
      - random
      - registry
      - roulette
      - rustpad
      - sflow
      - smokeping
      - sshwifty
      - syncthing
      - thelounge
      - trifecta
      - unifi
      - vaultwarden
      - whoami
    volumes:
      - type: bind
        source: /docker/traefik/certs
        target: /certs
      - type: bind
        source: /docker/traefik/config
        target: /conf
        read_only: true
      - type: bind
        source: /docker/traefik/logs
        target: /var/log
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
        read_only: true

  ### https://git.seedno.de/seednode/roulette
  audio:
    image: oci.seedno.de/seednode/roulette:latest
    container_name: audio
    restart: unless-stopped
    environment:
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--audio"
      - "--debug"
      - "--prefix=/random/"
      - "--recursive"
      - "--verbose"
      - "/data"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.audio.rule=Host(`voice.seedno.de`) && PathPrefix(`/random`)"
      - "traefik.http.routers.audio.entrypoints=https"
      - "traefik.http.routers.audio.service=audio"
      - "traefik.http.routers.audio.tls=true"
      - "traefik.http.routers.audio.tls.certresolver=letsencrypt"
      - "traefik.http.routers.audio.middlewares=compress,secure"
      - "traefik.http.services.audio.loadbalancer.server.port=8080"
    networks:
      - audio
    volumes:
      - type: bind
        source: /var/www/html/voice.seedno.de
        target: /data
        read_only: true

  ### https://github.com/coder/code-server
  code-server:
    image: lscr.io/linuxserver/code-server:latest
    container_name: code-server
    restart: unless-stopped
    privileged: true
    environment:
      PUID: ${UID:?not set}
      PGID: ${GID:?not set}
      SUDO_PASSWORD: ${CODE_SUDO_PASSWORD:?not set}
      TZ: ${TIMEZONE:?not set}
      DOCKER_MODS: "linuxserver/mods:code-server-dotnet|\
                    linuxserver/mods:code-server-extension-arguments|\
                    linuxserver/mods:code-server-golang|\
                    linuxserver/mods:code-server-java11|\
                    linuxserver/mods:code-server-julia|\
                    linuxserver/mods:code-server-nodejs|\
                    linuxserver/mods:code-server-php8|\
                    linuxserver/mods:code-server-powershell|\
                    linuxserver/mods:code-server-python3|\
                    linuxserver/mods:code-server-rust|\
                    linuxserver/mods:code-server-shellcheck|\
                    linuxserver/mods:code-server-terraform|\
                    linuxserver/mods:code-server-zsh|\
                    linuxserver/mods:universal-docker-in-docker"
      VSCODE_EXTENSION_IDS: "bungcip.better-toml|\
                             coolbear.systemd-unit-file|\
                             dbaeumer.vscode-eslint|\
                             esbenp.prettier-vscode|\
                             golang.go|\
                             julialang.language-julia|\
                             mads-hartmann.bash-ide-vscode|\
                             ms-azuretools.vscode-docker|\
                             ms-python.python|\
                             ms-vscode.PowerShell|\
                             muhammad-sammy.csharp|\
                             redhat.java|\
                             rust-lang.rust-analyzer|\
                             timonwong.shellcheck|\
                             ziglang.vscode-zig"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.code-server.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline' https://*.vscode-cdn.net; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.vscode-cdn.net; img-src 'self' data: https://*.vscode-cdn.net; connect-src 'self' https://open-vsx.org"
      - "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:
      - code-server
    volumes:
      - type: bind
        source: /docker/code-server/config
        target: /config
      - type: bind
        source: /home/sinc/code
        target: /config/workspace/code

  ### https://git.seedno.de/seednode/commands
  commands:
    image: oci.seedno.de/seednode/commands:latest
    container_name: commands
    restart: unless-stopped
    depends_on:
      - commands-db
    environment:
      - "COMMANDS_DB_TYPE=${COMMANDS_DB_TYPE:?not set}"
      - "COMMANDS_DB_HOST=${COMMANDS_DB_HOST:?not set}"
      - "COMMANDS_DB_PORT=${COMMANDS_DB_PORT:?not set}"
      - "COMMANDS_DB_USER=${COMMANDS_DB_USER:?not set}"
      - "COMMANDS_DB_PASS=${COMMANDS_DB_PASS:?not set}"
      - "COMMANDS_DB_NAME=${COMMANDS_DB_NAME:?not set}"
      - "COMMANDS_DB_TABLE=${COMMANDS_DB_TABLE:?not set}"
      - "COMMANDS_DB_SSL_MODE=${COMMANDS_DB_SSL_MODE:?not set}"
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--bind=0.0.0.0"
      - "--port=8080"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.commands.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline'"
      - "traefik.http.routers.commands.rule=Host(`commands.seedno.de`)"
      - "traefik.http.routers.commands.entrypoints=https"
      - "traefik.http.routers.commands.service=commands"
      - "traefik.http.routers.commands.tls=true"
      - "traefik.http.routers.commands.tls.certresolver=letsencrypt"
      - "traefik.http.routers.commands.middlewares=compress,errors,secure,commands,whitelist-vpn@file"
      - "traefik.http.services.commands.loadbalancer.server.port=8080"
    networks:
      - commands
      - commands-db

  commands-db:
    image: postgres:15-alpine
    container_name: commands-db
    restart: unless-stopped
    environment:
      - "POSTGRES_DB=${COMMANDS_DB_NAME:?not set}"
      - "POSTGRES_USER=${COMMANDS_DB_USER:?not set}"
      - "POSTGRES_PASSWORD=${COMMANDS_DB_PASS:?not set}"
    ports:
      - "127.0.0.1:5432:5432"
    networks:
      - commands-db
    volumes:
      - type: bind
        source: /docker/commands/database
        target: /var/lib/postgresql/data

  ### https://github.com/gchq/CyberChef
  cyberchef:
    image: mpepping/cyberchef:latest
    container_name: cyberchef
    restart: unless-stopped
    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,errors,secure,cyberchef"
      - "traefik.http.services.cyberchef.loadbalancer.server.port=8000"
    networks:
      - cyberchef

  ### https://github.com/jgraph/drawio
  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:
      - drawio

  ### https://git.seedno.de/seednode/docker-site-errors
  errors:
    image: oci.seedno.de/seednode/errors:latest
    container_name: errors
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.errors.entrypoints=http"
      - "traefik.http.services.errors.loadbalancer.server.port=8080"
    networks:
      - errors

  ### https://github.com/go-gitea/gitea
  gitea:
    image: gitea/gitea:nightly
    container_name: gitea
    restart: unless-stopped
    depends_on:
      - gitea-db
    environment:
      - "TMPDIR=/data/backups"
      - "USER_UID=${UID:?not set}"
      - "USER_GID=${GID:?not set}"
    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,errors,secure,gitea"
      - "traefik.http.services.gitea.loadbalancer.server.port=3000"
    ports:
      - "9023:22"
    networks:
      - gitea
      - gitea-db
    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

  gitea-db:
    image: postgres:13-alpine
    container_name: gitea-db
    restart: unless-stopped
    environment:
      - "POSTGRES_DB=${GITEA_DATABASE_NAME:?not set}"
      - "POSTGRES_USER=${GITEA_DATABASE_USER:?not set}"
      - "POSTGRES_PASSWORD=${GITEA_DATABASE_PASS:?not set}"
    networks:
      - gitea-db
    volumes:
      - type: bind
        source: /docker/gitea/database
        target: /var/lib/postgresql/data

  ### https://github.com/grafana/grafana
  ## Set data source to "http://prometheus:9090"
  ## Run `chown -R 472:472 /docker/grafana` to fix permissions
  grafana-render:
    image: grafana/grafana-image-renderer:latest
    container_name: grafana-render
    restart: unless-stopped
    depends_on:
      - grafana
    environment:
      - "BROWSER_TZ=${TIMEZONE}"
      - "HTTP_HOST=0.0.0.0"
      - "HTTP_PORT=8081"
    networks:
      - grafana-render

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    depends_on:
      - prometheus
    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_LOG_FILTERS=rendering:debug"
      - "GF_METRICS_ENABLED=true"
      - "GF_PATHS_TEMP_DATA_LIFETIME=0"
      - "GF_RENDERING_SERVER_URL=http://grafana-renderer:8081/render"
      - "GF_RENDERING_CALLBACK_URL=http://grafana:3000/"
      - "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=compress,errors,secure,grafana,whitelist-vpn@file"
      - "traefik.http.services.grafana.loadbalancer.server.port=3000"
    networks:
      - grafana
      - grafana-render
      - prometheus
    volumes:
      - type: bind
        source: /docker/grafana/data
        target: /var/lib/grafana

  ### https://github.com/yunginnanet/HellPot		
  hellpot:
    image: oci.seedno.de/seednode/hellpot:latest
    container_name: hellpot
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.hellpot.rule=Headers(`User-Agent`, `GPTBot`) || Headers(`User-Agent`, `ChatGPT-User/1.0`)"
      - "traefik.http.routers.hellpot.priority=255"
      - "traefik.http.routers.hellpot.entrypoints=https"
      - "traefik.http.routers.hellpot.service=hellpot"
      - "traefik.http.routers.hellpot.tls=true"
      - "traefik.http.routers.hellpot.tls.certresolver=letsencrypt"
      - "traefik.http.routers.hellpot.middlewares=compress,secure"
      - "traefik.http.services.hellpot.loadbalancer.server.port=8080"
    networks:
      - hellpot
    volumes:
      - type: bind
        source: /docker/hellpot/logs
        target: /logs

  ### https://git.seedno.de/seednode/roulette
  nature:
    image: oci.seedno.de/seednode/roulette:latest
    container_name: nature
    restart: unless-stopped
    environment:
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--admin-prefix=${ROULETTE_ADMIN_PREFIX:?not set}"
      - "--api"
      - "--debug"
      - "--filter"
      - "--images"
      - "--index"
      - "--index-file=/index/index.zstd"
      - "--recursive"
      - "--refresh"
      - "--sort"
      - "--verbose"
      - "/data"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nature.rule=Host(`nature.seedno.de`)"
      - "traefik.http.routers.nature.entrypoints=https"
      - "traefik.http.routers.nature.service=nature"
      - "traefik.http.routers.nature.tls=true"
      - "traefik.http.routers.nature.tls.certresolver=letsencrypt"
      - "traefik.http.routers.nature.middlewares=compress,secure"
      - "traefik.http.services.nature.loadbalancer.server.port=8080"
    networks:
      - nature
    volumes:
      - type: bind
        source: /docker/nature/index
        target: /index
      - type: bind
        source: /media/nature
        target: /data
        read_only: true

  ### https://git.seedno.de/seednode/docker-site-naughty
  naughty:
    image: oci.seedno.de/seednode/naughty:latest
    container_name: naughty
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.naughty.rule=PathPrefix(`/{path:.*(\\.env|\\.aws|xmlrpc|wp-admin|wp-login).*}`)"
      - "traefik.http.routers.naughty.priority=254"
      - "traefik.http.routers.naughty.entrypoints=https"
      - "traefik.http.routers.naughty.service=naughty"
      - "traefik.http.routers.naughty.tls=true"
      - "traefik.http.routers.naughty.tls.certresolver=letsencrypt"
      - "traefik.http.routers.naughty.middlewares=compress,errors,secure"
      - "traefik.http.services.naughty.loadbalancer.server.port=8080"
    networks:
      - naughty

  ### https://git.seedno.de/seednode/docker-nginx
  ## All my sites are configured via the file provider
  ## An example is available here:
  ## https://cdn.seedno.de/txt/access.seedno.de.yaml
  nginx:
    image: oci.seedno.de/seednode/nginx:latest
    container_name: nginx
    restart: unless-stopped
    depends_on:
      - nginx-php-fpm
    networks:
      - nginx
      - nginx-php
    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

  nginx-php-fpm:
    image: php:8-fpm-alpine
    container_name: nginx-php-fpm
    restart: unless-stopped
    networks:
      - nginx-php
    volumes:
      - type: bind
        source: /storage
        target: /storage
        read_only: true
      - type: bind
        source: /var/www/html
        target: /var/www/html
        read_only: true

  ## https://github.com/prometheus/prometheus
  ## Run `chown -R 65534:65534 /docker/prometheus` to fix permissions
  ## See https://cdn.seedno.de/txt/prometheus.yml for example config file
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    command:
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=30d"
      - "--web.console.libraries=/usr/share/prometheus/console_libraries"
      - "--web.console.templates=/usr/share/prometheus/consoles"
    networks:
      - prometheus
    volumes:
      - type: bind
        source: /docker/prometheus/config/prometheus.yml
        target: /prometheus/prometheus.yml
        read_only: true
      - type: bind
        source: /docker/prometheus/data
        target: /prometheus

  ### https://git.seedno.de/seednode/query
  query:
    image: oci.seedno.de/seednode/query:latest
    container_name: query
    restart: unless-stopped
    environment:
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--all"
      - "--profile"
      - "--max-dice-rolls=256"
      - "--max-dice-sides=256"
      - "--max-image-height=1024"
      - "--max-image-width=1024"
      - "--profile"
      - "--qr-size=512"
      - "--verbose"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.query.headers.contentSecurityPolicy=default-src 'self'"
      - "traefik.http.routers.query.rule=Host(`q.seedno.de`)"
      - "traefik.http.routers.query.entrypoints=https"
      - "traefik.http.routers.query.service=query"
      - "traefik.http.routers.query.tls=true"
      - "traefik.http.routers.query.tls.certresolver=letsencrypt"
      - "traefik.http.routers.query.middlewares=compress,secure,query"
      - "traefik.http.routers.query-profiling.rule=Host(`q.seedno.de`) && PathPrefix(`/pprof/`)"
      - "traefik.http.routers.query-profiling.entrypoints=https"
      - "traefik.http.routers.query-profiling.service=query"
      - "traefik.http.routers.query-profiling.tls=true"
      - "traefik.http.routers.query-profiling.tls.certresolver=letsencrypt"
      - "traefik.http.routers.query-profiling.middlewares=compress,secure,query,whitelist-vpn@file"
      - "traefik.http.services.query.loadbalancer.server.port=8080"
    networks:
      - query

  ### https://git.seedno.de/seednode/roulette
  random:
    image: oci.seedno.de/seednode/roulette:latest
    container_name: random
    restart: unless-stopped
    environment:
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--all"
      - "--debug"
      - "--prefix=/random/"
      - "--recursive"
      - "--verbose"
      - "/data"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.random.rule=Host(`cdn.seedno.de`) && PathPrefix(`/random`)"
      - "traefik.http.routers.random.entrypoints=https"
      - "traefik.http.routers.random.service=random"
      - "traefik.http.routers.random.tls=true"
      - "traefik.http.routers.random.tls.certresolver=letsencrypt"
      - "traefik.http.routers.random.middlewares=compress,secure"
      - "traefik.http.services.random.loadbalancer.server.port=8080"
    networks:
      - random
    volumes:
      - type: bind
        source: /var/www/html/cdn.seedno.de
        target: /data
        read_only: true

  ### https://hub.docker.com/_/registry
  registry:
    image: registry:2
    container_name: registry
    restart: unless-stopped
    environment:
      - "REGISTRY_HTTP_ADDR=0.0.0.0:5000"
      - "REGISTRY_HTTP_SECRET=${REGISTRY_SECRET:-not set}"
    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,errors,secure"
      - "traefik.http.services.registry.loadbalancer.server.port=5000"
    networks:
      - registry
    volumes:
      - type: bind
        source: /docker/registry/config/config_private.yml
        target: /etc/docker/registry/config.yml
        read_only: true
      - type: bind
        source: /docker/registry/data
        target: /var/lib/registry

  ### Some people follow the actual guide for running a public registry,
  ### and some people just run a second copy of the service in maintenance
  ### mode and then disable write access to the volume
  registry-public:
    image: registry:2
    container_name: registry-public
    restart: unless-stopped
    environment:
      - "REGISTRY_HTTP_ADDR=0.0.0.0:5000"
      - "REGISTRY_HTTP_SECRET=${REGISTRY_SECRET:-not set}"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.registry-protected.rule=Host(`oci.seedno.de`) && PathPrefix(`/v2/_catalog`)"
      - "traefik.http.routers.registry-protected.entrypoints=https"
      - "traefik.http.routers.registry-protected.service=registry"
      - "traefik.http.routers.registry-protected.tls=true"
      - "traefik.http.routers.registry-protected.tls.certresolver=letsencrypt"
      - "traefik.http.routers.registry-protected.middlewares=adminauth,compress,errors,secure"
      - "traefik.http.services.registry-protected.loadbalancer.server.port=5000"
      - "traefik.http.routers.registry-public.rule=Host(`oci.seedno.de`)"
      - "traefik.http.routers.registry-public.entrypoints=https"
      - "traefik.http.routers.registry-public.service=registry-public"
      - "traefik.http.routers.registry-public.tls=true"
      - "traefik.http.routers.registry-public.tls.certresolver=letsencrypt"
      - "traefik.http.routers.registry-public.middlewares=compress,errors,secure"
      - "traefik.http.services.registry-public.loadbalancer.server.port=5000"
    networks:
      - registry
    volumes:
      - type: bind
        source: /docker/registry/config/config_public.yml
        target: /etc/docker/registry/config.yml
        read_only: true
      - type: bind
        source: /docker/registry/data
        target: /var/lib/registry
        read_only: true

  ### https://git.seedno.de/seednode/roulette
  roulette:
    image: oci.seedno.de/seednode/roulette:latest
    container_name: roulette
    restart: unless-stopped
    environment:
      - "TZ=${TIMEZONE:?not set}"
    command:
      - "--api"
      - "--debug"
      - "--filter"
      - "--ignore=.roulette-ignore"
      - "--images"
      - "--index"
      - "--index-file=/index/index.zstd"
      - "--index-interval=1h"
      - "--profile"
      - "--recursive"
      - "--refresh"
      - "--sort"
      - "--verbose"
      - "/data/Images"
      - "/data/GIFs"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.roulette.rule=Host(`roulette.seedno.de`)"
      - "traefik.http.routers.roulette.entrypoints=https"
      - "traefik.http.routers.roulette.service=roulette"
      - "traefik.http.routers.roulette.tls=true"
      - "traefik.http.routers.roulette.tls.certresolver=letsencrypt"
      - "traefik.http.routers.roulette.middlewares=compress,secure,whitelist@file"
      - "traefik.http.services.roulette.loadbalancer.server.port=8080"
    networks:
      - roulette
    volumes:
      - type: bind
        source: /docker/roulette/index
        target: /index
      - type: bind
        source: /media/private
        target: /data
        read_only: true

  ### https://github.com/ekzhang/rustpad
  rustpad:
    image: ekzhang/rustpad:latest
    container_name: rustpad
    restart: unless-stopped
    environment:
      - "EXPIRY_DAYS=1"
      - "SQLITE_URI=file:/app/db.sqlite;Version=3;"
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.rustpad.headers.contentSecurityPolicy=default-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net; font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net; worker-src 'self' blob:"
      - "traefik.http.routers.rustpad.rule=Host(`notes.seedno.de`)"
      - "traefik.http.routers.rustpad.entrypoints=https"
      - "traefik.http.routers.rustpad.service=rustpad"
      - "traefik.http.routers.rustpad.tls=true"
      - "traefik.http.routers.rustpad.tls.certresolver=letsencrypt"
      - "traefik.http.routers.rustpad.middlewares=compress,errors,secure,rustpad"
      - "traefik.http.services.rustpad.loadbalancer.server.port=3030"
    networks:
      - rustpad
    volumes:
      - type: bind
        source: /docker/rustpad/data
        target: /app

  ### https://hub.docker.com/r/sflow/prometheus
  sflow-collector:
    image: sflow/prometheus:latest
    container_name: sflow-collector
    restart: unless-stopped
    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=compress,errors,secure,sflow,whitelist-vpn@file"
      - "traefik.http.services.sflow.loadbalancer.server.port=8008"
    ports:
      - "10.25.0.1:6343:6343/udp"
    networks:
      - sflow
      - prometheus

  ### https://github.com/sflow/host-sflow
  sflow-exporter:
    image: sflow/host-sflow:latest
    container_name: sflow-exporter
    restart: unless-stopped
    environment:
      - "COLLECTOR=flows.seedno.de"
      - "DROPMON=enable"
      - "NET=wan"
      - "POLLING=20"
      - "PORT=6343"
      - "SAMPLING=1000"
    network_mode: host

  ### https://github.com/oetiker/SmokePing
  smokeping:
    image: lscr.io/linuxserver/smokeping:latest
    container_name: smokeping
    restart: unless-stopped
    environment:
      - "PUID=${UID:?not set}"
      - "PGID=${GID:?not set}"
      - "TZ=${TIMEZONE:?not set}"
    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,errors,secure,smokeping,whitelist-vpn@file"
      - "traefik.http.services.smokeping.loadbalancer.server.port=80"
    networks:
      - smokeping
    volumes:
      - type: bind
        source: /docker/smokeping/config
        target: /config
        read_only: true
      - type: bind
        source: /docker/smokeping/data
        target: /data

  ### https://github.com/nirui/sshwifty
  sshwifty:
    image: niruix/sshwifty:latest
    container_name: sshwifty
    restart: unless-stopped
    environment:
      - "SSHWIFTY_HOSTNAME="
      - "SSHWIFTY_LISTENPORT=8182"
      - "SSHWIFTY_SHAREDKEY=${SSHWIFTY_SHARED_KEY:?not set}"
      - "SSHWIFTY_SERVERMESSAGE=Hi"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.sshwifty.rule=Host(`ssh.seedno.de`)"
      - "traefik.http.routers.sshwifty.entrypoints=https"
      - "traefik.http.routers.sshwifty.service=sshwifty"
      - "traefik.http.routers.sshwifty.tls=true"
      - "traefik.http.routers.sshwifty.tls.certresolver=letsencrypt"
#      - "traefik.http.routers.sshwifty.middlewares=compress,errors,secure"
      - "traefik.http.services.sshwifty.loadbalancer.server.port=8182"
    networks:
      - sshwifty

  ### https://github.com/gabe565/ascii-movie
  starwars:
    image: ghcr.io/gabe565/ascii-movie:latest
    container_name: starwars
    restart: unless-stopped
    command:
      - "serve"
      - "--api-enabled=false"
      - "--concurrent-streams=32"
      - "--telnet-address=:2023"
      - "--ssh-enabled=false"
      - "--timeout=30m"
    ports:
      - "23:2023"

  ### https://github.com/syncthing/syncthing
  syncthing:
    image: lscr.io/linuxserver/syncthing:amd64-latest
    container_name: syncthing
    restart: unless-stopped
    environment:
      - "PUID=${UID:?not set}"
      - "PGID=${GID:?not set}"
      - "TZ=${TIMEZONE:?not set}"
      - "UMASK_SET=022"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.syncthing.rule=Host(`sync.crimson.seedno.de`)"
      - "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=compress,errors,secure,whitelist-vpn@file"
      - "traefik.http.services.syncthing.loadbalancer.server.port=8384"
    ports:
      - "22000:22000"
      - "22000:22000/udp"
    networks:
      - syncthing
    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

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

  ### https://github.com/berthubert/trifecta
  trifecta:
    image: berthubert/trifecta:latest
    container_name: trifecta
    restart: unless-stopped
    environment:
      - "TRIFECTA_DB=/data/trifecta.sqlite"
      - "TRIFECTA_LOCAL=0.0.0.0"
      - "TRIFECTA_URL=img.seedno.de"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.trifecta.rule=Host(`img.seedno.de`)"
      - "traefik.http.routers.trifecta.entrypoints=https"
      - "traefik.http.routers.trifecta.service=trifecta"
      - "traefik.http.routers.trifecta.tls=true"
      - "traefik.http.routers.trifecta.tls.certresolver=letsencrypt"
      - "traefik.http.routers.trifecta.middlewares=compress,secure"
      - "traefik.http.services.trifecta.loadbalancer.server.port=1234"
    networks:
      - trifecta
    volumes:
      - type: bind
        source: /docker/trifecta/data
        target: /data

  ### https://github.com/jacobalberty/unifi-docker
  unifi:
    image: jacobalberty/unifi:latest
    container_name: unifi
    restart: unless-stopped
    environment:
    - "BIND_PRIV=false"
    - "RUNAS_UID0=false"
    - "UNIFI_UID=${UID:?not set}"
    - "UNIFI_GID=${GID:?not set}"
    - "TZ=${TIMEZONE:?not set}"
    networks:
      - unifi
    ports:
      - "8080:8080"
    volumes:
      - type: bind
        source: /docker/unifi/data
        target: /unifi

  ### https://github.com/dani-garcia/vaultwarden
  vaultwarden:
    image: vaultwarden/server:alpine
    container_name: vaultwarden
    restart: unless-stopped
    depends_on:
      - vaultwarden-db
    environment:
      - "DATABASE_URL=postgresql://${VAULTWARDEN_DATABASE_USER:?not set}:${VAULTWARDEN_DATABASE_PASS:?not set}@vaultwarden-db:5432/${VAULTWARDEN_DATABASE_NAME:?not set}"
      - "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,errors,secure,vaultwarden"
      - "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
    networks:
      - vaultwarden
      - vaultwarden-db
    volumes:
      - type: bind
        source: /docker/vaultwarden/data
        target: /data

  vaultwarden-db:
    image: postgres:13-alpine
    container_name: vaultwarden-db
    restart: unless-stopped
    environment:
      - "POSTGRES_DB=${VAULTWARDEN_DATABASE_NAME:?not set}"
      - "POSTGRES_USER=${VAULTWARDEN_DATABASE_USER:?not set}"
      - "POSTGRES_PASSWORD=${VAULTWARDEN_DATABASE_PASS:?not set}"
    networks:
      - vaultwarden-db
    volumes:
      - type: bind
        source: /docker/vaultwarden/database
        target: /var/lib/postgresql/data

  ### https://hub.docker.com/r/containous/whoami
  whoami:
    image: containous/whoami:latest
    container_name: whoami
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.middlewares.whoami.headers.contentSecurityPolicy=default-src 'self'"
      - "traefik.http.routers.whoami.rule=Host(`whoami.seedno.de`)"
      - "traefik.http.routers.whoami.entrypoints=https"
      - "traefik.http.routers.whoami.service=whoami"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
      - "traefik.http.routers.whoami.middlewares=compress,errors,secure,ratelimit,whoami"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"
    networks:
      - whoami

networks:
  audio:
    name: audio
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: audio
  code-server:
    name: code-server
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: code-server
  commands:
    name: commands
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: commands
  commands-db:
    name: commands-db
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: commands-db
  cyberchef:
    name: cyberchef
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: cyberchef
  drawio:
    name: drawio
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: drawio
  errors:
    name: errors
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: errors
  gitea:
    name: gitea
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: gitea
  gitea-db:
    name: gitea-db
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: gitea-db
    internal: true
  grafana:
    name: grafana
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: grafana
  grafana-render:
    name: grafana-render
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: grafana-render
    internal: true
  hellpot:
    name: hellpot
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: hellpot
  nature:
    name: nature
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: nature
  naughty:
    name: naughty
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: naughty
  nginx:
    name: nginx
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: nginx
  nginx-php:
    name: nginx-php
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: nginx-php
    internal: true
  prometheus:
    name: prometheus
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: prometheus
    internal: true
  query:
    name: query
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: query
  random:
    name: random
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: random
  registry:
    name: registry
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: registry
  roulette:
    name: roulette
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: roulette
  rustpad:
    name: rustpad
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: rustpad
  sflow:
    name: sflow
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: sflow
  smokeping:
    name: smokeping
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: smokeping
  sshwifty:
    name: sshwifty
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: sshwifty
  syncthing:
    name: syncthing
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: syncthing
  thelounge:
    name: thelounge
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: thelounge
  traefik:
    name: traefik
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: traefik
  trifecta:
    name: trifecta
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: trifecta
  unifi:
    name: unifi
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: unifi
  vaultwarden:
    name: vaultwarden
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: vaultwarden
  vaultwarden-db:
    name: vaultwarden-db
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: vaultwarden-db
    internal: true
  whoami:
    name: whoami
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: whoami