Deploy infra-controller to services server
Some checks failed
Deploy / deploy (push) Failing after 9s

This commit is contained in:
Jeremie Fraeys 2026-01-23 14:01:54 -05:00
parent 7a8403e51c
commit 6ca0219902
No known key found for this signature in database
13 changed files with 88 additions and 145 deletions

View file

@ -1,3 +1 @@
CONFIG_PATH=/etc/infra-controller/config.yml
ACTIVE_APPS_DIR=/var/run/active-apps
LOG_LEVEL=INFO
CONFIG_PATH=/etc/infra-controller/config.toml

View file

@ -59,34 +59,59 @@ jobs:
exit 1
}
# Deploy app locally on the runner host
- name: Deploy App (Docker Compose)
shell: bash
run: |
set -euo pipefail
APP_NAME="${{ github.event.repository.name }}"
APP_PATH="/srv/apps/$APP_NAME"
echo "Deploying $APP_NAME from $APP_PATH..."
if [[ ! -d "$APP_PATH" ]]; then
echo "Skipping deploy: $APP_PATH not found on this runner"
exit 0
fi
cd "$APP_PATH"
docker compose pull
docker compose up -d
# Register app on the services server (triggers infra-controller.path)
- name: Register App Requirements
# Deploy infra-controller to services server
- name: Deploy infra-controller (services server)
shell: bash
env:
SERVICE_HOST: ${{ secrets.SERVICE_HOST }}
SERVICE_USER: ${{ secrets.SERVICE_USER }}
run: |
set -euo pipefail
APP_NAME="${{ github.event.repository.name }}"
echo "Registering app $APP_NAME with infra-controller..."
if [[ -f .infra.toml ]]; then
ssh -i ~/.ssh/id_ed25519 "$SERVICE_USER@$SERVICE_HOST" infra-register-stdin "$APP_NAME" < .infra.toml
else
ssh -i ~/.ssh/id_ed25519 "$SERVICE_USER@$SERVICE_HOST" infra-deregister "$APP_NAME"
fi
: "${SERVICE_HOST:?Missing secret SERVICE_HOST}"
: "${SERVICE_USER:?Missing secret SERVICE_USER}"
GIT_SHA="${{ github.sha }}"
REPO_URL="$(git remote get-url origin)"
echo "Deploying infra-controller ($GIT_SHA) to $SERVICE_USER@$SERVICE_HOST ..."
ssh -i ~/.ssh/id_ed25519 "$SERVICE_USER@$SERVICE_HOST" /bin/sh -lc "set -euo pipefail
sudo mkdir -p /opt/infra-controller /etc/infra-controller /var/lib/infra-controller /var/log/infra-controller
if [ ! -d /opt/infra-controller/.git ]; then
sudo rm -rf /opt/infra-controller/*
sudo git clone '$REPO_URL' /opt/infra-controller
fi
cd /opt/infra-controller
sudo git fetch --all --prune
sudo git checkout -f '$GIT_SHA'
if [ ! -d /opt/infra-controller/venv ]; then
sudo python3 -m venv /opt/infra-controller/venv
fi
sudo /opt/infra-controller/venv/bin/pip install --upgrade pip
sudo /opt/infra-controller/venv/bin/pip install -e .
if [ ! -f /etc/infra-controller/config.toml ]; then
sudo cp config/controller.toml.example /etc/infra-controller/config.toml
fi
if [ ! -f /etc/infra-controller/controller.env ]; then
sudo cp systemd/infra-controller.env /etc/infra-controller/controller.env
fi
sudo cp systemd/infra-controller.service /etc/systemd/system/
sudo cp systemd/infra-controller-once.service /etc/systemd/system/
sudo cp systemd/infra-controller-watch.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl disable --now infra-controller.path 2>/dev/null || true
sudo systemctl enable --now infra-controller-watch.service
sudo systemctl restart infra-controller-watch.service
sudo chown -R infractl:infractl /opt/infra-controller /var/lib/infra-controller /var/log/infra-controller || true
/opt/infra-controller/venv/bin/infra-controller --once
"

View file

@ -18,7 +18,6 @@ fi
sudo mkdir -p /opt/infra-controller
sudo mkdir -p /etc/infra-controller
sudo mkdir -p /var/run/active-apps
sudo mkdir -p /var/lib/infra-controller
sudo mkdir -p /var/log/infra-controller
@ -27,13 +26,6 @@ sudo python3 -m venv /opt/infra-controller/venv
sudo /opt/infra-controller/venv/bin/pip install --upgrade pip
sudo /opt/infra-controller/venv/bin/pip install -e .
echo "Installing helper scripts..."
sudo install -d /usr/local/sbin
sudo install -m 0755 scripts/deploy-app /usr/local/sbin/deploy-app
sudo install -m 0755 scripts/sync-infra /usr/local/sbin/sync-infra
sudo install -m 0755 scripts/infra-register-stdin /usr/local/sbin/infra-register-stdin
sudo install -m 0755 scripts/infra-deregister /usr/local/sbin/infra-deregister
if [ ! -f /etc/infra-controller/config.toml ]; then
echo "Installing default configuration..."
sudo cp config/controller.toml.example /etc/infra-controller/config.toml
@ -46,16 +38,14 @@ fi
echo "Installing systemd service..."
sudo cp systemd/infra-controller.service /etc/systemd/system/
sudo cp systemd/infra-controller-once.service /etc/systemd/system/
sudo cp systemd/infra-controller.path /etc/systemd/system/
sudo cp systemd/infra-controller-watch.service /etc/systemd/system/
sudo systemctl daemon-reload
echo "Enabling infra-controller path trigger..."
sudo systemctl enable infra-controller.path
echo "Enabling infra-controller watch service..."
sudo systemctl enable infra-controller-watch.service
sudo chown -R infractl:infractl /opt/infra-controller
sudo chown -R infractl:infractl /var/lib/infra-controller
sudo chown -R infractl:infractl /var/log/infra-controller
sudo chown -R infractl:infractl /var/run/active-apps
sudo chmod 755 /var/run/active-apps
echo "Installation complete!"

View file

@ -39,5 +39,3 @@ else
echo "ERROR: deploy.sh missing or not executable" >&2
exit 1
fi
/usr/local/sbin/sync-infra "$APP_NAME" "$APP_DIR"

View file

@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="${1:-}"
if [[ -z "$APP_NAME" ]]; then
echo "usage: infra-deregister <app_name>" >&2
exit 2
fi
if ! [[ "$APP_NAME" =~ ^[A-Za-z0-9._-]+$ ]]; then
echo "invalid app name: $APP_NAME" >&2
exit 2
fi
rm -f "/var/run/active-apps/$APP_NAME.toml" "/var/run/active-apps/$APP_NAME.yml" "/var/run/active-apps/$APP_NAME.yaml"

View file

@ -1,24 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="${1:-}"
if [[ -z "$APP_NAME" ]]; then
echo "usage: infra-register-stdin <app_name>" >&2
exit 2
fi
if ! [[ "$APP_NAME" =~ ^[A-Za-z0-9._-]+$ ]]; then
echo "invalid app name: $APP_NAME" >&2
exit 2
fi
DST_DIR="/var/run/active-apps"
DST="$DST_DIR/$APP_NAME.toml"
TMP="$DST.toml.tmp"
mkdir -p "$DST_DIR"
cat > "$TMP"
mv "$TMP" "$DST"

View file

@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
APP_NAME="${1:-}"
APP_DIR="${2:-}"
if [[ -z "$APP_NAME" || -z "$APP_DIR" ]]; then
echo "usage: sync-infra <app_name> <app_dir>" >&2
exit 2
fi
if ! [[ "$APP_NAME" =~ ^[A-Za-z0-9._-]+$ ]]; then
echo "invalid app name: $APP_NAME" >&2
exit 2
fi
INFRA_FILE="$APP_DIR/.infra.toml"
if [[ -f "$INFRA_FILE" ]]; then
ssh infra@services-server infra-register-stdin "$APP_NAME" < "$INFRA_FILE"
else
ssh infra@services-server infra-deregister "$APP_NAME"
fi

View file

@ -181,20 +181,7 @@ def parse_logging_config(config: ControllerConfig, data: Any) -> None:
def apply_env_overrides(config: ControllerConfig) -> None:
"""Apply environment variable overrides to configuration."""
if val := os.getenv("ACTIVE_APPS_DIR"):
config.discovery.file_based_path = Path(val)
if val := os.getenv("SCAN_PATHS"):
config.discovery.scan_paths = [Path(p.strip()) for p in val.split(",") if p.strip()]
if val := os.getenv("DOCKER_BASE_DIR"):
config.docker.base_dir = Path(val)
if val := os.getenv("DOCKER_COMPOSE_FILE"):
config.docker.compose_file = val
if val := os.getenv("CHECK_INTERVAL"):
config.services.check_interval_seconds = int(val)
if val := os.getenv("GRACE_PERIOD_MINUTES"):
config.services.grace_period_minutes = int(val)
if val := os.getenv("LOG_LEVEL"):
config.logging.level = val
return
def load_config(config_path: str | os.PathLike[str] | None = None) -> ControllerConfig:

View file

@ -16,8 +16,8 @@ WorkingDirectory=/opt/infra-controller
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/run/active-apps /var/lib/infra-controller
ProtectHome=read-only
ReadWritePaths=/var/lib/infra-controller /var/log/infra-controller
CapabilityBoundingSet=
ExecStart=/opt/infra-controller/venv/bin/infra-controller --once

View file

@ -0,0 +1,29 @@
[Unit]
Description=Watch for .infra.* changes and run infra-controller
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=infractl
Group=infractl
EnvironmentFile=/etc/infra-controller/controller.env
Environment=PYTHONUNBUFFERED=1
WorkingDirectory=/opt/infra-controller
ExecStart=/bin/sh -lc 'inotifywait -m -r -e create,modify,delete,move --format "%w%f" /home /opt/apps | while read -r p; do case "$p" in *"/.infra."*) /opt/infra-controller/venv/bin/infra-controller --once ;; esac; done'
Restart=always
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/lib/infra-controller /var/log/infra-controller
CapabilityBoundingSet=
StandardOutput=journal
StandardError=journal
SyslogIdentifier=infra-controller
[Install]
WantedBy=multi-user.target

View file

@ -1,11 +1 @@
CONFIG_PATH=/etc/infra-controller/config.toml
ACTIVE_APPS_DIR=/var/run/active-apps
DOCKER_BASE_DIR=/opt
DOCKER_COMPOSE_FILE=docker-compose.yml
CHECK_INTERVAL=60
GRACE_PERIOD_MINUTES=15
LOG_LEVEL=INFO

View file

@ -1,11 +0,0 @@
[Unit]
Description=Run infra-controller when active app registrations change
[Path]
PathExists=/var/run/active-apps
PathModified=/var/run/active-apps
DirectoryNotEmpty=/var/run/active-apps
Unit=infra-controller-once.service
[Install]
WantedBy=multi-user.target

View file

@ -18,8 +18,8 @@ WorkingDirectory=/opt/infra-controller
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/run/active-apps /var/lib/infra-controller
ProtectHome=read-only
ReadWritePaths=/var/lib/infra-controller /var/log/infra-controller
CapabilityBoundingSet=
# Execution