Self-hosted deployment platform for Nix flake applications. Connect a GitHub or Harbur repository, pick a flake output, and deploy. Nix Ship supervises the process, streams logs, assigns a stable LAN port, and optionally exposes it through Cloudflare Tunnel.
| Feature | Description |
|---|---|
| GitHub auto-deploy | Push to your production branch, Nix Ship redeploys the exact commit. Branch reconciliation catches missed webhooks. |
| Harbur merge deploys | Poll durable merge events and deploy the exact digest-verified immutable snapshot. |
| LAN-first | Every application gets a stable port reachable at http://<device-ip>:<port> with no external dependency. |
| Quick Tunnels | Account-free temporary trycloudflare.com URLs for the dashboard and every active web deployment, shown only after the public edge reaches that deployment when cloudflared is available. |
| Release retention & promotion | Retain a global number of active releases per project, preview each independently, and point a configured production domain at any healthy retained release without rebuilding it. |
| Persistent named tunnels | Optional restricted Cloudflare API-token connection for custom domains, DNS management and multi-zone support. |
| Encrypted secrets | Environment variables are encrypted at rest and never returned by APIs. Paste directly from a .env file. |
| Zero-downtime deploys | The current healthy release stays routed until the candidate passes health checks. |
| Approval-gated AI assistant | An optional OpenAI-compatible model can answer from live state and propose typed operations across applications, deployments, sources, Cloudflare, Harbur, settings and AI runtime management. Exact hash approval, RBAC, reauthentication, preconditions and deterministic verification remain outside the model. |
Prerequisites: a working Nix installation on
x86_64-linux, aarch64-linux, or aarch64-darwin.
nix develop
pnpm install
pnpm devOpen one of the clearly marked setup URLs printed in your terminal to claim the
instance and create the owner account. Nix Ship prints the LAN URL (or a local
URL for a loopback-only binding) and also prints a Quick Tunnel URL when
cloudflared becomes available. The link carries the one-time claim token, so
there is no token field to copy. Creating the owner account signs you in
immediately.
- Connect a source: use the GitHub App manifest flow, paste a public GitHub URL, or verify a Harbur instance once with its read token.
- Search and select a trusted repository with a locked flake.
- Pick the flake output (defaults to
apps.<system>.default). - Configure health path and environment variables.
- Deploy: Nix Ship clones, evaluates the flake, builds via
nix run, and health-checks the candidate before switching traffic.
A web application must remain in the foreground and listen on HOST and PORT.
Mutable state belongs under DATA_DIR. The repository must contain flake.nix
and flake.lock.
apps.${system}.default = {
type = "app";
program = "${package}/bin/server";
};See docs/DEPLOYMENT_CONTRACT.md and the
example projects.
- Next.js App Router, React, TypeScript strict mode
- Node.js 24, SQLite through
better-sqlite3 - Tailwind CSS, daisyUI
- Zod validation, Server-Sent Events
- Biome (format + lint), Vitest, Playwright
- Nix, Git and cloudflared as managed executables
The dashboard includes a global AI assistant drawer. It can answer questions through bounded read capabilities and can operate applications, deployments, environment metadata, GitHub/Harbur sources, Cloudflare domains, AI providers, and model defaults.
The model receives role-filtered read tools as JSON-Schema function definitions and
discovers mutation descriptors through capabilities_search. It can return an
answer, request an input, or call propose_plan with the strict versioned plan
schema. Mutation implementations are never model-callable.
Plans are bound to a canonical SHA-256 hash, state snapshot, capability versions and
the authenticated human. Approval reloads the persisted plan and starts deterministic
Nix Ship code; deployment progress comes from real runtime events.
Sensitive/destructive plans require current-password re-authentication, and secure
input plaintext never enters model context; the model sees only a scoped, expiring,
one-use opaque reference. See
docs/AI_CONTROL_PLANE.md for the exact model message,
tool-call, plan, approval and execution-result formats.
Public GitHub repositories are inspected first. Both flake.nix and flake.lock
must be committed; otherwise the assistant provides a starter flake and exact
lock/hash instructions instead of proposing deployment. Models must pass the
strict tool/plan compatibility probe before planning; failures remain answer-only.
Operators can configure any OpenAI-compatible provider (Ollama, Anthropic Claude,
Google Gemini, OpenAI, Groq, Mistral, DeepSeek, or a LiteLLM Proxy) via the dashboard
/ai page or via environment variables before startup:
PLATFORM_AI_BASE_URL=https://provider.example/v1
PLATFORM_AI_MODEL=model-id
PLATFORM_AI_API_KEY=... # optional for a trusted local endpointPrivate external endpoints, including operator-run Ollama on loopback, additionally require
PLATFORM_AI_ALLOW_PRIVATE_NETWORK=true. Plain HTTP is accepted only for an
explicitly enabled private endpoint. Never paste credentials into chat; use the
masked secure-input card or provider management card.
For a flake-pinned local Ollama development environment, use the optional AI shell:
nix develop .#ai
ollama serveIn a second nix develop .#ai shell, pull an exact model tag, export that tag as
both PLATFORM_AI_MODEL and AI_LOCAL_TEST_MODEL, then run pnpm test:ai-local.
The AI shell sets the loopback endpoint, private-network opt-in and a repository-local
Ollama model directory.
See SPECIFICATION.md for the normative platform requirements,
docs/ARCHITECTURE.md for the AI control-plane design, and
docs/OPERATIONS.md for configuration and local-model probing.
- Architecture
- AI capability and plan protocol
- Deployment contract
- Security model
- GitHub integration
- Cloudflare integration
- Android and Nix-on-Droid
- Operations
- Testing
- Known limitations
- Harbur deployment integration
- Product requirements
- Specification
- Implementation status
Every imported repository executes arbitrary code under the Nix Ship OS account. Nix flakes provide reproducibility, not a security boundary. Only deploy repositories you trust.
Apache-2.0. Copyright 2026 Rituraj Basak. See LICENSE.