Documentation

Administrator guide

Install, configure, secure and operate a Promulga instance.

Overview

Promulga is a small web application (Python, FastAPI) packaged as Docker containers:

ContainerRole
appportal (/) and workspace (/admin), database (SQLite by default, PostgreSQL optional), background jobs (e-mails, reminders, exports)
gotenbergconverts Word / LibreOffice files to PDF at publication
caddyreverse proxy with automatic HTTPS (Let's Encrypt)
onlyofficeoptional online editor (profile editor)

All data (database, files, published PDFs, signing key) lives in the Docker volume promulga-data. Source code and full documentation: GitHub.

Installation

Follow the download page for Windows, macOS or Linux. In short:

curl -L -o promulga.zip https://github.com/OlivierBouchezDataGovernance/promulga/releases/latest/download/promulga-docker.zip
unzip promulga.zip -d promulga && cd promulga
./deploy/setup.sh && nano .env
docker compose pull && docker compose up -d
docker compose logs app | grep set-password

The last command prints a one-time link (valid 24 h) to choose the password of the first administrator (ADMIN_EMAIL).

Server with a domain name (HTTPS)

  1. Create a Linux VM (2 vCPU, 4 GB RAM; Ubuntu 24.04), open ports 80 and 443, and give it a fixed IP address.
  2. Point a DNS record (A) to it, e.g. docs.example.org.
  3. In .env: SITE_DOMAIN=docs.example.org, BASE_URL=https://docs.example.org, SECURE_COOKIES=true.
  4. docker compose up -d: Caddy obtains the certificate automatically.

A complete step-by-step guide for a Google Cloud VM is in INSTALL.md. Two sites (portal and workspace on separate host names) and an intranet-only portal are possible with PUBLIC_HOST, ADMIN_HOST and PORTAL_ALLOWED_IPS.

Configuration (.env)

VariablePurpose
SITE_DOMAIN, BASE_URLhost name(s) served with HTTPS; public address used in e-mails
ADMIN_EMAILfirst administrator (one-time link in the logs)
REF_PATTERNdocument reference, default {TYPE_CODE}-{ID} (POL-0007)
FILENAME_PATTERNfile names, e.g. {CODE:domain}-{TYPE_CODE}-{VERSION}-{SUBVERSION}-{TITLE}
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_FROMoutgoing e-mail; the password goes in secrets/smtp_password
OIDC_ISSUER, OIDC_CLIENT_IDsingle sign-on (Entra ID, Google, Keycloak...); secret in secrets/oidc_client_secret
EXPORT_TAG, GITHUB_REPO, GITHUB_FOLDERpublic export; token in secrets/github_token
ONLYOFFICE_URL/onlyoffice to enable the online editor
SIGN_PDFSelectronic seal (PAdES) of published PDFs

Everything visual and functional (colours, logo, banner and footer HTML, deadlines, reminders, document types, portal access) is set in the application, Admin > Settings.

Secrets and security

  • No password in .env: each secret is a file in secrets/ (mode 600), mounted as a Docker secret; it never appears in docker inspect.
  • ./deploy/check.sh verifies the permissions of .env and secrets/ and warns about passwords left in .env.
  • Admin > Security lists the checks the application can do itself: HTTPS, temporary passwords, secrets, backups, administrators without passkey or SSO.
  • Recommend passkeys to administrators (My account > Passkeys).

First steps in the application

  1. Settings > Appearance: site name, colours, logo, banner and footer HTML.
  2. Settings > Deadlines and alerts: stage durations (default 28/14/14/14 days), reminders, periodic review, document types (Name=PREFIX=icon), Word template.
  3. Tags: taxonomies (Domain, Regulation, Audience, Visibility) and their codes; the tag public marks documents for the public export.
  4. Users: invite Document Managers and contributors (participants of a document are invited automatically).
  5. + New document: title, type, owner, reviewers, approvers, tags; the owner receives an e-mail.

Roles

RoleCan
viewerread the portal when it requires a sign-in
contributorbe owner, reviewer or approver of documents (counts as an editor)
managerDocument Manager: create documents, change participants, close a stuck review, start new revisions, withdraw, tags, audit log, indicators
adminmanager + users, settings, outbox, export, API tokens, security

Word templates, cover page and file names

For .docx files Promulga inserts a locked cover page (metadata and version history) and refreshes variables written as {{TITLE}}, {{VERSION}}, {{STATUS}}... at every check-in, download and publication. Other formats show a "limited capability" warning; their published PDF still gets a generated cover page. Details: WORD-TEMPLATES.md.

Online editor (OnlyOffice)

Set ONLYOFFICE_URL=/onlyoffice and start with docker compose --profile editor up -d. Owners edit in Draft and Revision; reviewers comment and suggest changes in the same single version during Review; everybody else reads. The Community Edition allows up to 20 simultaneous editors.

Export, API, webhooks, seal

  • Public export (Admin > Export): index page, PDFs, DCAT-AP / JSON / CSV catalogues and checksums of the documents tagged public; zip download or one-commit push to GitHub (fine-grained token, Contents: read and write on one repository).
  • REST API (Admin > API): read-only tokens; GET /api/v1/documents, /api/v1/documents/{ref}, /api/v1/taxonomies.
  • Webhooks (Settings > Integrations): Microsoft Teams, Slack or any JSON endpoint at each workflow event.
  • Electronic seal: SIGN_PDFS=true, with a self-signed certificate or your organisation's.

Details: INTEGRATIONS.md.

Backup, update, restore

# back up (database + files) inside the data volume, then copy it out
docker compose exec app promulga backup
docker compose cp app:/data/backups ./backups

# update: back up, pull the new images, restart (the database is migrated automatically)
docker compose pull && docker compose up -d

# restore an archive (replaces the current data)
docker compose stop app
docker compose run --rm app promulga restore /data/backups/promulga-backup-<date>.tar.gz --yes
docker compose up -d

Schedule the backup (cron) and keep copies off the server. Other commands: promulga reminders, promulga flush-outbox, promulga export --github, promulga create-admin [email protected] (one-time link for a lost administrator password).

Troubleshooting

  • Cannot sign in over HTTP: set SECURE_COOKIES=false for a local test only.
  • E-mails not sent: Admin > Outbox shows the error; check SMTP_* and secrets/smtp_password (cloud providers block port 25: use 587 or 465).
  • Publication fails: the PDF converter (gotenberg) must run; or check in a PDF.
  • Port 80 in use: HTTP_PORT=8080 and BASE_URL=http://localhost:8080.
  • Logs: docker compose logs --tail 200 app. Questions: [email protected] (best effort).