Install kitshn
kitshn runs on your own Cloudflare account, on the free plan. You set it up once, then every repo deploys with a push.
What you need
- A Cloudflare account, and a domain on it. The free plan is enough.
- A GitHub account. Its repos deploy; other accounts cannot.
curl,shandjqon the computer where you run the setup.- For Compose apps only: a Linux or macOS machine with Docker. Static sites and Worker apps need no machine.
Set up kitshn
-
Make a Cloudflare API token
Open the token page with the permissions filled in, then create the token. When a permission is missing later, the setup names it and prints this link.
-
Turn on Zero Trust
kitshn uses Cloudflare Access for every login. Open Zero Trust in the Cloudflare dashboard once and pick the free plan. The setup stops with the link when this step is missing.
-
Run the setup
Pick the admin address, for example
kit.example.comon your domain:curl -fsSL https://kit.yarden-zamir.com/install | \ CLOUDFLARE_API_TOKEN=... \ KITSHN_HOST=kit.example.com \ KITSHN_OWNER_EMAILS=you@example.com \ KITSHN_DEPLOY_OWNERS=your-github-name shIt makes the Worker, its database, the R2 bucket, the Access applications and the Owner circle. Run it again at any time: it changes only what is not right, and prints each change.
-
Add your passkey and open the map
At the end, the setup prints the admin address and a link to register your passkey. Register it, then open
https://kit.example.com. You log in with an email code and the passkey.
Deploy your first app
-
Add a recipe
Put
kitshn.config.tsat the root of the repo. A static site:import { defineApp } from "kitshn"; export default defineApp({ static: { build: "npm ci && npm run build", output: "dist" }, deploy: [ { on: "push", branch: "main", name: "prod", startsIn: "Everyone" }, { on: "pull_request", name: "pr-{pr}", ephemeral: true }, ], });Use
compose: { runsOn: ["docker"] }for a Compose app, orworker: { ... }for a Worker app. kitshn reads the recipe as data and never runs it, so it holds no loops and no function calls. -
Add the workflow
Put this in
.github/workflows/kitshn.yml. It is the same for every app:on: push: pull_request: types: [opened, synchronize, reopened, closed] workflow_dispatch: permissions: contents: read id-token: write jobs: kitshn: uses: Yarden-zamir/kitshn/.github/workflows/kitshn2-deploy.yml@main with: server: https://kit.example.com secrets: inheritThe repo needs no secret. GitHub signs each run, and kitshn checks the signature.
-
Push, then Allow
The first push of a new repo waits. The map shows "1 repo waiting": click Allow, and the deploy starts. Every later push deploys at once.
-
Share it
The new card starts in the
startsIncircle, or in the tray, private. Drag it into a circle to share it. Its address is<repo>.<your domain>.
Add a machine
-
Get a join command
On the map, click +, then Add a machine. kitshn shows a command with a one-time code that ends after 10 minutes.
-
Run it on the machine
curl -fsSL https://kit.example.com/join | sh -s -- <code> https://kit.example.comIt installs the daemon and its tunnel as services of your user. The machine needs no Node.js and opens no port.
-
Give it labels
In the machine panel, add the label
deployso that apps may run there, and labels such asdockerthat recipes ask for inrunsOn.
Pull request previews
A pull_request entry gives each pull request its own address,
<repo>-pr-<n>.<your domain>. It starts private, and goes away when
the pull request closes.
Values and secrets
A GitHub secret or variable named KITSHN_<NAME> reaches the app as
<NAME>. A secret only for production goes in the GitHub Environment
prod.
More addresses
A push entry can list up to 5 addresses. The first one is under your kitshn domain. Others may use
further domains that you add with KITSHN_ZONES in the setup.
Share a dev server
kitshn expose 5173 --name demo --dev shares a dev server of a machine at
demo.<your domain>, behind its circles. When the machine is off, visitors get the
offline page.
Move an app from KitSHn 1
KitSHn 1 deployed over SSH to one VPS with Caddy. kitshn replaces it. To move an app, replace
.kitshn.yaml with kitshn.config.ts, and point the workflow at
kitshn2-deploy.yml. A compose.yml of KitSHn 1 keeps working, within the safety checks that kitshn runs on Compose files.
The first deploy on the same machine takes over the KitSHn 1 data once, and keeps the old copy for a rollback. Then move the DNS record of the address to kitshn. The migration notes have the details.