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
curl http://localhost:8080/api/v1/healthz
Expected response: ok
Access the Web Dashboard
Open your browser and navigate to:
You'll see the Nekzus dashboard with:
| Page | Description |
|---|---|
| Overview | System status and quick actions |
| Discovery | Auto-discovered services and proposals |
| Routes | Active proxy routes |
| Catalog | Available applications |
| Settings | Theme customization (7 themes available) |
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
- docker run
services:
my-app:
image: myapp:latest
labels:
nekzus.enable: "true"
nekzus.app.name: "My Application"
nekzus.app.id: "myapp"
nekzus.route.path: "/apps/myapp/"
docker run -d \
--name my-app \
--label nekzus.enable=true \
--label nekzus.app.name="My Application" \
--label nekzus.app.id=myapp \
--label nekzus.route.path="/apps/myapp/" \
myapp:latest
Label Reference
| Label | Required | Description |
|---|---|---|
nekzus.enable | Yes | Set to "true" to enable discovery |
nekzus.app.name | No | Display name in dashboard |
nekzus.app.id | No | Unique identifier (auto-generated if omitted) |
nekzus.route.path | No | Proxy path (e.g., /apps/myapp/) |
Example: Grafana with Discovery
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
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:
- Open the Discovery page in the dashboard
- View pending proposals
- 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:
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
| Option | Type | Description |
|---|---|---|
id | string | Unique route identifier (e.g., route:myapp) |
app_id | string | Associated application ID |
path_base | string | URL path prefix (e.g., /apps/myapp/) |
to | string | Upstream service URL |
strip_prefix | boolean | Remove path prefix before forwarding |
websocket | boolean | Enable WebSocket proxying |
scopes | array | Required 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:
- Open the Route Tester page
- Select a route from the dropdown
- Enter a request path
- Click Send Request
- 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 addressX-Forwarded-Host: Original host headerX-Forwarded-Proto: Original protocol (http/https)
Production Configuration
For production deployments, configure secure secrets:
- Environment Variables
- .env File
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
NEKZUS_JWT_SECRET=your-secure-random-secret-min-32-chars
NEKZUS_BOOTSTRAP_TOKEN=your-bootstrap-token
NEKZUS_BASE_URL=https://your-server:8443
docker run -d \
--name nekzus \
--env-file .env \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v nekzus-data:/app/data \
nstalgic/nekzus:latest
Always use strong, randomly generated secrets in production:
NEKZUS_JWT_SECRET: Minimum 32 charactersNEKZUS_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 ComposeQuick Reference
Essential Environment Variables
| Variable | Default | Description |
|---|---|---|
NEKZUS_ADDR | :8080 | Server listen address |
NEKZUS_JWT_SECRET | - | JWT signing secret (32+ chars) |
NEKZUS_BOOTSTRAP_TOKEN | - | Bootstrap authentication token |
NEKZUS_BASE_URL | auto-detect | Public URL for QR pairing |
NEKZUS_DATABASE_PATH | ./data/nexus.db | SQLite database path |
Discovery Labels
| Label | Example | Description |
|---|---|---|
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
| Port | Protocol | Description |
|---|---|---|
| 8080 | HTTP | Web dashboard and API |
| 8443 | HTTPS | Secure access (with Caddy) |
| 7946 | TCP/UDP | Federation gossip (optional) |