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 .env3. 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=offAdd 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:latestPin 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 -dInitial 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.
| Error | Cause / Sebep | Fix / Çözüm |
|---|---|---|
| PAPYRO_LICENSE_KEY is not set | Env 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 envelope | The 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 signature | Wrong 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 revoked | The 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 user | Your 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 appSupport
Email: [email protected]
Response within 48 hours. Use subject prefix "URGENT" for emergencies.