pdf-gen-v42-prod — Operations Workbook
Puppeteer / headless-Chromium HTML→PDF renderer for the p24-back-ts (W4 TypeScript) backend.
One of three HTML→PDF paths on bms-1 (see Consolidation review).
Host: bms-1 (94.23.26.113)
Public endpoint: https://pdf-gen-api.w4.pinbox24.com (LetsEncrypt via nginx-proxy)
Compose project: p24-back-ts, service pdf-gen — defined in docs/bms-1/docker-compose-w4.yml
Container name: pdf-gen-v42-prod
Image: private-registry.dev.pinbox24.com/pdf-gen-v42-prod (custom, private registry)
Not to be confused with:
wkhtml-v42-prod(bms-1,openlabs/docker-wkhtmltopdf-aas) — wkhtmltopdf-based renderer, internal-only, actively serves invoice/dispatch-book PDFs for the legacyv42-prod(JavaScript) backendpdf-service(vps-i1, FastAPI + Gotenberg) — internal MD→PDF service for Claude MCP tooling; unrelated to the Pinbox24 stack
Full identity audit: issue #3735.
Identity
| Attribute | Value |
|---|---|
| Purpose | Node.js PDF-generation microservice — accepts HTML/body payload, returns rendered PDF |
| App | pinbox24-starter → PM2 app pdf-gen-backend (Express, cluster mode) |
| Render engine | Puppeteer ^5.0.0 — puppeteer.launch() + page.pdf() in helper/pdfGen.helper.js |
| Entrypoint | ./bin/www |
| Internal port | 3000 (no host port binding — reached only via nginx-proxy) |
| Networks | prod-v-4-net + test-net (see Consolidation review for the two-network rationale) |
| Mounts | bind /var/log → /var/log (PM2 logs) |
Deploy pipeline
Deployed by GitLab CI — outside p24-infra’s SOPS+age flow.
| Attribute | Value |
|---|---|
| Source repo | pinbox24/p24-back-ts (GitLab) |
| CI job | .gitlab-ci.yml builds the image and pushes to private-registry.dev.pinbox24.com/pdf-gen-v42-prod |
| CI builder path | /root/builds/7N4sbbrB/0/pinbox24/p24-back-ts/ (on bms-1, shared with other p24-back-ts services) |
| Docker compose | docker-compose.yml in the builder path (mirrored in git-tracked source of truth at docs/bms-1/docker-compose-w4.yml) |
| Env file | /root/builds/7N4sbbrB/0/pinbox24/p24-back-ts/backend-environment.env (shared with other p24-back-ts services; maintained by the GitLab CI “autoheal” step from SOPS — see docs/playbooks/w4-gitlab-ci-image-pipeline.md) |
Redeploys land through GitLab CI, not through radieu/p24-infra PR merges.
Credentials / SOPS coverage
Zero credential env vars — none required.
The audit (#3735) enumerated the full container env: CONTAINER_NAME, VIRTUAL_HOST,
LETSENCRYPT_HOST, NODE_ENV=production, PORT/port=3000, TZ=Europe/Warsaw, NODE_VERSION,
YARN_VERSION, PATH. No DB URI, JWT, S3, or API keys — it is a stateless renderer: takes
HTML in, returns PDF out. No persistence, no auth secrets, no upstream API calls.
→ No SOPS entry needed and nothing to flag for secret-manager. The container reads
backend-environment.env for compose-level defaults (shared with other p24-back-ts services), but
nothing in that file is consumed by the renderer itself.
If the container ever grows a real credential (e.g. auth in front of the renderer, or an outbound
S3 call for asset caching), add it to secrets/pinbox24-w4.env.sops — the V42_* bucket for
p24-back-ts runtime — and route it in via the shared backend-environment.env autoheal step.
Health check
There is no formalized /health endpoint. Live-status verification uses the public vhost + docker inspect:
# From anywhere — verify TLS + reachability
curl -sfI https://pdf-gen-api.w4.pinbox24.com | head -5
# On bms-1 — container status
docker inspect pdf-gen-v42-prod --format '{{.State.Status}} restarts={{.RestartCount}}'
# On bms-1 — PM2 boot banner + any recent activity
docker logs pdf-gen-v42-prod --tail 50The audit observed only PM2 boot logs — no request activity — see Consolidation review.
Backup / restore
No persistent state — nothing to back up.
Rebuild is driven by GitLab CI in the pinbox24/p24-back-ts repo. Recovery = re-run the CI
pipeline (or docker compose up -d pdf-gen on bms-1 from the shared p24-back-ts builder path).
Monitoring
Not currently scraped by Prometheus (no /metrics endpoint). Container-level presence is visible
via cAdvisor on bms-1 (container_name="pdf-gen-v42-prod"), but no service-specific dashboards or
alerts exist.
If usage picks up: add a Blackbox probe against https://pdf-gen-api.w4.pinbox24.com and a
container-restart alert in monitoring/prometheus/rules/. Not urgent while activity is at zero.
Consolidation review
Filed as a documentation-only follow-up per issue #3975 — the audit deliberately deferred the keep-vs-consolidate decision to the W4 dev team.
Decision (2026-08-01): keep both engines — do not consolidate. pdf-gen-v42-prod (Puppeteer) is
now confirmed live-serving (root cause of a corrupt-PDF incident fixed and verified end-to-end, see
radieu/p24-infra#4792) and is the newer path, but
wkhtml-v42-prod (wkhtmltopdf) is specifically wired into postbook report generation and stays in
active use for that. No decommission of either engine is planned. This closes the three open questions
below — kept for historical context.
Current state — three HTML→PDF paths on bms-1
| Container | Engine | Compose project | Vhost | Status (2026-08-01) |
|---|---|---|---|---|
wkhtml-v42-prod | wkhtmltopdf (openlabs/docker-wkhtmltopdf-aas) | v42 | internal only (prod-v-4-net) | active — invoice/dispatch + postbook report rendering; stays in use, no decommission planned |
wkhtml-v42-stage | wkhtmltopdf (same image) | p24-back-ts | internal only | staging counterpart to the above — kept |
pdf-gen-v42-prod | Puppeteer / headless Chromium | p24-back-ts (actual source: pinbox24/p24-ms-pdfgen) | pdf-gen-api.w4.pinbox24.com | confirmed live — fixed 2026-08-01 (EOL Debian base + dead CI pipeline, #4792), verified with a real end-to-end PDF |
Resolved questions (originally for the W4 dev team, answered 2026-08-01)
- Is
pdf-gen-api.w4.pinbox24.comlive-serving today? Yes — confirmed via #4792 investigation and a live end-to-end PDF generation test. - Which PDF engine is the target end-state? Neither is being fully retired — both stay. Puppeteer
is the newer path (used where
pdf-gen-v42-prodis wired in); wkhtmltopdf remains required for postbook generation specifically. - Can
wkhtml-v42-stagebe removed now? No — kept as the staging counterpart towkhtml-v42-prod, which is staying in active use.
No decommission of either engine is planned. Revisit only if postbook generation itself is ever migrated off wkhtmltopdf.
Compliance
| Check | Status |
|---|---|
dev_r_services row | pdf-gen-v42-prod row exists, compliance_workbook='yes' |
| Workbook URL | docs/pdf-gen-v42-prod-operations.md (this file) |
| SOPS coverage | n/a — no credential env vars |
| Healthcheck | container-level only (no /health endpoint) — see Health check |
| Backup | n/a — stateless renderer |
| Monitoring | container-level presence via cAdvisor; no service-specific scrape/alerts yet |
| Restore | rebuild via GitLab CI pipeline |
| Password rotation | n/a — no credentials |
References
- Identity audit: #3735 (closed)
- Compliance follow-up: #3975 (this file)
- Compose definition:
docs/bms-1/docker-compose-w4.yml - Related services:
docs/pdf-service-operations.md(vps-i1, Gotenberg — unrelated),wkhtml-v42-prod(same host, legacy path) - W4 CI pipeline:
docs/playbooks/w4-gitlab-ci-image-pipeline.md - bms-1 operations:
docs/servers/p4-ovh-bms-1-ns367522-operations.md