Install Folio on Coolify
You already run Coolify v4 on your own server and want Folio next to your other apps. Coolify adds the domain, HTTPS and the proxy.
What you need
- A Coolify v4 instance with a server attached, and a wildcard or custom domain.
- 2 GB of RAM or more on that server.
Steps
Step 1: In Coolify open Projects, pick a project and environment, then + New > Docker Compose Empty.
Step 2: Paste the whole compose file and Save.
Show docker-compose.yaml (86 lines) and copy it
docker-compose.yaml# Folio for Coolify: paste into "Docker Compose Empty". # Image: ghcr.io/evergreen-it-dev/folio, built for amd64 and arm64. # # Coolify fills in the SERVICE_* variables below: # SERVICE_URL_FOLIO_4870 the address of the app (with https://) and the # port the proxy sends traffic to # SERVICE_PASSWORD_POSTGRES 32 random characters, shared with the database # SERVICE_PASSWORD_64_FOLIOSECRET 64 random characters, kept across redeploys # Everything else is optional; empty variables show up in Coolify's # Environment Variables tab, ready to fill in. services: folio: image: 'ghcr.io/evergreen-it-dev/folio:${FOLIO_TAG:-latest}' environment: - SERVICE_URL_FOLIO_4870 - NODE_ENV=production - PORT=4870 - 'PUBLIC_URL=${SERVICE_URL_FOLIO}' - 'DATABASE_URL=postgresql://folio:${SERVICE_PASSWORD_POSTGRES}@postgres:5432/folio' - 'REDIS_URL=redis://redis:6379' - ASSET_BACKEND=local # Encrypts saved git tokens and personal AI keys. Generated once by # Coolify. Never change it: credentials saved earlier would stop working. - 'FOLIO_SECRET=${SERVICE_PASSWORD_64_FOLIOSECRET}' # "Sign in with Google" (optional). Redirect URI to register with Google: # <your address>/api/auth/google/callback - 'GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}' - 'GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}' - 'GOOGLE_ALLOWED_DOMAINS=${GOOGLE_ALLOWED_DOMAINS}' # AI assistant (optional). People normally add their own key in their # account settings; this is a shared fallback. - 'CURSOR_API_KEY=${CURSOR_API_KEY}' - 'CURSOR_AGENT_MODEL=${CURSOR_AGENT_MODEL:-auto}' - CURSOR_AGENT_WORKSPACE_ROOT=/app/data/assistant/workspaces - CURSOR_AGENT_STATE_DIR=/app/data/assistant/state volumes: # The content itself: git repositories of the spaces, uploaded files. - 'folio-data:/app/data' depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: - CMD - node - '-e' - "fetch('http://127.0.0.1:4870/api/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" interval: 30s timeout: 5s retries: 3 start_period: 60s postgres: image: 'postgres:17-alpine' environment: - POSTGRES_USER=folio - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}' - POSTGRES_DB=folio volumes: - 'postgres-data:/var/lib/postgresql/data' healthcheck: test: - CMD-SHELL - 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}' interval: 5s timeout: 5s retries: 20 # Transient data only (presence, rate limits): persistence is off on purpose. redis: image: 'redis:7-alpine' command: "redis-server --save '' --appendonly no" healthcheck: test: - CMD - redis-cli - PING interval: 5s timeout: 5s retries: 20 volumes: folio-data: postgres-data:Step 3: Open the folio service and set Domains to the address you want, for example https://wiki.example.com. Coolify may already have filled one in. Point its DNS record at the server.
Step 4: Deploy. The first start pulls the image and takes a few minutes. The service turns healthy when /api/health answers.
Step 5: Open the address. The first account you create is the administrator.
Settings
Coolify generates SERVICE_PASSWORD_POSTGRES and SERVICE_PASSWORD_64_FOLIOSECRET itself (its magic variables) and keeps them across redeploys. PUBLIC_URL follows the domain you set. Set the rest in the service's Environment Variables tab; empty ones are already listed there.
| Variable | Default | What it does |
|---|---|---|
FOLIO_TAG | latest | Image tag. Pin a release such as v0.1.0 to update only when you choose. |
SERVICE_PASSWORD_64_FOLIOSECRET | generated by Coolify | Becomes FOLIO_SECRET. Encrypts saved Git tokens and AI keys. Do not change or delete it after people have saved credentials. |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | empty | Turn on "Sign in with Google". Register <your address>/api/auth/google/callback with Google. |
GOOGLE_ALLOWED_DOMAINS | empty | Email domains allowed to sign in with Google. Empty means nobody. |
CURSOR_API_KEY | empty | Shared key for the AI assistant. Without it each person adds their own. |
CURSOR_AGENT_MODEL | auto | Model the assistant uses. |
Update
With FOLIO_TAG=latest, press Redeploy; Coolify pulls the image again. With a pinned tag, change FOLIO_TAG first. Database changes are applied by the app on start. Back up before a big jump.
Back up
Two things: the database and the folio-data volume. On the Coolify server, with the container names from docker ps | grep folio:
docker exec <postgres-container> pg_dump -U folio folio > folio-db.sql
docker exec <folio-container> tar czf - -C /app/data . > folio-data.tgzCoolify can schedule S3 backups for its own database resources, but not for a database inside a Compose file. Schedule the commands above (cron on the server) or snapshot the server's disk.
Limits and honest notes
- One instance of the app only. The disk is local to the container.
- Redeploys restart the app; open pages reconnect by themselves.
Platform documentation
Check the installation
From a clone of the repository, run the smoke test against a fresh instance. It needs Node 18 or newer. It creates the first account, a space and a page, and opens a WebSocket connection to the page. Delete the instance, or that space, afterwards.
node deploy/smoke.mjs https://wiki.example.comOther ways to install
Compare all platformsNot ready to install?
Try the public demo: https://demo.foliowiki.online. Pick Sam on the sign-in screen. The login is shared and the data resets every 24 hours, so don't enter personal data or API keys.