Initial Commit
This commit is contained in:
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/functions.sh"
|
||||
resolve_paths
|
||||
|
||||
TEMPLATE_FILE="${INIT_DIR}/templates/compose.yaml.template"
|
||||
OUTPUT_FILE="${ROOT_DIR}/compose.yaml"
|
||||
|
||||
require_file "$TEMPLATE_FILE" "Compose template"
|
||||
require_env
|
||||
|
||||
log_info "Configuring optional services..."
|
||||
|
||||
read -r -p "Enable LiveKit RTC Stack? (Y/n) [Y]: " LIVEKIT_INPUT
|
||||
LIVEKIT_INPUT="${LIVEKIT_INPUT:-Y}"
|
||||
if [[ "$LIVEKIT_INPUT" =~ ^[Yy]$ ]]; then
|
||||
INCLUDE_LIVEKIT=true
|
||||
LIVEKIT_KEY=$(openssl rand -hex 16)
|
||||
LIVEKIT_SECRET=$(openssl rand -hex 32)
|
||||
cat >> "$ENV_FILE" <<EOF
|
||||
LIVEKIT_FQDN="rtc.${DOMAIN}"
|
||||
JWT_FQDN="jwt.${DOMAIN}"
|
||||
LIVEKIT_API_KEY="${LIVEKIT_KEY}"
|
||||
LIVEKIT_API_SECRET="${LIVEKIT_SECRET}"
|
||||
LIVEKIT_UDP_RANGE="10000-20000"
|
||||
EOF
|
||||
else
|
||||
INCLUDE_LIVEKIT=false
|
||||
fi
|
||||
|
||||
echo "Select Web Client: 1) Element 2) Cinny 3) FluffyChat 4) None"
|
||||
read -r -p "Default [1]: " WEB_APP_INPUT
|
||||
WEB_APP_INPUT="${WEB_APP_INPUT:-1}"
|
||||
case "$WEB_APP_INPUT" in
|
||||
1) INCLUDE_ELEMENT=true; INCLUDE_CINNY=false; INCLUDE_FLUFFY=false ;;
|
||||
2) INCLUDE_ELEMENT=false; INCLUDE_CINNY=true; INCLUDE_FLUFFY=false ;;
|
||||
3) INCLUDE_ELEMENT=false; INCLUDE_CINNY=false; INCLUDE_FLUFFY=true ;;
|
||||
*) INCLUDE_ELEMENT=false; INCLUDE_CINNY=false; INCLUDE_FLUFFY=false ;;
|
||||
esac
|
||||
|
||||
echo "Select Reverse Proxy: 1) Traefik 2) nginx"
|
||||
read -r -p "Default [1]: " PROXY_INPUT
|
||||
PROXY_INPUT="${PROXY_INPUT:-1}"
|
||||
case "$PROXY_INPUT" in
|
||||
1) INCLUDE_NGINX=false; INCLUDE_TRAEFIK=true ;;
|
||||
*) INCLUDE_NGINX=true; INCLUDE_TRAEFIK=false ;;
|
||||
esac
|
||||
|
||||
cp "$TEMPLATE_FILE" "$OUTPUT_FILE"
|
||||
|
||||
toggle_block() {
|
||||
[[ "$3" == "true" ]] && sed -i "/$1/d; /$2/d" "$OUTPUT_FILE" || sed -i "/$1/,/$2/d" "$OUTPUT_FILE"
|
||||
}
|
||||
|
||||
toggle_block "# \[LIVEKIT_START\]" "# \[LIVEKIT_END\]" "$INCLUDE_LIVEKIT"
|
||||
toggle_block "# \[ELEMENT_START\]" "# \[ELEMENT_END\]" "$INCLUDE_ELEMENT"
|
||||
toggle_block "# \[CINNY_START\]" "# \[CINNY_END\]" "$INCLUDE_CINNY"
|
||||
toggle_block "# \[FLUFFYCHAT_START\]" "# \[FLUFFYCHAT_END\]" "$INCLUDE_FLUFFY"
|
||||
toggle_block "# \[NGINX_START\]" "# \[NGINX_END\]" "$INCLUDE_NGINX"
|
||||
toggle_block "# \[TRAEFIK_START\]" "# \[TRAEFIK_END\]" "$INCLUDE_TRAEFIK"
|
||||
|
||||
[[ "$INCLUDE_TRAEFIK" == "true" ]] && sed -i "/# \[TRAEFIK_LABELS_START\]/d; /# \[TRAEFIK_LABELS_END\]/d" "$OUTPUT_FILE" || \
|
||||
sed -i "/# \[TRAEFIK_LABELS_START\]/,/# \[TRAEFIK_LABELS_END\]/d" "$OUTPUT_FILE"
|
||||
|
||||
log_info "Compose file generated: $OUTPUT_FILE"
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/functions.sh"
|
||||
resolve_paths
|
||||
|
||||
require_env
|
||||
require_docker
|
||||
resolve_volume_path
|
||||
|
||||
mkdir -p "${VOLUME_PATH}/synapse" "${VOLUME_PATH}/mas" "${VOLUME_PATH}/postgres"
|
||||
|
||||
log_info "Initializing PostgreSQL..."
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --wait --timeout 60 matrix-db
|
||||
|
||||
# Wait for database readiness (silent except on failure)
|
||||
for ATTEMPT in $(seq 1 30); do
|
||||
if docker compose -f "$COMPOSE_FILE" exec -T matrix-db psql -U "$PG_USER" -c "SELECT 1;" > /dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
[[ $ATTEMPT -eq 30 ]] && { log_error "Database timeout"; exit 1; }
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Database initialization SQL
|
||||
INIT_SQL=$(cat <<EOF
|
||||
DO \$\$ BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'mas') THEN
|
||||
CREATE ROLE mas WITH LOGIN PASSWORD '${PG_PASSWORD_MAS}';
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'matrix') THEN
|
||||
CREATE ROLE matrix WITH LOGIN PASSWORD '${PG_PASSWORD_MATRIX}';
|
||||
END IF;
|
||||
END \$\$;
|
||||
|
||||
SELECT CASE WHEN NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'auth')
|
||||
THEN format('CREATE DATABASE %I OWNER %I', 'auth', 'mas') ELSE NULL END AS cmd \gexec
|
||||
|
||||
SELECT CASE WHEN NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'synapse')
|
||||
THEN format('CREATE DATABASE %I OWNER %I', 'synapse', 'matrix') ELSE NULL END AS cmd \gexec
|
||||
EOF
|
||||
)
|
||||
|
||||
echo "$INIT_SQL" | docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T matrix-db psql -U "$PG_USER" -f -
|
||||
|
||||
log_info "Generating Synapse configuration..."
|
||||
docker run -it --rm --network matrix_network \
|
||||
-v "${VOLUME_PATH}/synapse:/data" \
|
||||
-e SYNAPSE_SERVER_NAME="$HOMESERVER_FQDN" \
|
||||
-e SYNAPSE_REPORT_STATS=no \
|
||||
ghcr.io/element-hq/synapse:latest generate
|
||||
|
||||
fix_ownership "${VOLUME_PATH}/synapse"
|
||||
|
||||
log_info "Generating MAS configuration..."
|
||||
docker run -it --rm --network matrix_network \
|
||||
-v "${VOLUME_PATH}/mas:/data" \
|
||||
ghcr.io/element-hq/matrix-authentication-service:latest config generate \
|
||||
| grep -v '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}' > "${VOLUME_PATH}/mas/config.yaml"
|
||||
|
||||
fix_ownership "${VOLUME_PATH}/mas"
|
||||
log_info "Configuration complete"
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/functions.sh"
|
||||
resolve_paths
|
||||
|
||||
require_env
|
||||
require_command "yq"
|
||||
require_command "openssl"
|
||||
|
||||
SYNAPSE_CFG="${VOLUME_PATH}/synapse/homeserver.yaml"
|
||||
MAS_CFG="${VOLUME_PATH}/mas/config.yaml"
|
||||
|
||||
require_file "$SYNAPSE_CFG" "Synapse config"
|
||||
require_file "$MAS_CFG" "MAS config"
|
||||
|
||||
CLIENT_ID="synapse-client"
|
||||
CLIENT_SECRET=$(openssl rand -hex 32)
|
||||
|
||||
TEMP_FILTER=$(mktemp)
|
||||
trap "rm -f $TEMP_FILTER" EXIT
|
||||
|
||||
cat > "$TEMP_FILTER" <<EOF
|
||||
.oidc.providers += [{"id": "synapse", "client_id": "${CLIENT_ID}", "client_secret": "${CLIENT_SECRET}", "scopes": ["openid", "profile", "email"], "issuer": "http://mas:8000"}]
|
||||
EOF
|
||||
|
||||
yq -y -i "$(cat "$TEMP_FILTER")" "$MAS_CFG" || { log_error "Failed to update MAS config"; exit 1; }
|
||||
|
||||
CLIENT_ID=$(yq '.oidc.providers[0].client_id' "$MAS_CFG" | tr -d '"')
|
||||
CLIENT_SECRET=$(yq '.oidc.providers[0].client_secret' "$MAS_CFG" | tr -d '"')
|
||||
|
||||
ISSUER_URL="https://${MAS_FQDN}"
|
||||
|
||||
fix_ownership "$SYNAPSE_CFG"
|
||||
|
||||
cat > "$TEMP_FILTER" <<EOF
|
||||
.oidc_providers += [{"idp_id": "mas", "idp_name": "Matrix Authentication Service", "idp_brand": "mas", "issuer": "${ISSUER_URL}", "client_id": "${CLIENT_ID}", "client_secret": "${CLIENT_SECRET}", "scopes": ["openid", "profile"], "skip_verification": false}]
|
||||
EOF
|
||||
|
||||
if ! yq '.oidc_providers' "$SYNAPSE_CFG" 2>/dev/null | grep -q "idp_id"; then
|
||||
yq -y -i "$(cat "$TEMP_FILTER")" "$SYNAPSE_CFG" || { log_error "Failed to inject OIDC config"; exit 1; }
|
||||
fi
|
||||
|
||||
if [[ -n "${LIVEKIT_API_KEY:-}" ]]; then
|
||||
JWT_URL="https://${JWT_FQDN:-jwt.${DOMAIN}}"
|
||||
if yq '.livekit.url' "$SYNAPSE_CFG" 2>/dev/null | grep -q "."; then
|
||||
yq -y -i ".livekit.url = \"$JWT_URL\"" "$SYNAPSE_CFG"
|
||||
else
|
||||
yq -y -i ".livekit.url = \"$JWT_URL\"" "$SYNAPSE_CFG"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "OIDC and LiveKit linking complete"
|
||||
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env bash
|
||||
# AMMIDS Shared Functions Library
|
||||
# Location: init/scripts/functions.sh
|
||||
# Sourced by all other scripts in this directory
|
||||
|
||||
# Prevent direct execution
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
echo "This is a library, not a script. Source it instead."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Color Codes ---
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
TITLE='\033[38;2;17;97;2m'
|
||||
NC='\033[0m'
|
||||
|
||||
# --- Path Resolution ---
|
||||
# Standardised for project structure: /init/scripts/xxx.sh
|
||||
# Sets: SCRIPT_DIR, INIT_DIR, ROOT_DIR
|
||||
resolve_paths() {
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[1]}")" && pwd)"
|
||||
INIT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
ROOT_DIR="$(dirname "$INIT_DIR")"
|
||||
export SCRIPT_DIR INIT_DIR ROOT_DIR
|
||||
}
|
||||
|
||||
# --- Logging ---
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# --- State Management (init.ini) ---
|
||||
write_state() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
local init_file="${INIT_DIR}/init.ini"
|
||||
local upper_value
|
||||
upper_value=$(echo "$value" | tr '[:lower:]' '[:upper:]')
|
||||
echo "${key}=${upper_value}" >> "$init_file"
|
||||
}
|
||||
|
||||
load_state() {
|
||||
local init_file="${INIT_DIR}/init.ini"
|
||||
if [[ -f "$init_file" ]]; then
|
||||
source "$init_file"
|
||||
else
|
||||
log_warn "State file not found at ${init_file}. Using defaults."
|
||||
fi
|
||||
}
|
||||
|
||||
clear_state() {
|
||||
local init_file="${INIT_DIR}/init.ini"
|
||||
> "$init_file"
|
||||
}
|
||||
|
||||
# --- Secrets ---
|
||||
generate_secret() {
|
||||
local length="${1:-32}"
|
||||
if command -v openssl &> /dev/null; then
|
||||
openssl rand -hex "$((length / 2))"
|
||||
elif command -v pwgen &> /dev/null; then
|
||||
pwgen -s "$length" 1
|
||||
else
|
||||
tr -dc 'A-Za-z0-9' < /dev/urandom | head -c "$length"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- File Permissions ---
|
||||
fix_ownership() {
|
||||
local target="$1"
|
||||
local uid="${2:-${USER_ID:-1000}}"
|
||||
local gid="${3:-${GROUP_ID:-1000}}"
|
||||
|
||||
if [[ -e "$target" ]] && [[ "$(stat -c '%U' "$target" 2>/dev/null)" != "$USER" ]]; then
|
||||
log_warn "Fixing ownership on $target..."
|
||||
sudo chown -R "${uid}:${gid}" "$target"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Dependency Checks ---
|
||||
require_command() {
|
||||
local cmd="$1"
|
||||
if ! command -v "$cmd" &> /dev/null; then
|
||||
log_error "Required command '${cmd}' not found. Install it and retry."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_file() {
|
||||
local file="$1"
|
||||
local description="${2:-File}"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
log_error "${description} not found at ${file}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local file="${ROOT_DIR}/.env"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
log_error ".env file not found. Run set_env.sh first."
|
||||
exit 1
|
||||
fi
|
||||
source "$file"
|
||||
}
|
||||
|
||||
require_docker() {
|
||||
require_command "docker"
|
||||
require_command "docker compose"
|
||||
}
|
||||
|
||||
# --- Volume Path Resolution ---
|
||||
resolve_volume_path() {
|
||||
VOLUME_PATH="${VOLUME_PATH:-./matrix}"
|
||||
if [[ "$VOLUME_PATH" != /* ]]; then
|
||||
VOLUME_PATH="${ROOT_DIR}/${VOLUME_PATH}"
|
||||
fi
|
||||
export VOLUME_PATH
|
||||
}
|
||||
|
||||
# Add to functions.sh
|
||||
|
||||
|
||||
quiet_echo() {
|
||||
[[ "${QUIET_MODE:-0}" == "1" ]] || echo "$1"
|
||||
}
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/functions.sh"
|
||||
resolve_paths
|
||||
|
||||
require_command "openssl" || require_command "pwgen"
|
||||
|
||||
main() {
|
||||
> "$ENV_FILE"
|
||||
|
||||
read -r -p "Base Domain (e.g. example.org) [example.org]: " DOMAIN_INPUT
|
||||
BASE_DOMAIN="${DOMAIN_INPUT:-example.org}"
|
||||
|
||||
cat >> "$ENV_FILE" <<EOF
|
||||
DOMAIN="${BASE_DOMAIN}"
|
||||
HOMESERVER_FQDN="matrix.${BASE_DOMAIN}"
|
||||
MAS_FQDN="auth.${BASE_DOMAIN}"
|
||||
APP_FQDN="app.${BASE_DOMAIN}"
|
||||
EOF
|
||||
|
||||
log_info "Base Domain set to: ${BASE_DOMAIN}"
|
||||
|
||||
prompt_var "USER_ID" "Docker UserId" "1000" "no"
|
||||
prompt_var "GROUP_ID" "Docker GroupID" "1000" "no"
|
||||
prompt_var "VOLUME_PATH" "Install directory" "./matrix" "no"
|
||||
prompt_var "COUNTRY" "Country Code (e.g. GB)" "GB" "no"
|
||||
prompt_var "PG_USER" "PostgreSQL Superuser" "postgres" "no"
|
||||
prompt_var "PG_PASSWORD" "PostgreSQL Superuser Password" "generated" "yes"
|
||||
prompt_var "PG_USER_MATRIX" "Synapse Database User" "matrix" "no"
|
||||
prompt_var "PG_DB_MATRIX" "Synapse Database Name" "synapse" "no"
|
||||
prompt_var "PG_PASSWORD_MATRIX" "Synapse Database Password" "generated" "yes"
|
||||
prompt_var "PG_USER_MAS" "MAS Database User" "mas" "no"
|
||||
prompt_var "PG_DB_MAS" "MAS Database Name" "auth" "no"
|
||||
prompt_var "PG_PASSWORD_MAS" "MAS Database Password" "generated" "yes"
|
||||
|
||||
chmod 600 "$ENV_FILE"
|
||||
|
||||
log_info "Environment file created: $ENV_FILE"
|
||||
log_warn "Add $ENV_FILE to .gitignore and backup securely"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${SCRIPT_DIR}/functions.sh"
|
||||
resolve_paths
|
||||
|
||||
WORKER_COUNT=1
|
||||
while getopts "c:" opt; do
|
||||
case $opt in
|
||||
c) WORKER_COUNT="$OPTARG" ;;
|
||||
*) echo "Usage: $0 [-c count]"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_env
|
||||
resolve_volume_path
|
||||
|
||||
TEMPLATE_COMPOSE="${INIT_DIR}/templates/worker.yaml"
|
||||
TEMPLATE_CONFIG="${INIT_DIR}/config/worker.yaml"
|
||||
TEMPLATE_LOG="${INIT_DIR}/config/worker-log.yaml"
|
||||
|
||||
require_file "$TEMPLATE_COMPOSE" "Compose template"
|
||||
require_file "$TEMPLATE_CONFIG" "Config template"
|
||||
require_file "$TEMPLATE_LOG" "Log template"
|
||||
|
||||
WORKERS_DIR="${VOLUME_PATH}/synapse/workers"
|
||||
mkdir -p "$WORKERS_DIR" "${ROOT_DIR}/.tmp"
|
||||
|
||||
TRAEFIK_ENABLED="${PROXY:-0}"
|
||||
TEMP_COMPOSE="${ROOT_DIR}/.tmp/compose_workers.yaml"
|
||||
> "$TEMP_COMPOSE"
|
||||
|
||||
for ((i=1; i<=WORKER_COUNT; i++)); do
|
||||
worker_name="synapse-worker-${i}"
|
||||
port=$((9093 + i))
|
||||
|
||||
sed -e "s/{{WORKER_NAME}}/${worker_name}/g" \
|
||||
-e "s/{{PORT}}/${port}/g" \
|
||||
-e "s/{{SERVER_NAME}}/${HOMESERVER_FQDN}/g" \
|
||||
-e "s/{{DB_USER}}/${DB_USER:-synapse}/g" \
|
||||
-e "s/{{DB_PASSWORD}}/${DB_PASSWORD:-synapse_password}/g" \
|
||||
-e "s/{{DB_NAME}}/${DB_NAME:-synapse}/g" \
|
||||
"$TEMPLATE_CONFIG" > "${WORKERS_DIR}/${worker_name}.yaml"
|
||||
|
||||
sed -e "s/{{WORKER_NAME}}/${worker_name}/g" \
|
||||
-e "s/{{MAX_BYTES}}/${LOG_MAX_BYTES:-10485760}/g" \
|
||||
-e "s/{{BACKUP_COUNT}}/${LOG_BACKUP_COUNT:-5}/g" \
|
||||
-e "s/{{LOG_LEVEL}}/${LOG_LEVEL:-INFO}/g" \
|
||||
-e "s/{{SYNAPSE_LOG_LEVEL}}/${SYNAPSE_LOG_LEVEL:-INFO}/g" \
|
||||
"$TEMPLATE_LOG" > "${WORKERS_DIR}/${worker_name}.log.config"
|
||||
|
||||
TRAEFIK_LABELS=""
|
||||
if [[ "$TRAEFIK_ENABLED" == "1" && -n "$DOMAIN" ]]; then
|
||||
TRAEFIK_LABELS=" labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.services.${worker_name}.loadbalancer.server.port=${port}
|
||||
- traefik.http.routers.synapse-worker-${worker_name}.rule=Host(\`${DOMAIN}\`) && PathPrefix(\`/_matrix\`)
|
||||
- traefik.http.routers.synapse-worker-${worker_name}.entrypoints=websecure
|
||||
- traefik.http.routers.synapse-worker-${worker_name}.service=${worker_name}
|
||||
- traefik.http.routers.synapse-worker-${worker_name}.priority=10
|
||||
"
|
||||
fi
|
||||
|
||||
sed -e "s/{{WORKER_NAME}}/${worker_name}/g" \
|
||||
-e "s/{{PORT}}/${port}/g" \
|
||||
-e "s/{{APP_TYPE}}/synapse.app.generic_worker/g" \
|
||||
-e "s/{{TRAEFIK_LABELS}}/${TRAEFIK_LABELS}/g" \
|
||||
"$TEMPLATE_COMPOSE" >> "$TEMP_COMPOSE"
|
||||
|
||||
echo "" >> "$TEMP_COMPOSE"
|
||||
done
|
||||
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
if ! grep -qE "^ synapse-worker-[0-9]+:" "$COMPOSE_FILE"; then
|
||||
cat "$TEMP_COMPOSE" >> "$COMPOSE_FILE"
|
||||
log_info "Appended ${WORKER_COUNT} worker(s) to compose.yaml"
|
||||
else
|
||||
log_warn "Some workers already exist. Manual merge required"
|
||||
cp "$TEMP_COMPOSE" "${ROOT_DIR}/.tmp/compose_workers.yaml"
|
||||
fi
|
||||
else
|
||||
log_warn "compose.yaml not found. Generated: ${TEMP_COMPOSE}"
|
||||
fi
|
||||
|
||||
rm -f "$TEMP_COMPOSE"
|
||||
log_info "Worker generation complete"
|
||||
Reference in New Issue
Block a user