#!/bin/bash # Deploy a Veza service to Incus without Docker (native deployment) # Usage: ./deploy-service-native.sh set -e SERVICE=$1 PROJECT_NAME="veza" NETWORK="veza-network" PROFILE="veza-profile" PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" BUILD_DIR="${PROJECT_ROOT}/.build/incus" if [ -z "$SERVICE" ]; then echo "Usage: $0 " echo "Services: backend-api, chat-server, stream-server, web, haproxy, infra" exit 1 fi CONTAINER_NAME="${PROJECT_NAME}-${SERVICE}" echo "📦 Deploying ${SERVICE} to Incus (native, no Docker)..." # Check if network exists if ! incus network show ${NETWORK} >/dev/null 2>&1; then echo "Creating network ${NETWORK}..." incus network create ${NETWORK} \ ipv4.address=10.10.10.1/24 \ ipv4.nat=true fi # Check if profile exists if ! incus profile show ${PROFILE} >/dev/null 2>&1; then echo "Creating profile ${PROFILE}..." incus profile create ${PROFILE} incus profile device add ${PROFILE} eth0 nic network=${NETWORK} fi # Delete existing container if it exists if incus list -c n --format csv | grep -q "^${CONTAINER_NAME}$"; then echo "Removing existing container ${CONTAINER_NAME}..." incus delete ${CONTAINER_NAME} --force fi # Create and start container echo "Creating container ${CONTAINER_NAME}..." incus init images:ubuntu/22.04 ${CONTAINER_NAME} --profile ${PROFILE} incus start ${CONTAINER_NAME} # Wait for container to be ready echo "Waiting for container to be ready..." sleep 5 # Configure static IP based on service case ${SERVICE} in backend-api) STATIC_IP="10.10.10.2" ;; chat-server) STATIC_IP="10.10.10.3" ;; stream-server) STATIC_IP="10.10.10.4" ;; web) STATIC_IP="10.10.10.5" ;; haproxy) STATIC_IP="10.10.10.6" ;; infra) STATIC_IP="10.10.10.10" ;; *) STATIC_IP="" ;; esac # Set static IP if configured if [ -n "${STATIC_IP}" ]; then echo "Configuring static IP ${STATIC_IP}..." incus config device set ${CONTAINER_NAME} eth0 ipv4.address=${STATIC_IP} incus restart ${CONTAINER_NAME} sleep 3 fi # Install base dependencies echo "Installing base dependencies..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq curl wget ca-certificates systemd systemd-sysv " # Service-specific deployment case ${SERVICE} in backend-api) echo "Installing Go runtime dependencies..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ca-certificates libc6 " # Copy binary echo "Copying backend-api binary..." if [ ! -f "${BUILD_DIR}/veza-backend-api" ]; then echo "ERROR: Binary not found at ${BUILD_DIR}/veza-backend-api" echo "Please run: make build-all-native or ./config/incus/build-native.sh backend-api" exit 1 fi incus file push "${BUILD_DIR}/veza-backend-api" ${CONTAINER_NAME}/usr/local/bin/veza-backend-api incus exec ${CONTAINER_NAME} -- chmod +x /usr/local/bin/veza-backend-api # Create directories incus exec ${CONTAINER_NAME} -- bash -c " mkdir -p /opt/veza/backend-api mkdir -p /var/log/veza mkdir -p /etc/veza " # Copy systemd service incus file push "${PROJECT_ROOT}/config/incus/systemd/veza-backend-api.service" \ ${CONTAINER_NAME}/etc/systemd/system/veza-backend-api.service # Copy environment file template incus file push "${PROJECT_ROOT}/config/incus/env/backend-api.env" \ ${CONTAINER_NAME}/etc/veza/backend-api.env 2>/dev/null || true # Enable and start service incus exec ${CONTAINER_NAME} -- systemctl daemon-reload incus exec ${CONTAINER_NAME} -- systemctl enable veza-backend-api ;; chat-server) echo "Installing Rust runtime dependencies..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ca-certificates libc6 libssl3 " # Copy binary echo "Copying chat-server binary..." if [ ! -f "${BUILD_DIR}/veza-chat-server" ]; then echo "ERROR: Binary not found at ${BUILD_DIR}/veza-chat-server" echo "Please run: make build-all-native or ./config/incus/build-native.sh chat-server" exit 1 fi incus file push "${BUILD_DIR}/veza-chat-server" ${CONTAINER_NAME}/usr/local/bin/veza-chat-server incus exec ${CONTAINER_NAME} -- chmod +x /usr/local/bin/veza-chat-server # Create directories incus exec ${CONTAINER_NAME} -- bash -c " mkdir -p /opt/veza/chat-server mkdir -p /var/log/veza mkdir -p /etc/veza " # Copy systemd service incus file push "${PROJECT_ROOT}/config/incus/systemd/veza-chat-server.service" \ ${CONTAINER_NAME}/etc/systemd/system/veza-chat-server.service # Copy environment file template incus file push "${PROJECT_ROOT}/config/incus/env/chat-server.env" \ ${CONTAINER_NAME}/etc/veza/chat-server.env 2>/dev/null || true # Enable and start service incus exec ${CONTAINER_NAME} -- systemctl daemon-reload incus exec ${CONTAINER_NAME} -- systemctl enable veza-chat-server ;; stream-server) echo "Installing Rust runtime dependencies..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ca-certificates libc6 libssl3 " # Copy binary echo "Copying stream-server binary..." if [ ! -f "${BUILD_DIR}/veza-stream-server" ]; then echo "ERROR: Binary not found at ${BUILD_DIR}/veza-stream-server" echo "Please run: make build-all-native or ./config/incus/build-native.sh stream-server" exit 1 fi incus file push "${BUILD_DIR}/veza-stream-server" ${CONTAINER_NAME}/usr/local/bin/veza-stream-server incus exec ${CONTAINER_NAME} -- chmod +x /usr/local/bin/veza-stream-server # Create directories incus exec ${CONTAINER_NAME} -- bash -c " mkdir -p /opt/veza/stream-server mkdir -p /opt/veza/stream-server/audio mkdir -p /var/log/veza mkdir -p /etc/veza " # Copy systemd service incus file push "${PROJECT_ROOT}/config/incus/systemd/veza-stream-server.service" \ ${CONTAINER_NAME}/etc/systemd/system/veza-stream-server.service # Copy environment file template incus file push "${PROJECT_ROOT}/config/incus/env/stream-server.env" \ ${CONTAINER_NAME}/etc/veza/stream-server.env 2>/dev/null || true # Enable and start service incus exec ${CONTAINER_NAME} -- systemctl daemon-reload incus exec ${CONTAINER_NAME} -- systemctl enable veza-stream-server ;; web) echo "Installing web server (Apache/httpd)..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apache2 " # Copy web files echo "Copying web frontend files..." if [ ! -d "${BUILD_DIR}/web" ] || [ ! -f "${BUILD_DIR}/web/index.html" ]; then echo "ERROR: Web build not found at ${BUILD_DIR}/web" echo "Please run: make build-all-native or ./config/incus/build-native.sh web" exit 1 fi incus exec ${CONTAINER_NAME} -- mkdir -p /var/www/veza incus file push -r "${BUILD_DIR}/web"/* ${CONTAINER_NAME}/var/www/veza/ # Copy Apache config incus file push "${PROJECT_ROOT}/config/incus/apache/veza-web.conf" \ ${CONTAINER_NAME}/etc/apache2/sites-available/veza-web.conf # Enable Apache site and modules incus exec ${CONTAINER_NAME} -- bash -c " a2enmod rewrite a2enmod headers a2enmod expires a2enmod deflate a2dissite 000-default a2ensite veza-web apache2ctl configtest " # Enable and start Apache incus exec ${CONTAINER_NAME} -- systemctl enable apache2 ;; haproxy) echo "Installing HAProxy..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get install -y -qq haproxy " # Copy HAProxy config (Incus-specific) incus file push "${PROJECT_ROOT}/config/incus/haproxy.cfg" \ ${CONTAINER_NAME}/etc/haproxy/haproxy.cfg # Configure HAProxy to start incus exec ${CONTAINER_NAME} -- bash -c " echo 'ENABLED=1' > /etc/default/haproxy " # Enable and start HAProxy incus exec ${CONTAINER_NAME} -- systemctl enable haproxy ;; infra) echo "Installing infrastructure services (PostgreSQL, Redis)..." incus exec ${CONTAINER_NAME} -- bash -c " export DEBIAN_FRONTEND=noninteractive apt-get install -y -qq postgresql redis-server " # Configure PostgreSQL incus exec ${CONTAINER_NAME} -- bash -c " sudo -u postgres psql -c \"CREATE USER veza WITH PASSWORD 'password';\" || true sudo -u postgres psql -c \"CREATE DATABASE veza OWNER veza;\" || true sudo -u postgres psql -c \"GRANT ALL PRIVILEGES ON DATABASE veza TO veza;\" || true " # Configure Redis incus exec ${CONTAINER_NAME} -- bash -c " sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf || true " # Enable services incus exec ${CONTAINER_NAME} -- systemctl enable postgresql incus exec ${CONTAINER_NAME} -- systemctl enable redis-server ;; *) echo "Unknown service: ${SERVICE}" exit 1 ;; esac echo "✅ ${SERVICE} deployed successfully!" echo "Container: ${CONTAINER_NAME}" echo "Access: incus exec ${CONTAINER_NAME} -- bash" echo "" echo "To start the service:" echo " incus exec ${CONTAINER_NAME} -- systemctl start veza-${SERVICE}"