Initial commit: all 6 self-hosted app compose files + README
This commit is contained in:
commit
fa2a7e2282
7 changed files with 465 additions and 0 deletions
30
README.md
Normal file
30
README.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Manohar's Infrastructure
|
||||
|
||||
Self-hosted stack on Hetzner CX32 (Helsinki), deployed via Dokploy + Traefik.
|
||||
|
||||
## Services
|
||||
|
||||
AppURLPurposeForgejo<https://git.manohargupta.com>Self-hosted Gitn8n<https://automate.manohargupta.com>Workflow automationApprise<https://notify.manohargupta.com>Notification API (Tailscale only)Miniflux<https://feeds.manohargupta.com>RSS readerChangeDetection<https://watch.manohargupta.com>Webpage change monitorPaperless-ngx<https://docs.manohargupta.com>Document OCR + searchTiger Agent<https://agent.manohargupta.com>AI orchestrationDokploy<https://dokploy.manohargupta.com>Docker orchestrationUptime Kuma<https://status.manohargupta.com>MonitoringUmami<https://analytics.manohargupta.com>Web analytics
|
||||
|
||||
## Stack
|
||||
|
||||
- **Server**: Hetzner CX32, Ubuntu 24.04, Helsinki (hel1)
|
||||
- **Orchestration**: Dokploy (Docker Swarm)
|
||||
- **Reverse proxy**: Traefik with Let's Encrypt TLS
|
||||
- **Access**: Tailscale SSH only (`ssh root@manohar-ubuntu`)
|
||||
- **DNS**: Namecheap → [manohargupta.com](http://manohargupta.com)
|
||||
|
||||
## Deployment notes
|
||||
|
||||
- All compose files are in `deployments/`
|
||||
- Every compose declares `dokploy-network` as `external: true`
|
||||
- Labels duplicated under both `labels:` and `deploy.labels:` — required because Dokploy uses swarm stack deploy for multi-service composes (swarm provider reads deploy.labels; docker provider reads labels)
|
||||
- Secrets set in Dokploy Env tab, never hardcoded (except bcrypt hashes in labels which Dokploy cannot substitute)
|
||||
- Apprise and ChangeDetection restricted to Tailscale CGNAT range (100.64.0.0/10)
|
||||
|
||||
## Key learnings
|
||||
|
||||
- Forgejo Docker image uses /data as root, not /var/lib/gitea
|
||||
- n8n WEBHOOK_URL must match public domain exactly or webhook URLs are wrong
|
||||
- htpasswd hashes in Traefik labels need $$ escaping (Compose interpolates single $)
|
||||
- Dokploy env var substitution works in environment: blocks but NOT in labels:
|
||||
52
apprise.compose.yml
Normal file
52
apprise.compose.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Apprise — notify.manohargupta.com
|
||||
# Unified notification API. POST one message, fans out to Telegram, email, ~80 services.
|
||||
# Stateless except for YAML config files stored in the config volume.
|
||||
# No built-in auth -- protected by Traefik IP whitelist (Tailscale range only).
|
||||
#
|
||||
# Honest framing: n8n's built-in Telegram/email nodes cover most workflow notifications.
|
||||
# Apprise's value is for non-n8n scripts (Python crons, server healthchecks) that also
|
||||
# need to notify without importing the full n8n stack.
|
||||
|
||||
services:
|
||||
apprise:
|
||||
image: caronc/apprise:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# Persist notification configs (tagged YAML files) across restarts
|
||||
APPRISE_STATEFUL_MODE: simple
|
||||
# Allow API to update configs -- lock this down after initial setup
|
||||
APPRISE_CONFIG_LOCK: "no"
|
||||
volumes:
|
||||
- apprise_config:/config # stores per-tag YAML notification configs
|
||||
- apprise_attach:/attach # stores file attachments for notifications
|
||||
networks:
|
||||
- dokploy-network
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.apprise.rule=Host(`notify.manohargupta.com`)"
|
||||
- "traefik.http.routers.apprise.entrypoints=websecure"
|
||||
- "traefik.http.routers.apprise.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.apprise.loadbalancer.server.port=8000"
|
||||
# IP whitelist -- Tailscale CGNAT range only. Only your tailnet can call this API.
|
||||
# Without this, anyone who finds the URL can send notifications on your behalf.
|
||||
- "traefik.http.middlewares.apprise-ipallow.ipwhitelist.sourcerange=100.64.0.0/10"
|
||||
- "traefik.http.routers.apprise.middlewares=apprise-ipallow@docker"
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.apprise.rule=Host(`notify.manohargupta.com`)"
|
||||
- "traefik.http.routers.apprise.entrypoints=websecure"
|
||||
- "traefik.http.routers.apprise.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.apprise.loadbalancer.server.port=8000"
|
||||
- "traefik.http.middlewares.apprise-ipallow.ipwhitelist.sourcerange=100.64.0.0/10"
|
||||
- "traefik.http.routers.apprise.middlewares=apprise-ipallow@docker"
|
||||
|
||||
volumes:
|
||||
apprise_config:
|
||||
apprise_attach:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
61
changedetection.compose.yml
Normal file
61
changedetection.compose.yml
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# ChangeDetection.io — watch.manohargupta.com
|
||||
# Watches pages with no RSS: CERC orders, MNRE notifications, SECI tenders.
|
||||
# Browserless sidecar handles JS-rendered government portals (Angular/React).
|
||||
# Auth: bcrypt basic auth via Traefik (hash hardcoded -- env vars don't work in labels).
|
||||
# Memory budget: ~700 MB total (CD ~150 MB + browser sidecar ~550 MB).
|
||||
|
||||
services:
|
||||
|
||||
browser:
|
||||
image: dgtlmoon/sockpuppetbrowser:latest
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- SYS_ADMIN
|
||||
networks:
|
||||
- cd_internal
|
||||
environment:
|
||||
- SCREEN_WIDTH=1920
|
||||
- SCREEN_HEIGHT=1080
|
||||
|
||||
changedetection:
|
||||
image: ghcr.io/dgtlmoon/changedetection.io:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- browser
|
||||
environment:
|
||||
PLAYWRIGHT_DRIVER_URL: ws://browser:3000
|
||||
BASE_URL: https://watch.manohargupta.com
|
||||
TZ: Asia/Kolkata
|
||||
volumes:
|
||||
- cd_data:/datastore
|
||||
networks:
|
||||
- dokploy-network
|
||||
- cd_internal
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.changedetection.rule=Host(`watch.manohargupta.com`)"
|
||||
- "traefik.http.routers.changedetection.entrypoints=websecure"
|
||||
- "traefik.http.routers.changedetection.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.changedetection.loadbalancer.server.port=5000"
|
||||
- "traefik.http.middlewares.cd-auth.basicauth.users=manohar:$$2y$$05$$KMo07kusNXiLmQ8orl6HseY5KyVof74gw6Z.7MSFtqYhuNX0otSJm"
|
||||
- "traefik.http.routers.changedetection.middlewares=cd-auth@docker"
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.changedetection.rule=Host(`watch.manohargupta.com`)"
|
||||
- "traefik.http.routers.changedetection.entrypoints=websecure"
|
||||
- "traefik.http.routers.changedetection.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.changedetection.loadbalancer.server.port=5000"
|
||||
- "traefik.http.middlewares.cd-auth.basicauth.users=manohar:$$2y$$05$$KMo07kusNXiLmQ8orl6HseY5KyVof74gw6Z.7MSFtqYhuNX0otSJm"
|
||||
- "traefik.http.routers.changedetection.middlewares=cd-auth@docker"
|
||||
|
||||
volumes:
|
||||
cd_data:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
cd_internal:
|
||||
driver: bridge
|
||||
52
forgejo.compose.yml
Normal file
52
forgejo.compose.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Forgejo — git.manohargupta.com
|
||||
# Self-hosted Git for scripts, Power Query files, compose files, n8n exports.
|
||||
# Storage: SQLite (single-user, zero ops overhead vs Postgres).
|
||||
# SSH clone port: 2222 (host) -> 22 (container). Never conflicts with system SSH.
|
||||
# Fix v2: volume mounted to /data (Forgejo Docker standard), not /var/lib/gitea.
|
||||
|
||||
services:
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo/forgejo:10
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
USER_UID: "1000"
|
||||
USER_GID: "1000"
|
||||
FORGEJO__server__DOMAIN: git.manohargupta.com
|
||||
FORGEJO__server__ROOT_URL: https://git.manohargupta.com/
|
||||
FORGEJO__server__SSH_DOMAIN: git.manohargupta.com
|
||||
FORGEJO__server__SSH_PORT: "2222"
|
||||
FORGEJO__server__SSH_LISTEN_PORT: "22"
|
||||
FORGEJO__service__DISABLE_REGISTRATION: "true"
|
||||
FORGEJO__service__REQUIRE_SIGNIN_VIEW: "false"
|
||||
# /data is Forgejo Docker's standard root -- /var/lib/gitea was wrong
|
||||
FORGEJO__database__DB_TYPE: sqlite3
|
||||
FORGEJO__database__PATH: /data/gitea/forgejo.db
|
||||
volumes:
|
||||
- forgejo_data:/data # standard Forgejo Docker data root
|
||||
- forgejo_config:/etc/gitea
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "2222:22"
|
||||
networks:
|
||||
- dokploy-network
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.forgejo.rule=Host(`git.manohargupta.com`)"
|
||||
- "traefik.http.routers.forgejo.entrypoints=websecure"
|
||||
- "traefik.http.routers.forgejo.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.forgejo.loadbalancer.server.port=3000"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
forgejo_data:
|
||||
forgejo_config:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
68
miniflux.compose.yml
Normal file
68
miniflux.compose.yml
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# Miniflux — feeds.manohargupta.com
|
||||
# Minimal RSS reader. Postgres-only (no SQLite option in Miniflux).
|
||||
# Intended sources: MercomIndia, IEEFA, MNRE press releases, CERC, SECI, etc.
|
||||
# n8n will poll the Miniflux API to digest unread entries and push to Telegram.
|
||||
|
||||
services:
|
||||
|
||||
miniflux-db:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: miniflux
|
||||
POSTGRES_USER: miniflux
|
||||
POSTGRES_PASSWORD: ${MINIFLUX_DB_PASSWORD}
|
||||
volumes:
|
||||
- miniflux_db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- miniflux_internal # DB never touches the public network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U miniflux -d miniflux"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
miniflux:
|
||||
image: miniflux/miniflux:2.2.7 # Pinned -- upgrade deliberately
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
miniflux-db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
# Full Postgres DSN -- sslmode=disable is fine on the internal bridge network
|
||||
DATABASE_URL: postgres://miniflux:${MINIFLUX_DB_PASSWORD}@miniflux-db/miniflux?sslmode=disable
|
||||
# Run DB migrations automatically on boot
|
||||
RUN_MIGRATIONS: "1"
|
||||
# Auto-create admin account on first boot -- these env vars are ignored after that
|
||||
CREATE_ADMIN: "1"
|
||||
ADMIN_USERNAME: ${MINIFLUX_ADMIN_USERNAME}
|
||||
ADMIN_PASSWORD: ${MINIFLUX_ADMIN_PASSWORD}
|
||||
# IST so relative timestamps ("2 hours ago") match your timezone
|
||||
TZ: Asia/Kolkata
|
||||
networks:
|
||||
- dokploy-network
|
||||
- miniflux_internal
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.miniflux.rule=Host(`feeds.manohargupta.com`)"
|
||||
- "traefik.http.routers.miniflux.entrypoints=websecure"
|
||||
- "traefik.http.routers.miniflux.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.miniflux.loadbalancer.server.port=8080"
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.miniflux.rule=Host(`feeds.manohargupta.com`)"
|
||||
- "traefik.http.routers.miniflux.entrypoints=websecure"
|
||||
- "traefik.http.routers.miniflux.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.miniflux.loadbalancer.server.port=8080"
|
||||
|
||||
volumes:
|
||||
miniflux_db_data:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
miniflux_internal:
|
||||
driver: bridge
|
||||
79
n8n.compose.yml
Normal file
79
n8n.compose.yml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# n8n — automate.manohargupta.com
|
||||
# Visual workflow automation. Postgres-backed (SQLite locks under concurrent runs).
|
||||
# v2: Added deploy.labels for Traefik swarm provider (Dokploy uses swarm stack deploy).
|
||||
|
||||
services:
|
||||
|
||||
n8n-db:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: n8n
|
||||
POSTGRES_USER: n8n
|
||||
POSTGRES_PASSWORD: ${N8N_DB_PASSWORD}
|
||||
volumes:
|
||||
- n8n_db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- n8n_internal
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
n8n:
|
||||
image: docker.n8n.io/n8nio/n8n:1.83.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
n8n-db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
N8N_HOST: automate.manohargupta.com
|
||||
N8N_PORT: "5678"
|
||||
N8N_PROTOCOL: https
|
||||
WEBHOOK_URL: https://automate.manohargupta.com/
|
||||
N8N_EDITOR_BASE_URL: https://automate.manohargupta.com/
|
||||
DB_TYPE: postgresdb
|
||||
DB_POSTGRESDB_HOST: n8n-db
|
||||
DB_POSTGRESDB_PORT: "5432"
|
||||
DB_POSTGRESDB_DATABASE: n8n
|
||||
DB_POSTGRESDB_USER: n8n
|
||||
DB_POSTGRESDB_PASSWORD: ${N8N_DB_PASSWORD}
|
||||
# NEVER lose this key -- all stored credentials are encrypted with it
|
||||
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
|
||||
GENERIC_TIMEZONE: Asia/Kolkata
|
||||
TZ: Asia/Kolkata
|
||||
N8N_DIAGNOSTICS_ENABLED: "false"
|
||||
N8N_VERSION_NOTIFICATIONS_ENABLED: "false"
|
||||
volumes:
|
||||
- n8n_data:/home/node/.n8n
|
||||
networks:
|
||||
- dokploy-network
|
||||
- n8n_internal
|
||||
# Container-level labels (docker provider)
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.n8n.rule=Host(`automate.manohargupta.com`)"
|
||||
- "traefik.http.routers.n8n.entrypoints=websecure"
|
||||
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
|
||||
# Service-level labels (swarm provider) -- Dokploy deploys as swarm stack
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.n8n.rule=Host(`automate.manohargupta.com`)"
|
||||
- "traefik.http.routers.n8n.entrypoints=websecure"
|
||||
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
|
||||
|
||||
volumes:
|
||||
n8n_data:
|
||||
n8n_db_data:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
n8n_internal:
|
||||
driver: bridge
|
||||
123
paperless.compose.yml
Normal file
123
paperless.compose.yml
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# Paperless-ngx — docs.manohargupta.com
|
||||
# OCR + full-text search for PDFs and Office docs (lender drafts, tariff schedules, etc.)
|
||||
# 5 containers: webserver, redis broker, postgres, tika (Office), gotenberg (PDF render).
|
||||
# Tika + Gotenberg add ~400 MB RAM but are essential for .docx/.xlsx indexing.
|
||||
# First boot is slow (~90s) -- DB migrations run before the web UI becomes available.
|
||||
|
||||
services:
|
||||
|
||||
# Redis: job queue between the web UI and the OCR/consumer worker
|
||||
paperless-broker:
|
||||
image: redis:7-alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- paperless_redis:/data
|
||||
networks:
|
||||
- paperless_internal
|
||||
|
||||
# Postgres: document metadata, tags, correspondents, search index
|
||||
paperless-db:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: ${PAPERLESS_DB_PASSWORD}
|
||||
volumes:
|
||||
- paperless_db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- paperless_internal
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U paperless -d paperless"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Gotenberg: renders Office files (docx, xlsx) to PDF before OCR
|
||||
paperless-gotenberg:
|
||||
image: docker.io/gotenberg/gotenberg:8
|
||||
restart: unless-stopped
|
||||
command:
|
||||
- "gotenberg"
|
||||
- "--chromium-disable-javascript=true" # Security: no JS execution
|
||||
- "--chromium-allow-list=file:///tmp/.*" # Only allow local file access
|
||||
networks:
|
||||
- paperless_internal
|
||||
|
||||
# Tika: extracts text from Office formats that Gotenberg can't handle alone
|
||||
paperless-tika:
|
||||
image: docker.io/apache/tika:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- paperless_internal
|
||||
|
||||
# Main app: web UI + OCR worker + consumer (watches the consume volume)
|
||||
paperless:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
paperless-db:
|
||||
condition: service_healthy
|
||||
paperless-broker:
|
||||
condition: service_started
|
||||
paperless-gotenberg:
|
||||
condition: service_started
|
||||
paperless-tika:
|
||||
condition: service_started
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://paperless-broker:6379
|
||||
PAPERLESS_DBHOST: paperless-db
|
||||
PAPERLESS_DBNAME: paperless
|
||||
PAPERLESS_DBUSER: paperless
|
||||
PAPERLESS_DBPASS: ${PAPERLESS_DB_PASSWORD}
|
||||
# Secret key for Django session signing -- must be stable across restarts
|
||||
PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET_KEY}
|
||||
PAPERLESS_URL: https://docs.manohargupta.com
|
||||
# Office doc support via Tika + Gotenberg
|
||||
PAPERLESS_TIKA_ENABLED: "1"
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://paperless-gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://paperless-tika:9998
|
||||
# OCR: 'skip' means don't re-OCR docs that already have a text layer (faster)
|
||||
# Add '+hin' to language if you have Hindi documents: eng+hin (adds ~200 MB)
|
||||
PAPERLESS_OCR_LANGUAGE: eng
|
||||
PAPERLESS_OCR_MODE: skip
|
||||
PAPERLESS_TIME_ZONE: Asia/Kolkata
|
||||
USERMAP_UID: "1000"
|
||||
USERMAP_GID: "1000"
|
||||
volumes:
|
||||
- paperless_data:/usr/src/paperless/data # search index, models
|
||||
- paperless_media:/usr/src/paperless/media # original files + thumbnails
|
||||
- paperless_export:/usr/src/paperless/export # manual export target
|
||||
- paperless_consume:/usr/src/paperless/consume # drop files here to auto-ingest
|
||||
networks:
|
||||
- dokploy-network
|
||||
- paperless_internal
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.paperless.rule=Host(`docs.manohargupta.com`)"
|
||||
- "traefik.http.routers.paperless.entrypoints=websecure"
|
||||
- "traefik.http.routers.paperless.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.paperless.loadbalancer.server.port=8000"
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=dokploy-network"
|
||||
- "traefik.http.routers.paperless.rule=Host(`docs.manohargupta.com`)"
|
||||
- "traefik.http.routers.paperless.entrypoints=websecure"
|
||||
- "traefik.http.routers.paperless.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.paperless.loadbalancer.server.port=8000"
|
||||
|
||||
volumes:
|
||||
paperless_redis:
|
||||
paperless_db_data:
|
||||
paperless_data:
|
||||
paperless_media:
|
||||
paperless_export:
|
||||
paperless_consume:
|
||||
|
||||
networks:
|
||||
dokploy-network:
|
||||
external: true
|
||||
paperless_internal:
|
||||
driver: bridge
|
||||
Loading…
Add table
Reference in a new issue