# Self-hosting on one page

**Today, PalmaPlan's code isn't published**: you can't install it yourself, and the service lives at `palmaplan.com`, in beta, by invitation. This page describes how an instance runs — it's how the `palmaplan.com` one runs — and will be useful the day the code is published, if that decision is made. It carries over what the repository's technical README says, rewritten for someone who doesn't need to read code.

## The simplest way: `pnpm start`

On a machine that already has Node and the cloned repository:

```
PALMAPLAN_TOKEN=a-long-secret PALMAPLAN_DB=~/palmaplan/palmaplan.sqlite pnpm start
```

A single process serves both the screen and the API, on `http://127.0.0.1:4785` by default. `PALMAPLAN_TOKEN` is the instance owner's token — keep it secret, it's the key to everything.

## With Docker

A `Dockerfile` and example configuration files (`deploy/Caddyfile`, `deploy/compose.yaml`) exist in the repository:

```
docker build -t palmaplan .
docker run -d --name palmaplan -p 127.0.0.1:4785:4785 -v palmaplan-data:/data \
  -e PALMAPLAN_TOKEN=<a long secret> -e PALMAPLAN_PUBLIC_URL=https://plan.example.com \
  -e PALMAPLAN_TRUST_PROXY=1 palmaplan
```

In front, a proxy that handles the HTTPS certificate — Caddy, for instance, with the provided `deploy/Caddyfile` example. The database and backups live in the `/data` volume: never delete it without having checked your backups.

## The variables that matter

| Variable | What it's for |
| --- | --- |
| `PALMAPLAN_TOKEN` | The instance owner's token. Required. |
| `PALMAPLAN_DB` | The path to the SQLite database file. |
| `PALMAPLAN_PORT` | The listening port (4785 by default). |
| `PALMAPLAN_HOST` | The network interface to listen on — `127.0.0.1` by default, `0.0.0.0` inside a container. |
| `PALMAPLAN_PUBLIC_URL` | The address as seen from the outside (`https://plan.example.com`) — needed as soon as people other than you connect: invitation links, the public page and secure cookies depend on it. |
| `PALMAPLAN_TRUST_PROXY` | Set to `1` when a reverse proxy (Caddy, nginx…) terminates HTTPS in front of the instance. |
| `PALMAPLAN_BACKUPS` | The daily backups folder (by default, a `backups` subfolder next to the database). |
| `PALMAPLAN_SMTP_URL` / `PALMAPLAN_MAIL_FROM` | So that invitations, forgotten-password mail and notifications go out by e-mail rather than being written to the server log. |

The full list, with every variable's detail, lives in the repository's `README.md`.

## Taking possession of the instance: `/setup`

The first time, open `/setup` on your instance. This screen asks for:

- the server's token (`PALMAPLAN_TOKEN`);
- your name, your e-mail, and a password.

This isn't open registration: it's the only way to create the first account, the owner's. Once `/setup` is done, other people join the instance only by invitation (from a schedule's *Settings › Sharing*), never through a public sign-up page.

## Backups

An hourly task, built into the process, makes a full copy of the database every day (the last fourteen copies are kept) before clearing out anything that's been sitting in the trash for more than thirty days. `GET /api/v1/health` (no token needed) reports the number of schedules, the last time this task ran, and the last backup — enough to monitor the instance from the outside without handing it any secret.

Still, make a manual backup before any significant upgrade: the hot-backup command, or simply a copy of the `.sqlite` file while the process is stopped.

## What this page doesn't cover

"Continue with Google" (requires a Google Cloud project), SMTP mail in detail, and connecting an MCP agent (`claude mcp add …`) — that last point is covered by the agent guide.
