Skip to content

Install Folio on Dokploy

You run Dokploy on your own server. Dokploy templates are three files: a Compose file, a template.toml that says which service gets a domain and which values to generate, and a meta.json for the catalog.

What you need

  • A Dokploy instance with a server of 2 GB RAM or more.

Steps

  1. Step 1: Create a project, then Create Service > Compose. Choose the Docker Compose type.

  2. Step 2: Paste the compose file into the editor.

    Show docker-compose.yml (67 lines) and copy it
    docker-compose.yml
    version: '3.8'
    
    services:
      folio:
        image: ghcr.io/evergreen-it-dev/folio:latest
        restart: unless-stopped
        environment:
          NODE_ENV: production
          PORT: '4870'
          DATABASE_URL: postgresql://folio:${POSTGRES_PASSWORD}@postgres:5432/folio
          REDIS_URL: redis://redis:6379
          PUBLIC_URL: ${PUBLIC_URL}
          ASSET_BACKEND: local
          FOLIO_SECRET: ${FOLIO_SECRET}
          GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
          GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
          GOOGLE_ALLOWED_DOMAINS: ${GOOGLE_ALLOWED_DOMAINS:-}
          CURSOR_API_KEY: ${CURSOR_API_KEY:-}
          CURSOR_AGENT_WORKSPACE_ROOT: /app/data/assistant/workspaces
          CURSOR_AGENT_STATE_DIR: /app/data/assistant/state
        volumes:
          - 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
        restart: unless-stopped
        environment:
          POSTGRES_USER: folio
          POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
          POSTGRES_DB: folio
        volumes:
          - folio-pg:/var/lib/postgresql/data
        healthcheck:
          test: ['CMD-SHELL', 'pg_isready -U folio -d folio']
          interval: 5s
          timeout: 5s
          retries: 20
    
      # Transient data only (presence, rate limits): persistence is off on purpose.
      redis:
        image: redis:7-alpine
        restart: unless-stopped
        command: redis-server --save '' --appendonly no
        healthcheck:
          test: ['CMD', 'redis-cli', 'ping']
          interval: 5s
          timeout: 5s
          retries: 20
    
    volumes:
      folio-data: {}
      folio-pg: {}
  3. Step 3: Open the Environment tab and set the three values. Replace the placeholders: openssl rand -hex 24 for the password, openssl rand -hex 32 for the secret.

    Environment
    PUBLIC_URL=https://wiki.example.com
    POSTGRES_PASSWORD=<run: openssl rand -hex 24>
    FOLIO_SECRET=<run: openssl rand -hex 32>
  4. Step 4: In Domains add wiki.example.com, service folio, port 4870, HTTPS on. Point the DNS record at the server.

  5. Step 5: Deploy. Open the address. The first account is the administrator.

Files

template.toml is the file Dokploy's template format uses to generate the domain, the password and the secret for you. The template is not in Dokploy's catalog yet.

template.toml
[variables]
main_domain = "${domain}"
postgres_password = "${password:32}"
folio_secret = "${hash:64}"

[[config.domains]]
serviceName = "folio"
port = 4870
host = "${main_domain}"

[config.env]
PUBLIC_URL = "https://${main_domain}"
POSTGRES_PASSWORD = "${postgres_password}"
FOLIO_SECRET = "${folio_secret}"
GOOGLE_CLIENT_ID = ""
GOOGLE_CLIENT_SECRET = ""
GOOGLE_ALLOWED_DOMAINS = ""
CURSOR_API_KEY = ""

Settings

Set these in the Environment tab.

Environment variables for Folio on Dokploy
VariableDefaultWhat it does
PUBLIC_URLrequiredThe address people open, with https. Invitation and share links are built from it.
POSTGRES_PASSWORDrequiredPassword of the PostgreSQL user.
FOLIO_SECRETrequiredEncrypts saved Git tokens and AI keys. Never change it afterwards.
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.

Update

In the service, change the image tag in the compose file (or keep latest and Redeploy), then deploy. The database migrates itself on start. Dokploy can schedule backups for its own database services; for the database inside this Compose file, use the commands below.

Back up

On the 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

Limits and honest notes

  • One instance of the app. The disk is local.

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