Use a dedicated Linux host
Run the installer as root or with sudo. Nearzero can install
Docker on supported distributions. If Compose is missing, a checksum-pinned
fallback covers x86_64 and arm64.
| Requirement | What to prepare |
|---|---|
| Host | A dedicated Linux server with a stable public IPv4 address and root or sudo access. |
| Tools | curl, CA certificates, and sha256sum. Docker may be installed by the script. |
| Storage | Persistent space for images, application builds, Postgres, Redis, DNS zones, and backups. |
| Domain | A domain you control. The browser setup wizard asks for a management hostname such as nearzero.example.com and an optional application zone such as apps.example.com. |
| Firewall | TCP 80 and 443 for Traefik/HTTPS; TCP and UDP 53 when using built-in authoritative DNS; SSH restricted to administrator addresses. |
| The exact first-owner email from the setup wizard. It is also the default Let's Encrypt and DNS SOA contact. |
Download, verify, then run
Quick start on a fresh Linux host (root or sudo). One command downloads the installer and runs it.
curl -fsSL https://nearzero.dev/install.sh | bash For production, prefer the checksum-verified path. It downloads the installer and its SHA-256 into a temporary directory and refuses to run if either download or verification fails.
(set -Eeuo pipefail
tmp="$(mktemp -d)"
trap 'rm -rf -- "$tmp"' EXIT
base_url="https://nearzero.dev"
curl --fail --location --proto '=https' --proto-redir '=https' --tlsv1.2 \
--output "$tmp/install.sh" "$base_url/install.sh"
curl --fail --location --proto '=https' --proto-redir '=https' --tlsv1.2 \
--output "$tmp/install.sh.sha256" "$base_url/install.sh.sha256"
(cd "$tmp" && sha256sum --check install.sh.sha256)
bash "$tmp/install.sh"
) For a reproducible installation, replace the base URL with https://nearzero.dev/releases/<published-version>. The same files are on https://cdn.nearzero.dev. Versioned installer artifacts are immutable; the unversioned URL tracks the current verified release.
What the default installation creates
- Nearzero platform and console on loopback host ports 3000 and 4321, with public management traffic handled by Traefik on 80 and 443. Without a hostname, all generated public/auth callback URLs use the tunnel-safe console origin at
http://127.0.0.1:4321. - Local PostgreSQL and Redis services with persistent Docker volumes.
- Loopback-only host monitoring on port 4500.
- Authoritative-only CoreDNS on TCP and UDP port 53, enabled by default and never used as a recursive resolver.
- A temporary pre-signup DNS zone, when configured, so delegation can be prepared before the first owner claims the installation.
- A mode-0600 configuration file under
/opt/nearzero/.envand anearzerooperations helper.
Give the console and the apps different DNS names
After install, open the one-time setup URL the installer prints
(SSH tunnel to http://127.0.0.1:4321/setup#token=…). The
wizard asks for two names with different jobs:
nearzero.example.comRequired. The HTTPS origin for the console, API, WebSockets, auth, and Git OAuth callbacks.
apps.example.comOptional application zone. Nearzero writes A records here, including records that target remote servers.
With a management hostname, Traefik and Let's Encrypt are configured for that hostname. Noninteractive installs may still set NEARZERO_MANAGEMENT_HOSTNAME, NEARZERO_ADMIN_EMAIL, and NEARZERO_MANAGED_DNS_ZONE to skip the wizard.
Records to create at the parent DNS provider
- Create an A record for the management hostname pointing to the Nearzero host's public IPv4 address.
- Create registrar glue/host A records for
ns1.apps.example.comandns2.apps.example.com, both pointing to that control-plane IP. The default pair is one failure domain, not DNS redundancy. - Delegate
apps.example.comwith NS records for those two nameservers. - Allow TCP 80/443 and TCP+UDP 53 through the host firewall, cloud firewall, and any NAT device.
The bootstrap zone exists before signup. After the first owner is created, Nearzero adopts it into that organization, preserves a management A record when it lies inside the zone, republishes it from Postgres, and selects it for new projects' default environments.
# Parent/public delegation
dig +short NS apps.example.com
# Ask the Nearzero authority directly
dig @203.0.113.10 apps.example.com SOA
# Management DNS and HTTPS
dig +short A nearzero.example.com
curl --fail --show-error --head https://nearzero.example.com Unattended equivalent
Automation must provide both names and the first-owner email explicitly. Nearzero detects the public IP, or you can set a publicly routable NEARZERO_PUBLIC_IP when detection is wrong. Private, shared, loopback, link-local, documentation, benchmark, multicast, and reserved ranges are rejected. The names are persisted and preserved on a normal rerun; changing either one requires a migration and is rejected by the installer.
NEARZERO_NONINTERACTIVE=true \
NEARZERO_MANAGEMENT_HOSTNAME=nearzero.example.com \
NEARZERO_MANAGED_DNS_ZONE=apps.example.com \
NEARZERO_MANAGED_DNS_SOA_EMAIL=admin@example.com \
NEARZERO_ADMIN_EMAIL=admin@example.com \
bash install.sh Claim the first owner, then deploy
- 1Open the management hostname over HTTPS.
Do not submit credentials to raw public ports 3000 or 4321. Traefik requests the Let's Encrypt certificate after the hostname is seeded.
- 2Register with the exact installer email.
Fresh production Community installs use bootstrap registration. Only the configured administrator may create the first owner; ordinary signup becomes invite-only afterward.
- 3Finish the setup panel.
Nearzero shows the management origin and the CoreDNS publish, delegation, and authoritative checks with the exact nameservers to copy.
- 4Create a project and deploy.
The new project's default environment inherits the adopted application zone, so generated app and preview names receive per-server A records automatically.
Invited users can register in bootstrap and invite-only modes after an owner exists. A first installer run rejects invite_only because nobody could issue the first invitation. To intentionally run public account creation, set NEARZERO_REGISTRATION_MODE=open; do not use it as the production default. A public management hostname always requires a valid administrator or SOA/ACME contact, even without a managed application zone.
Local or external Postgres and Redis
With no database settings, the installer provisions local Postgres and Redis. To use external services, select external mode and provide both URLs. Read credentials without terminal echo so they do not become shell arguments or history.
IFS= read -r -s -p "Database URL: " DATABASE_URL; printf '\n'
IFS= read -r -s -p "Redis URL: " REDIS_URL; printf '\n'
export NEARZERO_DATA_MODE=external DATABASE_URL REDIS_URL
bash install.sh
unset NEARZERO_DATA_MODE DATABASE_URL REDIS_URL The installer persists NEARZERO_DATA_MODE=local|external; a plain rerun preserves that mode and the stored URLs. It rejects partial URL input and implicit mode changes. To return to bundled services, unset both URL variables and run NEARZERO_DATA_MODE=local bash install.sh. Use provider-required TLS, percent-encode credentials inside connection URLs, and remember that the generated mode-0600 environment file is still privileged plaintext available to host administrators.
A plain rerun also preserves the Postgres identity, published ports, metrics settings, startup timeout, release image references, and additional single-line KEY=value integration settings unless you explicitly override a generated variable. Custom assignments are copied without being sourced or printed. Malformed lines or duplicate keys stop the rerun so configuration and secrets cannot be silently discarded.
NEARZERO_ENABLE_MANAGED_DNS=falseDisable the Compose-owned authoritative DNS service when port 53 is unavailable or an external provider owns DNS.
NEARZERO_DNS_BIND_ADDRESSChoose the host address used by CoreDNS. Public resolvers still require destination port 53.
NEARZERO_PUBLIC_IPOverride automatic detection with the publicly routable IPv4 address when the host is behind one-to-one NAT or detection is wrong.
NEARZERO_MANAGEMENT_HOSTNAMESet the public console hostname. The installer derives the HTTPS auth, trusted-origin, and Git callback settings together.
NEARZERO_MANAGED_DNS_ZONEStage the authoritative application zone that the first owner adopts. This is separate from the console hostname.
NEARZERO_ADMIN_EMAILChoose the only email allowed to claim a fresh bootstrap installation.
NEARZERO_MANAGEMENT_BIND_ADDRESSRaw ports default to 127.0.0.1. Use 0.0.0.0 only on a protected VPN/private network.
NEARZERO_PLATFORM_PORTChange the published platform API port. The container continues listening internally on 3000.
NEARZERO_CONSOLE_PORTChange the loopback console port. Public HTTPS remains on Traefik port 443.
NEARZERO_SSH_STRICT_HOST_KEY_CHECKING=trueRequire pre-seeded remote-server fingerprints instead of trust on first use.
Do not expose raw API and console ports
| Port | Role | Recommended exposure |
|---|---|---|
| 80 + 443/TCP | Traefik HTTP redirect, ACME, console HTTPS, and local workloads | Public when using the configured management hostname or hosting public services. |
| 3000/TCP | Raw platform API | Loopback by default. Private VPN override only. |
| 4321/TCP | Raw console | Loopback by default. Private VPN override only. |
| 53/TCP + UDP | Authoritative DNS | Public only when this host serves delegated managed zones. |
| 4500/TCP | Monitoring | Loopback only; the generated Compose file already binds it to 127.0.0.1. |
Status, updates, backups
sudo nearzero status
sudo nearzero logs platform
sudo nearzero restart
sudo nearzero update # pulls the image references already configured
# Local Postgres installations only
sudo install -d -m 0700 /var/backups/nearzero
sudo nearzero backup-db /var/backups/nearzero/control-plane.sql
sudo nearzero restore-db /path/to/verified-backup.sql The built-in backup and restore commands support the installer-managed local Postgres service. If you use an external database, follow that provider’s verified backup and point-in-time recovery process.
The helper reads the installed Postgres user and database from the protected environment file rather than the caller’s shell. It writes a same-directory temporary dump with mode 0600 and renames it only after pg_dump succeeds, so an interrupted or failed dump cannot replace the previous complete backup.
Database migrations run during platform startup, so there is no guaranteed one-command control-plane downgrade. A rollback can require the prior exact images plus a coordinated restoration of the pre-upgrade database, configuration, and volumes.
SQL dumps contain privileged workspace data and credentials. Keep the helper’s restrictive file mode, encrypt off-host copies, and back up application volumes, DNS data, configuration, and remote-server state separately—the helper covers only local control-plane Postgres.
- 1Back up before an update.
Store the database dump and privileged configuration in encrypted off-host storage.
- 2Pin the release you intend to run.
Confirm all companion image tags exist before changing image references.
- 3Test restoration.
A backup is useful only after a successful restore has been rehearsed on an isolated host.
- 4Recheck the perimeter.
Verify management, DNS, and workload ports externally after updates and host reboots.
Questions this page answers
How do I install Nearzero on a VPS?
Use a dedicated Linux host. Download the published installer, check the SHA-256 checksum, read the script, run it, then finish setup on your own HTTPS admin URL.
Does the installer terminate TLS for the admin UI?
No. Control-plane ports stay plain HTTP. Put TLS in front of them, or keep them on a management network, before production use.
How do I update or back up a self-hosted Nearzero install?
Use the packaged nearzero commands for status, logs, restart, and update. Back up Postgres and privileged configuration off-host, then test restore.