Files
Oclick021 a9a758d332 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
2026-07-02 14:13:15 +03:30

289 lines
6.5 KiB
Bash

#!/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