Skip to content
Noite
Esc
↑↓navigate↵open⌘Jpreview
On this page

Deploy

Create an app and ship it — push over Git, deploy from CI, and what each push triggers.

Create the app

Open the control UI and go to Apps → New app. Enter a name and slug. Creating the app provisions its git remote; deploys follow each push.

Slug rules: 1–48 chars, lowercase letters/digits/hyphens, starting and ending with a letter or digit. Reserved: _control, app, api, git.

Push with git

Every app has a Git remote at https://git.<domain>/<slug>. Authenticate as user git with an account API key (Account → API keys) as the password; the push needs the push role on the app. Each push to main deploys.

The smallest app is a Wrangler config plus a module Worker:

{
  "name": "hello",
  "main": "index.js",
  "compatibility_date": "2026-09-01",
}
export default {
  fetch: () => new Response("Hello from Noite"),
};
git init -b main
git add -A && git commit -m "first deploy"
git remote add origin "https://git:<api-key>@git.<domain>/<slug>"
git push -u origin main

Open the result at https://<slug>.<domain>. With a package.json, the runner runs bun install and bun run build first; without one it deploys the tree as is. Pushes must fast-forward unless you hold the admin role.

Deploy from CI

@noitenow/cli pushes a prebuilt dist/ plus wrangler.jsonc as a synthetic fast-forward commit — no server build, push role suffices, never force-pushes.

bunx @noitenow/cli deploy --slug <slug> --url https://git.<domain> --token "$NOITE_API_KEY"
- run: bun run build
- run: bunx @noitenow/cli deploy --comment update
  env:
    NOITE_API_KEY: ${{ secrets.NOITE_API_KEY }}
    NOITE_BASE: https://git.<domain>
Flag Env Default
--dist — dist
--slug NOITE_SLUG repo name, slugified
--url GIT_PUBLIC_BASE / NOITE_BASE http://git.localhost:9080
--token NOITE_API_KEY / NOITE_GIT_TOKEN —
--wrangler — wrangler.jsonc
--message — deploy <sha12>
--comment — update (create / off)

In Actions it writes url= + sha= to $GITHUB_OUTPUT and posts (or updates, via marker) a PR comment. A Worker may be declared in cloudflare.config.ts instead of wrangler.json(c) — the runner converts it after the build when no Wrangler config exists.

What happens on push

  1. Tip .bundle lands; the runner updates its bare mirror and worktree.
  2. Sandboxed bun install / bun run build run when the tree declares them.
  3. Optional release command (e.g. migrations) runs. A failed release keeps the old deployment serving.
  4. The config is stripped of Noite-only keys, then celld deploy ships the fleet; a new fleet spawns or the existing one gets POST /reload.

The Deployments tab shows status per push with a build-log pane. Deploy logs keep a 64 KB tail.

Rollback

POST /v1/apps/<id>/rollback {sha} redeploys a past successful SHA — bundles are immutable per SHA. The UI offers rollback on success rows.

Was this page helpful?