Installation
Install the NetStacks Terminal on macOS, Windows, and Linux, and deploy the Controller with Docker Compose.
Overview
NetStacks has two components you can install independently:
- NetStacks Terminal — a native desktop application (with a bundled Local Agent) for connecting to network devices via SSH, Telnet, and SFTP. Available for macOS (Intel and Apple Silicon), Windows (x64), and Linux (x64 and ARM). Free and open source.
- NetStacks Controller — a Docker-based server that adds a shared credential vault, RBAC, audit logging, templates, and scheduled automation. Optional for individual use, required for team deployments. Commercial, licensed separately.
Most users start with Terminal only (Personal Mode). You can add the Controller later when you need centralized, multi-user management.
The Terminal runs on macOS 10.15 (Catalina) or newer (Intel and Apple Silicon), Windows 10+ (x64), and Linux (x64 and ARM with glibc 2.31+). The Controller runs anywhere Docker Engine 20.10+ is available.
How It Works
Terminal is built with Tauri, which packages a Rust backend with a lightweight system WebView into a native binary for each platform. On first launch it starts the Local Agent sidecar, which performs SSH and holds your credential vault. The distribution format varies by OS:
- macOS — DMG disk image containing NetStacks.app
- Windows — MSI installer or NSIS setup executable
- Linux — AppImage (universal) or .deb package (Debian/Ubuntu)
All installers are code-signed and notarized. The Terminal includes a built-in auto-updater powered by the Tauri updater plugin: when a new version is available, it prompts you to download and install without leaving the app.
Controller runs as a set of Docker containers orchestrated by Docker Compose: the API server (Rust + Axum), an admin-ui container (nginx serving the React admin dashboard and the terminal web client over TLS), a required Valkey service for session sharing and pub/sub, and PostgreSQL 16 with pgvector. Updates are applied by pulling new images and restarting the stack.
Step-by-Step Guide
Choose the section that matches your platform. If you are deploying the Controller for your team, follow the Docker Compose instructions after installing the Terminal.
macOS (Intel and Apple Silicon)
NetStacks provides separate DMG installers for each Mac architecture. Choose the one for your processor:
- Apple Silicon (M1/M2/M3/M4) —
NetStacks-arm64.dmg - Intel —
NetStacks-x64.dmg
- Download the appropriate DMG from the downloads page.
- Open the DMG and drag NetStacks.app into your Applications folder.
- Launch NetStacks from Applications or Spotlight. Because the app is code-signed and notarized, Gatekeeper normally opens it without complaint. On first launch the Local Agent starts as a sidecar and you are prompted to set a master password.
- Verify the Terminal launches and shows the welcome screen.
Notarized apps open normally. If a stale quarantine flag triggers a "damaged" error (for example after copying the app off another Mac), clear the quarantine attribute:
xattr -cr /Applications/NetStacks.appClick the Apple menu and choose About This Mac. If the Chip line shows "Apple M1" or later, download the arm64 DMG. If it shows "Intel", download the x64 DMG.
Windows (x64)
Two installer options are available for Windows:
- MSI Installer —
NetStacks-x64.msi(recommended for most users and for enterprise deployment via Group Policy) - NSIS Setup —
NetStacks-x64.exe(alternative installer with custom install directory support)
- Download the MSI or NSIS installer from the downloads page.
- Double-click the installer and follow the wizard. The default install location is
C:\Program Files\NetStacks. - Launch NetStacks from the Start Menu or the desktop shortcut.
- Verify the Terminal launches and shows the welcome screen.
The Windows installer is code-signed. On rare occasions SmartScreen may still prompt for a recently released build — click More info, then Run anyway to proceed.
Linux (x64 and ARM)
NetStacks is distributed in two formats for Linux. Both x64 and ARM (aarch64) builds are available:
- AppImage — universal, runs on any distribution without installation
- .deb package — for Debian, Ubuntu, and derivatives
AppImage
# Download the AppImage for your architecture
# x64: NetStacks-x64.AppImage
# ARM64: NetStacks-aarch64.AppImage
chmod +x NetStacks-*.AppImage
./NetStacks-*.AppImageDebian/Ubuntu (.deb)
# Install the .deb package
sudo dpkg -i netstacks_*_amd64.deb
# If dependencies are missing, fix them
sudo apt-get install -fAfter installing the .deb package, launch NetStacks from your application menu or run netstacks from a terminal.
The .deb package declares two dependencies: libwebkit2gtk-4.1-0 and libgtk-3-0. On Ubuntu 22.04+ install them with sudo apt install libwebkit2gtk-4.1-0 libgtk-3-0. The AppImage bundles most libraries but additionally needs libfuse2 on the host to run.
Controller (Docker Compose)
The Controller is deployed as a Docker Compose stack. The production images are hosted on the NetStacks registry, so you must authenticate before pulling: docker login registry.netstacks.net. The stack consists of:
- api —
registry.netstacks.net/netstacks-controller/controller(Rust + Axum API server, serves over TLS on port 3000) - admin-ui —
registry.netstacks.net/netstacks-controller/admin-ui(nginx serving the React admin dashboard and terminal web client; publishes3000:443) - valkey —
valkey/valkey:8-alpine, a required service for session sharing and pub/sub - db —
pgvector/pgvector:pg16, the bundled PostgreSQL (only runs under thebundled-dbprofile; you may point at an external PostgreSQL instead)
For high-availability deployments, see HA Deployment.
Prerequisites
- Docker Engine 20.10 or later
- Docker Compose v2 (the
docker composesubcommand, not the legacydocker-composebinary) - An account on the NetStacks registry (Controller is commercial)
- 2 GB RAM minimum (4 GB recommended)
- 10 GB available disk space
Step 1: Log in and create a project directory
docker login registry.netstacks.net
mkdir netstacks-controller && cd netstacks-controllerStep 2: Create docker-compose.yml
This mirrors the official deploy file. The bundled db service is gated behind the bundled-db profile; to use an external PostgreSQL instead, set DATABASE_URL in your .env and start only valkey api admin-ui.
services:
db:
image: pgvector/pgvector:pg16
restart: unless-stopped
profiles:
- bundled-db
environment:
POSTGRES_USER: netstacks
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-}
POSTGRES_DB: netstacks
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U netstacks"]
interval: 5s
timeout: 5s
retries: 5
valkey:
image: valkey/valkey:8-alpine
restart: unless-stopped
volumes:
- valkey_data:/data
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
api:
image: registry.netstacks.net/netstacks-controller/controller:${NETSTACKS_VERSION:-latest}
restart: unless-stopped
depends_on:
valkey:
condition: service_healthy
environment:
DATABASE_URL: ${DATABASE_URL:-postgres://netstacks:${POSTGRES_PASSWORD:-}@db:5432/netstacks}
VALKEY_URL: "redis://valkey:6379"
VAULT_MASTER_KEY: ${VAULT_MASTER_KEY}
JWT_SECRET: ${JWT_SECRET}
SERVICE_TOKEN_SECRET: ${SERVICE_TOKEN_SECRET}
TLS_SANS: ${TLS_SANS:-localhost}
HOST: 0.0.0.0
API_PORT: 3000
RUST_LOG: ${RUST_LOG:-info}
NETSTACKS_MODE: enterprise
volumes:
- netstacks_data:/data
healthcheck:
test: ["CMD", "curl", "-fk", "https://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
admin-ui:
image: registry.netstacks.net/netstacks-controller/admin-ui:${NETSTACKS_VERSION:-latest}
restart: unless-stopped
depends_on:
api:
condition: service_healthy
ports:
- "3000:443"
volumes:
- netstacks_data:/data:ro
networks:
default:
name: netstacks_net
volumes:
pgdata:
valkey_data:
netstacks_data:Step 3: Create a .env file with production values
The Controller refuses to start without VAULT_MASTER_KEY, JWT_SECRET, and SERVICE_TOKEN_SECRET. Generate strong random values and keep them out of version control. If VAULT_MASTER_KEY is lost, encrypted credentials cannot be recovered.
# Generate secure values for each secret
openssl rand -hex 32 # VAULT_MASTER_KEY (64 hex chars)
openssl rand -base64 32 # JWT_SECRET
openssl rand -base64 32 # SERVICE_TOKEN_SECRET# .env — place next to docker-compose.yml
NETSTACKS_VERSION=latest
POSTGRES_PASSWORD=<strong random password>
VAULT_MASTER_KEY=<64 hex chars from openssl rand -hex 32>
JWT_SECRET=<string from openssl rand -base64 32>
SERVICE_TOKEN_SECRET=<string from openssl rand -base64 32>
TLS_SANS=<hostname or IP of this server>
# To use an external PostgreSQL instead of the bundled db:
# DATABASE_URL=postgres://user:pass@db-host:5432/netstacksStep 4: Start the stack
To run the bundled PostgreSQL, enable the bundled-db profile. With an external database, omit the profile and start only the other services.
# With the bundled PostgreSQL
docker compose --profile bundled-db up -d
# With an external PostgreSQL (DATABASE_URL set in .env)
docker compose up -d valkey api admin-uiStep 5: Get the first-boot admin password
On first boot the API prints a generated admin password to its logs. Retrieve it, then log in to the admin UI at https://<your-host>:3000:
docker compose logs api | grep "Password:"Set ADMIN_PASSWORD_RESET=true in the api environment, run docker compose up -d api, grab the new password from docker compose logs api | grep "Password:", then remove the variable and restart normally.
Step 6: Verify the Controller is healthy
# Check that the containers are running
docker compose ps
# Hit the TLS health endpoint (-k for the self-signed cert)
curl -sk https://localhost:3000/health | jq
# Expected output:
# {"status":"ok","version":"0.0.5"}Stream API logs with docker compose logs -f api. Database logs (when using the bundled db) are available via docker compose logs -f db.
Code Examples
Common installation and verification commands collected for quick reference.
Log in to the NetStacks registry
docker login registry.netstacks.netmacOS: clear a stale Gatekeeper quarantine flag
xattr -cr /Applications/NetStacks.appLinux: run the AppImage
chmod +x NetStacks-*.AppImage && ./NetStacks-*.AppImageGenerate Controller secrets
openssl rand -hex 32 # VAULT_MASTER_KEY
openssl rand -base64 32 # JWT_SECRET
openssl rand -base64 32 # SERVICE_TOKEN_SECRETGet the first-boot admin password
docker compose logs api | grep "Password:"Check Controller health
curl -sk https://localhost:3000/health | jqTail Controller API logs
docker compose logs -f apiUpdate the Controller to the latest version
docker compose pull && docker compose up -dQ&A
- How do I install NetStacks on macOS?
- Download the DMG for your architecture (arm64 for Apple Silicon, x64 for Intel) from the downloads page, open it, and drag NetStacks.app to Applications. The app is notarized, so it opens normally. See the macOS section for details.
- How do I deploy the Controller?
- Log in with
docker login registry.netstacks.net, create adocker-compose.ymland a.envwith secrets, then rundocker compose --profile bundled-db up -d. Grab the first-boot admin password from the api logs and log in athttps://<host>:3000. Full steps are in the Controller section. - What database and supporting services does the Controller need?
- PostgreSQL 16 with pgvector (bundled or external) plus a required Valkey service for session sharing and pub/sub. Valkey is always on, not HA-only.
- How do I get my first admin login for the Controller?
- The API prints a generated admin password to its logs on first boot. Run
docker compose logs api | grep "Password:"and log in athttps://<host>:3000. To reset it later, useADMIN_PASSWORD_RESET=true. - How do I update NetStacks Terminal?
- The Terminal includes a built-in auto-updater. When a new version is available you see an update prompt inside the app — click Update Now. No manual download required.
- How do I update the Controller?
- Pull the latest images and restart:
docker compose pull && docker compose up -d. Data is persisted in Docker volumes and survives restarts; migrations run automatically on startup. - What port does the Controller use?
- The admin UI and API are served over TLS on port 3000 (the admin-ui container maps
3000:443). If port 3000 is in use, change the host-side mapping indocker-compose.yml.
Troubleshooting
macOS: "NetStacks.app is damaged and can't be opened"
The app is signed and notarized, so this is rare. It usually means a stale quarantine flag (for example after copying the app between machines). Clear it:
xattr -cr /Applications/NetStacks.appWindows: SmartScreen prompt
The installer is code-signed. If SmartScreen still prompts for a brand-new build, click More info, then Run anyway.
Linux: missing libwebkit2gtk or libfuse2
The .deb depends on libwebkit2gtk-4.1-0 and libgtk-3-0. The AppImage additionally needs libfuse2 at runtime:
# .deb dependencies
sudo apt install libwebkit2gtk-4.1-0 libgtk-3-0
# Extra runtime library needed by the AppImage
sudo apt install libfuse2Cannot pull the Controller images
The Controller images live on a private registry. Authenticate first, then pull:
docker login registry.netstacks.net
docker compose pullDocker Compose: v1 syntax errors
The compose file uses Compose v2 syntax (no top-level version: key). Make sure you are running Compose v2 via docker compose:
docker compose version
# Expected: Docker Compose version v2.x.xPort 3000 already in use
The admin-ui publishes 3000:443. If port 3000 is taken, change the host-side mapping:
# In docker-compose.yml, under admin-ui > ports:
ports:
- "8443:443" # serve the Controller on host port 8443 insteadStart fresh (wipes all data)
docker compose down -v # WARNING: deletes all volumes/data
docker compose --profile bundled-db up -dRelated Features
Now that NetStacks is installed, continue with these guides:
- Introduction — how the Terminal, Local Agent, and Controller fit together
- System Requirements — full hardware, software, and network prerequisites
- Quick Start Guide — connect to your first device in minutes
- HA Deployment — multi-instance Controller deployments
- Terminal Overview — the interface, tabs, split panes, and shortcuts