feat: Add slcompose service orchestrator with Infisical secret injection
- Add slcompose.sh: Central orchestrator for managing all Docker services * Boot all services at startup with automated Infisical secret injection * Commands: up, down, restart, logs, logs-tail, env, env-all * Colored environment variable output (blue names, green values) - Add slcompose.service: Systemd service file for auto-boot on startup * Type=oneshot with RemainAfterExit=yes * Waits for Docker service before starting * Runs on multi-user.target - Add orchestration.md: Comprehensive documentation * Architecture and installation guide * Usage examples for all commands * Secret injection flow and troubleshooting * Performance and security notes - Update README.md and AI_CONTEXT.md * Document service orchestration architecture * Explain slcompose functionality and commands * Reference new orchestration documentation
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
BASE_DIR="/srv/docker"
|
||||
INFISICAL_TOKEN_FILE="/etc/infisical/token"
|
||||
INFISICAL_DOMAIN_FILE="/etc/infisical/domain"
|
||||
|
||||
function load_infisical() {
|
||||
if [ ! -f "$INFISICAL_TOKEN_FILE" ]; then
|
||||
echo "ERROR: Missing Infisical token at $INFISICAL_TOKEN_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export INFISICAL_TOKEN=$(cat "$INFISICAL_TOKEN_FILE")
|
||||
|
||||
if [ -f "$INFISICAL_DOMAIN_FILE" ]; then
|
||||
export INFISICAL_DOMAIN=$(cat "$INFISICAL_DOMAIN_FILE")
|
||||
fi
|
||||
}
|
||||
|
||||
function exec_with_infisical() {
|
||||
local service_name="$1"
|
||||
shift
|
||||
|
||||
infisical run \
|
||||
--token "$INFISICAL_TOKEN" \
|
||||
--env prod \
|
||||
--path="/$service_name" \
|
||||
--recursive \
|
||||
-- "$@"
|
||||
}
|
||||
|
||||
function run_service() {
|
||||
SERVICE_DIR="$1"
|
||||
shift
|
||||
|
||||
SERVICE_NAME=$(basename "$SERVICE_DIR")
|
||||
|
||||
cd "$SERVICE_DIR"
|
||||
|
||||
echo "-----------------------------------"
|
||||
echo "Booting: $SERVICE_DIR"
|
||||
|
||||
until docker info >/dev/null 2>&1; do
|
||||
echo "Waiting for Docker..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
load_infisical
|
||||
|
||||
echo "Using Infisical path: /$SERVICE_NAME"
|
||||
|
||||
exec_with_infisical "$SERVICE_NAME" docker compose "$@"
|
||||
}
|
||||
|
||||
function list_services() {
|
||||
echo "Available services:"
|
||||
echo "===================="
|
||||
for dir in "$BASE_DIR"/*; do
|
||||
if [ -f "$dir/docker-compose.yml" ]; then
|
||||
SERVICE_NAME=$(basename "$dir")
|
||||
echo " - $SERVICE_NAME"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function boot_all() {
|
||||
echo "==================================="
|
||||
echo "SilverLinux Boot Orchestrator START"
|
||||
echo "==================================="
|
||||
|
||||
load_infisical
|
||||
|
||||
for dir in "$BASE_DIR"/*; do
|
||||
if [ -f "$dir/docker-compose.yml" ]; then
|
||||
SERVICE_NAME=$(basename "$dir")
|
||||
echo "Booting: $SERVICE_NAME"
|
||||
run_service "$dir" up -d || {
|
||||
echo "FAILED: $SERVICE_NAME"
|
||||
}
|
||||
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
echo "==================================="
|
||||
echo "Boot orchestration finished"
|
||||
echo "==================================="
|
||||
}
|
||||
|
||||
function service_up() {
|
||||
SERVICE_NAME="$1"
|
||||
SERVICE_DIR="$BASE_DIR/$SERVICE_NAME"
|
||||
|
||||
if [ ! -d "$SERVICE_DIR" ] || [ ! -f "$SERVICE_DIR/docker-compose.yml" ]; then
|
||||
echo "ERROR: Service '$SERVICE_NAME' not found at $SERVICE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting service: $SERVICE_NAME"
|
||||
run_service "$SERVICE_DIR" up -d
|
||||
}
|
||||
|
||||
function service_down() {
|
||||
SERVICE_NAME="$1"
|
||||
SERVICE_DIR="$BASE_DIR/$SERVICE_NAME"
|
||||
|
||||
if [ ! -d "$SERVICE_DIR" ] || [ ! -f "$SERVICE_DIR/docker-compose.yml" ]; then
|
||||
echo "ERROR: Service '$SERVICE_NAME' not found at $SERVICE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Stopping service: $SERVICE_NAME"
|
||||
run_service "$SERVICE_DIR" down
|
||||
}
|
||||
|
||||
function service_restart() {
|
||||
SERVICE_NAME="$1"
|
||||
SERVICE_DIR="$BASE_DIR/$SERVICE_NAME"
|
||||
|
||||
if [ ! -d "$SERVICE_DIR" ] || [ ! -f "$SERVICE_DIR/docker-compose.yml" ]; then
|
||||
echo "ERROR: Service '$SERVICE_NAME' not found at $SERVICE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Restarting service: $SERVICE_NAME"
|
||||
run_service "$SERVICE_DIR" restart
|
||||
}
|
||||
|
||||
function service_logs() {
|
||||
SERVICE_NAME="$1"
|
||||
SERVICE_DIR="$BASE_DIR/$SERVICE_NAME"
|
||||
|
||||
if [ ! -d "$SERVICE_DIR" ] || [ ! -f "$SERVICE_DIR/docker-compose.yml" ]; then
|
||||
echo "ERROR: Service '$SERVICE_NAME' not found at $SERVICE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Tailing logs for: $SERVICE_NAME (Ctrl+C to exit)"
|
||||
run_service "$SERVICE_DIR" logs -f
|
||||
}
|
||||
|
||||
function service_logs_tail() {
|
||||
SERVICE_NAME="$1"
|
||||
NUM_LINES="${2:-200}"
|
||||
SERVICE_DIR="$BASE_DIR/$SERVICE_NAME"
|
||||
|
||||
if [ ! -d "$SERVICE_DIR" ] || [ ! -f "$SERVICE_DIR/docker-compose.yml" ]; then
|
||||
echo "ERROR: Service '$SERVICE_NAME' not found at $SERVICE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Last $NUM_LINES lines of logs for: $SERVICE_NAME"
|
||||
run_service "$SERVICE_DIR" logs --tail "$NUM_LINES"
|
||||
}
|
||||
|
||||
function service_env() {
|
||||
SERVICE_NAME="$1"
|
||||
SERVICE_DIR="$BASE_DIR/$SERVICE_NAME"
|
||||
|
||||
if [ ! -d "$SERVICE_DIR" ] || [ ! -f "$SERVICE_DIR/docker-compose.yml" ]; then
|
||||
echo "ERROR: Service '$SERVICE_NAME' not found at $SERVICE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
load_infisical
|
||||
|
||||
echo "========================================"
|
||||
echo "Environment Variables for: $SERVICE_NAME"
|
||||
echo "========================================"
|
||||
|
||||
exec_with_infisical "$SERVICE_NAME" env | grep -v "^_" | sort | while IFS='=' read -r name value; do
|
||||
printf "\033[34m%-50s\033[0m = \033[32m%s\033[0m\n" "$name" "$value"
|
||||
done
|
||||
}
|
||||
|
||||
function service_env_all() {
|
||||
load_infisical
|
||||
|
||||
echo "========================================"
|
||||
echo "All Services and Their Environment Variables"
|
||||
echo "========================================"
|
||||
|
||||
for dir in "$BASE_DIR"/*; do
|
||||
if [ -f "$dir/docker-compose.yml" ]; then
|
||||
SERVICE_NAME=$(basename "$dir")
|
||||
echo ""
|
||||
echo "--- $SERVICE_NAME ---"
|
||||
exec_with_infisical "$SERVICE_NAME" env | grep -v "^_" | sort | while IFS='=' read -r name value; do
|
||||
printf "\033[34m%-50s\033[0m = \033[32m%s\033[0m\n" "$name" "$value"
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function show_usage() {
|
||||
cat <<EOF
|
||||
SilverLinux Service Orchestrator
|
||||
|
||||
Usage: $0 <command> [service_name] [options]
|
||||
|
||||
Commands:
|
||||
boot Boot all services at startup
|
||||
list List all available services
|
||||
up <service> Start a service
|
||||
down <service> Stop a service
|
||||
restart <service> Restart a service
|
||||
logs <service> Tail logs for a service (Ctrl+C to exit)
|
||||
logs-tail <service> [lines] Show last N lines of logs (default: 200)
|
||||
env <service> Show injected environment variables for a service
|
||||
env-all Show injected environment variables for all services
|
||||
|
||||
Examples:
|
||||
$0 boot
|
||||
$0 list
|
||||
$0 up gitea
|
||||
$0 down gitea
|
||||
$0 restart gitea
|
||||
$0 logs gitea
|
||||
$0 logs-tail gitea
|
||||
$0 logs-tail gitea 500
|
||||
$0 env gitea
|
||||
$0 env-all
|
||||
EOF
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
boot)
|
||||
boot_all
|
||||
;;
|
||||
list)
|
||||
list_services
|
||||
;;
|
||||
up)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Service name required"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
service_up "$2"
|
||||
;;
|
||||
down)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Service name required"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
service_down "$2"
|
||||
;;
|
||||
restart)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Service name required"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
service_restart "$2"
|
||||
;;
|
||||
logs)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Service name required"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
service_logs "$2"
|
||||
;;
|
||||
logs-tail)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Service name required"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
service_logs_tail "$2" "$3"
|
||||
;;
|
||||
env)
|
||||
if [ -z "$2" ]; then
|
||||
echo "ERROR: Service name required"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
service_env "$2"
|
||||
;;
|
||||
env-all)
|
||||
service_env_all
|
||||
;;
|
||||
*)
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user