Skip to main content
Buy now

15-minute setup

Install Papyro

This guide walks through installing Papyro on your own server. Basic Docker knowledge is assumed.

1. Requirements

  • Docker 24+ and docker compose v2
  • Minimum 2 GB RAM, 10 GB disk
  • Reverse proxy with HTTPS (Cloudflare, Traefik, nginx)
  • A domain or subdomain (e.g. papyro.yourcompany.com)
  • Your purchased PAPYRO_LICENSE_KEY (emailed)
  • Your GHCR token (for image pull, emailed)

2. Set up the working directory

mkdir papyro && cd papyro
curl -fsSL https://papyro.dev/install/docker-compose.yml -o docker-compose.yml
curl -fsSL https://papyro.dev/install/env.example -o .env

3. Fill in the .env file

Paste the values from your purchase email:

# Domain
BETTER_AUTH_URL=https://papyro.yourcompany.com

# Database password (generate randomly)
DB_PASSWORD=$(openssl rand -hex 16)

# Better Auth secret (generate randomly)
BETTER_AUTH_SECRET=$(openssl rand -hex 32)

# Redis password (generate randomly)
REDIS_PASSWORD=$(openssl rand -hex 16)

# Cron secret (generate randomly)
CRON_SECRET=$(openssl rand -hex 32)

# License (from your purchase email)
PAPYRO_LICENSE_KEY=eyJ2IjoxLCJjdXN0b21lciI6...

# License check-in is ON by default. Uncomment to run fully air-gapped:
# PAPYRO_LICENSE_CHECKIN_URL=off

# AG Grid Enterprise license (data-grid block renders watermarked without it)
AG_GRID_LICENSE_KEY=

# OpenAI API key ("ask the grid" feature)
OPENAI_API_KEY=

# R2 backup (optional)
R2_ACCOUNT_ID=
R2_ACCESS_KEY_ID=
R2_SECRET_ACCESS_KEY=
R2_BUCKET=

Run the openssl rand commands in your terminal and paste the outputs. Don't lose these — they're required to access the DB.

License check-in (and how to switch it off)

Papyro posts a small license beacon to admin.papyro.dev roughly every 12 hours and gets back a signed entitlement, so plan, seat and expiry changes reach your install without a new key file. It sends your license id, a one-way hash of BETTER_AUTH_URL, seats in use, the Papyro version and a one-time nonce — never workspace content, user names or e-mail addresses.

PAPYRO_LICENSE_CHECKIN_URL=off

Add this line to .env for a fully air-gapped install. Your signed key keeps working offline at the level you purchased; plan changes then arrive as a re-issued key instead.

Optional modules and tuning

The downloaded .env carries more switches than the block above. Everything here is commented out by default — uncomment only what you need:

  • Meeting rooms — uncomment the livekit service, then set LIVEKIT_URL and LIVEKIT_API_SECRET. ROOMS_MAX_CONCURRENT caps concurrent participants across all rooms.
  • Live room captions (50 spoken languages → 51 caption languages) — add the translator service, set ROOMS_TRANSLATION_ENABLED=true plus your own DEEPGRAM_API_KEY and OPENAI_API_KEY. Usage bills to your accounts. The languages offered in the pickers are yours to choose via ROOMS_SPOKEN_LANGUAGES (default: the seven interface languages).
  • Off-site backups — uncomment the r2-sync service and fill the R2_* values to mirror database dumps and uploads to Cloudflare R2 nightly.
  • Retention — TRASH_RETENTION_DAYS, BOARD_TRASH_RETENTION_DAYS, ACTIVITY_RETENTION_DAYS, AUTH_EVENTS_RETENTION_DAYS and the rest override how long each record type is kept.
  • Helpdesk notifications — NETGSM_* sends an SMS when a call is marked unreachable; RESEND_API_KEY and RESEND_FROM e-mail field activity reports. Blank disables both.
  • Error tracking — ERROR_AI_ENABLED=0 turns off AI root-cause analysis (stack traces are sent to OpenAI when it is on). WEBHOOK_ALLOW_PRIVATE=1 lets board webhooks reach private-network receivers.
  • Operations — DB_POOL_MAX, SHUTDOWN_DRAIN_MS, REALTIME_MAX_* and UPLOAD_MIN_FREE_BYTES tune pool sizes, drain time, realtime connection ceilings and the free-space guard.

Every value is documented inline in the .env you downloaded. Blank means the built-in default applies.

Hardening: encryption at rest

Like other self-hosted collaboration tools, Papyro stores workspace content as regular PostgreSQL rows so search and exports work; application-layer secrets (integration credentials) are additionally encrypted. Protecting the data at rest is done at the disk layer of your server:

  • Encrypt the disk or volume that holds your Docker volumes — LUKS on bare-metal Linux, or your cloud provider's encrypted block storage.
  • Database dumps land in the dbbackups volume on the same disk. If you copy them elsewhere, keep them encrypted in transit and at the destination.
  • If you enable the optional R2 backup sync, Cloudflare encrypts stored objects at rest; scope the API token to that single bucket.

HTTPS in front of the app is already required (step 1). Combined with disk encryption and encrypted backups this matches the at-rest baseline that SOC 2 / ISO 27001 questionnaires expect.

4. Pull the Docker image

Use the GHCR token we emailed you to log in and pull the image:

echo "ghp_xxxxxxxxxxxx" | docker login ghcr.io \
  -u egebilge --password-stdin

docker pull ghcr.io/egebilge/papyro:latest

Pin a version tag (for example :v0.2.0) in docker-compose.yml for production, so an upgrade is something you choose rather than something that happens on the next restart.

5. Run it

docker compose up -d

Initial startup takes 30–60 seconds (migrations run, containers come up).

6. Create the first admin

Open https://papyro.yourdomain.com in a browser. The setup wizard appears — enter your first-user details. This first user is created with the super-admin role and the wizard runs exactly once.

7. Verify license status

Go to Admin → License (sidebar). Your customer name, edition, seat count and expiry date should appear.

Troubleshooting
ErrorCause / SebepFix / Çözüm
PAPYRO_LICENSE_KEY is not setEnv var missing or copied incorrectly.Paste the exact line from your purchase email into .env. Restart: docker compose up -d --force-recreate app
PAPYRO_LICENSE_KEY is invalid: malformed envelopeThe envelope was copied incompletely (truncated paste).Select and copy the entire PAPYRO_LICENSE_KEY=... line from the email. The value must contain a period (.) separating payload and signature.
PAPYRO_LICENSE_KEY is invalid: invalid signatureWrong image version, or the envelope belongs to a different vendor build.Check the image tag in your docker pull command. For help, contact [email protected].
PAPYRO_LICENSE_KEY is invalid: license revokedThe license was revoked in the vendor panel and the install picked that up at its last check-in.Contact [email protected]. If this is a mistake, a restore is applied at the next check-in — no new key needed.
LICENSE_OVER_SEAT — Cannot add new userYour license seat limit is full. Banned users do not occupy a seat.Email [email protected] to raise the seat count, or ban the users who have left.

Renewal

We email you 30 days before expiry. After payment a new PAPYRO_LICENSE_KEY arrives via email. Replace the value in .env and restart:

docker compose up -d --force-recreate app

Support

Email: [email protected]

Response within 48 hours. Use subject prefix "URGENT" for emergencies.