Skip to main content

Quick Start

Get Nekzus running in under 5 minutes. This guide focuses on the fastest path to a working setup with service discovery and reverse proxy functionality.


Start Nekzus

The fastest way to get started is with a single Docker command.

One-Liner (Docker)

docker run -d \
--name nekzus \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v nekzus-data:/app/data \
nstalgic/nekzus:latest

That's it. Nekzus is now running with:

  • Web dashboard on port 8080
  • Docker container discovery enabled
  • Persistent data storage
  • Default configuration
Verify it's running
curl http://localhost:8080/api/v1/healthz

Expected response: ok


Access the Web Dashboard

Open your browser and navigate to:

http://localhost:8080

You'll see the Nekzus dashboard with:

PageDescription
OverviewSystem status and quick actions
DiscoveryAuto-discovered services and proposals
RoutesActive proxy routes
CatalogAvailable applications
SettingsTheme customization (7 themes available)
Keyboard Shortcut

Press Ctrl+K (or Cmd+K on macOS) to open the theme switcher.


Enable Service Discovery

Nekzus automatically discovers Docker containers with the right labels. Add these labels to any container you want discovered.

Docker Container Labels

Add these labels to your docker-compose.yml or docker run command:

docker-compose.yml
services:
my-app:
image: myapp:latest
labels:
nekzus.enable: "true"
nekzus.app.name: "My Application"
nekzus.app.id: "myapp"
nekzus.route.path: "/apps/myapp/"

Label Reference

LabelRequiredDescription
nekzus.enableYesSet to "true" to enable discovery
nekzus.app.nameNoDisplay name in dashboard
nekzus.app.idNoUnique identifier (auto-generated if omitted)
nekzus.route.pathNoProxy path (e.g., /apps/myapp/)

Example: Grafana with Discovery

docker-compose.yml
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
labels:
nekzus.enable: "true"
nekzus.app.name: "Grafana"
nekzus.app.id: "grafana"
nekzus.route.path: "/apps/grafana/"
networks:
- nekzus-network

networks:
nekzus-network:
external: true
name: nekzus-network
Network Connectivity

For Nekzus to proxy requests to your containers, they must be on a network accessible to Nekzus. The easiest approach is to put them on the same Docker network.

View Discovered Services

After adding labels and restarting your container:

  1. Open the Discovery page in the dashboard
  2. View pending proposals
  3. Click Approve to create a route automatically

Or via API:

# List discovered proposals
curl http://localhost:8080/api/v1/discovery/proposals

# Approve a proposal
curl -X POST http://localhost:8080/api/v1/discovery/proposals/{id}/approve

Add a Route Manually

You can also add routes manually without discovery labels. This is useful for external services or services running outside Docker.

Via Configuration File

Create or edit your configuration file:

config.yaml
routes:
- id: "route:my-service"
app_id: "my-service"
path_base: "/apps/my-service/"
to: "http://192.168.1.100:8080"
strip_prefix: true
websocket: true
scopes: []

apps:
- id: "my-service"
name: "My External Service"
endpoints:
lan: "http://192.168.1.100:8080"

Then start Nekzus with the config:

docker run -d \
--name nekzus \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v $(pwd)/config.yaml:/app/configs/config.yaml:ro \
-v nekzus-data:/app/data \
nstalgic/nekzus:latest \
--config /app/configs/config.yaml

Route Configuration Options

OptionTypeDescription
idstringUnique route identifier (e.g., route:myapp)
app_idstringAssociated application ID
path_basestringURL path prefix (e.g., /apps/myapp/)
tostringUpstream service URL
strip_prefixbooleanRemove path prefix before forwarding
websocketbooleanEnable WebSocket proxying
scopesarrayRequired authentication scopes

Test the Proxy

Once you have a route configured (either via discovery or manually), test the proxy functionality.

Basic Proxy Test

# Replace 'grafana' with your app ID
curl http://localhost:8080/apps/grafana/

Using the Route Tester

The web dashboard includes a built-in route testing tool:

  1. Open the Route Tester page
  2. Select a route from the dropdown
  3. Enter a request path
  4. Click Send Request
  5. View the full request/response details

WebSocket Proxy Test

For WebSocket-enabled routes:

# Using websocat (install: cargo install websocat)
websocat ws://localhost:8080/apps/myapp/ws

# Using wscat (install: npm install -g wscat)
wscat -c ws://localhost:8080/apps/myapp/ws

Verify Proxy Headers

Nekzus automatically adds forwarding headers:

curl -v http://localhost:8080/apps/myapp/ 2>&1 | grep -i x-forwarded

Expected headers on upstream requests:

  • X-Forwarded-For: Client IP address
  • X-Forwarded-Host: Original host header
  • X-Forwarded-Proto: Original protocol (http/https)

Production Configuration

For production deployments, configure secure secrets:

docker run -d \
--name nekzus \
-p 8080:8080 \
-e NEKZUS_JWT_SECRET="$(openssl rand -base64 32)" \
-e NEKZUS_BOOTSTRAP_TOKEN="$(openssl rand -base64 24)" \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v nekzus-data:/app/data \
nstalgic/nekzus:latest
Security Notice

Always use strong, randomly generated secrets in production:

  • NEKZUS_JWT_SECRET: Minimum 32 characters
  • NEKZUS_BOOTSTRAP_TOKEN: Used for device pairing

Common Commands

Container Management

# View logs
docker logs -f nekzus

# Restart
docker restart nekzus

# Stop
docker stop nekzus

# Remove
docker rm -f nekzus

API Endpoints

# Health check
curl http://localhost:8080/healthz

# Instance info
curl http://localhost:8080/api/v1/admin/info

# List apps
curl http://localhost:8080/api/v1/apps

# List routes
curl http://localhost:8080/api/v1/routes

# List discovery proposals
curl http://localhost:8080/api/v1/discovery/proposals

Troubleshooting

Docker discovery not finding containers

Check 1: Ensure Docker socket is mounted correctly:

docker inspect nekzus | grep -A5 Mounts

Check 2: Verify container labels are correct:

docker inspect my-app | grep -A10 Labels

Check 3: Check Nekzus logs:

docker logs nekzus 2>&1 | grep -i discovery
Proxy returns 502 Bad Gateway

Check 1: Verify the upstream service is running:

curl http://upstream-host:port/

Check 2: Ensure network connectivity:

docker exec nekzus ping upstream-host

Check 3: Containers must be on the same Docker network or use host networking.

Cannot access dashboard from other devices

Check 1: Bind to all interfaces:

-e NEKZUS_ADDR=":8080"  # Listens on all interfaces

Check 2: Ensure firewall allows port 8080:

# Linux (ufw)
sudo ufw allow 8080

# Linux (firewalld)
sudo firewall-cmd --add-port=8080/tcp --permanent

Check 3: Set NEKZUS_BASE_URL for QR code pairing:

-e NEKZUS_BASE_URL="http://192.168.1.100:8080"

Next Steps

Now that Nekzus is running, explore these features:

⚙️ Configuration Reference

Learn about all configuration options including authentication, TLS, and advanced routing.

→ Configuration

🐳 Docker Compose Guide

Production-ready Docker Compose setup with Caddy for TLS termination.

→ Docker Compose

🔍 Discovery Features

Deep dive into Docker, Kubernetes, and mDNS service discovery.

→ Discovery

🧰 Toolbox

One-click deployment of popular services from the built-in catalog.

→ Toolbox

📡 API Reference

Complete API documentation for integrations and automation.

→ API Reference

🖥️ Platform Guides

Specific instructions for Synology, Unraid, Proxmox, and Raspberry Pi.

→ Platforms

Quick Reference

Essential Environment Variables

VariableDefaultDescription
NEKZUS_ADDR:8080Server listen address
NEKZUS_JWT_SECRET-JWT signing secret (32+ chars)
NEKZUS_BOOTSTRAP_TOKEN-Bootstrap authentication token
NEKZUS_BASE_URLauto-detectPublic URL for QR pairing
NEKZUS_DATABASE_PATH./data/nexus.dbSQLite database path

Discovery Labels

LabelExampleDescription
nekzus.enable"true"Enable discovery
nekzus.app.name"My App"Display name
nekzus.app.id"myapp"Unique identifier
nekzus.route.path"/apps/myapp/"Proxy path

Default Ports

PortProtocolDescription
8080HTTPWeb dashboard and API
8443HTTPSSecure access (with Caddy)
7946TCP/UDPFederation gossip (optional)