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.
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.0
LOGWARD_FRONTEND_IMAGE=logward/frontend:0.3.0Ready to Go
Frontend: http://localhost:3000 | API: http://localhost:8080
Remote Deployment
When deploying on a remote server (not localhost), you must configure PUBLIC_API_URL so the frontend knows where to find the backend.
Without this, users accessing http://your-server:3000 will get errors
because the frontend will try to connect to localhost:8080 (which doesn't exist on their machine).
Configure for Remote Access
In your .env file, set the public URL where the backend API is accessible:
# .env file on your server
# Replace with your server's IP or domain
PUBLIC_API_URL=http://your-server-ip:8080
# Or if using a domain
PUBLIC_API_URL=https://api.yourdomain.comExample: VPS Deployment
# Server IP: 192.168.1.100
# .env configuration
DB_PASSWORD=secure_password
REDIS_PASSWORD=secure_password
API_KEY_SECRET=your_32_character_secret_key_here
PUBLIC_API_URL=http://192.168.1.100:8080
# Access points:
# Frontend: http://192.168.1.100:3000
# API: http://192.168.1.100:8080With Reverse Proxy (nginx/Traefik)
If you're using a reverse proxy in front of LogWard, configure accordingly:
# With nginx/Traefik proxying to LogWard
# If frontend and API are on same domain (recommended)
# nginx proxies / to frontend:3000 and /api to backend:8080
PUBLIC_API_URL=
# If API is on a subdomain
# frontend at example.com, api at api.example.com
PUBLIC_API_URL=https://api.example.com| Scenario | PUBLIC_API_URL |
|---|---|
| Local development | http://localhost:8080 |
| Remote server (IP) | http://192.168.1.100:8080 |
| With domain | https://api.example.com |
| Same-origin proxy | (empty - uses relative URLs) |
| LogWard Cloud | https://api.logward.dev |
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
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