diff --git a/Website/launch_prod.sh b/Website/launch_prod.sh deleted file mode 100755 index 0540f33..0000000 --- a/Website/launch_prod.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd "$SCRIPT_DIR" - -export SESSION_COOKIE_SECURE="1" -export INSTANCE_TLS_MODE="production" -export INSTANCE_PARENT_DOMAIN="${INSTANCE_PARENT_DOMAIN:-meine-domain}" -export INSTANCE_WILDCARD_CERT_FILE="${INSTANCE_WILDCARD_CERT_FILE:-/etc/nginx/certs/wildcard.meine-domain.crt}" -export INSTANCE_WILDCARD_KEY_FILE="${INSTANCE_WILDCARD_KEY_FILE:-/etc/nginx/certs/wildcard.meine-domain.key}" - -if [[ ! -f "$INSTANCE_WILDCARD_CERT_FILE" || ! -f "$INSTANCE_WILDCARD_KEY_FILE" ]]; then - echo "Error: Wildcard certificate missing for production mode" - echo " CERT: $INSTANCE_WILDCARD_CERT_FILE" - echo " KEY: $INSTANCE_WILDCARD_KEY_FILE" - exit 1 -fi - -echo "Launching PRODUCTION stack" -echo " SESSION_COOKIE_SECURE=$SESSION_COOKIE_SECURE" -echo " INSTANCE_TLS_MODE=$INSTANCE_TLS_MODE" -echo " INSTANCE_PARENT_DOMAIN=$INSTANCE_PARENT_DOMAIN" -echo " INSTANCE_WILDCARD_CERT_FILE=$INSTANCE_WILDCARD_CERT_FILE" -echo " INSTANCE_WILDCARD_KEY_FILE=$INSTANCE_WILDCARD_KEY_FILE" - -docker compose build website -docker compose up -d - -NGINX_SCRIPT="$SCRIPT_DIR/../nginx.sh" -if [[ -x "$NGINX_SCRIPT" ]]; then - echo "Aktualisiere Nginx Reverse Proxy..." - sudo "$NGINX_SCRIPT" apply || echo "Warnung: Nginx konnte nicht automatisch aktualisiert werden." -fi - -# Automatically sync hosts after container start -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -if [[ -x "$SCRIPT_DIR/sync_dev_hosts.sh" ]]; then - echo "Warte auf MongoDB-Verfügbarkeit..." - sleep 5 - "$SCRIPT_DIR/sync_dev_hosts.sh" || true - echo "Production Hosts werden synchronisiert (stündlich)" - - # Starte Background-Daemon für stündliche Sync - if [[ "${PROD_HOSTS_REFRESH_INTERVAL}" != "0" ]]; then - nohup bash -lc "while true; do '$SCRIPT_DIR/sync_dev_hosts.sh' >/dev/null 2>&1 || true; sleep ${PROD_HOSTS_REFRESH_INTERVAL:-3600}; done" \ - >"$SCRIPT_DIR/prod-hosts-sync.log" 2>&1 & - echo " Prod-Hosts-Sync läuft im Hintergrund (Log: $SCRIPT_DIR/prod-hosts-sync.log)" - fi -fi - -echo "Production stack is running on http://localhost:4999" -echo "Provisioning expects wildcard certificate for all subdomains." diff --git a/Website/provision_instance.sh b/Website/provision_instance.sh deleted file mode 100755 index f998d88..0000000 --- a/Website/provision_instance.sh +++ /dev/null @@ -1,765 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ACTION="create" -SCHOOL_NAME="" -SUBDOMAIN="" -REPO_URL="" -BASE_DIR="" -PARENT_DOMAIN="" -HTTPS_PORT="" -HTTP_PORT="" -TLS_MODE="development" -APP_IMAGE_TAG="latest" -LIBRARY_ENABLED="0" -WILDCARD_CERT_FILE="/etc/nginx/certs/wildcard.meine-domain.crt" -WILDCARD_KEY_FILE="/etc/nginx/certs/wildcard.meine-domain.key" -NGINX_SITES_AVAILABLE="/etc/nginx/sites-available" -NGINX_SITES_ENABLED="/etc/nginx/sites-enabled" - -RELEASE_BUNDLE_ASSET="inventarsystem-docker-bundle.tar.gz" -RELEASE_IMAGE_ASSET_PREFIX="inventarsystem-image-" - -print_kv() { - local key="$1" - local value="$2" - printf '%s=%s\n' "$key" "$value" -} - -fail() { - local message="$1" - print_kv "MESSAGE" "$message" - print_kv "ERROR" "$message" - exit 1 -} - -slugify() { - local input="$1" - input="${input,,}" - input="$(echo "$input" | sed -E 's/ä/ae/g; s/ö/oe/g; s/ü/ue/g; s/ß/ss/g')" - input="$(echo "$input" | sed -E 's/[^a-z0-9-]+/-/g; s/-+/-/g; s/^-+//; s/-+$//')" - printf '%s' "${input:0:63}" -} - -is_valid_subdomain() { - local value="$1" - [[ "$value" =~ ^[a-z0-9]([a-z0-9-]{1,61}[a-z0-9])$ ]] -} - -require_cmd() { - local cmd="$1" - command -v "$cmd" >/dev/null 2>&1 || fail "Fehlender Befehl: $cmd" -} - -is_port_in_use() { - local port="$1" - - # Running inside container namespaces cannot reliably see host listeners, - # but docker CLI can inspect host-published ports via the socket. - if docker ps --format '{{.Ports}}' | grep -Eq "(^|[,[:space:]])((0\.0\.0\.0|\[::\]):)?${port}->"; then - return 0 - fi - - if command -v ss >/dev/null 2>&1; then - ss -ltn "( sport = :$port )" 2>/dev/null | awk 'NR>1 {print $4}' | grep -q . && return 0 - fi - - return 1 -} - -next_free_port() { - local start_port="$1" - local current="$start_port" - while is_port_in_use "$current"; do - current=$((current + 1)) - done - printf '%s' "$current" -} - -write_env_file() { - local target_dir="$1" - local http_port="$2" - local https_port="$3" - local app_image_tag="$4" - - cat > "$target_dir/.docker-build.env" < 4: - continue - in_build = False - - if re.match(r"^\s{4}build:\s*$", line): - in_build = True - continue - - if re.match(r"^\s{4}image:\s*", line): - if image_set: - continue - out.append(f" image: {target_image}\n") - image_set = True - continue - - out.append(line) - -with open(compose_file, "w", encoding="utf-8") as fh: - fh.writelines(out) -PY - done -} - -install_from_release() { - local target_dir="$1" - local repo_url="$2" - local requested_tag="$3" - local tmp_dir="" - local repo_slug="" - local meta_file="" - local bundle_path="" - local image_path="" - local tag="" - local bundle_url="" - local image_url="" - - repo_slug="$(repo_slug_from_url "$repo_url")" || fail "Repository-URL nicht unterstützbar für Release-Install: $repo_url" - - tmp_dir="$(mktemp -d)" - - meta_file="$tmp_dir/release.json" - - if ! fetch_release_metadata "$repo_slug" "$requested_tag" "$meta_file"; then - fail "Release-Metadaten konnten nicht geladen werden (Repo: $repo_slug, Tag: $requested_tag)." - fi - - mapfile -t release_info < <(extract_release_info "$meta_file") - tag="${release_info[0]:-}" - bundle_url="${release_info[1]:-}" - image_url="${release_info[2]:-}" - - [ -n "$tag" ] || fail "Release-Metadaten enthalten keinen gültigen Tag." - [ -n "$bundle_url" ] || fail "Release-Asset fehlt: $RELEASE_BUNDLE_ASSET" - [ -n "$image_url" ] || fail "Release-Image-Asset fehlt: ${RELEASE_IMAGE_ASSET_PREFIX}${tag}.tar.gz" - - bundle_path="$tmp_dir/$RELEASE_BUNDLE_ASSET" - image_path="$tmp_dir/${RELEASE_IMAGE_ASSET_PREFIX}${tag}.tar.gz" - - curl -fsSL "$bundle_url" -o "$bundle_path" || fail "Release-Bundle konnte nicht geladen werden." - curl -fsSL "$image_url" -o "$image_path" || fail "Release-Image konnte nicht geladen werden." - - mkdir -p "$target_dir" - tar -xzf "$bundle_path" -C "$target_dir" || fail "Release-Bundle konnte nicht entpackt werden." - docker load -i "$image_path" >/dev/null 2>&1 || fail "Docker-Image konnte nicht geladen werden." - docker tag "ghcr.io/aiirondev/legendary-octo-garbanzo:$tag" "ghcr.io/aiirondev/legendary-octo-garbanzo:latest" >/dev/null 2>&1 || true - - pin_compose_app_image "$target_dir" "$tag" - rm -rf "$tmp_dir" >/dev/null 2>&1 || true - print_kv "APP_IMAGE_TAG" "$tag" -} - -ensure_requested_app_image() { - local app_image_tag="$1" - local app_image="ghcr.io/aiirondev/legendary-octo-garbanzo:$app_image_tag" - - if docker image inspect "$app_image" >/dev/null 2>&1; then - return 0 - fi - - if ! docker pull "$app_image" >/dev/null 2>&1; then - return 1 - fi - - return 0 -} - -set_library_enabled() { - local instance_dir="$1" - local enabled="$2" - local cfg="$instance_dir/config.json" - [ -f "$cfg" ] || return 0 - - python3 - <<'PY' "$cfg" "$enabled" -import json -import sys - -cfg_path = sys.argv[1] -enabled = sys.argv[2] == "1" - -with open(cfg_path, "r", encoding="utf-8") as fh: - data = json.load(fh) - -modules = data.get("modules") -if not isinstance(modules, dict): - modules = {} - data["modules"] = modules - -library = modules.get("library") -if not isinstance(library, dict): - library = {} - modules["library"] = library - -library["enabled"] = enabled - -with open(cfg_path, "w", encoding="utf-8") as fh: - json.dump(data, fh, indent=2, ensure_ascii=False) - fh.write("\n") -PY -} - -normalize_instance_compose() { - local compose_file="" - - for compose_file in "docker-compose.yml" "docker-compose-multitenant.yml"; do - [ -f "$compose_file" ] || continue - - python3 - <<'PY' "$compose_file" -from pathlib import Path -import sys - -path = Path(sys.argv[1]) -content = path.read_text(encoding="utf-8") -lines = content.splitlines() - -out = [] -in_nginx = False -in_ports = False -ports_indent = "" -in_app = False -seen_app_image = False -i = 0 - -while i < len(lines): - line = lines[i] - stripped = line.strip() - indent = len(line) - len(line.lstrip(" ")) - - if stripped.startswith("nginx:") and indent == 2: - in_nginx = True - in_ports = False - out.append(line) - i += 1 - continue - - if indent == 2 and stripped.endswith(":"): - in_app = stripped.startswith("app:") - seen_app_image = False - - if in_nginx and indent == 2 and stripped.endswith(":") and not stripped.startswith("nginx:"): - in_nginx = False - in_ports = False - - if stripped.startswith("container_name:") and indent == 4: - i += 1 - continue - - if in_app and indent == 4 and stripped.startswith("image:"): - if seen_app_image: - i += 1 - continue - seen_app_image = True - - if in_nginx and stripped.startswith("ports:") and indent == 4: - out.append(line) - out.append(" - \"${INVENTAR_HTTP_PORT:-80}:80\"") - out.append(" - \"${INVENTAR_HTTPS_PORT:-443}:443\"") - i += 1 - in_ports = True - ports_indent = " " - while i < len(lines): - nxt = lines[i] - nxt_stripped = nxt.strip() - nxt_indent = len(nxt) - len(nxt.lstrip(" ")) - if nxt_stripped.startswith("-") and nxt_indent >= len(ports_indent): - i += 1 - continue - break - continue - - out.append(line) - i += 1 - -normalized = "\n".join(out) -if content.endswith("\n"): - normalized += "\n" - -if normalized != content: - path.write_text(normalized, encoding="utf-8") -PY - done -} - -run_instance_start() { - local start_output - local retry_output - local update_output - local compose_file - local has_redis=0 - - compose_file="$(preferred_compose_file)" - if [ -f "$compose_file" ] && grep -Eq '^\s{2}redis:\s*$' "$compose_file"; then - has_redis=1 - fi - - stack_is_running() { - local running_services - running_services="$(docker compose -f "$compose_file" --env-file .docker-build.env ps --status running --services 2>/dev/null || true)" - printf '%s\n' "$running_services" | grep -Fxq app || return 1 - printf '%s\n' "$running_services" | grep -Fxq nginx || return 1 - printf '%s\n' "$running_services" | grep -Fxq mongodb || return 1 - if [ "$has_redis" = "1" ]; then - printf '%s\n' "$running_services" | grep -Fxq redis || return 1 - fi - return 0 - } - - if [ "$compose_file" = "docker-compose-multitenant.yml" ]; then - if start_output="$(docker compose -f "$compose_file" --env-file .docker-build.env up -d --remove-orphans 2>&1)"; then - print_kv "MESSAGE" "Instanz gestartet (Inventarsystem Multiinstancing aktiv)." - return 0 - fi - - if stack_is_running; then - print_kv "MESSAGE" "Instanz gestartet (Multiinstancing läuft, Healthcheck im Startskript war nicht erreichbar)." - return 0 - fi - - if printf '%s' "$start_output" | grep -qi "local app image not found"; then - if [ ! -x ./update.sh ]; then - fail "Multiinstancing-Start fehlgeschlagen und update.sh fehlt. Letzte Meldung: $(printf '%s' "$start_output" | tail -n1)" - fi - - if ! update_output="$(bash ./update.sh 2>&1)"; then - if stack_is_running; then - print_kv "MESSAGE" "Instanz gestartet (update.sh meldete Healthcheck-Fehler, Multiinstancing-Dienste laufen)." - return 0 - fi - fail "update.sh fehlgeschlagen: $(printf '%s' "$update_output" | tail -n1)" - fi - - if retry_output="$(docker compose -f "$compose_file" --env-file .docker-build.env up -d --remove-orphans 2>&1)"; then - print_kv "MESSAGE" "Instanz gestartet (Multiinstancing-Image automatisch per update.sh geladen)." - return 0 - fi - - fail "Multiinstancing-Start nach update.sh fehlgeschlagen: $(printf '%s' "$retry_output" | tail -n1)" - fi - - fail "Multiinstancing-Start fehlgeschlagen: $(printf '%s' "$start_output" | tail -n1)" - fi - - if start_output="$(INVENTAR_SETUP_CRON=0 INVENTAR_HTTP_PORT="$HTTP_PORT" INVENTAR_HTTPS_PORT="$HTTPS_PORT" bash ./start.sh --no-cron 2>&1)"; then - return 0 - fi - - if stack_is_running; then - print_kv "MESSAGE" "Instanz gestartet (Healthcheck im Startskript war nicht erreichbar, Dienste laufen)." - return 0 - fi - - if printf '%s' "$start_output" | grep -qi "local app image not found"; then - if [ ! -x ./update.sh ]; then - fail "start.sh fehlgeschlagen und update.sh fehlt. Letzte Meldung: $(printf '%s' "$start_output" | tail -n1)" - fi - - if ! update_output="$(bash ./update.sh 2>&1)"; then - if stack_is_running; then - print_kv "MESSAGE" "Instanz gestartet (update.sh meldete Healthcheck-Fehler, Dienste laufen)." - return 0 - fi - fail "update.sh fehlgeschlagen: $(printf '%s' "$update_output" | tail -n1)" - fi - - if retry_output="$(INVENTAR_SETUP_CRON=0 INVENTAR_HTTP_PORT="$HTTP_PORT" INVENTAR_HTTPS_PORT="$HTTPS_PORT" bash ./start.sh --no-cron 2>&1)"; then - print_kv "MESSAGE" "Instanz gestartet (Image automatisch per update.sh geladen)." - return 0 - fi - - fail "Start nach update.sh fehlgeschlagen: $(printf '%s' "$retry_output" | tail -n1)" - fi - - fail "start.sh fehlgeschlagen: $(printf '%s' "$start_output" | tail -n1)" -} - -setup_or_update_repo() { - local target_dir="$1" - local repo_url="$2" - local app_image_tag="$3" - - if [ -f "$target_dir/start.sh" ]; then - # Existing installation: keep update flow inside Inventarsystem tooling. - if [ "$app_image_tag" = "latest" ] && [ -x "$target_dir/update.sh" ]; then - (cd "$target_dir" && bash ./update.sh >/dev/null 2>&1 || true) - fi - return 0 - fi - - if [ -d "$target_dir" ] && [ "$(find "$target_dir" -mindepth 1 -maxdepth 1 | wc -l)" -gt 0 ]; then - fail "Zielverzeichnis ist nicht leer: $target_dir" - fi - - install_from_release "$target_dir" "$repo_url" "$app_image_tag" -} - -write_nginx_site() { - local subdomain="$1" - local full_domain="$2" - local https_port="$3" - local cert_file="" - local key_file="" - local cert_dir="/etc/nginx/certs" - local site_name="inventarsystem-${subdomain}.conf" - local avail_file="$NGINX_SITES_AVAILABLE/$site_name" - local enabled_file="$NGINX_SITES_ENABLED/$site_name" - - if [ ! -d "$NGINX_SITES_AVAILABLE" ] || [ ! -d "$NGINX_SITES_ENABLED" ]; then - print_kv "NGINX_STATUS" "skipped" - print_kv "MESSAGE" "Instanz gestartet. Nginx-Verzeichnisse nicht gefunden, Reverse-Proxy manuell anlegen." - return 0 - fi - - if [ ! -w "$NGINX_SITES_AVAILABLE" ] || [ ! -w "$NGINX_SITES_ENABLED" ]; then - print_kv "NGINX_STATUS" "manual_required" - print_kv "MESSAGE" "Instanz gestartet. Keine Schreibrechte auf Nginx-Konfiguration, bitte als root/sudo ausführen." - return 0 - fi - - if [ "$TLS_MODE" = "production" ]; then - cert_file="$WILDCARD_CERT_FILE" - key_file="$WILDCARD_KEY_FILE" - - if [ ! -f "$cert_file" ] || [ ! -f "$key_file" ]; then - print_kv "NGINX_STATUS" "error" - print_kv "MESSAGE" "Produktivmodus aktiv, aber Wildcard-Zertifikat fehlt: $cert_file / $key_file" - return 0 - fi - else - cert_file="$cert_dir/$full_domain.crt" - key_file="$cert_dir/$full_domain.key" - - if [ ! -f "$cert_file" ] || [ ! -f "$key_file" ]; then - if ! command -v openssl >/dev/null 2>&1; then - print_kv "NGINX_STATUS" "manual_required" - print_kv "MESSAGE" "Instanz gestartet. openssl fehlt für Development-Zertifikat, Zertifikat bitte manuell anlegen." - return 0 - fi - - if [ ! -d "$cert_dir" ] || [ ! -w "$cert_dir" ]; then - print_kv "NGINX_STATUS" "manual_required" - print_kv "MESSAGE" "Instanz gestartet. Keine Schreibrechte auf $cert_dir für Development-Zertifikat." - return 0 - fi - - if ! openssl req -x509 -nodes -newkey rsa:2048 -sha256 \ - -days 825 \ - -keyout "$key_file" \ - -out "$cert_file" \ - -subj "/CN=$full_domain" \ - -addext "subjectAltName=DNS:$full_domain" >/dev/null 2>&1; then - openssl req -x509 -nodes -newkey rsa:2048 -sha256 \ - -days 825 \ - -keyout "$key_file" \ - -out "$cert_file" \ - -subj "/CN=$full_domain" >/dev/null 2>&1 || { - print_kv "NGINX_STATUS" "manual_required" - print_kv "MESSAGE" "Instanz gestartet. Development-Zertifikat konnte nicht erstellt werden." - return 0 - } - fi - - chmod 600 "$key_file" 2>/dev/null || true - chmod 644 "$cert_file" 2>/dev/null || true - fi - fi - - cat > "$avail_file" </dev/null 2>&1; then - print_kv "NGINX_STATUS" "manual_required" - print_kv "MESSAGE" "Instanz gestartet. Nginx-Site wurde geschrieben, Reload bitte auf dem Host ausführen." - return 0 - fi - - if nginx -t >/dev/null 2>&1; then - nginx -s reload >/dev/null 2>&1 || true - print_kv "NGINX_STATUS" "ok" - else - print_kv "NGINX_STATUS" "error" - print_kv "MESSAGE" "Instanz gestartet, aber nginx -t ist fehlgeschlagen." - return 0 - fi -} - -while [ "$#" -gt 0 ]; do - case "$1" in - --action) - ACTION="${2:-}" - shift 2 - ;; - --school-name) - SCHOOL_NAME="${2:-}" - shift 2 - ;; - --subdomain) - SUBDOMAIN="${2:-}" - shift 2 - ;; - --repo) - REPO_URL="${2:-}" - shift 2 - ;; - --base-dir) - BASE_DIR="${2:-}" - shift 2 - ;; - --domain) - PARENT_DOMAIN="${2:-}" - shift 2 - ;; - --https-port) - HTTPS_PORT="${2:-}" - shift 2 - ;; - --http-port) - HTTP_PORT="${2:-}" - shift 2 - ;; - --tls-mode) - TLS_MODE="${2:-}" - shift 2 - ;; - --wildcard-cert-file) - WILDCARD_CERT_FILE="${2:-}" - shift 2 - ;; - --wildcard-key-file) - WILDCARD_KEY_FILE="${2:-}" - shift 2 - ;; - --app-image-tag) - APP_IMAGE_TAG="${2:-latest}" - shift 2 - ;; - --library-enabled) - LIBRARY_ENABLED="${2:-0}" - shift 2 - ;; - *) - fail "Unbekannter Parameter: $1" - ;; - esac -done - -[ -n "$REPO_URL" ] || fail "Repository-URL fehlt" -[ -n "$BASE_DIR" ] || fail "Basisverzeichnis fehlt" -[ -n "$PARENT_DOMAIN" ] || fail "Parent-Domain fehlt" - -if [ -z "$SUBDOMAIN" ]; then - SUBDOMAIN="$(slugify "$SCHOOL_NAME")" -else - SUBDOMAIN="$(slugify "$SUBDOMAIN")" -fi - -is_valid_subdomain "$SUBDOMAIN" || fail "Ungueltige Subdomain: $SUBDOMAIN" - -INSTANCE_DIR="$BASE_DIR/$SUBDOMAIN" -FULL_DOMAIN="$SUBDOMAIN.$PARENT_DOMAIN" - -require_cmd docker -require_cmd bash -require_cmd curl -require_cmd tar -require_cmd python3 - -mkdir -p "$BASE_DIR" - -if [ -z "$HTTPS_PORT" ]; then - HTTPS_PORT="$(next_free_port 15443)" -fi - -if [ -z "$HTTP_PORT" ]; then - HTTP_PORT="$(next_free_port 15080)" -fi - -if [ "$ACTION" = "create" ] || [ "$ACTION" = "start" ]; then - setup_or_update_repo "$INSTANCE_DIR" "$REPO_URL" "$APP_IMAGE_TAG" - - [ -f "$INSTANCE_DIR/start.sh" ] || fail "start.sh im Zielrepository nicht gefunden: $INSTANCE_DIR" - - if ! ensure_requested_app_image "$APP_IMAGE_TAG"; then - fail "App-Image konnte nicht geladen werden: ghcr.io/aiirondev/legendary-octo-garbanzo:$APP_IMAGE_TAG" - fi - - write_env_file "$INSTANCE_DIR" "$HTTP_PORT" "$HTTPS_PORT" "$APP_IMAGE_TAG" - set_library_enabled "$INSTANCE_DIR" "$LIBRARY_ENABLED" - - cd "$INSTANCE_DIR" - normalize_instance_compose - run_instance_start - - write_nginx_site "$SUBDOMAIN" "$FULL_DOMAIN" "$HTTPS_PORT" - - print_kv "SUBDOMAIN" "$SUBDOMAIN" - print_kv "DOMAIN" "$FULL_DOMAIN" - print_kv "HTTPS_PORT" "$HTTPS_PORT" - print_kv "HTTP_PORT" "$HTTP_PORT" - print_kv "APP_IMAGE_TAG" "$APP_IMAGE_TAG" - print_kv "LIBRARY_ENABLED" "$LIBRARY_ENABLED" - print_kv "INSTANCE_DIR" "$INSTANCE_DIR" - exit 0 -fi - -fail "Nicht unterstuetzte Action: $ACTION" diff --git a/setup-first-install.sh b/setup-first-install.sh deleted file mode 100755 index bdaf28d..0000000 --- a/setup-first-install.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -RUN_START=1 -RUN_NGINX=1 -RUN_HOSTS_SYNC=1 -RUN_AUTOSTART=1 - -usage() { - cat <<'EOF' -Usage: sudo ./setup-first-install.sh [options] - -Options: - --skip-start Skip stack start via gitea.sh - --skip-nginx Skip nginx apply via nginx.sh - --skip-hosts-sync Skip installation of invario-hosts-sync.service - --skip-autostart Skip installation of invario-stack-autostart.service - -h, --help Show this help - -Default behavior: - 1) Start stack - 2) Apply nginx - 3) Install hosts-sync service - 4) Install stack-autostart service -EOF -} - -while [[ $# -gt 0 ]]; do - case "$1" in - --skip-start) - RUN_START=0 - shift - ;; - --skip-nginx) - RUN_NGINX=0 - shift - ;; - --skip-hosts-sync) - RUN_HOSTS_SYNC=0 - shift - ;; - --skip-autostart) - RUN_AUTOSTART=0 - shift - ;; - -h|--help) - usage - exit 0 - ;; - *) - echo "Unknown option: $1" - usage - exit 1 - ;; - esac -done - -if [[ "${EUID}" -ne 0 ]]; then - echo "This script must be run as root. Use: sudo $0" - exit 1 -fi - -require_script() { - local file="$1" - if [[ ! -f "$file" ]]; then - echo "Missing required file: $file" - exit 1 - fi - if [[ ! -x "$file" ]]; then - chmod +x "$file" - fi -} - -require_script "$SCRIPT_DIR/gitea.sh" -require_script "$SCRIPT_DIR/nginx.sh" -require_script "$SCRIPT_DIR/setup-hosts-sync.sh" -require_script "$SCRIPT_DIR/setup-stack-autostart.sh" - -echo "Running first installation setup in: $SCRIPT_DIR" - -action_or_skip() { - local flag="$1" - local title="$2" - shift 2 - - if [[ "$flag" -eq 1 ]]; then - echo "[RUN ] $title" - "$@" - else - echo "[SKIP] $title" - fi -} - -action_or_skip "$RUN_START" "Start stack (gitea.sh start)" "$SCRIPT_DIR/gitea.sh" start -action_or_skip "$RUN_NGINX" "Apply nginx (nginx.sh apply)" "$SCRIPT_DIR/nginx.sh" apply -action_or_skip "$RUN_HOSTS_SYNC" "Install hosts-sync service" "$SCRIPT_DIR/setup-hosts-sync.sh" -action_or_skip "$RUN_AUTOSTART" "Install stack-autostart service" "$SCRIPT_DIR/setup-stack-autostart.sh" - -echo -echo "First installation setup completed." -echo "Service status checks:" -echo " systemctl status invario-hosts-sync" -echo " systemctl status invario-stack-autostart" -echo "Stack status:" -echo " $SCRIPT_DIR/gitea.sh status"