Architecture
Understand how Haloy’s components work together to manage your deployments.
System Components
Haloy consists of several components working in harmony:
- Haloy CLI (
haloy) - Command-line interface for deployments from your local machine - Haloy Admin CLI (
haloyadm) - Setup and administration tool for the server - Haloy Daemon (
haloyd) - Service discovery, configuration, and container orchestration - HAProxy - External load balancer for SSL termination and traffic routing
- Application Containers - Your deployed applications orchestrated by
haloyd
Component Overview
Haloy CLI (haloy)
Runs on: Your local development machine, CI/CD systems, or any machine that can reach your server’s API
Purpose: Trigger deployments and manage applications
Key Functions:
- Read and validate configuration files
- Build Docker images locally (optional)
- Upload images to servers
- Send deployment commands to
haloydAPI - Display deployment status and logs
Location: ~/.local/bin/haloy
See the full command reference for available commands.
Haloy Admin CLI (haloyadm)
Runs on: Your server
Purpose: Set up and administrate the Haloy daemon
Key Functions:
- Initialize
haloydand HAProxy - Start/stop/restart services
- Generate API tokens
- Configure API domains and SSL
Location: /usr/local/bin/haloyadm (system) or ~/.local/bin/haloyadm (user)
See the full command reference for available commands.
Haloy Daemon (haloyd)
Runs on: Your server (as a Docker container)
Purpose: Container orchestration and service discovery
Key Functions:
- Accept deployment commands via REST API
- Pull or load Docker images
- Start and stop application containers
- Monitor container health
- Generate HAProxy configuration dynamically
- Manage SSL certificates via ACME (Let’s Encrypt)
- Track deployment history for rollbacks
Configuration: /etc/haloy/haloyd.yaml or ~/.config/haloy/haloyd.yaml
Data storage: /var/lib/haloy/ or ~/.local/share/haloy/
HAProxy
Runs on: Your server (as a Docker container)
Purpose: Load balancing and SSL termination
Key Functions:
- Route external traffic to application containers
- SSL/TLS termination
- HTTP to HTTPS redirects
- Domain routing
- Load balancing across replicas
- Health check integration
Configuration: Auto-generated by haloyd
Listens on: Ports 80 (HTTP) and 443 (HTTPS)
Application Containers
Runs on: Your server
Purpose: Your deployed applications
Managed by: haloyd
Networking: Connected to Haloy’s Docker network
Health monitoring: Via configured health check endpoints
Architecture Diagram
┌─────────────────────┐
│ Developer Machine │
│ │
│ ┌──────────────┐ │
│ │ haloy CLI │ │
│ └──────┬───────┘ │
└─────────┼───────────┘
│ HTTPS
│ (API calls)
▼
┌─────────────────────────────────────────┐
│ Server │
│ │
│ ┌──────────────────┐ │
│ │ haloyd (Docker) │ │
│ │ │ │
│ │ - API Server │ │
│ │ - Orchestration │ │
│ │ - Service Disc. │ │
│ └────┬─────────────┘ │
│ │ Generates │
│ │ config │
│ ▼ │
│ ┌──────────────────┐ │
│ │ HAProxy (Docker) │ │
│ │ │ │
│ │ Ports: 80, 443 │ │
│ └────┬─────────────┘ │
│ │ Routes traffic │
│ │ │
│ ├──────────┬──────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ App │ │ App │ │ App │ │
│ │ (8080) │ │ (8080) │ │ (8080) │ │
│ └────────┘ └────────┘ └────────┘ │
│ Replica 1 Replica 2 Replica 3 │
└─────────────────────────────────────────┘
┌─────────────────────┐
│ Developer Machine │
│ │
│ ┌──────────────┐ │
│ │ haloy CLI │ │
│ └──────┬───────┘ │
└─────────┼───────────┘
│ HTTPS
│ (API calls)
▼
┌─────────────────────────────────────────┐
│ Server │
│ │
│ ┌──────────────────┐ │
│ │ haloyd (Docker) │ │
│ │ │ │
│ │ - API Server │ │
│ │ - Orchestration │ │
│ │ - Service Disc. │ │
│ └────┬─────────────┘ │
│ │ Generates │
│ │ config │
│ ▼ │
│ ┌──────────────────┐ │
│ │ HAProxy (Docker) │ │
│ │ │ │
│ │ Ports: 80, 443 │ │
│ └────┬─────────────┘ │
│ │ Routes traffic │
│ │ │
│ ├──────────┬──────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ App │ │ App │ │ App │ │
│ │ (8080) │ │ (8080) │ │ (8080) │ │
│ └────────┘ └────────┘ └────────┘ │
│ Replica 1 Replica 2 Replica 3 │
└─────────────────────────────────────────┘
Traffic Flow
Incoming Requests
Internet
│
├─ HTTP (port 80)
│ └─► HAProxy → Redirects to HTTPS
│
└─ HTTPS (port 443)
└─► HAProxy
├─ SSL Termination
├─ Domain Routing (my-app.com → my-app)
└─► Load Balance
├─► App Container 1 (port 8080)
├─► App Container 2 (port 8080)
└─► App Container 3 (port 8080)
Internet
│
├─ HTTP (port 80)
│ └─► HAProxy → Redirects to HTTPS
│
└─ HTTPS (port 443)
└─► HAProxy
├─ SSL Termination
├─ Domain Routing (my-app.com → my-app)
└─► Load Balance
├─► App Container 1 (port 8080)
├─► App Container 2 (port 8080)
└─► App Container 3 (port 8080)
Deployment Flow
Developer: haloy deploy
│
└─► Build image locally (if configured)
│
└─► Upload to server or push to registry
│
└─► API call to haloyd
│
├─► haloyd pulls/loads image
├─► haloyd starts new containers
├─► haloyd waits for health checks
├─► haloyd updates HAProxy config
├─► HAProxy routes to new containers
└─► haloyd stops old containers
Developer: haloy deploy
│
└─► Build image locally (if configured)
│
└─► Upload to server or push to registry
│
└─► API call to haloyd
│
├─► haloyd pulls/loads image
├─► haloyd starts new containers
├─► haloyd waits for health checks
├─► haloyd updates HAProxy config
├─► HAProxy routes to new containers
└─► haloyd stops old containers
Service Discovery
Haloy uses Docker labels for service discovery. You can leverage this feature in two ways:
- Via Haloy CLI - Deploy using
haloy deploy(recommended) - Direct container labels - Start containers manually with appropriate labels
Using Haloy CLI
The standard approach is to use haloy deploy which handles labeling automatically based on your configuration.
Using Container Labels Directly
You can start containers manually (using docker run, Docker Compose, or other orchestration tools) and haloyd will automatically discover and route traffic to them:
# Start a container with Haloy labels
docker run -d \
--name my-app \
--network haloy \
--label dev.haloy.appName=my-app \
--label dev.haloy.deployment-id=manual-001 \
--label dev.haloy.role=app \
--label dev.haloy.domain.0=example.com \
--label dev.haloy.domain.0.alias.0=www.example.com \
--label dev.haloy.port=8080 \
--label dev.haloy.health-check-path=/health \
my-image:latest
# Start a container with Haloy labels
docker run -d \
--name my-app \
--network haloy \
--label dev.haloy.appName=my-app \
--label dev.haloy.deployment-id=manual-001 \
--label dev.haloy.role=app \
--label dev.haloy.domain.0=example.com \
--label dev.haloy.domain.0.alias.0=www.example.com \
--label dev.haloy.port=8080 \
--label dev.haloy.health-check-path=/health \
my-image:latest
# Docker Compose example
services:
my-app:
image: my-image:latest
networks:
- haloy
labels:
dev.haloy.appName: my-app
dev.haloy.deployment-id: manual-001 # Make sure to increment this manually for the changes to take effect
dev.haloy.role: app
dev.haloy.domain.0: example.com
dev.haloy.domain.0.alias.0: www.example.com
dev.haloy.port: "8080"
dev.haloy.health-check-path: /health
networks:
haloy:
external: true
# Docker Compose example
services:
my-app:
image: my-image:latest
networks:
- haloy
labels:
dev.haloy.appName: my-app
dev.haloy.deployment-id: manual-001 # Make sure to increment this manually for the changes to take effect
dev.haloy.role: app
dev.haloy.domain.0: example.com
dev.haloy.domain.0.alias.0: www.example.com
dev.haloy.port: "8080"
dev.haloy.health-check-path: /health
networks:
haloy:
external: true
Required labels:
dev.haloy.appName- Application identifierdev.haloy.deployment-id- Unique deployment identifierdev.haloy.role- Must be set toappdev.haloy.domain.0- Primary domain (use.1,.2for additional domains)
Optional labels:
dev.haloy.port- Container port (default:8080)dev.haloy.health-check-path- Health check endpoint (default:/)dev.haloy.domain.0.alias.0- Domain alias (use.1,.2for additional aliases)dev.haloy.acme.email- Email for Let’s Encrypt certificates
Discovery Process:
haloydmonitors Docker for labeled containers- Extracts routing information from labels
- Generates HAProxy configuration
- Reloads HAProxy with zero downtime
This allows you to integrate Haloy’s routing and SSL management with your existing deployment workflows.
Networking
Docker Networks
Haloy creates and uses Docker networks:
- haloy (default): Application containers and HAProxy
- Custom networks: Via
networkconfiguration option
Port Mapping
HAProxy:
- 80:80 (HTTP)
- 443:443 (HTTPS)
Application Containers:
- No direct port exposure
- Internal network only
- HAProxy routes traffic
HAProxy:
- 80:80 (HTTP)
- 443:443 (HTTPS)
Application Containers:
- No direct port exposure
- Internal network only
- HAProxy routes traffic
Data Storage
System Installation
/etc/haloy/
├── haloyd.yaml # Daemon configuration
└── .env # API tokens
/var/lib/haloy/
├── haproxy-config/ # HAProxy configurations
├── cert-storage/ # SSL certificates
└── db/ # Deployment database
/etc/haloy/
├── haloyd.yaml # Daemon configuration
└── .env # API tokens
/var/lib/haloy/
├── haproxy-config/ # HAProxy configurations
├── cert-storage/ # SSL certificates
└── db/ # Deployment database
User Installation
~/.config/haloy/
├── haloyd.yaml # Daemon configuration
└── .env # API tokens
~/.local/share/haloy/
├── haproxy-config/ # HAProxy configurations
├── cert-storage/ # SSL certificates
└── db/ # Deployment database
~/.config/haloy/
├── haloyd.yaml # Daemon configuration
└── .env # API tokens
~/.local/share/haloy/
├── haproxy-config/ # HAProxy configurations
├── cert-storage/ # SSL certificates
└── db/ # Deployment database
SSL/TLS Certificates
Certificate Management:
- Automatic via ACME (Let’s Encrypt)
- Certificates stored in
cert-storage/ - Auto-renewal before expiration
- Per-domain certificates
Process:
- Domain configured in
haloy.yaml haloydrequests certificate from Let’s Encrypt- ACME challenge validation (HTTP-01)
- Certificate issued and stored
- HAProxy configured to use certificate
- Auto-renewal 30 days before expiration
Health Checks
Flow:
HAProxy → Health Check → App Container (/health endpoint)
│ │
│ ├─ 200 OK → Healthy
│ └─ Other → Unhealthy
│
└─ Routes traffic only to healthy containers
HAProxy → Health Check → App Container (/health endpoint)
│ │
│ ├─ 200 OK → Healthy
│ └─ Other → Unhealthy
│
└─ Routes traffic only to healthy containers
Check Frequency: Every few seconds
Actions on Failure:
- Container marked unhealthy
- Traffic stops routing to container
- Container visible in
haloy statusas unhealthy
High Availability
Haloy achieves HA through:
- Multiple replicas: Run 3+ instances
- Health monitoring: Remove unhealthy containers from rotation
- Rolling deployments: Update without downtime
- Load balancing: Distribute traffic evenly
- Automatic recovery: Restart failed containers
Deployment Strategies
Rolling Deployment
Old containers: [1] [2] [3]
│ │ │
Step 1: │ │ │ New [1] starts
Step 2: │ │ │ New [1] healthy → Old [1] stops
Step 3: │ │ │ New [2] starts
Step 4: │ │ │ New [2] healthy → Old [2] stops
Step 5: │ │ │ New [3] starts
Step 6: │ │ │ New [3] healthy → Old [3] stops
▼ ▼ ▼
New containers: [1] [2] [3]
Old containers: [1] [2] [3]
│ │ │
Step 1: │ │ │ New [1] starts
Step 2: │ │ │ New [1] healthy → Old [1] stops
Step 3: │ │ │ New [2] starts
Step 4: │ │ │ New [2] healthy → Old [2] stops
Step 5: │ │ │ New [3] starts
Step 6: │ │ │ New [3] healthy → Old [3] stops
▼ ▼ ▼
New containers: [1] [2] [3]
Replace Deployment
Old containers: [1] [2] [3]
│ │ │
Step 1: Stop all old containers
Step 2: Start all new containers
Step 3: Wait for health checks
▼ ▼ ▼
New containers: [1] [2] [3]
Old containers: [1] [2] [3]
│ │ │
Step 1: Stop all old containers
Step 2: Start all new containers
Step 3: Wait for health checks
▼ ▼ ▼
New containers: [1] [2] [3]
Security
API Authentication:
- API tokens generated by
haloyadm - Tokens stored securely with restrictive permissions
- HTTPS for all API communication (when domain configured)
Container Isolation:
- Docker network isolation
- No direct container exposure to internet
- All traffic through HAProxy
SSL/TLS:
- Automatic certificate management
- Strong cipher suites
- HTTP to HTTPS redirect
Scalability
Horizontal Scaling:
- Add more replicas in configuration
- Load balanced automatically
- Linear scaling for stateless apps
Multi-Server:
- Deploy to multiple servers
- Independent server scaling
- Geographic distribution
Monitoring
Built-in Monitoring:
- Container health checks
- Deployment status tracking
- Application logs via
haloy logs - Service status via
haloy status
External Monitoring:
- Expose health check endpoints
- Monitor via Prometheus/Grafana
- Alert on health check failures
Limitations
- Single server orchestration: Each server managed independently
- No automatic scaling: Manual replica configuration
- No built-in monitoring: Use external tools
- Docker required: All components run in Docker
- Linux only: Server must be Linux-based
Next Steps
- Commands Reference - Complete CLI command documentation
- Learn about Multi-Server Deployments
- Configure Health Checks
- Set up Horizontal Scaling
- Understand Authentication