Kiln docs
v1.1.0
Get help
● Start · About 20 minutes

Installation
from the ZIP to a working builder.

This page takes you from the downloaded files to a working builder. Allow about 20 minutes.

npm cinpm run buildnpm startDockersystemd · PM2

01Requirements

  • Node.js 22.12 or newer with npm. Check with node -v. Get it from nodejs.org or your system's package manager.
  • A machine to run it on. A Linux VPS (Ubuntu, Debian or similar) is the usual choice. Any machine that runs Node.js works, including a Mac. On Windows, use WSL (see below).
  • About 1 GB of memory and a few GB of disk for the database and images.
  • For production: a domain name and HTTPS in front of Kiln (see Hosting).

Outside services (AI provider, Stripe, Cloudflare, Resend, Pexels) are optional and each bills your own account for what you use; none is included in the price.

Kiln needs no separate database server. It creates its SQLite files itself.

Windows

The commands on this page are for a Linux or macOS terminal. On Windows, use WSL (Windows Subsystem for Linux) with Ubuntu, install Node.js inside it and type the commands there. Native Windows (without WSL) is not supported.

021. Install the dependencies

Unpack the ZIP, open a terminal in the folder that contains package.json, and run:

npm ci

This installs the exact package versions from package-lock.json. better-sqlite3 is a native module: on most systems a ready-made binary is downloaded. If the install fails with a compiler error, install the build tools (sudo apt install python3 make g++ on Debian/Ubuntu) and run npm ci again.

032. Create the configuration file

cp .env.example .env
openssl rand -hex 32

Open .env in a text editor and paste the 64-character output of openssl rand -hex 32 after ADMIN_SECRET_KEY=. This key encrypts every API key you later save in the console.

If ADMIN_SECRET_KEY is missing or not 64 hex characters, Kiln still starts. It then generates a key, saves it in data/.admin-secret-key and prints a warning on every start. Copy that key into .env and back it up.

The other values in .env are optional. Everything else is set later in the console.

VariableDefaultWhat it does
ADMIN_SECRET_KEYgenerated64 hex characters. Encrypts the saved API keys.
PORT8787The port Kiln listens on.
HOST0.0.0.0The address Kiln listens on. Use 127.0.0.1 when a reverse proxy runs on the same machine.
DATA_DIRdataFolder for the databases and images, relative to the project folder.
KILN_PUBLIC_URLemptyThe https address of the builder. Locks the console's Public URL field. Also turns on the Secure cookie flag.
KILN_SITES_DOMAINemptyLocks the console's Domain for published sites field.
TRUST_PROXY_HOPS0Number of reverse proxies in front of Kiln. Set 1 behind Caddy or nginx.
COOKIE_SECUREoff1 forces the Secure flag on builder sign-in cookies.
ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, CLOUDFLARE_API_TOKEN, RESEND_API_KEY, PEXELS_API_KEYemptyOptional. A key set here is used instead of the console field, and the field shows as locked.
KILN_DEMO, KILN_DEMO_PASSWORD, ADMIN_DEMO_PASSWORDemptyOnly for a public read-only demo. Never set them on a real install (see Security).

043. Build

npm run build

This compiles the server into dist/ and the builder app into web/dist/. Run it again after every update.

054. Start

npm start

npm start runs node dist/src/server/index.js. You see a line like this:

[kiln] 1.1.0 on http://localhost:8787  builder: /app  console: /admin

On the very first start the log also prints a one-time setup code for the console, for example K7QM-2XRP-9DWA-HT4N. Copy it. It is shown only in the log.

Prefer not to read logs (for example on a platform that hides them)? Set ADMIN_SETUP_TOKEN in .env to a secret of at least 24 characters (openssl rand -hex 24) before the first start. No code is printed then, and the console asks for that secret instead.

Check it from a second terminal: curl http://localhost:8787/healthz answers {"ok":true,"version":"1.1.0"}.

065. Create your console account

  1. Open http://<your server>:8787/admin (or your https address once the proxy is set up).
  2. Enter the setup code, your e-mail and a password. This creates the owner of the console.
  3. Turn on two-factor sign-in under your account. It is strongly recommended.

Lost the code before you used it? Restart Kiln. Each start before the owner exists prints a new code, and any printed code works until the owner is created.

076. First settings

In the console:

  1. Hosting → Public URL of this server: the https address of the builder, e.g. https://build.your-agency.example. Forms, review links, invite links and Stripe use it. The Public URL is https check stays red until it is set.
  2. Brand: product name, accent colour, logo, support e-mail.
  3. Integrations: add an AI key if you have one. Without one, sites are built as drafts without AI.
  4. E-mail: a Resend key and a sender, if you want invite, review and form e-mails.

087. Invite yourself to the builder

The console account and the builder account are separate.

  1. Console → Users → Invite agency staff (e-mail) → enter your e-mail → Create invite link.
  2. Open the link it shows (it is also e-mailed if e-mail is set up). It is valid for 7 days.
  3. Choose a password (at least 10 characters). You are now signed in at /app as agency staff.
  4. Create a workspace for your first client and a site. See Using the builder.
Console Users page with the Invite agency staff field and a created invite linkBuilder invite page: Set up your account with name and password

09Docker instead of Node.js

A Dockerfile is included. It builds everything and runs as the unprivileged node user.

docker build -t kiln .
docker run -d --name kiln --restart unless-stopped \
  -p 8787:8787 -v kiln-data:/app/data --env-file .env kiln
docker logs kiln          # shows the one-time setup code

The kiln-data volume holds the databases and images. Keep it when you replace the container.

10Keeping Kiln running

npm start stops when you close the terminal. On a server, use a process manager.

systemd (most Linux servers)

Save as /etc/systemd/system/kiln.service, adjusting the user and folder:

[Unit]
Description=Kiln website builder
After=network.target

[Service]
Type=simple
User=kiln
WorkingDirectory=/opt/kiln
ExecStart=/usr/bin/node dist/src/server/index.js
Restart=on-failure
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now kiln
journalctl -u kiln -f      # the log, including the setup code

Kiln reads .env from its own folder, so the unit needs no EnvironmentFile. Check the Node path with which node. The user must be able to write to the data/ folder.

PM2

npm install -g pm2
pm2 start dist/src/server/index.js --name kiln
pm2 save && pm2 startup    # start again after a reboot
pm2 logs kiln

Run only one Kiln process per data folder. Rate limits are kept in memory per process.

11Windows

Use WSL (Windows Subsystem for Linux) with Ubuntu, install Node.js inside it and follow the Linux steps. Native Windows (without WSL) is not supported.

12Backups

Everything Kiln stores is in the data/ folder:

FileContents
kiln.sqliteBuilder accounts, workspaces, sites, versions, form messages, plans, credits, payments.
admin.sqliteThe console: settings, encrypted API keys, console team, audit log.
media/Every uploaded, imported or generated image.
.admin-secret-keyOnly if you did not set ADMIN_SECRET_KEY.

The databases run in WAL mode, so -wal and -shm files can sit next to them. The safe way to back up:

sudo systemctl stop kiln
tar czf kiln-backup-$(date +%F).tar.gz data .env
sudo systemctl start kiln

Keep a copy of ADMIN_SECRET_KEY apart from the data, for example in a password manager.

If you lose ADMIN_SECRET_KEY

The saved API keys (AI, Stripe, Cloudflare, Resend, Pexels, webhook secrets) cannot be decrypted without it. Sites, accounts and settings are not encrypted and stay intact. To recover:

  1. Put a new key in .env (openssl rand -hex 32) and restart.
  2. In the console, open Integrations and enter every key again. Use Test on each one.
  3. Enter the Stripe webhook signing secret again under Integrations.