Server Configuration¶
The server
section defines how Navigator binds to network interfaces and serves HTTP requests.
Basic Configuration¶
server:
listen: 3000 # Port to bind to (required)
hostname: "localhost" # Hostname for routing (optional)
public_dir: "./public" # Default public directory (optional)
root_path: "" # URL path prefix (optional)
Configuration Options¶
listen¶
Required: Port number or address to bind to.
# Port only (binds to all interfaces)
server:
listen: 3000
# Specific interface and port
server:
listen: "127.0.0.1:3000"
# IPv6 address
server:
listen: "[::1]:3000"
# Environment variable
server:
listen: "${PORT:-3000}"
Examples by Environment:
- Development: 3000
or 9999
- Production: 3000
, 80
, or 8080
- Docker: 3000
(expose via container ports)
- Heroku: "${PORT}"
(dynamic port assignment)
hostname¶
Optional: Expected hostname for Host header validation.
server:
hostname: "myapp.com" # Production domain
# or
hostname: "localhost" # Development
# or
hostname: "" # Accept any hostname (default)
Use Cases:
- Production: Set to your domain for security
- Multi-domain: Leave empty to accept all domains
- Development: Use localhost
for local testing
public_dir¶
Optional: Default directory for serving static files when no specific static configuration is provided.
server:
public_dir: "./public" # Relative to working directory
# or
public_dir: "/var/www/public" # Absolute path
# or
public_dir: "/app/public" # Docker container path
Default Behavior: If not specified, Navigator looks for public/
in the current working directory.
root_path¶
Optional: URL prefix to strip from all requests before processing.
Example:
- Request: GET /myapp/users/123
- After root_path processing: GET /users/123
- Useful for deploying behind reverse proxies
Environment-Specific Examples¶
Development¶
Characteristics: - Low port number for easy access - Localhost-only for security - Relative paths for portability
Staging¶
Characteristics: - Production-like configuration - Specific hostname for staging domain - Absolute paths for production similarity
Production¶
Characteristics: - Environment variable for flexibility - Production domain name - Absolute paths for security
Docker¶
server:
listen: 3000 # Internal container port
hostname: "" # Accept any hostname
public_dir: "/app/public"
Characteristics: - Fixed internal port (expose via Docker) - Accept any hostname (Docker networking) - Container-specific paths
Behind Reverse Proxy¶
server:
listen: 3000 # Internal port
hostname: "" # Proxy handles hostname
public_dir: "/app/public"
root_path: "/api" # Strip /api prefix
nginx Configuration:
location /api/ {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Advanced Configuration¶
Multi-Interface Binding¶
# Development - bind to all interfaces
server:
listen: "0.0.0.0:3000"
# Production - bind to specific interface
server:
listen: "10.0.1.100:3000"
Load Balancer Integration¶
# Health check endpoint
server:
listen: 3000
hostname: "" # Accept health check requests from any source
# In your Rails routes.rb:
# get '/up', to: 'health#show'
Kubernetes Deployment¶
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: navigator
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
Security Considerations¶
Hostname Validation¶
# Secure - validate hostname
server:
hostname: "myapp.com"
# Less secure - accept any hostname
server:
hostname: ""
Recommendation: Always set hostname in production to prevent Host header attacks.
Interface Binding¶
# Secure - localhost only
server:
listen: "127.0.0.1:3000"
# Less secure - all interfaces
server:
listen: "0.0.0.0:3000"
# Most secure - specific interface
server:
listen: "10.0.1.100:3000"
Recommendation: Bind to specific interfaces in production, use localhost in development.
Performance Considerations¶
Port Selection¶
- Standard HTTP ports (80, 8080): May require root privileges
- High ports (3000, 8000): No special privileges required
- Ephemeral ports (32768+): Avoid for servers
File System Performance¶
# Fast - SSD storage
server:
public_dir: "/var/www/app/public"
# Slower - network storage
server:
public_dir: "/nfs/shared/public"
# Fastest - memory filesystem (temporary files only)
server:
public_dir: "/tmp/public"
Connection Limits¶
Navigator handles connection limits at the OS level:
# Check current limits
ulimit -n
# Increase for production
echo "navigator soft nofile 65536" >> /etc/security/limits.conf
echo "navigator hard nofile 65536" >> /etc/security/limits.conf
Testing Server Configuration¶
Validate Configuration¶
# Test configuration syntax
navigator --validate config.yml
# Test with specific config
navigator --validate production.yml
Network Testing¶
# Test port binding
netstat -tlnp | grep :3000
# Test hostname resolution
curl -H "Host: myapp.com" http://localhost:3000/
# Test public directory
curl -I http://localhost:3000/favicon.ico
Load Testing¶
# Simple load test
ab -n 1000 -c 10 http://localhost:3000/
# WebSocket testing (if applicable)
wscat -c ws://localhost:3000/cable
Common Issues¶
Port Already in Use¶
Error: bind: address already in use
Solutions:
# Find process using port
lsof -i :3000
sudo fuser -k 3000/tcp
# Use different port
server:
listen: 3001
Permission Denied¶
Error: bind: permission denied
Causes: Trying to bind to ports < 1024 without root privileges
Solutions:
# Use unprivileged port
server:
listen: 3000
# Or use capabilities (Linux)
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/navigator
# Or run as root (not recommended)
sudo navigator config.yml
Public Directory Not Found¶
Error: Static files return 404
Solutions:
# Verify directory exists
ls -la /var/www/app/public/
# Check permissions
stat /var/www/app/public/
# Use absolute path
server:
public_dir: "/var/www/app/public"
Hostname Mismatch¶
Error: Requests rejected or routed incorrectly
Solutions:
# Accept all hostnames (development)
server:
hostname: ""
# Set correct hostname (production)
server:
hostname: "myapp.com"
# Test with curl
curl -H "Host: myapp.com" http://localhost:3000/
Integration Examples¶
systemd Service¶
[Service]
Environment=PORT=3000
ExecStart=/usr/local/bin/navigator /etc/navigator/config.yml
Docker Compose¶
services:
navigator:
ports:
- "3000:3000"
environment:
- PORT=3000
volumes:
- ./public:/app/public:ro
Heroku Deployment¶
Best Practices¶
1. Environment Variables¶
# Good - flexible configuration
server:
listen: "${PORT:-3000}"
hostname: "${HOSTNAME:-localhost}"
# Bad - hardcoded values
server:
listen: 3000
hostname: "localhost"
2. Security First¶
# Production configuration
server:
listen: "127.0.0.1:3000" # Specific interface
hostname: "myapp.com" # Validate hostname
public_dir: "/var/www/app/public" # Absolute path
3. Path Management¶
# Development - relative paths
server:
public_dir: "./public"
# Production - absolute paths
server:
public_dir: "/var/www/app/public"
4. Testing Strategy¶
# Always validate before deployment
navigator --validate config.yml
# Test connectivity
curl -I http://localhost:3000/up
# Verify static files
curl -I http://localhost:3000/favicon.ico