services: # ------------------------------------------------------ # Traefik Reverse Proxy # ------------------------------------------------------ traefik: image: traefik:v2.11 container_name: traefik restart: unless-stopped command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" - "--certificatesresolvers.letsencrypt.acme.email=inventor@txproducts.de" - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "443:443" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./letsencrypt:/letsencrypt" # ------------------------------------------------------ # Tika (Office text extraction) # ------------------------------------------------------ tika: image: apache/tika:latest container_name: tika restart: unless-stopped # ------------------------------------------------------ # Gotenberg (Office → PDF conversion) # ------------------------------------------------------ gotenberg: image: gotenberg/gotenberg:latest container_name: gotenberg restart: unless-stopped command: - "gotenberg" - "--chromium-disable-javascript=true" - "--chromium-allow-list=file:///tmp/.*" - "--libreoffice-start-timeout=900s" - "--chromium-start-timeout=900s" - "--libreoffice-auto-start=true" # ------------------------------------------------------ # Paperless-NGX # ------------------------------------------------------ paperless: image: ghcr.io/paperless-ngx/paperless-ngx:latest container_name: paperless restart: unless-stopped depends_on: - redis - paperless_db - tika - gotenberg environment: PAPERLESS_URL: https://paperless.txproducts.de PAPERLESS_REDIS: redis://redis:6379 PAPERLESS_DBHOST: paperless_db PAPERLESS_DBNAME: paperless PAPERLESS_DBUSER: paperless PAPERLESS_DBPASS: AVeryStrong123Password PAPERLESS_CONSUMER_RECURSIVE: "true" PAPERLESS_CONSUMER_DELETE_DUPLICATES: "true" PAPERLESS_EMAIL_HOST: "mail.cs537.de" PAPERLESS_EMAIL_PORT: 465 PAPERLESS_EMAIL_HOST_USER: "system@txproducts.de" PAPERLESS_EMAIL_HOST_PASSWORD: "OubveTtORoOmPRItNITeRbIDECUppEcT,=,42" PAPERLESS_EMAIL_FROM: "system@txproducts.de" PAPERLESS_EMAIL_USE_TLS: "true" PAPERLESS_EMAIL_USE_SSL: "false" # --- Office document support --- PAPERLESS_TIKA_ENABLED: "true" PAPERLESS_TIKA_GOTENBERG_ENDPOINT: "http://gotenberg:3000" PAPERLESS_TIKA_ENDPOINT: "http://tika:9998" volumes: - ./paperless/data:/usr/src/paperless/data - ./paperless/media:/usr/src/paperless/media - ./paperless/export:/usr/src/paperless/export - ./paperless/consume:/usr/src/paperless/consume labels: - "traefik.enable=true" - "traefik.http.routers.paperless.rule=Host(`paperless.txproducts.de`)" - "traefik.http.routers.paperless.entrypoints=websecure" - "traefik.http.routers.paperless.tls.certresolver=letsencrypt" paperless_db: image: postgres:14 restart: unless-stopped environment: POSTGRES_DB: paperless POSTGRES_USER: paperless POSTGRES_PASSWORD: AVeryStrong123Password volumes: - ./paperless/postgres:/var/lib/postgresql/data redis: image: redis:7 restart: unless-stopped # ------------------------------------------------------ # Paperless AI # ------------------------------------------------------ paperless_ai: image: clusterzx/paperless-ai:latest container_name: paperless_ai restart: unless-stopped environment: PUID: 1000 PGID: 1000 # Port config PAPERLESS_AI_PORT: 3000 # RAG engine (enabled by default) RAG_SERVICE_URL: http://paperless_ai:8000 RAG_SERVICE_ENABLED: "true" # Connect to Paperless PAPERLESS_URL: https://paperless.txproducts.de # ==== OpenRouter (Custom Provider) ==== AI_PROVIDER: custom CUSTOM_AI_BASE_URL: https://openrouter.ai/api/v1 CUSTOM_AI_API_KEY: "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" CUSTOM_AI_MODEL: "stepfun/step-3.5-flash:free" # OpenRouter required headers! HTTP_REFERER: "https://paperai.txproducts.de" X_TITLE: "Paperless-AI" volumes: - ./paperless-ai/data:/app/data labels: - "traefik.enable=true" - "traefik.http.routers.paperlessai.rule=Host(`paperai.txproducts.de`)" - "traefik.http.routers.paperlessai.entrypoints=websecure" - "traefik.http.routers.paperlessai.tls.certresolver=letsencrypt" # ------------------------------------------------------ # InvenTree + DB # ------------------------------------------------------ inventree: image: inventree/inventree:stable container_name: inventree restart: unless-stopped depends_on: - inventree_db environment: INVENTREE_DB_ENGINE: postgresql INVENTREE_DB_NAME: inventree INVENTREE_DB_USER: inventree INVENTREE_DB_PASSWORD: AVeryStrong123Password INVENTREE_DB_HOST: inventree_db INVENTREE_ADMIN_USER: admin INVENTREE_ADMIN_PASSWORD: AVeryStrong123Password INVENTREE_ADMIN_EMAIL: dschmidt@txproducts.de INVENTREE_PLUGINS_ENABLED: 1 INVENTREE_PLUGIN_FILE: /home/inventree/data/plugins.txt # Required for reverse-proxy setups INVENTREE_SITE_URL: https://inventree.txproducts.de CSRF_TRUSTED_ORIGINS: https://inventree.txproducts.de ALLOWED_HOSTS: inventree.txproducts.de,localhost,127.0.0.1 volumes: - ./inventree/data:/home/inventree/data labels: - "traefik.enable=true" - "traefik.http.routers.inventree.rule=Host(`inventree.txproducts.de`)" - "traefik.http.routers.inventree.entrypoints=websecure" - "traefik.http.routers.inventree.tls.certresolver=letsencrypt" # Static files service - "traefik.http.services.inventree.loadbalancer.server.port=8000" inventree_db: image: postgres:14 restart: unless-stopped environment: POSTGRES_DB: inventree POSTGRES_USER: inventree POSTGRES_PASSWORD: AVeryStrong123Password volumes: - ./inventree/postgres:/var/lib/postgresql/data inventree_worker: image: inventree/inventree:stable container_name: inventree_worker command: invoke worker restart: unless-stopped depends_on: - inventree environment: INVENTREE_DB_ENGINE: postgresql INVENTREE_DB_NAME: inventree INVENTREE_DB_USER: inventree INVENTREE_DB_PASSWORD: AVeryStrong123Password INVENTREE_DB_HOST: inventree_db INVENTREE_SITE_URL: https://inventree.txproducts.de CSRF_TRUSTED_ORIGINS: https://inventree.txproducts.de volumes: - ./inventree/data:/home/inventree/data # ------------------------------------------------------ # Nextcloud + DB # ------------------------------------------------------ nextcloud-db: image: mariadb:11 container_name: nextcloud-db restart: unless-stopped command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW environment: MYSQL_DATABASE: nextcloud MYSQL_USER: nextcloud MYSQL_PASSWORD: A_Very_Strong_DB_Password MYSQL_ROOT_PASSWORD: A_Very_Strong_Root_Password volumes: - ./nextcloud/db:/var/lib/mysql nextcloud: image: nextcloud:latest container_name: nextcloud restart: unless-stopped depends_on: - nextcloud-db - redis environment: # DB connection MYSQL_HOST: nextcloud-db MYSQL_DATABASE: nextcloud MYSQL_USER: nextcloud MYSQL_PASSWORD: A_Very_Strong_DB_Password REDIS_HOST: redis # URL & proxy config #NEXTCLOUD_ADMIN_USER: admin #NEXTCLOUD_ADMIN_PASSWORD: 97v2*r7APuS^RV3d$YPU NEXTCLOUD_TRUSTED_DOMAINS: cloud.txproducts.de OVERWRITEHOST: cloud.txproducts.de OVERWRITEPROTOCOL: https OVERWRITECLIURL: https://cloud.txproducts.de TRUSTED_PROXIES: 172.16.0.0/12 volumes: - ./nextcloud/html:/var/www/html - ./nextcloud/data:/var/www/html/data - ./paperless:/paperless labels: - "traefik.enable=true" - "traefik.http.routers.nextcloud.rule=Host(`cloud.txproducts.de`)" - "traefik.http.routers.nextcloud.entrypoints=websecure" - "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt" # Optional: increase timeouts for large uploads - "traefik.http.services.nextcloud.loadbalancer.server.port=80" - "traefik.http.routers.nextcloud-http.entrypoints=web" - "traefik.http.routers.nextcloud-http.rule=Host(`cloud.txproducts.de`)" - "traefik.http.routers.nextcloud-http.middlewares=nextcloud-redirect" - "traefik.http.middlewares.nextcloud-redirect.redirectscheme.scheme=https" nextcloud-cron: image: nextcloud:latest container_name: nextcloud-cron restart: unless-stopped volumes: - ./nextcloud/html:/var/www/html - ./nextcloud/data:/var/www/html/data entrypoint: /cron.sh depends_on: - nextcloud-db - redis talk-hpb: image: ghcr.io/nextcloud-releases/aio-talk:latest container_name: nextcloud-talk-hpb restart: unless-stopped init: true labels: - "traefik.enable=true" # 1. HTTP Router (Redirect HTTP to HTTPS) - "traefik.http.routers.talk-http.entrypoints=web" - "traefik.http.routers.talk-http.rule=Host(`signal.cloud.txproducts.de`)" - "traefik.http.routers.talk-http.middlewares=nextcloud-redirect" # 2. HTTPS Router (Secure WebSocket Access) - "traefik.http.routers.talk-https.entrypoints=websecure" - "traefik.http.routers.talk-https.rule=Host(`signal.cloud.txproducts.de`)" - "traefik.http.routers.talk-https.tls=true" - "traefik.http.routers.talk-https.tls.certresolver=letsencrypt" # The Talk service is available internally on port 8081 - "traefik.http.services.talk-hpb.loadbalancer.server.port=8081" environment: - NC_DOMAIN=cloud.txproducts.de - TALK_HOST=signal.cloud.txproducts.de - TALK_PORT=3478 - TURN_SECRET=1ph34w9hrs0gka5xi2qfbn2ti48390 - SIGNALING_SECRET=avzeyam5ak1e4a4xseak2m43kih3vp - INTERNAL_SECRET=e5hr4dgxnjbsl71kr1stkubqyrz3zh ports: # Expose the TURN ports (required for external clients) - "3478:3478/tcp" - "3478:3478/udp" # Expose the internal signaling port for the reverse proxy - "8081:8081/tcp" depends_on: - nextcloud nextcloud-whiteboard: image: ghcr.io/nextcloud-releases/whiteboard:stable container_name: nextcloud-whiteboard restart: unless-stopped environment: NEXTCLOUD_URL: https://cloud.txproducts.de JWT_SECRET_KEY: "d7a6599a3864220838281e1796fb06cb90441519a39621ce077a87f80b9c96a6" labels: - "traefik.enable=true" - "traefik.http.routers.whiteboard.rule=Host(`cloud.txproducts.de`) && PathPrefix(`/whiteboard`)" - "traefik.http.routers.whiteboard.entrypoints=websecure" - "traefik.http.routers.whiteboard.tls.certresolver=letsencrypt" - "traefik.http.services.whiteboard.loadbalancer.server.port=3002" - "traefik.http.middlewares.strip-whiteboard.stripprefix.prefixes=/whiteboard" - "traefik.http.routers.whiteboard.middlewares=strip-whiteboard" depends_on: - nextcloud # ------------------------------------------------------ # Gitea # ------------------------------------------------------ gitea: image: gitea/gitea:latest container_name: gitea restart: unless-stopped depends_on: - gitea_db environment: USER_UID: 1000 USER_GID: 1000 GITEA__database__DB_TYPE: postgres GITEA__database__HOST: gitea_db:5432 GITEA__database__NAME: gitea GITEA__database__USER: gitea GITEA__database__PASSWD: AVeryStrongGiteaPassword GITEA__server__DOMAIN: git.txproducts.de GITEA__server__ROOT_URL: https://git.txproducts.de GITEA__server__HTTP_PORT: 3000 GITEA__server__SSH_DOMAIN: git.txproducts.de GITEA__server__SSH_PORT: 2222 GITEA__mailer__ENABLED: true GITEA__mailer__PROTOCOL: smtps GITEA__mailer__SMTP_ADDR: mail.cs537.de GITEA__mailer__SMTP_PORT: 465 GITEA__mailer__USER: system@txproducts.de GITEA__mailer__PASSWD: OubveTtORoOmPRItNITeRbIDECUppEcT,=,42 GITEA__mailer__FROM: system@txproducts.de GITEA__service__REGISTER_EMAIL_CONFIRM: true GITEA__service__DISABLE_REGISTRATION: false GITEA__service__ALLOW_ONLY_INTERNAL_REGISTRATION: true GITEA__service__ENABLE_NOTIFY_MAIL: true volumes: - ./gitea/data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "222:22" # SSH access for git push/pull labels: - "traefik.enable=true" - "traefik.http.routers.gitea.rule=Host(`git.txproducts.de`)" - "traefik.http.routers.gitea.entrypoints=websecure" - "traefik.http.routers.gitea.tls.certresolver=letsencrypt" - "traefik.http.services.gitea.loadbalancer.server.port=3000" - "traefik.http.routers.gitea-http.entrypoints=web" - "traefik.http.routers.gitea-http.rule=Host(`git.txproducts.de`)" - "traefik.http.routers.gitea-http.middlewares=gitea-redirect" - "traefik.http.middlewares.gitea-redirect.redirectscheme.scheme=https" gitea_db: image: postgres:14 container_name: gitea_db restart: unless-stopped environment: POSTGRES_DB: gitea POSTGRES_USER: gitea POSTGRES_PASSWORD: AVeryStrongGiteaPassword volumes: - ./gitea/postgres:/var/lib/postgresql/data # ------------------------------------------------------ # HiActs Conference Poll # ------------------------------------------------------ hiacts-poll: build: context: ./poll dockerfile_inline: | FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 5001 CMD ["python", "app.py"] container_name: hiacts-poll restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.hiacts-poll.rule=Host(`poll.txproducts.de`)" - "traefik.http.routers.hiacts-poll.entrypoints=websecure" - "traefik.http.routers.hiacts-poll.tls.certresolver=letsencrypt" - "traefik.http.services.hiacts-poll.loadbalancer.server.port=5001" networks: default: driver: bridge enable_ipv6: true ipam: config: - subnet: "172.20.0.0/16" - subnet: "fd01::/80"