Introduction
usulnet is a self-hosted Docker management platform built with Go. It ships as a single binary (~50 MB) with 39 backend services, 36 database migrations, and 60+ embedded application templates. It provides a unified web interface for managing containers, images, volumes, networks, stacks, security scanning, monitoring, reverse proxy, backups, registry browsing, and multi-node deployments.
Designed for sysadmins, DevOps engineers, and platform teams who need a production-grade, self-hosted alternative to Portainer and cloud-native container management solutions — without vendor lock-in, telemetry, or external dependencies.
v26.2.0 is the first public beta release. The platform is functional and actively used in production, but you may encounter bugs or incomplete features. Report issues on GitHub.
Key Highlights
- Single binary — No runtime dependencies. Templ templates and Tailwind CSS compiled at build time. ~50 MB.
- Multi-node — Master/agent architecture with NATS JetStream, mTLS, and persistent event logging.
- Security-first — Trivy CVE scanning, CIS benchmarks, SBOM generation, RBAC (44+ permissions), TOTP 2FA, LDAP/OIDC, AES-256-GCM encrypted secrets.
- Full-stack — Containers, images, stacks, proxies, backups (with full stack restore), SSH, Git, registry browsing, template catalog — all in one UI.
- No phone-home — Zero telemetry. Offline JWT license validation with RSA-4096 public key embedded in the binary.
- REST API — Full CRUD API at
/api/v1with OpenAPI 3.0 spec, Swagger UI, and WebSocket real-time streams. - Observable — Prometheus
/metricsendpoint, OpenTelemetry tracing, structured JSON logging (zap).
Tech Stack
| Component | Technology |
|---|---|
| Language | Go 1.25+ |
| Web Framework | Chi router (go-chi/chi/v5) |
| Templates | Templ (compile-time, type-safe) |
| Styling | Tailwind CSS + Alpine.js + HTMX |
| Database | PostgreSQL with pgx/v5 + sqlx |
| Cache / Sessions | Redis |
| Messaging | NATS with JetStream |
| Security Scanning | Trivy |
| Reverse Proxy | Caddy / Nginx Proxy Manager |
| Terminal | xterm.js + Monaco Editor + Neovim |
| Charts | Chart.js (vendored UMD) |
| Observability | OpenTelemetry + Prometheus + zap |
| Remote Desktop | Apache Guacamole (guacd + WebSocket) |
Quick Deploy
Deploy usulnet in one command. All secrets (database passwords, JWT keys, encryption keys) are generated automatically.
bashcurl -fsSL https://raw.githubusercontent.com/fr4nsys/usulnet/main/deploy/install.sh | bash
This will:
- Download the production Docker Compose configuration
- Auto-generate secure database passwords, JWT secrets, and encryption keys
- Start usulnet with PostgreSQL, Redis, and NATS
- Be ready in under 60 seconds (pre-built images)
Access at https://your-server-ip:7443. Default credentials: admin / usulnet. Change the password immediately after first login.
Manual Installation
For more control over the deployment, install manually with Docker Compose:
bash# Create installation directory
mkdir -p /opt/usulnet && cd /opt/usulnet
# Download production files
curl -fsSL https://raw.githubusercontent.com/fr4nsys/usulnet/main/deploy/docker-compose.prod.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/fr4nsys/usulnet/main/deploy/.env.example -o .env
# Generate secrets (or edit .env manually)
sed -i "s|CHANGE_ME_GENERATE_RANDOM_PASSWORD|$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 32)|" .env
sed -i "s|CHANGE_ME_GENERATE_WITH_OPENSSL_RAND_HEX_32|$(openssl rand -hex 32)|" .env
# Start
docker compose up -d
Docker Compose Example
yamlservices:
usulnet:
image: ghcr.io/fr4nsys/usulnet:latest
ports:
- "8080:8080" # HTTP
- "7443:7443" # HTTPS (auto-TLS)
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- usulnet-data:/var/lib/usulnet
environment:
- USULNET_DATABASE_URL=postgres://usulnet:secret@postgres:5432/usulnet?sslmode=disable
- USULNET_REDIS_URL=redis://redis:6379/0
- USULNET_NATS_URL=nats://nats:4222
- USULNET_SECURITY_JWT_SECRET=your-secret-key-min-32-chars-long
- USULNET_SECURITY_CONFIG_ENCRYPTION_KEY=your-64-hex-char-aes-256-key
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
Build from Source
Prerequisites: Go 1.25+, Make, Docker.
bashgit clone https://github.com/fr4nsys/usulnet.git
cd usulnet
# Full build (templ + tailwind css + go build)
make build
# Run locally
make run
# Or build and run with Docker Compose
docker compose -f docker-compose.dev.yml build
docker compose -f docker-compose.dev.yml up -d
Makefile Targets
| Command | Description |
|---|---|
make build | Full build (templ + CSS + Go binary) |
make templ | Generate Go code from .templ files |
make css | Compile Tailwind CSS |
make run | Run the application |
make test | Run tests with race detection and coverage |
make lint | Run golangci-lint |
make dev-up | Start dev environment (PostgreSQL, Redis, NATS, MinIO) |
make dev-down | Stop dev environment |
make migrate | Run database migrations up |
Configuration
usulnet is configured via config.yaml and environment variables. Environment variables override config file values using the pattern USULNET_<SECTION>_<KEY>.
Server & TLS
yamlserver:
host: "0.0.0.0"
port: 8080
https_port: 7443
read_timeout: "30s"
write_timeout: "30s"
idle_timeout: "120s"
shutdown_timeout: "10s"
tls:
enabled: true # HTTPS on port 7443 (auto self-signed cert)
auto_tls: true # Auto-generate from internal CA
# cert_file: "" # Custom certificate path
# key_file: "" # Custom private key path
When TLS is enabled, the server listens on both :8080 (HTTP) and :7443 (HTTPS). The auto-generated self-signed certificate is suitable for internal use. For production with a public domain, use Caddy or NPM integration for Let's Encrypt certificates.
Database
yamldatabase:
url: "postgres://usulnet:password@postgres:5432/usulnet?sslmode=disable"
max_open_conns: 25
max_idle_conns: 10
conn_max_lifetime: "30m"
conn_max_idle_time: "5m"
Environment variable: USULNET_DATABASE_URL
Redis
yamlredis:
url: "redis://redis:6379"
password: ""
db: 0
Used for session management, caching, and real-time pub/sub. Environment variable: USULNET_REDIS_URL
NATS
yamlnats:
url: "nats://nats:4222"
name: "usulnet"
jetstream:
enabled: true
# tls:
# enabled: false
# cert_file: "" # Client certificate (mTLS)
# key_file: "" # Client private key
# ca_file: "" # CA certificate
# skip_verify: false
NATS with JetStream provides inter-node communication in multi-node deployments. In standalone mode, it is used for internal event streaming.
Security
yamlsecurity:
jwt_secret: "..." # openssl rand -hex 32
jwt_expiry: "24h"
refresh_expiry: "168h"
config_encryption_key: "..." # openssl rand -hex 32 (64 hex chars)
cookie_secure: false # Set true if using HTTPS in production
cookie_samesite: "lax"
password_min_length: 8
Generate unique secrets for production. Never use the default values from config.yaml. Use openssl rand -hex 32 to generate random keys.
Storage & Backups
yamlstorage:
type: "local" # "local" or "s3"
path: "/app/data"
backup:
compression: "gzip" # "gzip" or "zstd"
default_retention_days: 30
# S3-compatible storage (MinIO, AWS S3, etc.)
minio:
endpoint: "minio:9000"
access_key: "minioadmin"
secret_key: "minioadmin"
bucket: "usulnet-backups"
use_ssl: false
Docker
yamldocker:
host: "unix:///var/run/docker.sock" # Docker daemon socket
version: "" # Docker API version (auto-detect)
tls_verify: false
cert_path: ""
usulnet connects to the Docker daemon via the socket. In production, mount it read-only (/var/run/docker.sock:/var/run/docker.sock:ro). For remote Docker hosts, configure the host with a TCP address and enable TLS verification.
Observability
yamlmetrics:
enabled: true
path: "/metrics" # Prometheus scrape endpoint
observability:
tracing:
enabled: false
endpoint: "" # OTLP endpoint (e.g., "localhost:4317")
sampling_rate: 0.1 # 10% sampling rate
service_name: "usulnet"
logging:
level: "info" # debug, info, warn, error, fatal
format: "json" # "json" (production) or "console" (development)
output: "stdout" # "stdout" or "file"
file: "" # Log file path (when output=file)
The /metrics endpoint exposes Prometheus-compatible metrics (requires admin JWT). A pre-built Grafana dashboard is available at deploy/grafana/. OpenTelemetry tracing sends spans via OTLP gRPC to any compatible collector (Jaeger, Tempo, etc.).
Environment Variables
All configuration values can be overridden via environment variables using the format USULNET_<SECTION>_<KEY>:
| Variable | Config Path | Example |
|---|---|---|
USULNET_DATABASE_URL | database.url | postgres://user:pass@host:5432/db |
USULNET_REDIS_URL | redis.url | redis://host:6379 |
USULNET_NATS_URL | nats.url | nats://host:4222 |
USULNET_SECURITY_JWT_SECRET | security.jwt_secret | 64 hex characters |
USULNET_SECURITY_CONFIG_ENCRYPTION_KEY | security.config_encryption_key | 64 hex characters |
USULNET_MODE | mode | standalone, master, agent |
USULNET_SERVER_PORT | server.port | 8080 |
USULNET_SERVER_HTTPS_PORT | server.https_port | 7443 |
USULNET_LOGGING_LEVEL | logging.level | info, debug, warn |
USULNET_METRICS_ENABLED | metrics.enabled | true / false |
USULNET_STORAGE_TYPE | storage.type | local / s3 |
Containers
Full container lifecycle management with a rich set of operations available from the web UI and API.
- Lifecycle — Create, start, stop, restart, pause, unpause, kill, remove
- Bulk operations — Select multiple containers and apply actions in batch
- Real-time stats — CPU, memory, network I/O, disk I/O via WebSocket
- Exec terminal — Open a shell inside any running container (xterm.js)
- Filesystem browser — Browse, edit, upload, download files inside containers
- Settings editor — Modify environment variables, labels, restart policy without recreating
- Logs — Real-time log streaming with search and filtering
Images
Complete Docker image management with update detection and registry browsing.
- Browse and search — List local images, search Docker Hub, filter by repository, tag, or size
- Pull and push — Pull images from any registry (with stored credentials). Push images to private registries
- Update detection — Automatic digest comparison against Docker Hub, GHCR, and generic v2 registries. Detects when a newer version of a tag is available
- Image history — View the full layer history and Dockerfile instructions for any image
- Dangling cleanup — Identify and remove unused images (dangling and unreferenced) to reclaim disk space
- Bulk operations — Select multiple images for batch removal
- SBOM export — Generate Software Bill of Materials in CycloneDX and SPDX formats via Trivy
Volumes & Networks
Manage Docker volumes and networks directly from the web UI.
Volumes
- Create and remove — Named volumes with driver options (local, NFS, CIFS, etc.)
- Browse contents — Inspect files inside volumes via the filesystem browser
- Usage tracking — See which containers reference each volume
- Backup integration — Volumes are included in container and stack backups (AES-encrypted, compressed)
Networks
- Create and remove — Bridge, overlay, macvlan, and host networks with custom IPAM configuration
- Connect / disconnect — Attach and detach running containers to networks
- Inspect — View connected containers, subnet, gateway, and driver options
Stacks / Compose
Deploy and manage Docker Compose stacks directly from the web UI.
- Visual editor — Write docker-compose.yml with syntax highlighting
- Environment variables — Manage .env files per stack
- Git-based deploys — Pull stacks from Git repositories with auto-deploy on push
- Stack catalog — One-click deployment of popular applications
- Monitoring — View container status, logs, and resource usage per stack
Template Catalog
usulnet ships with a built-in application template catalog — 60+ ready-to-deploy templates across 10 categories, embedded directly in the binary.
Categories
| Category | Examples |
|---|---|
| Databases | PostgreSQL, MySQL, MariaDB, MongoDB, Redis, CockroachDB, InfluxDB |
| CMS | WordPress, Ghost, Strapi |
| Monitoring | Grafana, Prometheus, Uptime Kuma, Netdata |
| Development | Gitea, GitLab, Drone CI, code-server |
| Storage | MinIO, Nextcloud, Seafile |
| Networking | Pi-hole, AdGuard Home, WireGuard, Traefik, Caddy |
| Communication | Mattermost, Rocket.Chat, Matrix Synapse |
| Security | Vaultwarden, Keycloak, Authelia |
| Media | Jellyfin, Plex, PhotoPrism |
| Productivity | n8n, Outline, BookStack, Wiki.js |
Features
- One-click deploy — Select a template, customize environment variables, and deploy as a stack
- Search and filter — Find templates by name, category, or keyword
- Custom templates — Add your own templates with docker-compose.yml definitions
- Import / Export — Export templates as JSON for sharing across instances. Import Portainer-compatible template JSON files
API Endpoints
httpGET /api/v1/templates # List all templates (with ?category= filter)
GET /api/v1/templates/:id # Get template by ID
POST /api/v1/templates # Create custom template
PUT /api/v1/templates/:id # Update custom template
DELETE /api/v1/templates/:id # Delete custom template
POST /api/v1/templates/import # Import templates from JSON
GET /api/v1/templates/export # Export all templates as JSON
GET /api/v1/templates/categories # List available categories
The import endpoint accepts Portainer v2 template JSON format, automatically converting templates to usulnet's native format. This makes migration from Portainer straightforward.
Security Scanning
Integrated security scanning powered by Trivy.
- CVE scanning — Detect vulnerabilities in container images and filesystems
- CIS Docker Benchmark — Evaluate Docker host configuration against CIS standards
- SBOM generation — Software Bill of Materials in CycloneDX and SPDX formats
- Security scoring — Composite 0-100 score per container and across infrastructure
- Trend tracking — Monitor security posture over time
- Actionable remediation — Specific guidance on how to fix each finding
Monitoring & Alerts
Real-time metrics and alerting system with multiple notification channels.
- Metrics — CPU, memory, network, disk I/O per container and host (WebSocket live updates)
- Alert rules — Threshold-based alerts with states: OK → Pending → Firing → Resolved
- 11 notification channels — Email, Slack, Discord, Telegram, Gotify, ntfy, PagerDuty, Opsgenie, Teams, Webhook, Custom
- Prometheus endpoint — Native
/metricsendpoint for external scrapers (admin JWT required) - Grafana dashboard — Pre-built dashboard at
deploy/grafana/for visualizing usulnet metrics - Prometheus alerting — Pre-configured alert rules at
deploy/prometheus/ - OpenTelemetry — Distributed tracing via OTLP gRPC (configurable sampling rate)
- Event stream — Real-time Docker events with filtering via WebSocket
Reverse Proxy
Manage Caddy and Nginx Proxy Manager reverse proxy configurations directly from usulnet.
- Caddy integration — Configure via Caddy Admin API. Automatic HTTPS with Let's Encrypt.
- NPM integration — Full Nginx Proxy Manager support: proxy hosts, certificates, redirections, streams, access lists
- Certificate management — Auto-renewal, custom certificates, expiration alerts
- Stream proxying — TCP/UDP proxy for non-HTTP services
Backups
- Targets — Back up individual containers, volumes, or entire stacks
- Scheduling — Cron-based scheduling with configurable retention policies
- Storage backends — Local filesystem, AWS S3, MinIO, Azure Blob, GCS, Backblaze B2, SFTP
- Encryption — AES-256-GCM encryption at rest
- Compression — gzip or zstd with configurable levels
- One-click restore — Restore to original or different target
- Full stack restore — Restores docker-compose.yml, .env files, and all named volumes. Stops the existing stack, restores volume data, and redeploys automatically
Stack Restore Process
When restoring a stack backup, usulnet performs the following steps automatically:
- Extracts the backup archive and reads the stored
docker-compose.ymland.envfiles - Stops the existing stack (if running) to prevent data conflicts
- Restores all named volumes from the backup to their original Docker volume paths
- Redeploys the stack using the restored compose configuration
Web Terminal
- Terminal Hub — Multi-tab xterm.js terminal with container exec and host SSH
- Monaco Editor — VS Code editor in the browser for files inside containers and hosts
- Neovim — Neovim with lazy.nvim running directly in the browser via WebSocket
- SFTP browser — Remote filesystem browsing over SSH/SFTP
Authentication
- Local auth — Username/password with bcrypt hashing
- TOTP 2FA — Google Authenticator, Authy, etc. with backup codes
- RBAC — 44+ granular permissions with custom roles (Business edition)
- OAuth / OIDC — GitHub, Google, Microsoft, custom providers (Business edition)
- LDAP / AD — Active Directory and LDAP integration (Business edition)
- API keys — Programmatic access via
X-API-KEYheader - Audit logging — Every user action logged with IP, timestamp, and details
Custom Dashboards
Build personalized monitoring dashboards with drag-and-drop widgets. Available in the Enterprise edition.
Widget Types
| Widget | Description |
|---|---|
cpu_gauge | Real-time CPU usage gauge |
memory_gauge | Memory usage gauge |
disk_gauge | Disk usage gauge |
cpu_chart | CPU usage over time |
memory_chart | Memory usage over time |
network_chart | Network I/O over time |
container_table | Container status table |
container_count | Running/stopped container counters |
alert_feed | Recent alert activity |
log_stream | Live log stream widget |
security_score | Infrastructure security score |
compliance_status | CIS compliance summary |
top_containers | Top resource-consuming containers |
host_info | Host system information |
custom_metric | Custom Prometheus metric display |
Layouts
- Multiple layouts — Create and switch between different dashboard views
- Default layout — Set one layout as your landing page
- Shared layouts — Share layouts with other users in your organization
- Grid positioning — Place widgets at exact grid coordinates with configurable width and height
API Endpoints
http# Layouts
GET /api/v1/dashboards/layouts # List your layouts
POST /api/v1/dashboards/layouts # Create a layout
GET /api/v1/dashboards/layouts/:id # Get layout by ID
PUT /api/v1/dashboards/layouts/:id # Update layout
DELETE /api/v1/dashboards/layouts/:id # Delete layout
# Widgets
GET /api/v1/dashboards/layouts/:id/widgets # List widgets in a layout
POST /api/v1/dashboards/layouts/:id/widgets # Add widget to layout
PUT /api/v1/dashboards/widgets/:id # Update widget
DELETE /api/v1/dashboards/widgets/:id # Remove widget
Registry Browsing
Browse repositories, tags, and manifests from any Docker-compatible v2 registry directly from usulnet. Available in the Business edition.
Supported Registries
| Registry | Features |
|---|---|
| Docker Hub | Namespace browsing (user/org repos), tag listing, manifest details, pull count, star count |
| GHCR (GitHub) | Tag listing, manifest details, token-based auth |
| Harbor | Full v2 catalog, tag listing, manifest details |
| GitLab Registry | Full v2 catalog, tag listing, manifest details |
| Generic OCI v2 | Any registry implementing the OCI Distribution Spec (catalog, tags, manifests) |
Authentication
Registry credentials are stored encrypted (AES-256-GCM) in the database. The browsing service automatically handles token exchange via the Www-Authenticate challenge flow, supporting both Bearer token and Basic auth schemes.
API Endpoints
http# Registry CRUD
GET /api/v1/registries # List registries
POST /api/v1/registries # Add registry
PUT /api/v1/registries/:id # Update registry
DELETE /api/v1/registries/:id # Delete registry
# Browsing
GET /api/v1/registries/:id/repositories # List repos
GET /api/v1/registries/:id/repositories/{repo}/tags # List tags
GET /api/v1/registries/:id/repositories/{repo}/tags/{ref} # Get manifest
Example: Browse Docker Hub Tags
bash# List tags for the official nginx image
curl -s -H "Authorization: Bearer <JWT>" \
"https://your-server:7443/api/v1/registries/<id>/repositories/library/nginx/tags" | jq
Operation Modes
usulnet supports three operation modes configured via mode in config.yaml or USULNET_MODE:
| Mode | Description |
|---|---|
standalone | Single-node deployment (default). All features on one host. |
master | Central control plane. Manages agents and routes API requests. |
agent | Worker node. Connects to master via NATS, executes Docker operations locally. |
Agent Deployment
Deploy agents from the web UI or manually.
From the Web UI
Navigate to Nodes → Add Node. Provide SSH credentials for the target host. usulnet will install Docker (if needed), deploy the agent container, and configure mTLS certificates automatically.
Manual Agent Deployment
bashdocker run -d \
--name usulnet-agent \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-e USULNET_MODE=agent \
-e USULNET_NATS_URL=nats://master-ip:4222 \
-e USULNET_AGENT_NAME=worker-01 \
ghcr.io/fr4nsys/usulnet:latest
Agent Configuration
yaml# config.agent.yaml
mode: "agent"
agent:
name: "worker-01" # Unique agent name
master_url: "nats://master:4222"
heartbeat_interval: "30s"
reconnect_delay: "5s"
max_reconnect: -1 # Unlimited retries
nats:
url: "nats://master:4222"
tls:
enabled: true
cert_file: "/etc/usulnet/agent.crt"
key_file: "/etc/usulnet/agent.key"
ca_file: "/etc/usulnet/ca.crt"
Agent Events
In multi-node deployments, agent events are persisted to PostgreSQL for audit and troubleshooting. The gateway automatically stores events from remote agents based on severity and type.
Persisted Event Types
Events with operational significance are automatically persisted. These include:
- Agent lifecycle — Connected, disconnected, registered, deregistered
- Container operations — Started, stopped, created, removed, health changes
- System events — Resource threshold alerts, errors, task completions
- Security events — Scan results, policy violations
Event Attributes
| Field | Description |
|---|---|
event_type | Event type identifier (e.g., agent.connected, container.started) |
agent_id | Originating agent identifier |
host_id | Associated host UUID (if applicable) |
severity | info, warning, error, or critical |
message | Human-readable event description |
actor | Who or what triggered the event (user, system, agent) |
attributes | Key-value metadata pairs |
data | Structured event payload (JSON) |
Querying Events
Events can be filtered by host, agent, type, severity, and time range via the API:
bash# List events for a specific agent
curl -s -H "Authorization: Bearer <JWT>" \
"https://your-server:7443/api/v1/events?agent_id=worker-01&severity=error"
Old events are automatically cleaned up based on the configured retention policy.
REST API
usulnet exposes a full CRUD REST API at /api/v1. OpenAPI 3.0 spec is available at /api/v1/openapi.json and Swagger UI at /docs/api.
Base URL
https://your-server:7443/api/v1
Example: List Containers
bashcurl -s -H "Authorization: Bearer <JWT>" \
https://your-server:7443/api/v1/containers | jq
Endpoint Reference
| Resource | Endpoints | Auth Level |
|---|---|---|
| Auth | POST /auth/login, /auth/logout, /auth/refresh, /auth/2fa/* | Public / Bearer |
| Users | GET|POST /users, GET|PUT|DELETE /users/:id | Admin |
| Containers | GET /containers/:hostID, POST /:id/start|stop|restart|kill|remove | Viewer / Operator |
| Images | GET /images/:hostID, POST /pull|push, GET /:id/update-check | Viewer / Operator |
| Volumes | GET|POST /volumes/:hostID, DELETE /:id | Viewer / Operator |
| Networks | GET|POST /networks/:hostID, DELETE /:id | Viewer / Operator |
| Stacks | GET|POST /stacks, GET|PUT|DELETE /stacks/:id, POST /:id/deploy|stop | Viewer / Operator |
| Hosts | GET|POST /hosts, GET|PUT|DELETE /hosts/:id | Viewer / Admin |
| Backups | GET|POST /backups, POST /:id/restore, DELETE /:id | Viewer / Operator |
| Security | POST /security/scan, GET /security/reports, GET /security/sbom/:id | Viewer / Operator |
| Monitoring | GET|POST /notifications/channels, GET|POST /notifications/rules | Viewer / Operator |
| Registries | GET|POST /registries, GET /:id/repositories, GET /.../tags | Viewer / Operator |
| Templates | GET /templates, POST /templates/import, GET /templates/export | Viewer / Operator |
| Dashboards | GET|POST /dashboards/layouts, GET|POST /.../widgets | Enterprise |
| Audit | GET /audit/logs | Admin |
| Proxy | GET|POST /proxy/hosts, GET /proxy/health | Viewer / Operator |
| SSH | GET|POST /ssh/keys, GET|POST /ssh/connections | Operator |
| Settings | GET|PUT /settings | Admin |
| License | GET|POST /license | Admin |
All paginated endpoints support ?page= and ?per_page= query parameters. Responses include total, page, per_page, and total_pages metadata. Swagger UI is available at /docs/api.
API Authentication
Two authentication methods are supported:
| Method | Header | Format |
|---|---|---|
| JWT Bearer Token | Authorization | Bearer <token> |
| API Key | X-API-KEY | <api-key> |
Obtain a JWT
bashcurl -s -X POST https://your-server:7443/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"usulnet"}' | jq .token
WebSocket API
Real-time streams are available via WebSocket:
| Endpoint | Description |
|---|---|
/api/v1/ws/containers/:id/logs | Live container log streaming |
/api/v1/ws/containers/:id/exec | Interactive container terminal |
/api/v1/ws/containers/:id/stats | Real-time container stats |
/api/v1/ws/events | Docker event stream |
/api/v1/ws/terminal | Host SSH terminal |
CLI Commands
bash# Run the application
./bin/usulnet serve
# Database migrations
./bin/usulnet migrate up
./bin/usulnet migrate down
./bin/usulnet migrate status
# Show version
./bin/usulnet version
Migrations
Database migrations are embedded in the binary and run automatically on startup. To manage them manually:
bash# Apply all pending migrations
make migrate
# Roll back last migration
make migrate-down
# Check migration status
make migrate-status
Licensing
usulnet uses a three-tier licensing model:
| Edition | License | Limits | Key Features |
|---|---|---|---|
| Community (CE) | AGPLv3 | 1 node, 3 users, 1 team, 1 role | Full Docker management, security scanning, monitoring, terminal, backups |
| Business | Commercial | Per-node, configurable users | CE + template catalog, registry browsing, OAuth/OIDC, LDAP, RBAC, Git sync, import/export |
| Enterprise | Commercial | Unlimited | Business + custom dashboards, agent events, compliance, OPA policies, runtime security, log aggregation |
License Activation
- Purchase at usulnet.com/pricing
- Retrieve your JWT license key from the License Portal
- In your usulnet dashboard, go to Settings → License → Activate
- Paste the JWT and click Activate
License validation is performed entirely offline using JWT (RS512) with an RSA-4096 public key embedded in the binary. No internet connection is required after activation.