From fad8e60ec1894af3cc72e05eaaf34e1d1ce7253954370a4c58a1c5822a3d1109 Mon Sep 17 00:00:00 2001 From: Till Wegmueller Date: Mon, 17 Nov 2025 19:57:19 +0100 Subject: [PATCH] Add Debian packaging support and network configuration enhancements - Introduce Debian package build script using `cargo-deb` for orchestrator releases. - Add systemd unit file and post-installation script for automatic service setup. - Update `compose.yml` with host-only port bindings for Postgres and RabbitMQ. - Introduce NGINX-based log proxy for orchestrator logs with Traefik support. - Bump orchestrator version to 0.1.1 and update related Cargo metadata for packaging. - Add example environment file for orchestrator configuration. Signed-off-by: Till Wegmueller --- .idea/dataSources.xml | 2 +- .mise/tasks/build/deb | 15 +++++++++++ crates/orchestrator/Cargo.toml | 24 +++++++++++++++-- crates/orchestrator/packaging/debian/postinst | 20 ++++++++++++++ .../packaging/solstice-orchestrator.service | 23 ++++++++++++++++ deploy/podman/compose.yml | 20 ++++++++++++++ deploy/podman/nginx/orchestrator-logs.conf | 14 ++++++++++ examples/etc/solstice/orchestrator.env.sample | 27 +++++++++++++++++++ 8 files changed, 142 insertions(+), 3 deletions(-) create mode 100755 .mise/tasks/build/deb create mode 100644 crates/orchestrator/packaging/debian/postinst create mode 100644 crates/orchestrator/packaging/solstice-orchestrator.service create mode 100644 deploy/podman/nginx/orchestrator-logs.conf create mode 100644 examples/etc/solstice/orchestrator.env.sample diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 96021f3..e5905a9 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -5,7 +5,7 @@ postgresql true org.postgresql.Driver - jdbc:postgresql://172.18.0.5:5432/postgres + jdbc:postgresql://127.0.0.1:5432/postgres $ProjectFileDir$ diff --git a/.mise/tasks/build/deb b/.mise/tasks/build/deb new file mode 100755 index 0000000..9a62b79 --- /dev/null +++ b/.mise/tasks/build/deb @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Build Debian package for the orchestrator using cargo-deb +if ! command -v cargo-deb >/dev/null 2>&1; then + cargo install cargo-deb +fi + +# Build release binary first for reproducible asset path +cargo build -p orchestrator --release + +# Package orchestrator +cargo deb -p orchestrator --no-build + +echo "\nDebs written under target/debian/*.deb" \ No newline at end of file diff --git a/crates/orchestrator/Cargo.toml b/crates/orchestrator/Cargo.toml index 9542b32..c946ea2 100644 --- a/crates/orchestrator/Cargo.toml +++ b/crates/orchestrator/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orchestrator" -version = "0.1.0" +version = "0.1.1" edition = "2024" build = "build.rs" @@ -38,7 +38,27 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "std" dashmap = "6" async-trait = "0.1" uuid = { version = "1", features = ["v4", "serde"] } -futures-util = "0.3.31" [target.'cfg(target_os = "linux")'.dependencies] virt = { version = "0.4.3" } + +[package.metadata.deb] +name = "solstice-orchestrator" +maintainer = "Solstice CI " +section = "utils" +priority = "optional" +assets = [ + ["target/release/orchestrator", "/usr/bin/solstice-orchestrator", "755"], + ["packaging/solstice-orchestrator.service", "/lib/systemd/system/solstice-orchestrator.service", "644"], + ["../../examples/orchestrator-image-map.yaml", "/etc/solstice/orchestrator.yaml", "644"], + ["../../examples/etc/solstice/orchestrator.env.sample", "/etc/solstice/orchestrator.env", "640"], +] +depends = [ + "libvirt-daemon-system", + "libvirt-clients", + "ca-certificates", + "openssh-client", +] +recommends = ["qemu-kvm", "virtinst"] +conf-files = ["/etc/solstice/orchestrator.yaml", "/etc/solstice/orchestrator.env"] +maintainer-scripts = "packaging/debian/" diff --git a/crates/orchestrator/packaging/debian/postinst b/crates/orchestrator/packaging/debian/postinst new file mode 100644 index 0000000..fd18478 --- /dev/null +++ b/crates/orchestrator/packaging/debian/postinst @@ -0,0 +1,20 @@ +#!/bin/sh +set -e + +# Create solstice system user/group if not present +if ! id -u solstice >/dev/null 2>&1; then + adduser --system --group --no-create-home --home /nonexistent --shell /usr/sbin/nologin solstice || true +fi + +# Ensure config directory exists +mkdir -p /etc/solstice +chown root:root /etc/solstice +chmod 755 /etc/solstice + +# Reload systemd units and enable service +if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload || true + systemctl enable solstice-orchestrator.service || true +fi + +exit 0 diff --git a/crates/orchestrator/packaging/solstice-orchestrator.service b/crates/orchestrator/packaging/solstice-orchestrator.service new file mode 100644 index 0000000..a6614a7 --- /dev/null +++ b/crates/orchestrator/packaging/solstice-orchestrator.service @@ -0,0 +1,23 @@ +[Unit] +Description=Solstice CI Orchestrator +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +EnvironmentFile=-/etc/default/solstice-orchestrator +EnvironmentFile=-/etc/solstice/orchestrator.env +ExecStart=/usr/bin/solstice-orchestrator +Restart=on-failure +RestartSec=3s +User=solstice +Group=solstice +AmbientCapabilities= +NoNewPrivileges=yes +ProtectSystem=full +ProtectHome=true +PrivateTmp=true +RuntimeDirectory=solstice + +[Install] +WantedBy=multi-user.target diff --git a/deploy/podman/compose.yml b/deploy/podman/compose.yml index aa5004b..6a7afe5 100644 --- a/deploy/podman/compose.yml +++ b/deploy/podman/compose.yml @@ -77,6 +77,8 @@ services: timeout: 5s retries: 5 start_period: 10s + ports: + - "127.0.0.1:5432:5432" # expose Postgres to host only volumes: - postgres-data:/var/lib/postgresql/data:Z networks: @@ -113,6 +115,8 @@ services: timeout: 5s retries: 5 start_period: 5s + ports: + - "127.0.0.1:5672:5672" # expose AMQP to host only volumes: - rabbitmq-data:/var/lib/rabbitmq:Z networks: @@ -236,6 +240,22 @@ services: - traefik.http.routers.api.tls.certresolver=le - traefik.http.services.api.loadbalancer.server.port=8081 + orchestrator-logs-proxy: + image: docker.io/library/nginx:alpine + container_name: solstice-orchestrator-logs + restart: unless-stopped + volumes: + - ./nginx/orchestrator-logs.conf:/etc/nginx/conf.d/default.conf:ro,Z + networks: + - core + labels: + - traefik.enable=true + # Expose orchestrator HTTP (logs) running on the host via a tiny proxy + - traefik.http.routers.logs.rule=Host(`logs.${ENV}.${DOMAIN}`) + - traefik.http.routers.logs.entrypoints=websecure + - traefik.http.routers.logs.tls.certresolver=le + - traefik.http.services.logs.loadbalancer.server.port=80 + forge-integration: build: context: ../.. diff --git a/deploy/podman/nginx/orchestrator-logs.conf b/deploy/podman/nginx/orchestrator-logs.conf new file mode 100644 index 0000000..6f86183 --- /dev/null +++ b/deploy/podman/nginx/orchestrator-logs.conf @@ -0,0 +1,14 @@ +server { + listen 80; + server_name _; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 300s; + proxy_connect_timeout 5s; + proxy_pass http://host.containers.internal:8081; + } +} diff --git a/examples/etc/solstice/orchestrator.env.sample b/examples/etc/solstice/orchestrator.env.sample new file mode 100644 index 0000000..0f9aeb0 --- /dev/null +++ b/examples/etc/solstice/orchestrator.env.sample @@ -0,0 +1,27 @@ +# Solstice Orchestrator environment overrides +# Copy to /etc/solstice/orchestrator.env and edit values as needed. +# Anything unset falls back to compiled defaults or other env vars. + +# Networking +HTTP_ADDR=0.0.0.0:8081 + +# Messaging (RabbitMQ) +AMQP_URL=amqp://user:pass@mq.svc.example:5672/%2f +AMQP_EXCHANGE=solstice.jobs +AMQP_QUEUE=solstice.jobs.v1 +AMQP_ROUTING_KEY=jobrequest.v1 +AMQP_PREFETCH=16 + +# Database (optional) +# Leave empty to disable persistence +DATABASE_URL=postgres://solstice:solstice@db.svc.example:5432/solstice_prod + +# Libvirt +LIBVIRT_URI=qemu:///system +LIBVIRT_NETWORK=default + +# Scheduler +MAX_CONCURRENCY=2 + +# Telemetry +# OTEL_EXPORTER_OTLP_ENDPOINT=http://otelcol.svc.example:4317