Server Installation
The Haloy daemon (haloyd) runs on your server and manages container deployments, service discovery, and traffic routing.
After running the installation script, you’ll need to configure your server with a domain for remote access.
Prerequisites
- Linux server (Debian/Ubuntu, RHEL/CentOS, Alpine, or other distributions)
- Docker installed and running (can be auto-installed)
- Root or sudo access
- A domain or subdomain pointing to your server (for HTTPS API access)
Quick Install (with configuration)
If you already have a domain pointing to your server:
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | API_DOMAIN=api.example.com sh
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | API_DOMAIN=api.example.com sh
wget -qO- https://sh.haloy.dev/install-haloyd.sh | API_DOMAIN=api.example.com sh
wget -qO- https://sh.haloy.dev/install-haloyd.sh | API_DOMAIN=api.example.com sh
Standard Install (configure after)
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | sh
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | sh
wget -qO- https://sh.haloy.dev/install-haloyd.sh | sh
wget -qO- https://sh.haloy.dev/install-haloyd.sh | sh
Note: If you’re not logged in as root, use | sudo sh instead of | sh.
After installation, the script will display your server’s public IP address. You’ll need to:
1. Point your domain to the server
Create a DNS A record pointing your chosen domain to the server’s IP address.
Cloudflare users: Set the proxy status to “DNS only” (grey cloud), or ensure your SSL/TLS encryption mode is set to “Full (Strict)”. See Troubleshooting if you experience redirect loops.
2. Configure haloy
sudo haloyd config set api-domain YOUR_DOMAIN
sudo systemctl restart haloyd
sudo haloyd config set api-domain YOUR_DOMAIN
sudo systemctl restart haloyd
Alpine Linux (OpenRC): Use sudo rc-service haloyd restart instead of systemctl restart.
3. Add the server to your local CLI
On your local machine, run the command shown at the end of installation:
haloy server add YOUR_DOMAIN YOUR_API_TOKEN
haloy server add YOUR_DOMAIN YOUR_API_TOKEN
You can retrieve the API token later by running on the server:
sudo haloyd config get api-token
sudo haloyd config get api-token
Options
The install script accepts both command-line flags and environment variables:
| Flag | Environment Variable | Description |
|---|---|---|
--api-domain=DOMAIN | API_DOMAIN | Domain for the haloy API (e.g., api.example.com) |
--version=VERSION | VERSION | Install a specific version (default: latest) |
--skip-start | SKIP_START=true | Don’t start the service after installation |
--skip-docker-install | SKIP_DOCKER_INSTALL=true | Skip automatic Docker installation |
Examples:
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | sh -s -- --api-domain=api.example.com
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | sh -s -- --api-domain=api.example.com
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | VERSION=v0.1.0 sh
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | VERSION=v0.1.0 sh
Docker Installation
If Docker is not installed on your server, the install script will automatically install it for you. This is the default behavior.
If you prefer to install Docker manually or use a custom Docker installation, you can skip automatic installation:
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | sh -s -- --skip-docker-install
curl -fsSL https://sh.haloy.dev/install-haloyd.sh | sh -s -- --skip-docker-install
Standalone Docker Install Script
You can also install Docker separately using the standalone script:
curl -fsSL https://sh.haloy.dev/install-docker.sh | sh
curl -fsSL https://sh.haloy.dev/install-docker.sh | sh
This script automatically detects your Linux distribution and installs Docker accordingly:
- Alpine Linux: Uses
apk add docker docker-cli-compose - Ubuntu, Debian, CentOS, Fedora, RHEL, and others: Uses the official Docker installation script from get.docker.com
The script enables and starts the Docker daemon automatically.
Manual Installation
If you prefer to install manually or the script doesn’t work for your system:
1. Install haloyd Binary
Download and install the binary:
# Download latest release (adjust architecture as needed: amd64, arm64)
curl -fsSL -o /usr/local/bin/haloyd https://releases.haloy.dev/haloyd-linux-amd64
chmod +x /usr/local/bin/haloyd
# Download latest release (adjust architecture as needed: amd64, arm64)
curl -fsSL -o /usr/local/bin/haloyd https://releases.haloy.dev/haloyd-linux-amd64
chmod +x /usr/local/bin/haloyd
2. Create System User
# Create haloy user and add to docker group
useradd -r -s /bin/false haloy
usermod -aG docker haloy
# Create haloy user and add to docker group
useradd -r -s /bin/false haloy
usermod -aG docker haloy
3. Initialize haloyd
Run the init command to create configuration and directories:
sudo haloyd init --api-domain haloy.yourserver.com
sudo haloyd init --api-domain haloy.yourserver.com
This creates:
/etc/haloy/haloyd.yaml- Daemon configuration/etc/haloy/.env- API token/var/lib/haloy/- Data directoryhaloyDocker network
4. Install Service
Systemd
cat > /etc/systemd/system/haloyd.service << 'EOF'
[Unit]
Description=Haloy Daemon
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service
[Service]
Type=simple
User=haloy
Group=haloy
ExecStart=/usr/local/bin/haloyd serve
Restart=always
RestartSec=5
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/haloy /etc/haloy
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now haloyd
cat > /etc/systemd/system/haloyd.service << 'EOF'
[Unit]
Description=Haloy Daemon
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service
[Service]
Type=simple
User=haloy
Group=haloy
ExecStart=/usr/local/bin/haloyd serve
Restart=always
RestartSec=5
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/haloy /etc/haloy
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now haloyd
OpenRC
cat > /etc/init.d/haloyd << 'EOF'
#!/sbin/openrc-run
name="haloyd"
description="Haloy Daemon"
command="/usr/local/bin/haloyd"
command_args="serve"
command_user="haloy:haloy"
pidfile="/run/haloyd.pid"
command_background=true
depend() {
need net docker
after firewall
}
EOF
chmod +x /etc/init.d/haloyd
rc-update add haloyd default
rc-service haloyd start
cat > /etc/init.d/haloyd << 'EOF'
#!/sbin/openrc-run
name="haloyd"
description="Haloy Daemon"
command="/usr/local/bin/haloyd"
command_args="serve"
command_user="haloy:haloy"
pidfile="/run/haloyd.pid"
command_background=true
depend() {
need net docker
after firewall
}
EOF
chmod +x /etc/init.d/haloyd
rc-update add haloyd default
rc-service haloyd start
Service Management
Systemd
# Start the service
sudo systemctl start haloyd
# Stop the service
sudo systemctl stop haloyd
# Restart the service
sudo systemctl restart haloyd
# Check service status
sudo systemctl status haloyd
# View logs
sudo journalctl -u haloyd -f
# Start the service
sudo systemctl start haloyd
# Stop the service
sudo systemctl stop haloyd
# Restart the service
sudo systemctl restart haloyd
# Check service status
sudo systemctl status haloyd
# View logs
sudo journalctl -u haloyd -f
OpenRC
# Start the service
sudo rc-service haloyd start
# Stop the service
sudo rc-service haloyd stop
# Restart the service
sudo rc-service haloyd restart
# Check service status
sudo rc-service haloyd status
# Start the service
sudo rc-service haloyd start
# Stop the service
sudo rc-service haloyd stop
# Restart the service
sudo rc-service haloyd restart
# Check service status
sudo rc-service haloyd status
Configuration
The haloyd configuration file is located at /etc/haloy/haloyd.yaml:
api_domain: haloy.yourserver.com
health_monitor:
enabled: true
interval: "15s"
fall: 3
rise: 2
timeout: "5s"
api_domain: haloy.yourserver.com
health_monitor:
enabled: true
interval: "15s"
fall: 3
rise: 2
timeout: "5s"
View or Update Configuration
# View a configuration value
sudo haloyd config get api-domain
# Set a configuration value
sudo haloyd config set api-domain haloy.newdomain.com
# Get the API token
sudo haloyd config get api-token
# View a configuration value
sudo haloyd config get api-domain
# Set a configuration value
sudo haloyd config set api-domain haloy.newdomain.com
# Get the API token
sudo haloyd config get api-token
Directory Structure
/etc/haloy/ # Configuration
├── haloyd.yaml # Daemon settings
└── .env # API token
/var/lib/haloy/ # Data
├── certs/ # SSL certificates
└── db/ # Deployment database
/etc/haloy/ # Configuration
├── haloyd.yaml # Daemon settings
└── .env # API token
/var/lib/haloy/ # Data
├── certs/ # SSL certificates
└── db/ # Deployment database
Verify Installation
Run the verify command to check that everything is working:
sudo haloyd verify
sudo haloyd verify
This checks:
- Configuration directory and files
- Data directory
- Docker connectivity
- Docker network
- API health
Same-Server Deployment
If you want to run the haloy CLI directly on the server (instead of from your local machine), you can add the server using localhost:
haloy server add localhost <api-token>
haloy server add localhost <api-token>
This is useful for:
- Single-server setups
- CI/CD pipelines running on the server
- Situations where external API access isn’t available
Troubleshooting
Docker Not Installed
If you used --skip-docker-install and Docker is not installed, the script will show:
✗ Docker is not installed
Troubleshooting:
- Install Docker manually: curl -fsSL https://sh.haloy.dev/install-docker.sh | sh
- Or remove SKIP_DOCKER_INSTALL to install automatically
✗ Docker is not installed
Troubleshooting:
- Install Docker manually: curl -fsSL https://sh.haloy.dev/install-docker.sh | sh
- Or remove SKIP_DOCKER_INSTALL to install automatically
See Docker Installation for installation options.
Service Won’t Start
Check the logs:
sudo journalctl -u haloyd -n 50
sudo journalctl -u haloyd -n 50
Common issues:
- Docker not running:
sudo systemctl start docker - Port 80/443 in use: Check with
sudo ss -tlnp | grep -E ':80|:443' - Permission issues: Ensure the
haloyuser is in thedockergroup
Cannot Connect to API
Verify the service is running and listening:
# Check service status
sudo systemctl status haloyd
# Check if ports are open
sudo ss -tlnp | grep haloyd
# Test API locally
curl -k https://localhost/health
# Check service status
sudo systemctl status haloyd
# Check if ports are open
sudo ss -tlnp | grep haloyd
# Test API locally
curl -k https://localhost/health
Verify Docker Access
# Test that haloy user can access Docker
sudo -u haloy docker ps
# Test that haloy user can access Docker
sudo -u haloy docker ps
Redirect Loop (ERR_TOO_MANY_REDIRECTS)
If you see “too many redirects” errors in the browser, this is typically caused by Cloudflare proxy settings.
Cause: Cloudflare’s “Flexible” SSL mode connects to your origin via HTTP. Haloy redirects HTTP to HTTPS, creating an infinite loop.
Solutions:
-
Use DNS-only mode (recommended for simplicity): In Cloudflare, click the orange cloud icon to turn it grey. This disables the proxy and lets traffic go directly to your server.
-
Use Full (Strict) SSL mode: In Cloudflare dashboard, go to SSL/TLS → Overview and change the mode to “Full (Strict)”. This makes Cloudflare connect to your origin via HTTPS.
After changing settings, you may need to:
- Clear your browser cache or use incognito mode
- Flush your local DNS cache:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder(macOS) - Wait a few minutes for DNS changes to propagate
Uninstalling
To completely remove Haloy from your server:
curl -sL https://sh.haloy.dev/uninstall-server.sh | sh
curl -sL https://sh.haloy.dev/uninstall-server.sh | sh
This will:
- Stop and remove the haloyd service
- Optionally back up your data
- Remove configuration and data directories
- Remove the haloyd binary
- Optionally remove the haloy user
See Uninstalling for more details.
Upgrading
To upgrade an existing haloyd installation, use one of the dedicated upgrade methods described in Upgrading. Do not re-run the install script to upgrade, as it will overwrite your systemd/OpenRC service file and discard any manual customizations you’ve made to it.