Skip to Content
CLI Referencenkapp deploy

nkapp deploy

Deploy your application directly to a VPS via SSH. Optimized for Linux servers with automated bootstrap, ephemeral key support, and selective service targeting.

nkapp deploy [service] [options]

Options

FlagTypeDefaultDescription
-e, --env <env>stringstageTarget environment
--ssh <host>stringSSH connection string (e.g., root@192.168.1.1). Overrides deploy.target in config.
-p, --port <port>number22SSH port
-s, --service <name>stringDeploy only a specific service (alias for positional)
--cachebooleanfalseKeep persistent cache volumes (node_modules, build artifacts) on the remote host. By default Nanokit prunes the env-scoped cache paths before each deploy for a clean build.
--rollbackbooleanfalseRollback to the previous state
--forcebooleanfalseBypass health checks during deploy (an unhealthy or slow-starting service will not abort the deploy)
-y, --yesbooleanfalseSkip confirmation prompts

Workflow

1. Load & Resolve

Configuration is loaded, environment overrides are merged, and all secrets are resolved — including the deploy.sshKey field itself, which can be a vault:// URI.

2. SSH Connection

Nanokit connects to the target host using the resolved credentials.

3. VPS Bootstrap Check

If Docker is not installed on the remote host, Nanokit offers to automatically bootstrap the VPS:

  • Installs Docker Engine
  • Configures UFW firewall (opens ports 80, 443)
  • Creates the Nanokit project directory structure

4. Code Synchronization

Project files are synced to /opt/nanokit/projects/<name>/ on the remote host using the configured method:

  • rsync (default): Incremental file sync, respects .gitignore
  • git: Remote git pull from your repository

5. SSL Factory Reset

If public domains are detected (.app, .dev), Nanokit purges stale Caddy certificates to ensure fresh ACME challenges.

6. Service Orchestration

The Reconciler runs on the remote Docker daemon to create/update containers.


Ephemeral SSH Keys

Nanokit supports in-memory SSH keys resolved from Vault. If the sshKey value contains a raw PEM key (from vault://), Nanokit:

  1. Writes it to a temporary file with 0600 permissions
  2. Uses it for the SSH connection
  3. Deletes it immediately after deployment
deploy: target: root@185.47.172.104 sshKey: "vault://infra/ssh#private_key"

Deploy only a single service without touching the rest of the stack using the positional argument (recommended) or the flag:

# Recommended nkapp deploy api -e stage # Also supported nkapp deploy -e stage -s api

Examples

# Deploy to staging using config defaults nkapp deploy -e stage # Deploy to a specific host (override config) nkapp deploy --ssh root@10.0.0.5 -p 2222 # Deploy only the API service nkapp deploy api -e production -y # Rollback to previous state nkapp deploy -e stage --rollback

[!WARNING] The --rollback flag reverts to the previous reconciler state. It does not revert code changes on the remote host.


Excluding files from the deploy (.nanokitignore)

Deploys sync the project to the remote with rsync. Beyond the built-in excludes (.nanokit/, node_modules, dist, .next, .nx, .nk-serve, *-live, .nanokit-mock), add your own by placing a .nanokitignore at the project root. One glob per line; lines starting with # are comments.

# .nanokitignore — extra paths to keep out of the deploy payload *.log fixtures/ docs/internal/

The built-in excludes always apply; .nanokitignore only adds to them. It only affects what is shipped on deploy, not what is committed to git.