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
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
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

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

You can retrieve the API token later by running on the server:

sudo haloyd config get api-token

Options

The install script accepts both command-line flags and environment variables:

FlagEnvironment VariableDescription
--api-domain=DOMAINAPI_DOMAINDomain for the haloy API (e.g., api.example.com)
--version=VERSIONVERSIONInstall a specific version (default: latest)
--skip-startSKIP_START=trueDon’t start the service after installation
--skip-docker-installSKIP_DOCKER_INSTALL=trueSkip 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 | 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

Standalone Docker Install Script

You can also install Docker separately using the standalone script:

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

2. Create System User

# 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

This creates:

  • /etc/haloy/haloyd.yaml - Daemon configuration
  • /etc/haloy/.env - API token
  • /var/lib/haloy/ - Data directory
  • haloy Docker 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

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

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

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

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"

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

Directory Structure

/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

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>

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

See Docker Installation for installation options.

Service Won’t Start

Check the logs:

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 haloy user is in the docker group

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

Verify Docker Access

# 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:

  1. 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.

  2. 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

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.

Next Steps