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)