Deployment
Surfly is deployed as containerized microservices managed by Podman and systemd. The deployment uses Podman quadlet files that generate systemd services automatically.
Architecture Overview
Section titled “Architecture Overview”The deployment uses Podman quadlets - container definitions that systemd automatically converts to service files using /usr/lib/systemd/system-generators/podman-system-generator --user. This provides native systemd integration with automatic startup, dependency management, and logging.
Installation Steps
Section titled “Installation Steps”1. Create Required Directories
Section titled “1. Create Required Directories”# Main surfly directory - mounted on all containers for shared accessmkdir -p ~/surfly/certs
# Quadlet files - container definitions that generate systemd servicesmkdir -p ~/.config/containers/systemd
# Systemd user service files and target definitionsmkdir -p ~/.config/systemd/userThe ~/surfly/ directory is mounted on all Podman containers, while ~/surfly/certs/ contains SSL certificates read by HAProxy for the HTTPS frontend.
2. Create Configuration File
Section titled “2. Create Configuration File”# Set your Surfly credentialsexport CLIENT_ID=your_client_idexport CLIENT_SECRET=your_client_secret
# Create environment file - loaded by all containersecho "CLIENT_ID=$CLIENT_ID" > ~/surfly/config.envecho "CLIENT_SECRET=$CLIENT_SECRET" >> ~/surfly/config.env
# Used in Dashboard and Studio to secure signed data. Must be kept secure.echo "SECRET_KEY=$(openssl rand -base64 32)" >> ~/surfly/config.env
# Authorization tokens for internal dashboard API.echo "DASHBOARD_AUTH_TOKEN=$(openssl rand -base64 32)" >> ~/surfly/config.env
# Authorization token for internal cobro API.echo "COBRO_AUTH_TOKEN=$(openssl rand -base64 32)" >> ~/surfly/config.env
# Space separated list of the DNS servers.echo "NGINX_DNS_RESOLVERS=1.1.1.1 8.8.8.8" >> ~/surfly/config.envThe config.env file is mounted as an environment file in all containers.
3. Copy SSL Certificates
Section titled “3. Copy SSL Certificates”# Copy certificates to directory read by HAProxy containercp /path/to/your/certificates/* ~/surfly/certs/
# If using lego-generated certificatescp ~/.lego/certificates/${DOMAIN}.pem ~/surfly/certs/4. Download Installation Files
Section titled “4. Download Installation Files”# Download Surfly license filecurl -u "$CLIENT_ID:$CLIENT_SECRET" https://build-agent.surfly.com/license -o ~/surfly/license.env
# Download Updated CA bundlecurl https://build-agent.surfly.com/public/ca_bundle.pem -o ~/surfly/ca_bundle.pem
# Download desired version of Surfly systemd services archiveVERSION="v5.1" # Update this version
# Create a temporary installation directorymkdir ~/install/
# Download Surfly systemd services archivecurl -u "$CLIENT_ID:$CLIENT_SECRET" \ https://build-agent.surfly.com/systemd/$VERSION.tar.gz \ -o ~/install/systemd.tar.gz5. Setup Container Registry Authentication
Section titled “5. Setup Container Registry Authentication”# Login to Surfly container registrypodman login --authfile ~/.config/containers/auth.json \ --username "$CLIENT_ID" \ --password "$CLIENT_SECRET" \ images.surfly.comIf you see cgroupv2 warnings, ensure systemd user-linger is enabled and XDG_RUNTIME_DIR is set.
6. Install and Start Services
Section titled “6. Install and Start Services”# Extract quadlet files and systemd targetscd ~/install/tar -xzf systemd.tar.gz
# Download all container images./pull_images.sh
# Install quadlet files to user containers directorycp ss-*.container ~/.config/containers/systemd/
# Install target files to user systemd directorycp ss-*.target ~/.config/systemd/user/
# Generate systemd services from quadlets and startsystemctl --user daemon-reloadsystemctl --user start ss-surfly.targetsystemctl --user enable ss-surfly.target7. Verify Deployment
Section titled “7. Verify Deployment”# Check all services statussystemctl --user status ss-surfly.target
# List service dependenciessystemctl --user list-dependencies ss-surfly.target
# Verify that all services are running and healthycurl http://127.0.0.1:8017/healthcheck/ | jq
# Example output:[ { "status": "UP", "service": "cmproxy", "took": "3ms" }, { "status": "UP", "service": "proxy", "took": "4ms" }, { "status": "UP", "service": "xresproxy", "took": "4ms" }, { "status": "UP", "service": "haproxy", "took": "5ms" } // Additional services will be listed here]Access Application
Section titled “Access Application”Once all services show “active (running)” status, access the Surfly dashboard:
https://app.yourdomain.comReplace yourdomain.com with your actual domain from the SSL certificates.
Service Management
Section titled “Service Management”# Check specific service logsjournalctl -f --user-unit ss-haproxy
# Restart all servicessystemctl --user restart ss-surfly.target
# Stop all servicessystemctl --user stop ss-surfly.target
# View quadlet-generated service filessystemctl --user cat ss-haproxy