Skip to content

Deploy Tiers

github-actions[bot] edited this page Oct 15, 2026 · 5 revisions

Deploy tiers and targets

The control plane reads .nself/control-plane.yaml at schema version 2. Version 1 files migrate in memory when loaded; nself env target migrate writes the version 2 file. A missing file synthesizes one local environment and one remote environment per NSELF_DEPLOY_HOST_<ENV> variable.

Each environment has a tier: local, local-servers, or prod. When omitted, kind: local derives local, prod or production derives prod, and every other name derives local-servers. A custom name such as live with tier: prod receives the same production confirmation gate. Exactly one local environment is required. A prod environment needs a host and exactly one primary server. Server names are unique across the inventory.

schema_version: 2
project: example
environments:
  local:
    name: local
    kind: local
    tier: local
    servers:
      - {name: local-app, role: app, primary: true}
  qa:
    name: qa
    kind: remote
    tier: local-servers
    require_verified_release: false
    servers:
      - {name: qa-app, role: app, host: deploy@qa.example.test:2222, remote_path: /opt/nself, primary: true, arch: amd64}

host accepts [user@]host[:port], including a bracketed IPv6 literal. Put the install path in remote_path. Legacy user@host:/absolute/path and user@host plus NSELF_REMOTE_PATH_<ENV> still load. In v1.5 mode, the legacy path form warns once per process; it is removed at v1.6.0. Invalid hosts are refused before ssh starts.

Before a remote deploy changes a host, the architecture guard checks every image in the generated compose files. Set a server's arch to amd64 or arm64; when omitted, the guard runs one cached uname -m through the SSH prober. Images present in the image lock use its per-platform digests. Other images use a registry manifest lookup without pulling. Services with a build: context are built on the host and skipped. A missing platform, unknown architecture, or registry lookup error refuses with E491 and names the affected image and host.

nself env target add <env> <server> --tier <tier> --arch <arch> --host <host> adds a server. For a secret-bearing deploy or a prod target in v1.5 mode, an unknown host key is refused before any copy. Verify the reported SHA256 fingerprint independently, then run the exact nself env target add <env> <server> --trust-host-key SHA256:<fingerprint> command. nSelf pins the verified key in ~/.config/nself/deploy_known_hosts; it does not write ~/.ssh/known_hosts.

nself deploy targets --json emits a v1 JSON envelope with every target sorted by environment and server. Rows include tier, role, primary status, user, host, port, ssh_hostname, sorted DNS addresses, known-hosts fingerprints, architecture and source. The command runs ssh -G, DNS lookup and ssh-keygen -F; it never opens a connection to a deploy host. OpenSSH ssh -G evaluates the operator's Match exec configuration, which can run local operator-configured commands.

controlplane.ResolveTargets filters by environment, tier and server and returns matches ordered by environment, role (observability, app, load balancer, database, worker), and name. An empty result is E486.

Pinned host key files

Deploy, access and admin SSH connections quote the absolute deploy pin-file path as one OpenSSH GlobalKnownHostsFile entry, including when HOME contains spaces. They refuse a path containing a double quote, literal backslash or control character before connecting. Windows directory separators are converted to forward slashes. The deploy rsync transport preserves these quotes when parsing its SSH options.

The deploy pin file (~/.config/nself/deploy_known_hosts) and the backup pin file (~/.config/nself/backup_known_hosts, or the path in NSELF_BACKUP_KNOWN_HOSTS) follow the same rules. nSelf refuses to read or change a pin file when:

  • it holds a line nSelf cannot represent: an @cert-authority or @revoked marker, a wildcard, negation, host list, [host]:port or hashed host, a control character, or a short line. The error names the file and line numbers. Remove those lines by hand.
  • the file, its directory, or any directory above it is group or world writable, or is owned by someone other than you or root. A root-owned directory with the sticky bit, such as /tmp, is allowed. ssh opens the file by name when it connects, so a directory another user can write could swap the file after nSelf checked it. Run chmod go-w on the directory the error names, or move the file under a directory you own. A symlinked directory is checked along both its own path and the path it points to. In v1.4 mode a directory above the pin directory that fails this rule (Debian and Ubuntu often create ~/.config as 0775) only prints one warning and the command goes on; with NSELF_V15=1, and from v1.5 on, it is refused. The file and its own directory are refused in both modes.
  • you run nSelf with sudo while the pin directory belongs to your user. Run it as the user who owns the directory.

nSelf never changes the mode of these files or directories for you. Each change to a pin file holds a lock on <file>.lock. If another nSelf process holds that lock for more than 30 seconds, the command stops with an error naming the lock file; find the holder with lsof <file>.lock.

Home


Getting Started


Commands


Features


Configuration


Plugins (87 + 10 monitoring)

Free (25)
Pro (62)
Planned (26)
  • plugin-audit
  • plugin-blog
  • plugin-checkout
  • plugin-commerce
  • plugin-drm
  • plugin-export
  • plugin-flow
  • plugin-import
  • plugin-ldap
  • plugin-mailgun
  • plugin-media
  • plugin-oauth-providers
  • plugin-pages
  • plugin-postmark
  • plugin-rate-limit
  • plugin-reports
  • plugin-saml
  • plugin-scheduler
  • plugin-sendgrid
  • plugin-sso
  • plugin-subscription
  • plugin-thumb
  • plugin-transcoder
  • plugin-twilio
  • plugin-waf
  • plugin-watermark

Guides


Architecture


Reference


Machine interface


Licensing


Security


Brand


Operations


Contributing


Admin


Changelog


All commands (21)

Clone this wiki locally