services: targo-hub: image: node:20-alpine container_name: targo-hub working_dir: /app volumes: - ./server.js:/app/server.js:ro - ./lib:/app/lib:ro - ./public:/app/public:ro - ./package.json:/app/package.json:ro - ./data:/app/data # Templates RW so the campaign editor can save .html + .json + .mjml # files via PUT /campaigns/templates/:name. Was :ro previously which # broke save with EROFS — fixed when Unlayer started writing back. - ./templates:/app/templates # User-uploaded assets (images dragged into the editor) - ./uploads:/app/uploads - hub_modules:/app/node_modules command: sh -c "npm install --production 2>&1 | tail -1 && node server.js" env_file: .env restart: unless-stopped networks: - proxy - erpnext_erpnext - oktopus_oktopus labels: - "traefik.enable=true" - "traefik.docker.network=proxy" # Main router — webhooks + send + health (no auth) - "traefik.http.routers.targo-hub.rule=Host(`msg.gigafibre.ca`)" - "traefik.http.routers.targo-hub.entrypoints=websecure" - "traefik.http.routers.targo-hub.tls.certresolver=letsencrypt" - "traefik.http.services.targo-hub.loadbalancer.server.port=3300" # Disable response buffering for SSE - "traefik.http.middlewares.sse-headers.headers.customresponseheaders.X-Accel-Buffering=no" - "traefik.http.routers.targo-hub.middlewares=sse-headers" volumes: hub_modules: networks: proxy: external: true erpnext_erpnext: external: true oktopus_oktopus: external: true