NetStacksNetStacks

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.

Supported Platforms

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
  1. Download the appropriate DMG from the downloads page.
  2. Open the DMG and drag NetStacks.app into your Applications folder.
  3. 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.
  4. Verify the Terminal launches and shows the welcome screen.
Rare: 'App is damaged' after copying between machines

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.app
Which architecture am I running?

Click 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)
  1. Download the MSI or NSIS installer from the downloads page.
  2. Double-click the installer and follow the wizard. The default install location is C:\Program Files\NetStacks.
  3. Launch NetStacks from the Start Menu or the desktop shortcut.
  4. Verify the Terminal launches and shows the welcome screen.
Windows SmartScreen

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-*.AppImage

Debian/Ubuntu (.deb)

# Install the .deb package
sudo dpkg -i netstacks_*_amd64.deb

# If dependencies are missing, fix them
sudo apt-get install -f

After installing the .deb package, launch NetStacks from your application menu or run netstacks from a terminal.

Linux dependencies

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; publishes 3000: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 the bundled-db profile; 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 compose subcommand, not the legacy docker-compose binary)
  • 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-controller

Step 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.

docker-compose.ymlyaml
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

Generate and protect every secret

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
.envbash
# .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/netstacks

Step 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-ui

Step 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:"
Resetting the admin 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"}
View logs

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.net

macOS: clear a stale Gatekeeper quarantine flag

xattr -cr /Applications/NetStacks.app

Linux: run the AppImage

chmod +x NetStacks-*.AppImage && ./NetStacks-*.AppImage

Generate Controller secrets

openssl rand -hex 32      # VAULT_MASTER_KEY
openssl rand -base64 32   # JWT_SECRET
openssl rand -base64 32   # SERVICE_TOKEN_SECRET

Get the first-boot admin password

docker compose logs api | grep "Password:"

Check Controller health

curl -sk https://localhost:3000/health | jq

Tail Controller API logs

docker compose logs -f api

Update the Controller to the latest version

docker compose pull && docker compose up -d

Q&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 a docker-compose.yml and a .env with secrets, then run docker compose --profile bundled-db up -d. Grab the first-boot admin password from the api logs and log in at https://<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 at https://<host>:3000. To reset it later, use ADMIN_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 in docker-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.app

Windows: 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 libfuse2

Cannot pull the Controller images

The Controller images live on a private registry. Authenticate first, then pull:

docker login registry.netstacks.net
docker compose pull

Docker 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.x

Port 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 instead

Start fresh (wipes all data)

docker compose down -v   # WARNING: deletes all volumes/data
docker compose --profile bundled-db up -d

Now that NetStacks is installed, continue with these guides: