Get Zentinel up and running in under 5 minutes.
1. Install Zentinel
Run the install script:
curl -fsSL https://get.zentinelproxy.io | sh
Add to your PATH if needed:
export PATH="$HOME/.local/bin:$PATH"
Verify it works:
zentinel --version
2. Create a Configuration File
Create zentinel.kdl in your current directory:
system {
worker-threads 0
}
listeners {
listener "http" {
address "0.0.0.0:8080"
protocol "http"
}
}
routes {
route "api" {
matches {
path-prefix "/api/"
}
upstream "api-backend"
}
route "default" {
priority "low"
matches {
path-prefix "/"
}
upstream "web-backend"
}
}
upstreams {
upstream "api-backend" {
targets {
target { address "127.0.0.1:3000" }
}
}
upstream "web-backend" {
targets {
target { address "127.0.0.1:3001" }
}
}
}
observability {
metrics {
enabled #true
address "0.0.0.0:9090"
}
logging {
level "info"
format "json"
}
}
3. Start a Test Backend
For testing, start a simple backend server:
# Using Python (port 3000)
python3 -m http.server 3000 &
# Or using Node.js
npx http-server -p 3000 &
4. Run Zentinel
zentinel -c zentinel.kdl
You should see:
INFO zentinel starting up
INFO listener http listening on 0.0.0.0:8080
INFO metrics server listening on 0.0.0.0:9090
5. Test It
In a new terminal:
# Test the proxy
curl http://localhost:8080/
# Check metrics
curl http://localhost:9090/metrics
What’s Happening
- Listener accepts HTTP connections on port 8080
- Router matches requests against route rules:
/api/*requests go toapi-backend(port 3000)- All other requests go to
web-backend(port 3001)
- Upstream forwards requests to your backend servers
- Metrics are exposed on port 9090 for monitoring
Add Health Checks
Update your config to add health checks:
upstreams {
upstream "api-backend" {
targets {
target { address "127.0.0.1:3000" }
}
health-check {
type "http" {
path "/health"
}
interval-secs 10
unhealthy-threshold 3
}
}
}
Reload the configuration:
# Send SIGHUP to reload
kill -HUP $(pgrep zentinel)
Add TLS
For HTTPS, generate certificates and update the config:
# Generate self-signed cert for testing
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=localhost"
listeners {
listener "https" {
address "0.0.0.0:8443"
protocol "https"
tls {
cert-file "cert.pem"
key-file "key.pem"
}
}
}
Test with:
curl -k https://localhost:8443/
Proxy to an HTTPS Backend
If your backend serves HTTPS (e.g., an external API on port 443), add a tls block to the upstream:
upstreams {
upstream "api-backend" {
targets {
target { address "api.example.com:443" }
}
tls {
sni "api.example.com"
}
}
}
Important: Without the
tlsblock, Zentinel connects with plaintext HTTP regardless of the port number. This causes 502 errors or redirect loops when the backend expects HTTPS. See Upstream TLS for full details.
Troubleshooting
“command not found: zentinel”
The install directory isn’t in your PATH. Add it:
# Check where it was installed
ls ~/.local/bin/zentinel || ls /usr/local/bin/zentinel
# Add to PATH (add this to your ~/.bashrc or ~/.zshrc)
export PATH="$HOME/.local/bin:$PATH"
# Reload your shell
source ~/.bashrc # or source ~/.zshrc
“Permission denied” when installing
The installer needs write access to /usr/local/bin:
# Option 1: Use sudo (will prompt for password)
curl -fsSL https://get.zentinelproxy.io | sudo sh
# Option 2: Install to user directory (no sudo needed)
# The script will automatically fall back to ~/.local/bin
“Address already in use” when starting
Another process is using port 8080:
# Find what's using the port
lsof -i :8080
# Either stop that process, or change Zentinel's port
# In zentinel.kdl, change:
# address "0.0.0.0:8080"
# to:
# address "0.0.0.0:9000"
“Connection refused” when testing
Your backend server isn’t running or is on a different port:
# Check if backend is running
curl http://localhost:3000/
# If not, start one for testing
python3 -m http.server 3000
Configuration errors
Validate your config file:
zentinel --config zentinel.kdl --check
Common issues:
- Missing closing braces
} - Typos in property names (e.g.,
adressinstead ofaddress) - Invalid port numbers (must be 1-65535)
Next Steps
- Basic Configuration - Detailed configuration reference
- First Route - Deep dive into routing
- Service Types - Learn about API, web, and static modes
- Health Checks - Configure upstream monitoring