---
title: Run it yourself
description: One Node process and one SQLite file.
sidebar:
  label: Overview
---

Gitupcms is an Astro SSR app (`@astrojs/node`, standalone) with a SQLite database (better-sqlite3). It needs Node 22+ and pnpm.

- cms/
  - src/
    - lib/ (detection, GitHub, workspaces, media, SEO, comments)
    - components/ (React islands and Bejamas UI)
    - pages/ (Astro pages and API routes)
  - kit/i18n/ (the language kit copied into sites)
  - widget/ (the comments embed)
  - .env.example
- docs/ (this site)

## Local

1. **Create a GitHub OAuth app**

    Callback URL: `http://localhost:4321/api/auth/callback/github`.

2. **Configure**

    ```bash
    cd cms
    cp .env.example .env   # GitHub OAuth app + BETTER_AUTH_SECRET
    ```

3. **Run**

    ```bash
    pnpm install
    pnpm dev               # http://localhost:4321
    ```
    SQLite tables are created on boot.

## Production build

```bash
pnpm install --frozen-lockfile
pnpm build                       # also builds the comments widget
node ./dist/server/entry.mjs     # HOST and PORT from the environment
```

## Docker

`cms/` has a `Dockerfile` and a `docker-compose.yml`, so the CMS runs the same on any machine with Docker: no Node, pnpm or build tools on the host.

```bash
cd cms
cp .env.example .env               # GitHub OAuth app + BETTER_AUTH_SECRET
docker compose up -d --build       # http://localhost:4321
```

- The SQLite database and preview checkouts live in the `gitupcms-data` volume (`/data` in the container). Updating is `git pull` and `docker compose up -d --build`; the data stays.
- The port is bound to `127.0.0.1`. On a server, put Caddy or another proxy in front for HTTPS, as in [Server](/self-hosting/server).
- With `PREVIEW_RUNNER=1`, previews run inside the CMS container, as the same user. Turn it on only for sites you trust; leave `PREVIEW_DOCKER` unset, the container has no Docker.

See [Environment](/self-hosting/environment) for every variable and [Server](/self-hosting/server) for a full Linux setup.
