Skip to content

Getting Started with Nanokit ​

Nanokit is a developer-first container orchestration platform built around a single config file — nanokit.yml. This guide walks you from zero to a running local environment, then all the way through staging and production deployment.


Prerequisites ​

Before you begin, make sure the following are in place:

RequirementNotes
DockerMust be running locally. Used by nkapp up -e local.
nkapp CLIInstall via npm install -g @nkapp/cli or your package manager of choice.
SSH key pairRequired for VPS-based environments (staging, production).
A VPSAny Linux server accessible over SSH. Root access is recommended for first-time bootstrapping.

Note. You do not need Kubernetes or any cloud provider to get started. Nanokit runs on plain Docker — locally and on remote servers.


Step 1 — Initialize Your Project ​

Navigate to your project root and run:

bash
nkapp init

This scaffolds a nanokit.yml file in the current directory with sensible defaults derived from your project structure.

If you prefer an interactive setup wizard, use nkapp configure instead:

bash
nkapp configure

nkapp configure walks you through naming your project and defining its initial services. It is the recommended path if you are new to Nanokit.

configure only runs on a fresh project

If a nanokit.yml already exists, nkapp configure refuses to run and points you at nkapp service add. It is a scaffolder, not an editor. To change an existing configuration use nkapp service add, nkapp config set, or edit the YAML directly.


Step 2 — Understand nanokit.yml ​

nanokit.yml is the single source of truth for your entire project. It defines your services and how they behave across every environment.

Here is a realistic minimal example:

yaml
name: my-app

services:
  api:
    runtime: node
    port: 3000
    start: node dist/index.js
    host: api.my-app.localhost
    env:
      NODE_ENV: development

environments:
  local:
    infra:
      provider: docker
    services:
      api:
        start: npm run dev

  stage:
    infra:
      provider: docker
    deploy:
      target: root@185.47.172.104
      sshKey: ~/.ssh/id_rsa
      method: rsync
      prepare: npm ci && npm run build
    services:
      api:
        host: api.my-app.com
        env:
          NODE_ENV: production

Key concepts:

  • services — the top-level block defines service defaults shared across all environments. Each service gets a runtime, a port, a start command, and an optional host for routing.
  • environments.local — overrides for local development. Here, api uses npm run dev (hot-reload) instead of the production start command. The provider: docker means Nanokit manages everything through local Docker.
  • environments.stage — adds a deploy block pointing to a remote VPS. The prepare command runs on the server (in an isolated runtime container) after the code sync and before the reconcile. Service-level overrides (like host and env) replace the defaults for this environment only.
  • Environment promotion — the same nanokit.yml governs all environments. You promote by targeting a different environment, not by maintaining separate config files.

A non-empty per-environment services: block restricts membership

Listing any service under environments.<env>.services means only those services deploy to that environment. Root services you did not list are excluded, not merged. See Environments → Exclude by Default.

Important. Never commit secrets directly into nanokit.yml. Use the env block for non-sensitive values and manage secrets separately with nkapp secrets.


Step 3 — Start Local Development ​

With your nanokit.yml in place, bring up your local environment:

bash
nkapp up -e local

Nanokit will:

  1. Parse nanokit.yml and resolve the local environment block.
  2. Resolve every vault:// / env:// secret reference.
  3. Pull or build required Docker images.
  4. Start all services as containers on the shared private Docker network nanokit-net.
  5. Start the Caddy gateway and configure HTTPS routing to each service's .localhost domain.

Your API will be reachable at https://api.my-app.localhost (or whatever host you configured) within seconds. If a service has no explicit host, Nanokit derives one automatically as <service>.<project>.localhost.

Trust the local HTTPS certificate

The Caddy gateway issues certificates for .localhost domains from a local Nanokit Root CA. On first run, your browser may warn you. To silence the warning permanently, install the Root CA into your system trust store with one command:

bash
nkapp host trust

This works on macOS (System Keychain), Linux (update-ca-certificates + NSS databases for Chrome/Firefox), and WSL2 (also propagates to the Windows certificate store). Fully restart your browser afterwards. See nkapp host trust for details.

Open the Hub

nkapp up starts and manages the bridge container (nk-<project>-<env>-bridge) that feeds the Hub. To open the dashboard:

bash
nkapp hub

The Hub gives you a live view of running containers, resource usage, and log streams for every service in your project.


Step 4 — Run a Health Check ​

Before you start building in earnest, verify your environment is fully healthy:

bash
nkapp doctor

nkapp doctor is read-only and reports on:

  • System architecture support (x64 / arm64)
  • Docker daemon reachability and version
  • nanokit.yml syntax and schema validity
  • Gateway / infrastructure status for the current project
  • Cloud deploy preflight (a region must resolve for every cloud environment)
  • Mail delivery configuration (when configured)
  • Container hygiene — how many stale containers have accumulated
  • Image space — how much Docker image space is reclaimable
  • CLI freshness (whether a newer @nkapp/cli is available)

Warning. Always run nkapp doctor when switching machines or after a Docker/system update. It catches the majority of "why won't it start" issues before they become time sinks.

Fix any issues flagged by doctor before proceeding. Each problem comes with a suggested remediation step.


Step 5 — Useful Local Commands ​

Once your stack is running locally, these commands cover the most common day-to-day operations:

Tail logs from a service

bash
nkapp logs api

Stream live log output from a container. Press Ctrl+C to stop tailing.

Open a shell inside a container

bash
nkapp shell api

Drops you into an interactive shell inside the running api container. Useful for one-off commands, inspecting the filesystem, or debugging.

Stop all local services

bash
nkapp stop -e local

Gracefully stops all containers for the local environment without removing them — restart instantly with nkapp start. To remove the containers (and the project network and gateway), use nkapp destroy; volumes and images are preserved either way.

Tip. Use nkapp stop / nkapp destroy rather than raw docker commands — they ensure the Caddy gateway and project resources are managed consistently.


Step 6 — Deploy to Staging ​

When your local work is ready for a shared environment, deploy to your staging VPS.

Configure the stage environment

Make sure the stage block in your nanokit.yml is populated (see Step 2). At minimum you need:

yaml
environments:
  stage:
    infra:
      provider: docker
    deploy:
      target: root@<your-vps-ip>
      sshKey: ~/.ssh/id_rsa
      method: rsync
      prepare: npm ci && npm run build
    services:
      api:
        host: api.my-app.com
        env:
          NODE_ENV: production

Preview what will change

Before applying any changes to a remote environment, run a dry-run to see exactly what Nanokit would do:

bash
nkapp plan -e stage

This shows added, modified, and removed services — plus a preview of the deploy scope — without touching the server.

Provision and deploy

bash
nkapp deploy -e stage

deploy — not up — provisions a new environment

Since the up/deploy split, nkapp up no longer provisions infrastructure or syncs code by default. Against a never-provisioned remote environment it fails fast and tells you to run nkapp deploy. Use deploy for the first run and for every subsequent ship; use up for the service-only inner loop.

On first run, nkapp deploy -e stage:

  1. SSHes into the target server using your configured key.
  2. Offers to install Docker and configure the firewall if the VPS is bare.
  3. Ensures the private Docker network and the Caddy gateway on the host.
  4. Rsyncs your project code to /opt/nanokit/projects/my-app/.
  5. Runs the prepare command on the server (npm ci && npm run build).
  6. Starts all containers and configures the gateway for your production-style domains.

Subsequent runs are change-proportional: deploy computes which services actually changed since the last successful deploy to this target and deploys only those plus their dependents. When nothing changed it prints Nothing to deploy and exits without touching the server. Force a full deploy with --all. See deploy scoping.

Pull resolved secrets locally

If your project references remote secrets (e.g. vault:// URIs), resolve them into a local .env file:

bash
nkapp secrets pull            # writes .env (local environment)
nkapp secrets pull -e stage   # writes .env.stage

These files contain resolved plain-text values — keep them in .gitignore and never commit them.


Step 7 — The Two Loops ​

Once staging exists, you have two commands with different jobs:

LoopCommandWhat it does
Inner — iterate on a running environmentnkapp up -e stageReconciles services only. No provisioning, no code sync. Fast.
Outer — ship a changenkapp deploy -e stageSyncs code, runs prepare on the host, reconciles the changed services.
bash
# Typical workflow
git add .
git commit -m "fix: handle empty state in /api/items"
nkapp deploy -e stage
nkapp logs api          # confirm the fix is live

If you need up to behave the way it did before the split, pass --infra --sync (or --legacy).


Step 8 — Promote to Production ​

When staging has been validated, promote your changes to production:

bash
nkapp plan -e production      # dry-run first
nkapp deploy -e production    # provision (first run) and ship
nkapp up -e production        # service-only reconcile afterwards

Production environments follow the same structure as staging. Add a production block to nanokit.yml pointing to your production server(s):

yaml
environments:
  production:
    infra:
      provider: docker
    deploy:
      target: root@<prod-ip>
      sshKey: ~/.ssh/id_rsa_prod
      method: rsync
      prepare: npm ci && npm run build
    services:
      api:
        host: api.my-app.com
        env:
          NODE_ENV: production

Caution. Always run nkapp plan -e production and review the output before deploying. Changes to production are applied immediately. If a deploy goes wrong, nkapp deploy -e production --rollback restores the previous reconciler state — it does not revert code on the remote host, and it is never triggered automatically.


Multi-Environment Workflow at a Glance ​

Local (Docker)  →  Staging (VPS)  →  Production (VPS)
  nkapp up          nkapp deploy      nkapp deploy      ← provision + ship
  -e local          -e stage          -e production
                    nkapp up          nkapp up          ← service-only inner loop
                    -e stage          -e production

All three environments are driven by the same nanokit.yml. Environment-specific overrides (hosts, env vars, deploy targets) live in their respective environments.<name> blocks. There are no separate config files to keep in sync.


Next Steps ​