One docker compose file will run the same server behind
cloud.foliowriter.app on your own
machine: live co-editing, end-to-end-encrypted projects, typeset preview, and
PDF / Word / LaTeX export — Pandoc and Typst ship inside the image.
Free for personal use.
mkdir folio && cd folio
curl -fsSLO https://foliowriter.app/selfhost/docker-compose.yml
FOLIO_DOMAIN=folio.example.com docker compose up -d
The bundled Caddy fetches and renews the
Let’s Encrypt certificate for your domain and proxies HTTPS plus the
collaboration websockets. Then open https://folio.example.com.
No domain yet? docker compose up folio-web and open
http://localhost:8787.
foliowriter/folio-web is published for
amd64 and arm64.Start the server with your email in FOLIO_ADMIN_EMAILS:
FOLIO_DOMAIN=folio.example.com FOLIO_ADMIN_EMAILS=you@example.com \
docker compose up -d
Every address listed there is always an admin — no quotas, plus the
/admin dashboard (accounts, projects, storage, traffic). Sign in with
that email; with no SMTP configured, the magic sign-in link prints to the server
log instead of being emailed:
docker compose logs folio-web | grep -i http
Open the printed link and you’re in. For real email delivery, set the
SMTP_* variables — any relay works — and PUBLIC_BASE_URL
so emailed links use your domain.
Everything is environment variables. Put them in a .env file beside
docker-compose.yml (Compose reads it automatically):
FOLIO_DOMAIN=folio.example.com
PUBLIC_BASE_URL=https://folio.example.com
FOLIO_ADMIN_EMAILS=you@example.com
FOLIO_LIMIT_PROJECTS=0 # 0 = unlimited
FOLIO_LIMIT_STORAGE_MB=0 # 0 = unlimited
FOLIO_ENC_KEY=… # openssl rand -hex 32
| Variable | What it does |
|---|---|
FOLIO_DOMAIN | Domain Caddy serves and gets certificates for (default localhost). |
PUBLIC_BASE_URL | Absolute origin used in sign-in emails and share links. |
FOLIO_ADMIN_EMAILS | Comma-separated emails that are always admins — quota-exempt, may use /admin. |
SMTP_HOST / PORT / USER / PASS / SECURE / FROM | Outgoing mail for magic-link sign-in. Unset → links print to the container log. |
FOLIO_LIMIT_PROJECTS | Projects per account (default 2). 0 = unlimited — most self-hosters set this. |
FOLIO_LIMIT_STORAGE_MB | Storage per account in MB (default 50). 0 = unlimited. |
FOLIO_DEMOS | Comma-separated project ids offered as auto-resetting demo sandboxes. |
FOLIO_ALLOW_GUEST_PROJECTS | Set 1 to let visitors create projects without signing in (by default creation needs an account; demos are always open). |
FOLIO_ENC_KEY | 64-hex-char key encrypting stored authenticator secrets at rest. |
Update: docker compose pull && docker compose up -d. Tagged
versions exist (foliowriter/folio-web:0.2.0) if you prefer pinning to
tracking latest.
Everything — projects, accounts, sessions — lives in ./data beside the
compose file. Backup is that one folder:
docker compose stop folio-web
tar czf folio-backup-$(date +%F).tgz data
docker compose start folio-web
Restore — or move servers — by putting data/ back and running
docker compose up -d.
Personal use is free. The image is proprietary but costs nothing to self-host for yourself, your family, and your personal collaborators.
Teams and organizations need a commercial license. Running it for or within a company, school, or other organization — or commercially — requires one; it’s how the free tier stays funded. Get in touch and we’ll sort you out quickly.
No redistribution, rebranding, or derivative works; full terms ship with the image documentation. Prefer not to run a server at all? cloud.foliowriter.app is the hosted version — free to start.