Skip to content

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

  1. Step 1: In Coolify open Projects, pick a project and environment, then + New > Docker Compose Empty.

  2. 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:
  3. 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.

  4. Step 4: Deploy. The first start pulls the image and takes a few minutes. The service turns healthy when /api/health answers.

  5. 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.

Environment variables for Folio on Coolify
VariableDefaultWhat it does
FOLIO_TAGlatestImage tag. Pin a release such as v0.1.0 to update only when you choose.
SERVICE_PASSWORD_64_FOLIOSECRETgenerated by CoolifyBecomes 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_SECRETemptyTurn on "Sign in with Google". Register <your address>/api/auth/google/callback with Google.
GOOGLE_ALLOWED_DOMAINSemptyEmail domains allowed to sign in with Google. Empty means nobody.
CURSOR_API_KEYemptyShared key for the AI assistant. Without it each person adds their own.
CURSOR_AGENT_MODELautoModel 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:

bash
docker exec <postgres-container> pg_dump -U folio folio > folio-db.sql
docker exec <folio-container> tar czf - -C /app/data . > folio-data.tgz

Coolify 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.

bash
node deploy/smoke.mjs https://wiki.example.com

Other ways to install

Compare all platforms

Not 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.

Open the demo