Skip to content

Self-hosted ​

The self-hosted edition runs Plotic on your own server. It shares the writing core with the cloud edition while the infrastructure, database and backups stay under your control.

Requirements ​

  • Docker with Compose.
  • A server where you can publish the application.
  • Separate secret values for the database, authentication and collaboration.

Quick start ​

From the repository root:

bash
cp .env.example .env
openssl rand -base64 32
docker compose up -d --build

Set different values for POSTGRES_PASSWORD, BETTER_AUTH_SECRET and COLLABORATION_SECRET. Then open http://localhost or the domain you configured.

Google sign-in and Turnstile protection are optional. To enable either one, add both variables in its pair (GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET or TURNSTILE_SITE_KEY + TURNSTILE_SECRET_KEY) and rebuild the application; the server refuses to start when a pair is incomplete.

Google sign-in ​

Each self-hosted installation should use its own Google credentials. Do not copy credentials from another installation.

  1. Open Google Cloud Console, create or select a project, and configure the OAuth consent screen.

  2. Go to APIs & Services → Credentials → Create Credentials → OAuth client ID.

  3. Choose Web application.

  4. Add the exact redirect URI for your installation:

    text
    https://your-domain.example/api/auth/callback/google

    For local Docker Compose use http://localhost/api/auth/callback/google; for server development without Compose use http://127.0.0.1:3000/api/auth/callback/google. The host and protocol must match PLOTIC_ORIGIN/BETTER_AUTH_URL.

  5. Copy the client ID and secret into .env:

    env
    PLOTIC_ORIGIN=https://your-domain.example
    GOOGLE_CLIENT_ID=...
    GOOGLE_CLIENT_SECRET=...

    Better Auth uses that URL to build the callback. See the official Better Auth Google guide.

Turnstile bot protection ​

Turnstile protects account creation; normal sign-in does not require a captcha.

  1. Open the Cloudflare Turnstile dashboard and select Turnstile → Add widget.

  2. Create a Managed widget and add your installation's exact hostname, for example your-domain.example.

  3. Enter only the hostname: do not include https://, paths, or ports. For local development, use a separate widget with localhost and 127.0.0.1.

  4. Leave Pre-clearance disabled, create the widget, and copy the sitekey and secret key.

  5. Add them to .env:

    env
    TURNSTILE_SITE_KEY=...
    TURNSTILE_SECRET_KEY=...

    The sitekey is used in the browser; the secret key must stay on the server. See Cloudflare's widget creation guide and hostname management guide.

Rebuild the application after changing these variables:

bash
docker compose up -d --build

To disable either integration, leave both variables in its pair empty. Never commit secrets to Git. For local tests, use Cloudflare's official Turnstile test keys, never production keys.

Verify the installation ​

bash
docker compose ps
curl http://localhost/api/health
pnpm selfhost:verify

The complete reference and Nginx setup are in the repository README.

Write at your own pace. Keep your project yours.