MEGA-BOQ-WEBAPP/DEPLOY.md
MEGA INFRA 301d0fff44 MEGA INFRA BOQ Converter — Candy PDF to consultant Excel
Reads our Candy PDF (deterministically, no OCR or model needed) and populates
the consultant's own workbook using their formulas, column layout and PAYMENT
column. Nothing is ever silently overwritten: every disagreement is reported,
can be settled inside the app, and regenerated.

- extract   Candy text PDF -> tree (x-position column detection)
- template  layout detect, sequence align, write, totals, overrides
- validate  qty x rate and children-vs-subtotal reconciliation
- profiles  per-consultant layout profiles, stored on a volume

Shipped with a Dockerfile + docker-compose for Coolify.
2026-10-01 02:32:13 +02:00

3.4 KiB

Deploying MEGA BOQ Converter to Coolify

Docker Compose, using the Dockerfile in this repo. Coolify builds the image, publishes the port and puts its own HTTPS certificate in front — you do not need nginx, certbot or a separate database.

Before you start

Push the repo (already done if you followed the setup below), then in Coolify:

  1. New Resource → Docker Compose
  2. Source Type: Git Repository
  3. Repository: http://forgejo-b82b4lpyyzyg40thdsjdd38i.163.245.214.68.sslip.io/David/MEGA-BOQ-WEBAPP.git Branch main
  4. Docker Compose File: docker-compose.yml
  5. Base Directory: / (leave as-is)
  6. Deploy

Coolify reads expose: "8501" from the compose file and routes your domain to it. Set the domain in the resource's Domain tab and Coolify issues Let's Encrypt automatically.

First deploy checklist

check why
GET /_stcore/health returns ok the container is actually serving, not just running
Page loads over https with a valid cert Coolify's proxy is in front
Upload both files and regenerate proves the PDF path works with the container's libraries
Enter a consultant name, reload the page proves the profile volume is mounted

Environment variables

Only one matters, and it is already set in docker-compose.yml:

BOQ_PROFILES: /data/profiles

That path is on the named volume boq-profiles. If you move it, every saved consultant layout is lost on the next rebuild.

TZ: Africa/Johannesburg is set so container timestamps match SAST.

Override anything in Coolify's Environment Variables tab rather than editing the compose file, so redeploys do not fight you.

Things that will bite you

The container binds 0.0.0.0, not 127.0.0.1. The CMD in the Dockerfile passes --server.address=0.0.0.0 on purpose. .streamlit/config.toml binds 127.0.0.1 for local development, and that override would make the app invisible from outside the container. CLI flags beat the config file, which is why both exist.

XSRF protection is off (--server.enableXsrfProtection=false). Coolify's Traefik rewrites the request origin, and Streamlit's built-in origin check then rejects its own POSTs as forged. The app has no auth and no CSRF-sensitive state, so this is safe here — but it is another reason not to expose it to the open internet without putting auth in front.

Do not scale past one replica unless you move BOQ_PROFILES to a real shared store. Two replicas would each keep their own copy of the consultant profiles and quietly disagree. One replica is plenty for internal use.

Uploads are in-memory. Each conversion stages files in /tmp and discards them. Nothing about a client's BOQ persists unless you download the result, and the profile store holds only consultant names and column maps — never document content.

Rolling back

Coolify keeps the previous image. Rollback on the deployment reverts to it. If a redeploy somehow loses the profiles, the volume is still there — check that BOQ_PROFILES still points at /data/profiles in the environment tab.

Running it locally without Coolify

docker compose up -d          # http://127.0.0.1:8501

Or plain Docker:

docker build -t mega-boq .
docker run --rm -p 8501:8501 -v boq-profiles:/data/profiles mega-boq

Or without Docker at all:

./run_app.sh                   # creates a venv, runs on port 8501