Skip to content

Install Folio on Easypanel

You run Easypanel on your own server. A template is two files (the form and the texts, and the services to create), plus a logo and a screenshot. Until the template is published, create the three services by hand.

What you need

  • An Easypanel server with 2 GB of RAM or more.

Steps

  1. Step 1: In a project: + Service > Postgres. Name it folio-db. Note the generated password.

  2. Step 2: + Service > Redis. Name it folio-redis. Note its password.

  3. Step 3: + Service > App. Name it folio. Under Source choose Docker image and enter the image below.

    Image
    ghcr.io/evergreen-it-dev/folio:latest
  4. Step 4: Under Environment, replace the words in angle brackets. The project name is shown at the top of Easypanel; the database name is the project name.

    Environment
    NODE_ENV=production
    PORT=4870
    PUBLIC_URL=https://wiki.example.com
    DATABASE_URL=postgresql://postgres:<db password>@<project>_folio-db:5432/<project>
    REDIS_URL=redis://:<redis password>@<project>_folio-redis:6379
    ASSET_BACKEND=local
    FOLIO_SECRET=<run: openssl rand -hex 32>
  5. Step 5: Under Domains add your domain, port 4870.

  6. Step 6: Under Mounts add a Volume named data at /app/data.

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

Files

The template's index.ts does the same steps and generates both passwords and the secret. The template is not in Easypanel's catalog yet.

Show index.ts (64 lines) and copy it
index.ts
import { Output, randomPassword, randomString, Services } from "~templates-utils";
import { Input } from "./meta";

export function generate(input: Input): Output {
  const services: Services = [];

  const databasePassword = randomPassword();
  const redisPassword = randomPassword();
  // Encrypts saved Git tokens and personal AI keys. Generated once; never change it.
  const folioSecret = randomString(64);

  services.push({
    type: "app",
    data: {
      serviceName: input.appServiceName,
      env: [
        `NODE_ENV=production`,
        `PORT=4870`,
        `PUBLIC_URL=https://$(PRIMARY_DOMAIN)`,
        `DATABASE_URL=postgresql://postgres:${databasePassword}@$(PROJECT_NAME)_${input.appServiceName}-db:5432/$(PROJECT_NAME)`,
        `REDIS_URL=redis://:${redisPassword}@$(PROJECT_NAME)_${input.appServiceName}-redis:6379`,
        `ASSET_BACKEND=local`,
        `FOLIO_SECRET=${folioSecret}`,
        `CURSOR_AGENT_WORKSPACE_ROOT=/app/data/assistant/workspaces`,
        `CURSOR_AGENT_STATE_DIR=/app/data/assistant/state`,
      ].join("\n"),
      source: {
        type: "image",
        image: input.appServiceImage,
      },
      domains: [
        {
          host: "$(EASYPANEL_DOMAIN)",
          port: 4870,
        },
      ],
      mounts: [
        {
          type: "volume",
          name: "data",
          mountPath: "/app/data",
        },
      ],
    },
  });

  services.push({
    type: "postgres",
    data: {
      serviceName: `${input.appServiceName}-db`,
      password: databasePassword,
    },
  });

  services.push({
    type: "redis",
    data: {
      serviceName: `${input.appServiceName}-redis`,
      password: redisPassword,
    },
  });

  return { services };
}

Settings

Optional variables go in the same Environment field.

Environment variables for Folio on Easypanel
VariableDefaultWhat it does
FOLIO_SECRETrequiredEncrypts saved Git tokens and AI keys. Never change it later.
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

Change the image tag on the folio service (or keep latest) and Deploy. The database migrates itself on start. Back up first.

Back up

Easypanel can back up its Postgres service to S3 from the service page. The volume data is the other half: copy /app/data from the app's volume (Easypanel's server path is /etc/easypanel/projects/<project>/folio/volumes/data) or from a shell in the app:

bash
tar czf - -C /app/data .

Limits and honest notes

  • One instance of the app.
  • Easypanel's Redis service is password-protected, which the template accounts for.

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