Get started

Run Procera on your own server

Procera is pre-release and self-hosted: Docker Compose builds it from the repository and runs PostgreSQL, the server and the web app on one machine. These guides take you from an empty server to a first published policy that everyone has been asked to acknowledge.

  1. Install Procera with Docker Compose
  2. First-time setup
  3. Configuration reference
git clone https://github.com/CasualOffice/Procera.git && cd Procera
cp deploy/.env.example deploy/.env      # fill in the passwords and the master key
docker compose -f deploy/compose.yml up -d --build
docker compose -f deploy/compose.yml logs procera | grep bootstrap_token   # then open /setup

Install Procera with Docker Compose

This guide runs a complete Procera installation on one machine with Docker Compose: the database, the server and the web app. It takes about 20 minutes, most of it the first build.

Status: pre-release. There are no published images yet, so Compose builds Procera from this repository. Files are stored on local disk (a Docker volume) by default; set PROCERA_STORAGE=s3 to keep them in an S3-compatible bucket instead (see the configuration reference). External key management (KMS) is designed but not built yet.

Next steps after this guide: First-time setup and the configuration reference.

What you get

deploy/compose.yml starts these containers:

ServiceImageWhat it does
postgrespostgres:16The database. Data in the pgdata volume. On the first start it creates Procera's database roles (deploy/sql/00-roles.sql) and sets their passwords.
migratebuilt from DockerfileRuns procera migrate as the procera_migrator role, then exits. Runs on every up, before the server starts.
procerabuilt from DockerfileRuns procera serve --all: the API, the background worker (email, events) and the scheduler in one process. Uploaded files go to the files volume. Not published to the host.
webbuilt from deploy/web/DockerfileCaddy. Serves the web app (web/dist) and forwards /api, /sysapi, /healthz, /readyz and /version to procera, so the browser talks to one address. The only service with published ports.

The procera server serves the API only; it does not serve the web app's files. That is why the web container exists. If you already run a reverse proxy, see Using your own reverse proxy.

Optional services, each behind a Compose profile:

ProfileServiceTurn on withThen set in .env
cacheValkey 8--profile cachePROCERA_CACHE_URL=redis://valkey:6379
scanClamAV--profile scanPROCERA_CLAMD_ADDR=clamav:3310
mailMailpit (a test inbox at http://127.0.0.1:8025)--profile mailPROCERA_SMTP_URL=smtp://mailpit:1025

Without the cache, Procera uses an in-process cache, which is fine for one server. Without ClamAV, uploads are checked only for the EICAR test file, so turn on scan for real use. Mailpit catches email for testing; it never delivers to real inboxes.

Prerequisites

  • Docker Engine with the Compose v2 plugin (docker compose version works).
  • Memory: about 4 GB free for the first build (it compiles the Rust server); about 1 GB to run. ClamAV needs roughly 2 to 3 GB more.
  • Disk: about 10 GB for build caches and images, plus your data.
  • A clone of this repository. Run every command below from its root.
  • For production: a domain name pointing at the machine, and ports 80 and 443 open (see HTTPS).

1. Create the env file

All settings and secrets live in one file, deploy/.env. Compose reads it automatically because it sits next to deploy/compose.yml. It is ignored by git; keep it that way.

cp deploy/.env.example deploy/.env

Fill in the three database passwords. Hex passwords are safest because they go into connection URLs:

openssl rand -hex 24   # run it three times, once per password
  • POSTGRES_PASSWORD is the database superuser. Only the init scripts and your backups use it.
  • PROCERA_MIGRATOR_DB_PASSWORD is for procera_migrator, which owns the schema and runs migrations.
  • PROCERA_APP_DB_PASSWORD is for procera_app, the role the server uses. It can read and write rows but never change the schema, and row-level security always applies to it.

The role passwords are set once, when the pgdata volume is first created. Changing them in .env later does not change them in the database (see Troubleshooting).

2. Generate the master key

The master key protects everything Procera encrypts: each workspace's keys, stored files, two-step verification secrets and the saved email password. Generate it once:

docker compose -f deploy/compose.yml run --rm --no-deps -T procera keygen

The first time, this builds the server image, which takes a while. The command prints a base64 key on its own line (and a log line about it). Put the key in deploy/.env:

PROCERA_MASTER_KEY=…the printed key…

openssl rand -base64 32 produces an equivalent key if you prefer.

Back up the master key now, separately from your database backups, for example in a password manager or secret store. If you lose it, the encrypted data in the database and the stored files cannot be read again. Nobody can recover it for you. Don't change it on a running installation either: data encrypted with the old key would become unreadable.

The server refuses to start with a database but without a master key.

3. Set the address

PROCERA_PUBLIC_URL is the address people type into their browser. Procera uses it in email links and for passkeys.

  • Trying it on your own computer: keep PROCERA_PUBLIC_URL=http://localhost:8080 and PROCERA_HTTP_PORT=8080.
  • A server with a domain: see HTTPS.

4. Start Procera

docker compose -f deploy/compose.yml up -d --build

With optional services, add profiles, for example docker compose -f deploy/compose.yml --profile scan --profile mail up -d --build, or set COMPOSE_PROFILES=scan,mail in deploy/.env. Remember to set the matching variables (table above).

Compose starts postgres, waits until it's healthy, runs migrate, starts procera once migrations succeed, and starts web once procera answers its health check. Check the state:

docker compose -f deploy/compose.yml ps
curl -s http://localhost:8080/healthz    # {"status":"ok"}
curl -s http://localhost:8080/readyz     # {"status":"ready","database":"ok",…}

migrate shows as exited (0); that is expected.

5. Find the one-time setup token

There are no default accounts. The first time Procera starts, it prints a one-time setup token to its log. The token is valid for 24 hours and works once.

docker compose -f deploy/compose.yml logs procera | grep bootstrap_token

The log is JSON; the token is the value of bootstrap_token, in a line that says platform not bootstrapped. If it has expired, restart the server to print a new one: docker compose -f deploy/compose.yml restart procera. Tokens are printed only until setup is finished.

6. Open /setup

Open http://localhost:8080/setup (or https://your-domain/setup) and paste the token. Then follow First-time setup: you create the system owner, turn on two-step verification, set up email and create the first workspace.

HTTPS

Run Procera over HTTPS for anything beyond a local trial. Sign-in cookies are Secure with the __Host- prefix, so browsers only send them over HTTPS (they make an exception for http://localhost).

The bundled Caddy can get and renew a certificate for you. Point a DNS record at the machine, open ports 80 and 443, and set in deploy/.env:

PROCERA_SITE_ADDRESS=procera.example.com
PROCERA_HTTP_PORT=80
PROCERA_HTTPS_PORT=443
PROCERA_PUBLIC_URL=https://procera.example.com

Then docker compose -f deploy/compose.yml up -d. Certificates are kept in the caddy_data volume.

Using your own reverse proxy

If a reverse proxy already terminates TLS on the machine, keep PROCERA_SITE_ADDRESS=:80, publish the web container on a local port (for example PROCERA_HTTP_PORT=127.0.0.1:8080) and proxy your domain to it. The proxy must replace any X-Forwarded-For header from the client with the real client address: Procera takes the first address in that header for sign-in rate limits and the audit log. The configuration guide has Caddy and nginx examples, including running without the web container.

Backups

Back up three things, and test restoring them:

  1. The database.
  2. The files volume (uploaded files, encrypted).
  3. The master key (PROCERA_MASTER_KEY). Without it, 1 and 2 are unreadable. Keep it apart from the other backups.

For a consistent pair, stop the server briefly, back up, and start it again:

docker compose -f deploy/compose.yml stop procera

# 1. Database (custom format, compressed)
docker compose -f deploy/compose.yml exec -T postgres \
  pg_dump -U postgres -Fc procera > procera-db-$(date +%F).dump

# 2. Files volume (the volume is named <project>_files; the project is "procera")
docker run --rm -v procera_files:/data:ro -v "$PWD":/backup alpine \
  tar czf /backup/procera-files-$(date +%F).tgz -C /data .

docker compose -f deploy/compose.yml start procera

Keep deploy/.env safe too: it holds the database passwords.

Restoring

Restore into a fresh stack with the same deploy/.env (above all the same master key):

docker compose -f deploy/compose.yml down              # keep volumes unless you are replacing them
docker volume rm procera_pgdata procera_files          # only when replacing the data
docker compose -f deploy/compose.yml up -d postgres     # creates the roles and their passwords
docker compose -f deploy/compose.yml exec -T postgres \
  pg_restore -U postgres -d procera --clean --if-exists < procera-db-YYYY-MM-DD.dump
docker run --rm -v procera_files:/data -v "$PWD":/backup alpine \
  sh -c 'tar xzf /backup/procera-files-YYYY-MM-DD.tgz -C /data && chown -R 65532:65532 /data'
docker compose -f deploy/compose.yml up -d

pg_restore may report that the discovery schema or the extensions already exist; those notices are harmless. The files volume must stay owned by user 65532, the server's non-root user.

Upgrades

Procera has no packaged releases yet, so upgrading means updating your checkout and rebuilding:

# back up first (see above)
git pull
docker compose -f deploy/compose.yml up -d --build

migrate applies new migrations before the new server starts. Migrations only move forward: to go back to an older version, restore the backup you took before upgrading. Read the release notes or commit log for changes to environment variables.

Day-to-day commands

docker compose -f deploy/compose.yml ps                  # what is running
docker compose -f deploy/compose.yml logs -f procera     # server logs (JSON lines)
docker compose -f deploy/compose.yml restart procera     # restart the server
docker compose -f deploy/compose.yml down                # stop everything, keep data
docker compose -f deploy/compose.yml down -v             # stop and DELETE all data volumes

Change the log detail with PROCERA_LOG (for example PROCERA_LOG=debug), then docker compose -f deploy/compose.yml up -d.

Troubleshooting

required variable POSTGRES_PASSWORD is missing a value (or one of the other passwords). Fill it in deploy/.env. Compose refuses to start without the three database passwords.

procera exits with PROCERA_MASTER_KEY is required when a database is configured. Set PROCERA_MASTER_KEY (step 2). PROCERA_MASTER_KEY must be 32 bytes (base64) means the value is truncated or isn't a key from procera keygen.

migrate fails with password authentication failed for user "procera_migrator". The role passwords were set when the pgdata volume was created, and .env has changed since. Either put the original passwords back, or set the new ones in the database:

docker compose -f deploy/compose.yml exec postgres psql -U postgres -d procera \
  -c "ALTER ROLE procera_migrator PASSWORD 'new-migrator-password'" \
  -c "ALTER ROLE procera_app PASSWORD 'new-app-password'"

On a trial install with no data you want to keep, docker compose -f deploy/compose.yml down -v starts from scratch.

There is no bootstrap_token line in the log. Either setup is already finished (opening /setup then says "Procera is already set up"; sign in instead), or the log has rotated. Restart procera to print a fresh token while setup is unfinished.

"This setup token doesn't work". Each token works once and expires after 24 hours. A rejected password or an email that already exists also uses the token up. Restart procera for a new one.

Signing in works, but you're signed out again straight away. The browser isn't keeping the Secure cookie because the address is plain HTTP and not localhost. Use HTTPS. For a short trial on a private network only, set PROCERA_INSECURE_COOKIES=true.

Emails aren't arriving. The log says email delivery isn't set up: emails are queued but not sent until you set up email in the system console (Email & platform) or set PROCERA_SMTP_URL. Queued emails go out once delivery works. With Mailpit, use PROCERA_SMTP_URL=smtp://mailpit:1025: the console's form allows unencrypted delivery only to localhost, and Mailpit's address in Compose is mailpit.

Links in emails point to the wrong address. Set PROCERA_PUBLIC_URL to the address people use. System › Email & platform shows the value the server is using and where it came from.

Uploads say they aren't scanned for real malware. Turn on the scan profile and set PROCERA_CLAMD_ADDR=clamav:3310. ClamAV downloads its signatures on first start, which can take several minutes; docker compose -f deploy/compose.yml ps shows it as healthy when ready.

The port is already in use. Change PROCERA_HTTP_PORT (and PROCERA_PUBLIC_URL to match).

The build runs out of memory. Give Docker more memory (Docker Desktop: Settings › Resources), or build on a bigger machine and copy the images.

Source: docs/guides/install-docker-compose.md

First-time setup

This guide takes a new Procera installation from the one-time setup token to a first published policy that everyone has been asked to acknowledge. It assumes Procera is running and you can open it in a browser (see Install with Docker Compose). Names in bold are the exact labels you'll see on screen.

There are two kinds of administration in Procera:

  • The system console (/system) runs the installation: workspaces, quotas, email and platform health. Its users manage workspaces, not their content.
  • A workspace is one organisation's space: its people, documents and settings. Its owner and admins run it from Admin.

The person who sets up the installation can also own the first workspace, or invite someone else to.

Overview

  1. Create the system owner with the setup token.
  2. Turn on two-step verification.
  3. Set up email (or skip it for now).
  4. Create the first workspace and invite its owner.
  5. The owner joins and turns on two-step verification.
  6. Guided setup in the workspace.
  7. The first policy: write, submit, review, publish, and ask everyone to acknowledge it.

You need an authenticator app on your phone (for example 1Password, Google Authenticator or Microsoft Authenticator).

1. Create the system owner

  1. Get the setup token from the server log. With Docker Compose: docker compose -f deploy/compose.yml logs procera | grep bootstrap_token
  2. Open /setup on your Procera address, for example http://localhost:8080/setup. The page is Set up Procera.
  3. Fill in Setup token, Work email, Your name, Password (at least 12 characters; a short sentence works well) and Confirm password.
  4. Click Create system owner.

The token works once and expires after 24 hours. If the page says This setup token doesn't work, restart the server to print a new one. A rejected password or an email that already exists also uses the token up, so check the password rules before you submit. If the page says Procera is already set up, someone has finished this step: sign in instead.

2. Turn on two-step verification

The system console always requires two-step verification. Right after creating the account, Procera signs you in and asks you to turn it on:

  1. On Turn on two-step verification, click Get started.
  2. On Scan this code, scan the QR code with your authenticator app (or use Can't scan? Enter this key), type the 6-digit code and click Verify and turn on.
  3. On Save your recovery codes, Download or Copy the codes and keep them somewhere safe. Each one lets you sign in once if you lose your phone.
  4. Click I've saved them, continue. You go straight on to the console, without signing in again.

3. Set up email

You land on Finish setting up (/system/setup), which has two short steps: 1. Email (optional) and 2. First workspace.

Procera emails invitations, reminders and password resets. Without email they wait in a queue, and nothing is lost: they go out once email works. But the workspace owner joins through an emailed invitation, so set up email now if you can.

On Set up email, enter your mail provider's details:

FieldWhat to enter
SMTP hostThe server name only, such as smtp.example.com.
PortFilled in from the encryption choice: 587 for STARTTLS, 465 for implicit TLS.
EncryptionSTARTTLS (required): delivery stops if the server doesn't offer encryption. Implicit TLS: encrypted from the first byte. None (only for a relay on this server): allowed only when the host is localhost.
Username / PasswordLeave empty if the server doesn't ask for a sign-in. The password is stored encrypted and never shown again.
From addressAn address your mail server is allowed to send from.
Sender nameShown as the sender. Workspaces can set their own.
Reply-to addressOptional.

Click Save and continue, then Send test email to check delivery end to end, and Continue. Saving asks you to confirm it's you (your password or a code) if you haven't verified recently.

  • If the server sets PROCERA_SMTP_URL, the step says Email is already set by the environment. There's nothing to enter: send a test email and continue.
  • To do it later, click Skip for now. You'll find the same form in the system console under Email & platform, which also shows the public address, file storage and malware scanning in use.
  • The page has DNS advice (SPF, DKIM, DMARC) to help email reach inboxes. Procera doesn't sign messages itself.

4. Create the first workspace

On Create your first workspace, click Create workspace. The New workspace dialog asks for:

  • Workspace name, for example your company's name.
  • Slug: identifies the workspace in addresses. It is suggested from the name; lowercase letters, numbers and hyphens, 3 to 63 characters.
  • Configuration profile: pre-sets security, review and retention defaults. Every setting can be changed later.
    • Starter: under 50 people. Two-step verification for owners and admins; the owner publishes without review.
    • Standard: most organisations. Invite-only, independent review for controlled processes.
    • Enterprise: many departments. Two-step verification for everyone, two-person rule, access reviews.
    • Regulated: pharma, finance, public sector. The dialog's hint mentions Part 11 signatures and Separation mode; what the profile sets today is two-step verification for everyone, a review with two reviewers for every document, and re-acknowledgement on every publish.
  • Owner email: the person who will own and set up the workspace. It can be your own address.

Click Create workspace. The confirmation says We invited … to own …, and the owner gets an email invitation. If email isn't set up, the invitation waits in the queue and goes out once you set up email in Email & platform.

Click Go to the system console to see the workspace under Workspaces. Quotas & usage shows seats and storage per workspace, and the default limits for each profile.

5. The owner joins

The owner opens the link in the invitation email. The page is Join followed by the workspace name.

  • New to Procera: fill in Your name, Password and Confirm password and click Create account and join.
  • Already has an account (for example the system owner inviting themselves): click Sign in to accept, or Join followed by the workspace name if already signed in with that email.

Every profile requires two-step verification for workspace owners, so a new owner sees Turn on two-step verification next. It's the same three steps as in step 2. After I've saved them, continue, the owner is in the workspace, on Home.

Invitation links expire. If one doesn't work, a workspace admin can Resend it from Admin › Members; the earlier link then stops working.

6. Guided setup in the workspace

Home shows a Set up (workspace name) checklist for owners and admins (it disappears when every step is done, or you can hide it). Click Start setup to open four short steps. Each one saves as it goes, and you can Skip for now and come back from Home.

  1. Your workspace
    • Workspace name and Accent colour (used for links and highlights; Procera adjusts it so text stays readable). Add a logo later in Settings.
    • How documents get approved:
      • Someone else reviews every document (recommended): the author can't approve their own work.
      • Only controlled documents: everyday documents publish straight away.
      • No review: authors publish directly.
    • Time zone: due dates, reminders and digests follow it.
    • Click Save and continue.
  2. Starting point: starter packs of reviewed documents. They install as drafts for you to adapt, review and publish. Click Install and continue. More packs are under Admin › Templates.
  3. Departments: type one per line (for example People, Finance, Engineering, Sales). They're used to target documents, campaigns and announcements, and to scope roles. Click Add … and continue.
  4. Invite people: an email and a role per person: Member, Reviewer, Compliance or Admin. Everyone can read and acknowledge; pick a role for people who review or manage. Invite at least one Reviewer if documents need review. Click Invite … and finish.

The Home checklist also links to the remaining steps: Choose who reviews and who manages (Admin › Roles & access), Publish your first policy, Ask everyone to acknowledge it and Require two-step verification for admins (Admin › Settings).

7. Your first policy

Write it

  1. Open Library and click New document (or use a draft from a starter pack).
  2. In New document, choose Policy, enter a Title (for example "Acceptable Use of IT"), and tick Controlled if it must always have an independent review. Click Create draft.
  3. Click Edit, write the content (type # for a heading, - for a list), and click Save draft. You can add files under Attachments with Attach a file.
  4. Optional: under Applies to, click Change to choose who the policy applies to (Everyone or Specific people by department, group, role or location). It then shows in their Applies to me list.

Nobody else sees a draft until it's published.

Submit it for review

Click Submit for review. The status changes from Draft to In review. There's no reviewer to pick: everyone who is allowed to review sees the task on Home under Needs you and gets a notification. While it's in review, you can Withdraw it back to a draft.

On the Starter profile (or with No review), submitting approves the draft straight away, unless it's marked Controlled.

Review it

The reviewer opens the task (Review) from Home or from the notification and reads the document. Then:

  • Approve: the status becomes Approved once enough reviewers have approved (the Approvals property shows how many so far).
  • Request changes: the dialog asks What should change? and sends the draft back to the author.

Authors can't review their own version. If the reviewer hasn't verified recently, Procera asks them to Confirm it's you first.

Publish it

Someone allowed to publish clicks Publish on the approved version. In the Publish v1 dialog:

  • Goes live (optional): leave it empty to publish now, or pick a date and time to schedule it.
  • Note (optional): for later versions this becomes What changed? (required), with a Type of change of Major or Minor.

Click Publish now (or Schedule). The status becomes Published (or Scheduled) and it's the version everyone reads. Publishing doesn't ask anyone to acknowledge it by itself; that's the next step. To change it later, click New version.

Ask everyone to acknowledge it

  1. Open Campaigns and click New campaign.
  2. Pick the Document (only published documents are listed). The Name defaults to "Acknowledge" followed by the title.
  3. Choose the Audience, tick Also ask people who join later if new joiners should be included, and optionally set Due on (empty uses the workspace default, counted from launch).
  4. Click Create draft. The campaign page shows how many people will be asked and the statement they confirm (by default "I have read and understood this document and will follow it.").
  5. Click Launch. People are notified.

Each person sees Acknowledge "…" on Home, clicks Read and acknowledge, reads the document and clicks I acknowledge. On the campaign page you can follow Acknowledged, Pending and Overdue, Remind pending, download the Evidence CSV, and Close the campaign when you're done. Reminders and manager escalation also run automatically according to the workspace settings.

Every step above is recorded in the audit log (Admin › Audit log).

Where to go next

  • Configuration reference: server settings, settings in the system console and in workspace Settings, and security notes.
  • Admin › Settings in the workspace: sign-in and security, documents and reviews, acknowledgements, notifications, retention and more.

Source: docs/guides/first-time-setup.md

Configuration reference

Procera is configured in three places:

  1. The server: command-line options and PROCERA_* environment variables, read at start-up. These are for whoever runs the installation.
  2. The system console (/system): email delivery, quotas and platform floors, changed in the app by system administrators and recorded in the system audit log.
  3. Workspace Settings (Admin › Settings): everything about how one workspace works, changed by its owner and admins and recorded in its audit log.

See also: Install with Docker Compose and First-time setup.

1. Server options and environment variables

The procera binary has five commands:

CommandWhat it does
procera serveRuns the server. Add --all to run the API, the background worker (event dispatch, email sending) and the scheduler in one process. Without --all, only the API runs: nothing sends email or publishes scheduled versions. Use --all today.
procera migrateApplies database migrations. Run it as the procera_migrator role, never the app role.
procera keygenPrints a new random master key (base64) for PROCERA_MASTER_KEY on standard output.
procera rotate-master-keyMoves the database to a new master key. Stop the server, back up, run procera keygen for a new key, then run this with PROCERA_DATABASE_URL, the current PROCERA_MASTER_KEY and the new key in PROCERA_NEW_MASTER_KEY (or --new-key; the variable keeps it out of the process list). In one transaction it re-seals every value sealed under the master key (workspace keys, two-step secrets, invitation tokens, older email bodies), checks each with the new key, and prints the counts; it refuses a malformed key, the same key, or a current key that doesn't open the data. Then put the new key in .env as PROCERA_MASTER_KEY and start the server. Access tokens and signed file links issued before stop working (people stay signed in). Keep the old key with backups taken before the rotation.
procera healthcheckExits 0 if the server on PROCERA_BIND answers GET /healthz with 200, else 1 (loopback is used when bound to 0.0.0.0). For container health checks.

Every option can be given as a flag or as its environment variable; a flag wins. An empty variable counts as not set. Logs are JSON lines on standard error; standard output is reserved for command output.

procera serve

VariableFlagDefaultRequiredPurpose
PROCERA_BIND--bind127.0.0.1:8080 (the container image sets 0.0.0.0:8080)NoAddress and port the HTTP API listens on.
(none)--alloffYes, in practiceRun the worker and scheduler in the same process (see above).
PROCERA_DATABASE_URL--database-urlnoneYesPostgreSQL URL for the runtime role procera_app, e.g. postgres://procera_app:PASSWORD@db:5432/procera. Without it the server starts in a smoke-test mode with no accounts or data. The server refuses to start if any workspace table lacks forced row-level security.
PROCERA_MASTER_KEY--master-keynoneYes, with a database32 random bytes, base64 (procera keygen or openssl rand -base64 32). Root key for secrets at rest (workspace keys, stored files, two-step secrets, the saved SMTP password) and for token signing.
PROCERA_PUBLIC_URL--public-urlhttp://127.0.0.1:8080Yes, in practiceThe address people use in the browser. Used in email links and as the default passkey relying party. System › Email & platform shows the value in use and where it came from.
PROCERA_WEBAUTHN_RP_ID--webauthn-rp-idthe host of PROCERA_PUBLIC_URL (a loopback IP maps to localhost)NoPasskey relying-party id, a registrable domain such as example.com. Changing it later invalidates registered passkeys.
PROCERA_SMTP_URL--smtp-urlnoneNoSMTP relay, e.g. smtp://user:pass@host:587?tls=required (STARTTLS) or smtps://user:pass@host:465 (implicit TLS). Wins over the email settings saved in the system console. With neither, emails stay queued.
PROCERA_MAIL_FROM--mail-fromProcera <no-reply@localhost>With PROCERA_SMTP_URLSender used with PROCERA_SMTP_URL. Console settings carry their own sender.
PROCERA_CACHE_URL--cache-urlnone (in-process cache)NoValkey/Redis URL for caches and rate limits, e.g. redis://valkey:6379. The cache is advisory: if it's unreachable at start-up the server logs a warning and uses the in-process cache. Use a shared cache once you run more than one server process.
PROCERA_INSECURE_COOKIES--insecure-cookiesfalseNoUse non-Secure cookies without the __Host- prefix. Only for local HTTP development and tests.
PROCERA_LOGIN_RATE_PER_MIN--login-rate-per-min30NoSign-in attempts allowed per client IP per minute. Raise only for test environments where everyone shares one IP.
PROCERA_TRUSTED_PROXY_HOPS--trusted-proxy-hops1NoHow many reverse proxies in front of the server append to X-Forwarded-For. The client address is taken that many entries from the end, so earlier (client-supplied) entries are ignored. Use 0 if the server is reached directly with no proxy.
PROCERA_FILES_DIR(none)a procera-files folder in the system temp directory (the container image sets /var/lib/procera/files)Yes, in practiceWhere uploaded files are stored (encrypted). Without it, files can be lost on restart, and the console warns about it. Used when PROCERA_STORAGE is local (the default).
PROCERA_STORAGElocal—Nolocal keeps files on disk (PROCERA_FILES_DIR); s3 keeps them in an S3-compatible bucket (AWS S3, Ceph, SeaweedFS, Cloudflare R2…; checked against SeaweedFS). Files are encrypted before they leave the server either way. A wrong S3 setting stops the server at start-up rather than failing uploads later.
PROCERA_S3_BUCKET(none)—With s3The bucket.
PROCERA_S3_REGION(from the AWS environment)—OftenFor example eu-west-1.
PROCERA_S3_ENDPOINTAWS—For non-AWS storesFor example https://s3.example.com or http://seaweedfs:8333.
PROCERA_S3_ACCESS_KEY_ID / PROCERA_S3_SECRET_ACCESS_KEY(from the AWS environment or instance role)—Unless a role provides themKeys for the bucket. Keep them in your secret store.
PROCERA_S3_PATH_STYLEtrue—Noendpoint/bucket/key addressing, which most non-AWS stores need. Set false for virtual-hosted AWS buckets.
PROCERA_S3_ALLOW_HTTPfalse—NoPlain HTTP endpoints, for development or a private network only.
PROCERA_S3_PREFIX(none)—NoA folder inside the bucket, so several environments can share one bucket.
PROCERA_CLAMD_ADDR(none)noneRecommendedClamAV clamd address (host:port, e.g. clamav:3310). Without it, uploads are checked only for the EICAR test file.
PROCERA_EGRESS_ALLOW(none)noneOnly for internal receiversComma-separated address ranges (CIDR, e.g. 10.0.0.0/8,192.168.10.5/32) that webhooks and single sign-on providers may reach even though they are private. Without it, webhooks go only to public https addresses on ports 443, 80, 8443 or 8080; with it, the listed ranges also accept plain http and any port.
PROCERA_LOG(none)infoNoLog filter in tracing EnvFilter syntax, e.g. warn, debug, info,procera_notify=debug.

procera migrate

VariableFlagDefaultRequiredPurpose
PROCERA_MIGRATOR_URL--migrator-urlnoneYesPostgreSQL URL for the procera_migrator role.
PROCERA_LOG(none)infoNoAs above.

procera healthcheck

VariableFlagDefaultPurpose
PROCERA_BIND--bind127.0.0.1:8080Address of the running server to probe.

Database roles

Run deploy/sql/00-roles.sql once per database, as a superuser, before the first migration. It creates:

  • procera_migrator: owns the schema and runs migrations. Never used by the running server.
  • procera_app: the runtime role. Not an owner, no BYPASSRLS, data changes only, so row-level security always applies.
  • procera_discovery: cannot log in. Owns only a few cross-workspace lookup functions that return ids.

It also creates the citext and ltree extensions. Set the two login roles' passwords yourself (the Compose stack does this from deploy/.env).

Endpoints for monitoring

PathAnswers
GET /healthz{"status":"ok"} while the process is up.
GET /readyzstatus (ready or not_ready), database (ok, unavailable or none) and the cache backend and health. A degraded cache stays ready.
GET /versionName, version and server time.

Variables used by the Compose files only

deploy/compose.yml also reads these from deploy/.env. The server never sees them directly.

VariableDefaultPurpose
POSTGRES_PASSWORDnone (required)Postgres superuser password.
PROCERA_MIGRATOR_DB_PASSWORDnone (required)Password set for procera_migrator on first start; builds PROCERA_MIGRATOR_URL.
PROCERA_APP_DB_PASSWORDnone (required)Password set for procera_app on first start; builds PROCERA_DATABASE_URL.
PROCERA_HTTP_PORT8080Host port (optionally ip:port) for the web container's HTTP.
PROCERA_HTTPS_PORT8443Host port for HTTPS, used when PROCERA_SITE_ADDRESS is a domain.
PROCERA_SITE_ADDRESS:80Caddy site address. A domain name turns on automatic HTTPS certificates.
PROCERA_IMAGE, PROCERA_WEB_IMAGEprocera:local, procera-web:localImage names to build or use.
MAILPIT_UI_PORT8025Mailpit's web inbox, on 127.0.0.1 (with the mail profile).
COMPOSE_PROFILESnoneOptional services to start: cache, scan, mail.

2. Settings in the app

System console

System administrators sign in and open System console (from Choose a workspace, or /system). Two-step verification is required. Changes are recorded in System audit.

PageWhat you can change
WorkspacesCreate workspaces (New workspace: name, slug, configuration profile, owner email), Make read-only, Lock, Reactivate, Schedule deletion (with a grace period), and Edit quotas per workspace (member limit, storage limit).
Quotas & usageSeats and storage per workspace, and Defaults by profile: the member and storage limits copied into each new workspace. The member limit is enforced when people are invited.
Email & platformEmail delivery: SMTP host, port, Encryption, username, password, from address, sender name and reply-to, plus Send test email. Changes apply without a restart. If PROCERA_SMTP_URL is set, it wins and the form is replaced by a notice. Platform basics, File storage and malware scanning: shown as configured on the server, with where each value comes from.
Platform healthStatus checks for the installation.
System auditThe system-plane audit log.

Platform floors set the minimum every workspace must meet. A workspace can be stricter but never looser: a looser value is rejected when saved, and existing looser values are clamped and shown as Platform minimum in workspace Settings. Keys with floors today: auth.mfa.required_roles, auth.mfa.allowed_methods, auth.password.min_length, auth.password.breach_check, auth.session.idle_timeout, auth.session.absolute_timeout, auth.stepup.window, api.tokens.max_ttl, access.admin_content_access_log, retention.governance_record.keep_for, files.max_size, files.scan.required. There is no console page for floors yet: set them through the system API (GET /sysapi/v1/settings, PUT /sysapi/v1/settings/{key} with {"value": …, "reason": "…"}), signed in as a system administrator.

Workspace Settings

Workspace owners and admins open Admin › Settings. Each setting shows its effective value and where it comes from (default, profile, workspace, department or platform minimum). The categories:

CategoryCovers
General & brandingName, logo, colours, language, time zone and the words Procera uses
Sign-in & securityPasswords, two-step verification, session length and admin access logging. Single sign-on has its own page, Admin › Single sign-on (see below)
People & directoryWho can join, what happens when someone leaves, positions
Documents & reviewsWho must review before publishing, review cycles, numbering
Acknowledgements & announcementsWhen people must re-acknowledge, campaign reminders and escalation, announcement rules
NotificationsWhich channels Procera uses, digests and quiet hours
Data, retention & filesUpload limits, malware scanning, and how long records are kept
Single sign-on (OpenID Connect)

In Admin › Single sign-on, copy the redirect URL (<PROCERA_PUBLIC_URL>/api/v1/auth/sso/callback) into a new OpenID Connect web application at your provider (Okta, Microsoft Entra ID, Google Workspace, Keycloak and others), then enter its issuer URL, client ID, client secret and the email domains it vouches for. Procera checks the provider's /.well-known/openid-configuration before saving. Members whose verified email is in a trusted domain can then choose Sign in with SSO; they must already be members (invite them as usual). Require it turns off passwords for everyone except workspace owners, who keep password + two-step verification so a provider outage can't lock you out. A provider on a private network must be listed in PROCERA_EGRESS_ALLOW. Decisions and limits: docs/22 A-50.

Some settings can be overridden per department. The configuration profile chosen when the workspace was created only sets the starting values. The full catalogue is in docs/20.

3. Security notes

Reverse proxy and TLS

The procera server speaks plain HTTP and does not serve the web app. Put a reverse proxy in front that:

  • terminates TLS (HTTPS is required outside local trials; see cookies below);
  • serves the built web app (npm run build in web/ produces web/dist) and falls back to index.html for unknown paths, because the app uses browser history routing;
  • forwards /api/, /sysapi/, /healthz, /readyz and /version to the server, on the same origin as the web app;
  • replaces X-Forwarded-For with the real client address. Procera trusts the first address in that header for sign-in rate limits and audit records, so a proxy that appends to a client-supplied header lets clients pick their own address. Don't expose the server port directly.

The Compose stack's web container (Caddy) does all of this. If you run your own proxy, a minimal Caddy setup:

procera.example.com {
	encode zstd gzip
	@api path /api/* /sysapi/* /healthz /readyz /version
	handle @api {
		reverse_proxy 127.0.0.1:8080
	}
	handle {
		root * /srv/procera/web/dist
		try_files {path} /index.html
		file_server
	}
}

Caddy gets the certificate automatically, and it replaces client-sent X-Forwarded-For unless you configure trusted_proxies.

A minimal nginx setup (certificates from your usual tooling):

server {
    listen 443 ssl;
    http2 on;
    server_name procera.example.com;
    ssl_certificate     /etc/ssl/procera/fullchain.pem;
    ssl_certificate_key /etc/ssl/procera/privkey.pem;

    root /srv/procera/web/dist;
    location ~ ^/(api|sysapi)/ {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;   # replace, don't append
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    location ~ ^/(healthz|readyz|version)$ {
        proxy_pass http://127.0.0.1:8080;
    }
    location / {
        try_files $uri /index.html;
    }
}

server {
    listen 80;
    server_name procera.example.com;
    return 301 https://$host$request_uri;
}

Set PROCERA_PUBLIC_URL=https://procera.example.com to match.

Cookies and sessions

  • The refresh cookie is HttpOnly, SameSite=Strict, Secure and named with the __Host- prefix, so browsers send it only over HTTPS, only to the exact host, and never on cross-site requests. Cookie endpoints also require a custom request header, which blocks cross-site form posts.
  • PROCERA_INSECURE_COOKIES=true drops Secure and the prefix so a plain-HTTP setup works. Use it only for local development and tests.
  • Session length, idle timeout and the step-up window are workspace settings (Sign-in & security), bounded by platform floors.

Master key

  • Generate it with procera keygen, store it in a secret manager, and back it up apart from database backups. Losing it makes the encrypted data unreadable: workspace keys, stored files, two-step secrets and the saved SMTP password.
  • Don't change it on an existing installation: there is no root-key rotation command yet. Each workspace's key can be rotated with Rotate key under Admin › Encryption.
  • External key management (KMS/HSM) is designed but not built yet; the key is read from the environment.

SMTP TLS modes

WhereModeSetting
System consoleSTARTTLS (required)Upgrades to TLS and stops delivery if the server doesn't offer it. Usually port 587. Recommended.
System consoleImplicit TLSTLS from the first byte. Usually port 465.
System consoleNoneUnencrypted. Accepted only when the host is localhost, 127.0.0.1 or ::1 (a relay on the same machine).
PROCERA_SMTP_URLsmtp://…:587?tls=requiredSTARTTLS required.
PROCERA_SMTP_URLsmtps://…:465Implicit TLS.
PROCERA_SMTP_URLsmtp://host:port with no tls parameterUnencrypted, with no host restriction. Use only for a test inbox such as Mailpit or a relay on a private network.

The saved SMTP password is encrypted under the system key and never shown again. A password in PROCERA_SMTP_URL lives wherever your environment is stored, so protect that file.

Other hardening

  • The container image runs as a non-root user on a distroless base (no shell).
  • Keep Postgres off the public network. The Compose stack publishes only the web container.
  • Turn on ClamAV (PROCERA_CLAMD_ADDR) before people upload files.
  • Keep /readyz internal if you don't want its database and cache status visible; the bundled Caddyfile forwards it.

Source: docs/guides/configuration.md