fix(hub): templates volume mount must be RW for editor saves

When the Unlayer editor calls PUT /campaigns/templates/:name to save a
design, the hub writes:
  • templates/<name>.html   (compiled email-safe HTML)
  • templates/<name>.json   (Unlayer design tree for editor restore)
  • templates/<name>.bak-<ts>.html  (backup of previous version)

All three need write access to /app/templates inside the container.
The mount was previously declared as :ro, which made these writes
fail with EROFS (read-only filesystem) once the editor was wired up.

Two changes:
  1. Local docker-compose.yml: add ./templates:/app/templates (without
     :ro) and ./uploads:/app/uploads (which was already RW on prod but
     missing from the committed file — local was out of sync).
  2. Prod docker-compose.yml: hot-patched via sed on prod to drop the
     :ro flag, then `docker compose down + up -d` to apply the mount
     change. PUT verified working (returns 200 with size + design_size).

The /app/lib, /app/server.js, /app/public, /app/package.json mounts stay
:ro since the hub never writes to those — keeping the read-only flag
there is defense-in-depth against compromised code overwriting itself.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
louispaulb 2026-05-22 06:49:48 -04:00
parent 73e4118901
commit 2f1ebae587

View File

@ -9,6 +9,12 @@ services:
- ./public:/app/public:ro - ./public:/app/public:ro
- ./package.json:/app/package.json:ro - ./package.json:/app/package.json:ro
- ./data:/app/data - ./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 - hub_modules:/app/node_modules
command: sh -c "npm install --production 2>&1 | tail -1 && node server.js" command: sh -c "npm install --production 2>&1 | tail -1 && node server.js"
env_file: .env env_file: .env