Deployment Guide
Deploy LogWard on your infrastructure using pre-built Docker images or build from source.
Pre-built Images (Recommended)
Quick Start (2 Minutes)
# Create project directory
mkdir logward && cd logward
# Download docker-compose.yml and environment template
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/docker-compose.yml
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/.env.example
mv .env.example .env
# Edit .env with secure passwords
nano .env
# Start LogWard
docker compose up -dRequired Environment Variables
| Variable | Description | Example |
|---|---|---|
| DB_PASSWORD | PostgreSQL password | random_secure_password |
| REDIS_PASSWORD | Redis password | another_secure_password |
| API_KEY_SECRET | Encryption key (32+ chars) | your_32_character_secret_key_here |
Database migrations run automatically on first start.
(Optional) Docker Log Collection with Fluent Bit
To automatically collect logs from all Docker containers using Fluent Bit:
# Download Fluent Bit configuration files
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/fluent-bit.conf
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/parsers.conf
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/extract_container_id.lua
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/wrap_logs.lua
# Add your LogWard API key to .env
echo "FLUENT_BIT_API_KEY=your_api_key_here" >> .env
# Start with logging profile enabled
docker compose --profile logging up -dThis profile is optional. Without it, LogWard runs without the Fluent Bit container.
Available Docker Images
| Image | Registry |
|---|---|
| logward/backend | Docker Hub |
| logward/frontend | Docker Hub |
| ghcr.io/logward-dev/logward-backend | GitHub Container Registry |
| ghcr.io/logward-dev/logward-frontend | GitHub Container Registry |
Always pin to a specific version in production instead of using latest:
# In your .env file
LOGWARD_BACKEND_IMAGE=logward/backend:0.3.2
LOGWARD_FRONTEND_IMAGE=logward/frontend:0.3.2Ready to Go
Frontend: http://localhost:3000 | API: http://localhost:8080
Remote Deployment
LogWard automatically detects the correct API URL based on how you access the frontend:
- Via IP:3000 (e.g.,
http://192.168.1.100:3000) → API auto-detected athttp://192.168.1.100:8080 - Via domain on port 80/443 (e.g.,
https://logward.example.com) → Uses relative URLs (assumes reverse proxy)
No PUBLIC_API_URL configuration needed for these scenarios!
Example: VPS Deployment (No Config Needed)
# Server IP: 192.168.1.100
# .env configuration - no PUBLIC_API_URL needed!
DB_PASSWORD=secure_password
REDIS_PASSWORD=secure_password
API_KEY_SECRET=your_32_character_secret_key_here
# Access points:
# Frontend: http://192.168.1.100:3000
# API: http://192.168.1.100:8080 (auto-detected)With Reverse Proxy (nginx/Traefik)
When using a domain (port 80/443), LogWard assumes a reverse proxy is in place and uses relative URLs (/api/v1).
Your reverse proxy must route both the frontend and the API, otherwise API calls will fail with 404.
Example nginx configuration:
server {
listen 443 ssl;
server_name logward.example.com;
# Frontend
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Backend API - REQUIRED for relative URLs to work
location /api/ {
proxy_pass http://localhost:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# SSE for live tail (requires special headers)
location /api/v1/logs/stream {
proxy_pass http://localhost:8080/api/v1/logs/stream;
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
}
}Alternative: API on Subdomain
If you prefer to host the API on a separate subdomain instead of proxying /api/:
# .env configuration
PUBLIC_API_URL=https://api.logward.example.com
# Access points:
# Frontend: https://logward.example.com
# API: https://api.logward.example.com| Scenario | PUBLIC_API_URL | Notes |
|---|---|---|
| Docker via IP:3000 | (not needed) | Auto-detected → IP:8080 |
| Domain + reverse proxy | (not needed) | Uses /api/v1 (proxy must route it) |
| API on subdomain | https://api.example.com | Explicit configuration |
| Custom port setup | http://host:custom-port | When backend is not on :8080 |
| LogWard Cloud | https://api.logward.dev | Pre-configured |
Horizontal Scaling
Enable Horizontal Scaling
The default docker-compose.yml runs a single instance of each service.
For horizontal scaling, download and use the Traefik overlay:
# Download Traefik overlay (adds load balancer)
curl -O https://raw.githubusercontent.com/logward-dev/logward/main/docker/docker-compose.traefik.yml
# Start with horizontal scaling support
docker compose -f docker-compose.yml -f docker-compose.traefik.yml up -d
# Scale to 3 backend instances and 2 workers
docker compose -f docker-compose.yml -f docker-compose.traefik.yml up -d --scale backend=3 --scale worker=2
# Check running instances
docker compose psWhen using the Traefik overlay, access changes to a single port:
- With Traefik:
http://localhost:3080(frontend + API on same port) - Without Traefik: Frontend at
:3000, API at:8080
The LOGWARD_PORT environment variable controls the Traefik port (default: 3080).
Architecture
| Component | Default | With Traefik | Notes |
|---|---|---|---|
| Traefik | - | 1 instance | Load balancer, reverse proxy |
| Backend | 1 instance | N instances | Stateless API servers |
| Worker | 1 instance | N instances | Background job processors (BullMQ) |
| Frontend | 1 instance | N instances | SvelteKit SSR |
| Redis | 1 instance | 1 instance | Rate limiting, job queues, cache |
| PostgreSQL | 1 instance | 1 instance | TimescaleDB for time-series data |
- Rate limiting: Stored in Redis (shared across all backend instances)
- Sessions: Stored in Redis (no sticky sessions required)
- Job queues: BullMQ distributes work across all workers automatically
- Health checks: Traefik removes unhealthy instances from rotation
Kubernetes (Helm)
Quick Install
# Add the LogWard Helm repository
helm repo add logward https://logward-dev.github.io/logward-helm-chart
helm repo update
# Install LogWard
helm install logward logward/logward \
--namespace logward \
--create-namespace \
--set timescaledb.auth.password=<your-db-password> \
--set redis.auth.password=<your-redis-password>What's Included
- Backend API (2+ replicas)
- Frontend (2+ replicas)
- Worker (BullMQ jobs)
- TimescaleDB StatefulSet
- Redis StatefulSet
- Horizontal Pod Autoscaler
- Ingress (nginx, ALB, etc.)
- ServiceMonitor (Prometheus)
Enable Ingress
helm install logward logward/logward \
--namespace logward \
--create-namespace \
--set timescaledb.auth.password=<password> \
--set redis.auth.password=<password> \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.hosts[0].host=logward.example.com \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix \
--set ingress.hosts[0].paths[0].service=frontendUse External Database
For production, you can use an external managed database (AWS RDS, Cloud SQL, etc.):
helm install logward logward/logward \
--namespace logward \
--create-namespace \
--set timescaledb.enabled=false \
--set externalDatabase.host=your-db.region.rds.amazonaws.com \
--set externalDatabase.port=5432 \
--set externalDatabase.database=logward \
--set externalDatabase.username=logward \
--set externalDatabase.password=<password> \
--set redis.auth.password=<password>Cloud-Specific Examples
AWS EKS
# values-eks.yaml
global:
storageClass: gp3
ingress:
enabled: true
className: alb
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ipGCP GKE
# values-gke.yaml
global:
storageClass: standard-rwo
ingress:
enabled: true
className: gce- Artifact Hub → Browse chart versions and values
- GitHub Repository → Source code and issues
Build from Source (Alternative)
Clone and Build
# Clone the repository
git clone https://github.com/logward-dev/logward.git
cd logward/docker
# Copy environment template
cp ../.env.example .env
# Edit .env with your configuration
nano .env
# Build and start all services
docker compose up -d --buildServices Running
Access LogWard at http://your-server-ip:3000
Monitoring & Maintenance
Health Checks
# Check all services status
docker compose ps
# Check backend health
curl http://localhost:8080/health
# With Traefik overlay
curl http://localhost:3080/health
# Check database
docker compose exec postgres psql -U logward -d logward -c "SELECT COUNT(*) FROM logs;"Common Commands
# Restart a service
docker compose restart backend
# View service logs
docker compose logs --tail=100 -f backend
# Stop all services
docker compose down
# Update to latest version
docker compose pull
docker compose up -dDatabase Backup
# Create backup
docker compose exec postgres pg_dump -U logward logward > backup_$(date +%Y%m%d).sql
# Restore from backup
docker compose exec -T postgres psql -U logward logward < backup_20250115.sql