Skip to content

Docs

EasyPages documentation

Install EasyPages on your own server and point it at your Cloudflare account.

Quick start with Docker

You need Docker Compose and a Cloudflare API token that can edit Pages. Five commands and the panel is running:

mkdir easypages && cd easypages
curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/KN990x/EasyPages/main/docker-compose.yml
curl -fsSL -o .env.example https://raw.githubusercontent.com/KN990x/EasyPages/main/.env.example
cp .env.example .env
docker compose up -d --pull always

Edit .env before the last command — CF_API_TOKEN is the only required variable.

There is no git clone in that list on purpose: Compose pulls a pinned image from GHCR, mounts ./easypages-data:/data and health-checks /api/health. Your account and the session secret live in that volume. The container runs as uid 1000, so if you created the directory as root, run chown -R 1000:1000 ./easypages-data.

Then open http://your-server:8002.

The Cloudflare API token

Create a custom API token in Cloudflare Dashboard → My Profile → API Tokens with a single permission:

  • AccountCloudflare PagesEdit

That is enough. You do not need to look up your account ID — it is inferred from the token, exactly as Cloudflare’s own SDK and Wrangler do. Set CF_ACCOUNT_ID only if the token can reach more than one account, the one case inference cannot resolve. The server logs say so explicitly and list the IDs to choose from.

Create your account

The first time you open the app you get a setup wizard. Create your account right away.

There is no user or password in .env, and no environment variable can create, replace or bypass the account. Until the account exists, anyone who can reach the port can create it — so do not leave a fresh instance exposed and unattended. See SECURITY.md for the full model.

Environment variables

Only the first one is required. Everything else has a working default.

VariableDefaultWhat it does
CF_API_TOKENRequired. Cloudflare API token with Cloudflare Pages: Edit.
CF_ACCOUNT_IDinferredOnly needed when the token reaches more than one account.
EASYPAGES_DATA_DIR/dataWhere the credential file and session secret live. Docker sets this already.
PORT8002Port the Node process listens on.
BIND_HOST127.0.0.1Interface to bind. The Docker image sets 0.0.0.0 so Compose can publish the port.
SESSION_COOKIE_SECUREfalseSet to true when HTTPS is terminated in front of the container.
TRUST_PROXYone hopSet to false when Node is reachable without a trusted reverse proxy in front.

The authoritative list is .env.example.

HTTPS and reverse proxies

Session data lives in a signed cookie (easypages_sid), not in a server-side session directory — so scaling out does not need sticky sessions.

  • Plain HTTP (default): SESSION_COOKIE_SECURE=false, as shipped.
  • HTTPS terminated in front: set SESSION_COOKIE_SECURE=true.
  • Behind a reverse proxy: keep the default TRUST_PROXY (one trusted hop for forwarded headers and rate limits).
  • Node exposed directly: set TRUST_PROXY=false, otherwise rate limiting can be spoofed through forwarded headers.

Running from source

Use Node.js 24 or newer — the same major as the Docker image and the release CI. With nvm, nvm use picks it from .nvmrc.

corepack enable
pnpm install --frozen-lockfile

Create .env from .env.example with your Cloudflare token. Local data (credential and session secret) goes to ./data by default. For a production-like run:

pnpm run build
pnpm start

During active development:

  • pnpm run dev — Express on port 8002 (watch mode).
  • pnpm run dev:ui — Vite on 5173, proxying /api, /login and /logout to http://localhost:8002.
  • pnpm run lint and pnpm test — ESLint, then the backend (node:test) and frontend (vitest) suites. Run pnpm run build first.

There is a Makefile with the same targets: make setup, make dev, make lint, make test, make clean-data.

Forgot your password?

There is no reset email. Stop the app, delete the credential file, start again — the wizard comes back:

docker compose down
rm ./easypages-data/credentials.json
docker compose up -d

From a git clone the file is at ./data/credentials.json, or run make clean-data.

Security model in short

  • No third-party servers. EasyPages talks straight to the Cloudflare API from your machine.
  • Your API token stays in your .env, next to the container. The operator account is hashed in credentials.json inside the data volume.
  • One operator account, created in the browser, stored hashed in the data volume.
  • Signed session cookie, rate-limited login, CSRF tokens on every mutating request.
  • Apache-2.0 — read the code, audit it, fork it.

Full detail, including the hardening checklist and known limits, is in SECURITY.md.

Where to go next