Add Gitea SSH setup script and integrate Gitea into partnership/failover
Partnership/gitea_ssh_setup.sh: generates ed25519 keypair, registers public key with Gitea API (POST /api/v1/user/keys), tests SSH connection, writes ~/.ssh/config entry. Idempotent — skips steps already done. --force regenerates and re-registers. Resolves Gitea endpoint from container IP first, falls back to GITEA_DOMAIN. common.sh: alias HOST*_GITEA_API_TOKEN → GITEA_API_TOKEN in detect_hosts(). Add to detect_hosts() doc comment. master.conf: add GITEA_HTTP_PORT=3000 for API endpoint construction. host1.conf: add HOST1_GITEA_API_TOKEN (fill in from Gitea Settings → Applications). Add my-Gitea.xml to HOST1_PARTNERSHIP_AUTH_STACK — onboard pushes it to HOST2. host2.conf: add Gitea to FALLBACK_HOST2_COVERS_HOST1_TIER1 — starts immediately when HOST1 goes down, making the source of truth reachable independently of HOST1's auth stack.
This commit is contained in:
Executable
+469
@@ -0,0 +1,469 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ==============================================================================================
|
||||||
|
# ============================= Gitea SSH Setup ================================================
|
||||||
|
# ==============================================================================================
|
||||||
|
#
|
||||||
|
# PURPOSE
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
# Generates an SSH keypair for Gitea authentication and registers the public
|
||||||
|
# key with Gitea via the API. Run after the Gitea container is up — typically
|
||||||
|
# called during onboard setup or when re-keying a server.
|
||||||
|
#
|
||||||
|
# Idempotent: skips key generation if key already exists and skips registration
|
||||||
|
# if the same public key is already registered in Gitea. Use --force to
|
||||||
|
# regenerate and re-register.
|
||||||
|
#
|
||||||
|
# ==============================================================================================
|
||||||
|
# OPERATIONAL MODEL
|
||||||
|
# ==============================================================================================
|
||||||
|
#
|
||||||
|
# 1. Resolve Gitea API endpoint
|
||||||
|
# Container running locally → use container IP + GITEA_HTTP_PORT
|
||||||
|
# Container not local → fall back to GITEA_DOMAIN
|
||||||
|
#
|
||||||
|
# 2. Validate GITEA_API_TOKEN is set
|
||||||
|
# Token needed for API calls — create once in Gitea UI (see CONFIGURATION)
|
||||||
|
#
|
||||||
|
# 3. Generate SSH keypair (ed25519) at GITEA_SSH_KEY
|
||||||
|
# Skipped if key already exists — use --force to regenerate
|
||||||
|
#
|
||||||
|
# 4. Check if public key already registered in Gitea
|
||||||
|
# Compares fingerprints — skips POST if already registered
|
||||||
|
#
|
||||||
|
# 5. Register public key via POST /api/v1/user/keys
|
||||||
|
# Title: "unraid-{host_id}" (e.g. unraid-host1)
|
||||||
|
#
|
||||||
|
# 6. Test SSH connection to Gitea
|
||||||
|
# ssh -i GITEA_SSH_KEY -p SSH_PORT git@<gitea_host>
|
||||||
|
# Success confirms key is accepted and auth works end-to-end
|
||||||
|
#
|
||||||
|
# 7. Write ~/.ssh/config Host entry for gitea
|
||||||
|
# Skipped if entry already exists — use --force to overwrite
|
||||||
|
#
|
||||||
|
# ==============================================================================================
|
||||||
|
# OPERATIONAL SAFEGUARDS
|
||||||
|
# ==============================================================================================
|
||||||
|
#
|
||||||
|
# Root Required
|
||||||
|
# ssh-keygen and ~/.ssh/ operations require consistent permissions.
|
||||||
|
#
|
||||||
|
# Single Instance Lock
|
||||||
|
# acquire_lock prevents concurrent runs.
|
||||||
|
#
|
||||||
|
# Token Validated Before Any API Call
|
||||||
|
# If HOST*_GITEA_API_TOKEN is empty, exits with a clear message pointing to
|
||||||
|
# Gitea Settings → Applications → Generate Token (scope: write:user).
|
||||||
|
#
|
||||||
|
# Key Never Clobbered Without --force
|
||||||
|
# Existing key at GITEA_SSH_KEY is left untouched unless --force is passed.
|
||||||
|
# Prevents accidentally invalidating working auth.
|
||||||
|
#
|
||||||
|
# Duplicate Registration Safe
|
||||||
|
# Checks existing keys before POST — will not create duplicate entries in Gitea.
|
||||||
|
#
|
||||||
|
# ==============================================================================================
|
||||||
|
# CONFIGURATION
|
||||||
|
# ==============================================================================================
|
||||||
|
#
|
||||||
|
# host*.conf
|
||||||
|
#
|
||||||
|
# HOST*_GITEA_API_TOKEN
|
||||||
|
# Personal access token for the Gitea user who owns the repository.
|
||||||
|
# Create in Gitea: Settings → Applications → Generate Token → scope: write:user
|
||||||
|
# Aliased by detect_hosts() → GITEA_API_TOKEN.
|
||||||
|
#
|
||||||
|
# master.conf
|
||||||
|
#
|
||||||
|
# GITEA_CONTAINER Container name for local IP detection (default: "Gitea")
|
||||||
|
# GITEA_DOMAIN Domain fallback if container is remote or not running
|
||||||
|
# GITEA_SSH_KEY Path for the SSH keypair (default: /root/.ssh/unraid_gitea)
|
||||||
|
# SSH_PORT Gitea SSH port (default: 221)
|
||||||
|
# GITEA_HTTP_PORT Gitea API port (default: 3000)
|
||||||
|
#
|
||||||
|
# ==============================================================================================
|
||||||
|
# STATE FILES
|
||||||
|
# ==============================================================================================
|
||||||
|
#
|
||||||
|
# ~/.ssh/config Updated with Host entry for gitea on successful setup
|
||||||
|
# GITEA_SSH_KEY Private key (permissions: 600)
|
||||||
|
# GITEA_SSH_KEY.pub Public key — registered with Gitea
|
||||||
|
#
|
||||||
|
# ==============================================================================================
|
||||||
|
# RUNTIME MODES
|
||||||
|
# ==============================================================================================
|
||||||
|
#
|
||||||
|
# gitea_ssh_setup.sh
|
||||||
|
# Generate key if missing, register with Gitea, test connection.
|
||||||
|
#
|
||||||
|
# gitea_ssh_setup.sh --force
|
||||||
|
# Regenerate key and re-register even if already set up.
|
||||||
|
#
|
||||||
|
# gitea_ssh_setup.sh --status
|
||||||
|
# Show key state, fingerprint, registration status, SSH test. No changes.
|
||||||
|
#
|
||||||
|
# gitea_ssh_setup.sh --dry-run
|
||||||
|
# Show what would be done without generating, registering, or writing files.
|
||||||
|
#
|
||||||
|
# gitea_ssh_setup.sh --log
|
||||||
|
# Verbose output for each step.
|
||||||
|
#
|
||||||
|
# ==============================================================================================
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SCRIPTS_ROOT="$SCRIPT_DIR/.."
|
||||||
|
|
||||||
|
source "$SCRIPTS_ROOT/load_config.sh"
|
||||||
|
|
||||||
|
# ── Parse --force before parse_args ───────────────────────────────────────────────────────────
|
||||||
|
FORCE=false
|
||||||
|
FILTERED_ARGS=()
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--force) FORCE=true ;;
|
||||||
|
*) FILTERED_ARGS+=("$arg") ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
parse_args "${FILTERED_ARGS[@]}"
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ Setup ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
if [[ "$EUID" -ne 0 ]]; then
|
||||||
|
error "Must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate_unraid_cmd \
|
||||||
|
"/usr/local/emhttp/plugins/dynamix/scripts/notify" \
|
||||||
|
"" "" \
|
||||||
|
"unRAID notify script" || warn "unRAID notify script not found — native notifications disabled"
|
||||||
|
|
||||||
|
acquire_lock
|
||||||
|
|
||||||
|
detect_hosts
|
||||||
|
|
||||||
|
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made"
|
||||||
|
[[ "$FORCE" == true ]] && warn "FORCE mode — existing key and registration will be replaced"
|
||||||
|
|
||||||
|
log "Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||||
|
log "SSH key: $GITEA_SSH_KEY"
|
||||||
|
log "SSH port: $SSH_PORT"
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ Resolve Gitea API Endpoint ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━ $ICON_GEAR Gitea API Endpoint ━━━"
|
||||||
|
|
||||||
|
GITEA_HOST=""
|
||||||
|
GITEA_API=""
|
||||||
|
|
||||||
|
# Try local container first
|
||||||
|
CONTAINER_IP=$(docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
|
||||||
|
"$GITEA_CONTAINER" 2>/dev/null | awk 'NF{print $1; exit}')
|
||||||
|
|
||||||
|
if [[ -n "$CONTAINER_IP" ]]; then
|
||||||
|
GITEA_HOST="$CONTAINER_IP"
|
||||||
|
GITEA_API="http://${CONTAINER_IP}:${GITEA_HTTP_PORT}/api/v1"
|
||||||
|
log "Gitea container running locally: $CONTAINER_IP:$GITEA_HTTP_PORT"
|
||||||
|
elif [[ -n "$GITEA_DOMAIN" ]]; then
|
||||||
|
GITEA_HOST="$GITEA_DOMAIN"
|
||||||
|
GITEA_API="https://${GITEA_DOMAIN}/api/v1"
|
||||||
|
warn "Gitea container not running locally — using domain: $GITEA_DOMAIN"
|
||||||
|
else
|
||||||
|
error "Cannot resolve Gitea API endpoint"
|
||||||
|
error "Gitea container ($GITEA_CONTAINER) is not running and GITEA_DOMAIN is not set in master.conf"
|
||||||
|
error "Start the Gitea container first, or set GITEA_DOMAIN"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "API endpoint: $GITEA_API"
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ Validate API Token ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━ $ICON_SHIELD API Token ━━━"
|
||||||
|
|
||||||
|
# Alias: detect_hosts() maps HOST*_GITEA_API_TOKEN → GITEA_API_TOKEN
|
||||||
|
if [[ -z "${GITEA_API_TOKEN:-}" ]]; then
|
||||||
|
error "HOST${MY_ID#HOST}_GITEA_API_TOKEN is not set in host${MY_ID#HOST}.conf"
|
||||||
|
error ""
|
||||||
|
error "Create a token in Gitea:"
|
||||||
|
error " 1. Log into Gitea"
|
||||||
|
error " 2. Top-right profile → Settings → Applications"
|
||||||
|
error " 3. Generate New Token → name: unraid-setup → scope: write:user"
|
||||||
|
error " 4. Copy the token (shown once) → paste into HOST${MY_ID#HOST}_GITEA_API_TOKEN in host${MY_ID#HOST}.conf"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test token against the API
|
||||||
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
|
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||||
|
"$GITEA_API/user" 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ "$HTTP_CODE" == "200" ]]; then
|
||||||
|
log "API token valid ✅"
|
||||||
|
elif [[ "$HTTP_CODE" == "401" ]]; then
|
||||||
|
error "API token rejected (HTTP 401) — token may be expired or have wrong scope"
|
||||||
|
error "Regenerate the token in Gitea: Settings → Applications → Generate Token → scope: write:user"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
error "Gitea API not reachable (HTTP $HTTP_CODE) at $GITEA_API"
|
||||||
|
error "Check that the Gitea container is healthy and the port is correct (GITEA_HTTP_PORT=$GITEA_HTTP_PORT)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Status mode exits here after full state display ───────────────────────────────────────────
|
||||||
|
if [[ "$SHOW_STATUS" == true ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━"
|
||||||
|
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||||
|
echo "$ICON_GEAR API endpoint: $GITEA_API"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ -f "${GITEA_SSH_KEY}.pub" ]]; then
|
||||||
|
FINGERPRINT=$(ssh-keygen -lf "${GITEA_SSH_KEY}.pub" 2>/dev/null | awk '{print $2}')
|
||||||
|
echo " $ICON_GEAR Key file: ${GITEA_SSH_KEY}.pub"
|
||||||
|
echo " $ICON_GEAR Fingerprint: $FINGERPRINT"
|
||||||
|
|
||||||
|
# Check registration
|
||||||
|
REGISTERED_KEYS=$(curl -s \
|
||||||
|
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||||
|
"$GITEA_API/user/keys" 2>/dev/null)
|
||||||
|
LOCAL_PUB=$(awk '{print $1" "$2}' "${GITEA_SSH_KEY}.pub")
|
||||||
|
if echo "$REGISTERED_KEYS" | grep -qF "$LOCAL_PUB"; then
|
||||||
|
echo " $ICON_GEAR Registered: YES ✅"
|
||||||
|
else
|
||||||
|
echo " $ICON_GEAR Registered: NO — run without --status to register"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " $ICON_GEAR Key file: NOT FOUND at $GITEA_SSH_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SSH connection test
|
||||||
|
echo ""
|
||||||
|
SSH_OUTPUT=$(ssh -i "$GITEA_SSH_KEY" -p "$SSH_PORT" \
|
||||||
|
-o StrictHostKeyChecking=no -o ConnectTimeout=5 \
|
||||||
|
git@"$GITEA_HOST" 2>&1 || true)
|
||||||
|
if echo "$SSH_OUTPUT" | grep -q "successfully authenticated"; then
|
||||||
|
echo " $ICON_DONE SSH test: connected ✅"
|
||||||
|
echo " $ICON_INFO $(echo "$SSH_OUTPUT" | grep "successfully authenticated")"
|
||||||
|
else
|
||||||
|
echo " $ICON_ERROR SSH test: failed"
|
||||||
|
echo " $ICON_INFO $SSH_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
START=$(date +%s)
|
||||||
|
SETUP_SUCCESS=true
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ Generate SSH Keypair ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━ $ICON_GEAR SSH Keypair ━━━"
|
||||||
|
|
||||||
|
KEY_TITLE="unraid-$(echo "$MY_ID" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
KEY_COMMENT="$KEY_TITLE@$(hostname)"
|
||||||
|
|
||||||
|
if [[ -f "$GITEA_SSH_KEY" ]] && [[ "$FORCE" == false ]]; then
|
||||||
|
FINGERPRINT=$(ssh-keygen -lf "${GITEA_SSH_KEY}.pub" 2>/dev/null | awk '{print $2}')
|
||||||
|
log "Key already exists — skipping generation (use --force to regenerate)"
|
||||||
|
log " Path: $GITEA_SSH_KEY"
|
||||||
|
log " Fingerprint: $FINGERPRINT"
|
||||||
|
else
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
warn "DRY RUN — would generate ed25519 key at $GITEA_SSH_KEY"
|
||||||
|
warn "DRY RUN — key comment: $KEY_COMMENT"
|
||||||
|
else
|
||||||
|
mkdir -p "$(dirname "$GITEA_SSH_KEY")"
|
||||||
|
chmod 700 "$(dirname "$GITEA_SSH_KEY")"
|
||||||
|
|
||||||
|
# Remove existing if --force
|
||||||
|
[[ "$FORCE" == true ]] && rm -f "$GITEA_SSH_KEY" "${GITEA_SSH_KEY}.pub"
|
||||||
|
|
||||||
|
if ssh-keygen -t ed25519 -f "$GITEA_SSH_KEY" -C "$KEY_COMMENT" -N "" -q; then
|
||||||
|
chmod 600 "$GITEA_SSH_KEY"
|
||||||
|
chmod 644 "${GITEA_SSH_KEY}.pub"
|
||||||
|
FINGERPRINT=$(ssh-keygen -lf "${GITEA_SSH_KEY}.pub" 2>/dev/null | awk '{print $2}')
|
||||||
|
warn "SSH key generated ✅"
|
||||||
|
log " Path: $GITEA_SSH_KEY"
|
||||||
|
log " Fingerprint: $FINGERPRINT"
|
||||||
|
else
|
||||||
|
error "Failed to generate SSH key"
|
||||||
|
SETUP_SUCCESS=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ Register Public Key with Gitea ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━ $ICON_LINK Register Key with Gitea ━━━"
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
warn "DRY RUN — would POST public key to $GITEA_API/user/keys"
|
||||||
|
warn "DRY RUN — key title: $KEY_TITLE"
|
||||||
|
elif [[ "$SETUP_SUCCESS" == true ]]; then
|
||||||
|
LOCAL_PUB=$(cat "${GITEA_SSH_KEY}.pub")
|
||||||
|
LOCAL_PUB_SHORT=$(awk '{print $1" "$2}' "${GITEA_SSH_KEY}.pub")
|
||||||
|
|
||||||
|
# Check if already registered
|
||||||
|
REGISTERED_KEYS=$(curl -s \
|
||||||
|
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||||
|
"$GITEA_API/user/keys" 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ "$FORCE" == false ]] && echo "$REGISTERED_KEYS" | grep -qF "$LOCAL_PUB_SHORT"; then
|
||||||
|
log "Public key already registered in Gitea — skipping (use --force to re-register)"
|
||||||
|
else
|
||||||
|
# If --force, delete the existing key with this title first
|
||||||
|
if [[ "$FORCE" == true ]]; then
|
||||||
|
EXISTING_ID=$(echo "$REGISTERED_KEYS" | \
|
||||||
|
python3 -c "import json,sys; keys=json.load(sys.stdin); [print(k['id']) for k in keys if k.get('title','')=='$KEY_TITLE']" 2>/dev/null)
|
||||||
|
if [[ -n "$EXISTING_ID" ]]; then
|
||||||
|
curl -s -X DELETE \
|
||||||
|
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||||
|
"$GITEA_API/user/keys/$EXISTING_ID" >/dev/null 2>&1
|
||||||
|
log "Removed existing key '$KEY_TITLE' (ID: $EXISTING_ID)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
|
||||||
|
-H "Authorization: token $GITEA_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"key\":$(echo "$LOCAL_PUB" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().strip()))'),\"read_only\":false,\"title\":\"$KEY_TITLE\"}" \
|
||||||
|
"$GITEA_API/user/keys" 2>/dev/null)
|
||||||
|
|
||||||
|
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
|
||||||
|
BODY=$(echo "$RESPONSE" | head -n -1)
|
||||||
|
|
||||||
|
if [[ "$HTTP_CODE" == "201" ]]; then
|
||||||
|
KEY_ID=$(echo "$BODY" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])" 2>/dev/null)
|
||||||
|
warn "Public key registered in Gitea ✅ (ID: $KEY_ID, title: $KEY_TITLE)"
|
||||||
|
elif [[ "$HTTP_CODE" == "422" ]]; then
|
||||||
|
warn "Key already registered under a different title — skipping"
|
||||||
|
log "Response: $BODY"
|
||||||
|
else
|
||||||
|
error "Failed to register key (HTTP $HTTP_CODE)"
|
||||||
|
log "Response: $BODY"
|
||||||
|
SETUP_SUCCESS=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ SSH Connection Test ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━ $ICON_GEAR SSH Connection Test ━━━"
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
warn "DRY RUN — would test: ssh -i $GITEA_SSH_KEY -p $SSH_PORT git@$GITEA_HOST"
|
||||||
|
else
|
||||||
|
SSH_OUTPUT=$(ssh -i "$GITEA_SSH_KEY" -p "$SSH_PORT" \
|
||||||
|
-o StrictHostKeyChecking=no \
|
||||||
|
-o ConnectTimeout=10 \
|
||||||
|
git@"$GITEA_HOST" 2>&1 || true)
|
||||||
|
|
||||||
|
if echo "$SSH_OUTPUT" | grep -q "successfully authenticated"; then
|
||||||
|
AUTHED_AS=$(echo "$SSH_OUTPUT" | grep "successfully authenticated" | sed 's/.*authenticated as //')
|
||||||
|
warn "SSH connection successful ✅ — authenticated as $AUTHED_AS"
|
||||||
|
else
|
||||||
|
error "SSH connection test failed"
|
||||||
|
log "Output: $SSH_OUTPUT"
|
||||||
|
warn "Key may not yet be active — Gitea sometimes takes a moment to pick up new keys"
|
||||||
|
warn "Run --status in 30 seconds to recheck"
|
||||||
|
SETUP_SUCCESS=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ SSH Config Entry ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━ $ICON_GEAR SSH Config Entry ━━━"
|
||||||
|
|
||||||
|
SSH_CONFIG="$HOME/.ssh/config"
|
||||||
|
ENTRY_MARKER="Host gitea-${MY_ID,,}"
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
warn "DRY RUN — would add Host entry to $SSH_CONFIG:"
|
||||||
|
warn " Host gitea-${MY_ID,,}"
|
||||||
|
warn " HostName $GITEA_HOST"
|
||||||
|
warn " Port $SSH_PORT"
|
||||||
|
warn " User git"
|
||||||
|
warn " IdentityFile $GITEA_SSH_KEY"
|
||||||
|
elif grep -qF "$ENTRY_MARKER" "$SSH_CONFIG" 2>/dev/null && [[ "$FORCE" == false ]]; then
|
||||||
|
log "SSH config entry already exists — skipping (use --force to update)"
|
||||||
|
else
|
||||||
|
if [[ "$FORCE" == true ]]; then
|
||||||
|
# Remove old entry block if present
|
||||||
|
if grep -qF "$ENTRY_MARKER" "$SSH_CONFIG" 2>/dev/null; then
|
||||||
|
python3 - "$SSH_CONFIG" "$ENTRY_MARKER" <<'PYEOF'
|
||||||
|
import sys
|
||||||
|
path, marker = sys.argv[1], sys.argv[2]
|
||||||
|
with open(path) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
out, skip = [], False
|
||||||
|
for line in lines:
|
||||||
|
if line.strip() == marker:
|
||||||
|
skip = True
|
||||||
|
elif skip and line.startswith('Host '):
|
||||||
|
skip = False
|
||||||
|
if not skip:
|
||||||
|
out.append(line)
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.writelines(out)
|
||||||
|
PYEOF
|
||||||
|
log "Removed old SSH config entry"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$SSH_CONFIG")"
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "Host gitea-${MY_ID,,}"
|
||||||
|
echo " HostName $GITEA_HOST"
|
||||||
|
echo " Port $SSH_PORT"
|
||||||
|
echo " User git"
|
||||||
|
echo " IdentityFile $GITEA_SSH_KEY"
|
||||||
|
} >> "$SSH_CONFIG"
|
||||||
|
chmod 600 "$SSH_CONFIG"
|
||||||
|
log "SSH config entry added: Host gitea-${MY_ID,,} ✅"
|
||||||
|
fi
|
||||||
|
|
||||||
|
END=$(date +%s)
|
||||||
|
|
||||||
|
# ==============================================================================================
|
||||||
|
# ━━━ Summary ━━━
|
||||||
|
# ==============================================================================================
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━ $ICON_SUMMARY GITEA SSH SETUP SUMMARY ━━━━━"
|
||||||
|
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||||
|
echo "$ICON_GEAR Key: $GITEA_SSH_KEY"
|
||||||
|
echo "$ICON_LINK Gitea: $GITEA_HOST:$SSH_PORT"
|
||||||
|
echo "$ICON_GEAR Key title: $KEY_TITLE"
|
||||||
|
echo "$ICON_TIME Duration: $(format_duration $(( END - START )))"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
warn "DRY RUN — no changes made"
|
||||||
|
elif [[ "$SETUP_SUCCESS" == true ]]; then
|
||||||
|
echo "$ICON_DONE Status: done ✅"
|
||||||
|
echo ""
|
||||||
|
echo "Git remote push:"
|
||||||
|
echo " GIT_SSH_COMMAND='ssh -i $GITEA_SSH_KEY -p $SSH_PORT' git push"
|
||||||
|
else
|
||||||
|
echo "$ICON_ERROR Status: SETUP HAD ERRORS — check output above"
|
||||||
|
notify "Gitea SSH setup errors on $(hostname) ($MY_ID)" \
|
||||||
|
"Gitea SSH Setup" "warning"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
@@ -391,6 +391,7 @@ validate_int() {
|
|||||||
# EMBY_CONTAINER ← HOST*_EMBY_CONTAINER
|
# EMBY_CONTAINER ← HOST*_EMBY_CONTAINER
|
||||||
# EMBY_URL ← HOST*_EMBY_URL
|
# EMBY_URL ← HOST*_EMBY_URL
|
||||||
# EMBY_API_KEY ← HOST*_EMBY_API_KEY
|
# EMBY_API_KEY ← HOST*_EMBY_API_KEY
|
||||||
|
# GITEA_API_TOKEN ← HOST*_GITEA_API_TOKEN
|
||||||
#
|
#
|
||||||
# Arr-specific vars set by detect_hosts() when needed by arr scripts:
|
# Arr-specific vars set by detect_hosts() when needed by arr scripts:
|
||||||
# LIDARR_URL / LIDARR_API_KEY / LIDARR_MUSIC_ROOT (MY_ID only — Lidarr is HOST1 only)
|
# LIDARR_URL / LIDARR_API_KEY / LIDARR_MUSIC_ROOT (MY_ID only — Lidarr is HOST1 only)
|
||||||
@@ -465,6 +466,9 @@ detect_hosts() {
|
|||||||
EMBY_API_KEY_VAR="${MY_ID}_EMBY_API_KEY"
|
EMBY_API_KEY_VAR="${MY_ID}_EMBY_API_KEY"
|
||||||
EMBY_API_KEY="${!EMBY_API_KEY_VAR:-}"
|
EMBY_API_KEY="${!EMBY_API_KEY_VAR:-}"
|
||||||
|
|
||||||
|
GITEA_API_TOKEN_VAR="${MY_ID}_GITEA_API_TOKEN"
|
||||||
|
GITEA_API_TOKEN="${!GITEA_API_TOKEN_VAR:-}"
|
||||||
|
|
||||||
local _prov_var
|
local _prov_var
|
||||||
for _prov_var in \
|
for _prov_var in \
|
||||||
PARTNERSHIP_PROVISION_EMBY_ADMIN \
|
PARTNERSHIP_PROVISION_EMBY_ADMIN \
|
||||||
|
|||||||
@@ -87,6 +87,12 @@
|
|||||||
HOST1_EMBY_URL="http://localhost:8096"
|
HOST1_EMBY_URL="http://localhost:8096"
|
||||||
HOST1_EMBY_API_KEY="0c27448d93a7431f9ac63569f7655829"
|
HOST1_EMBY_API_KEY="0c27448d93a7431f9ac63569f7655829"
|
||||||
|
|
||||||
|
# ━━━ Gitea ━━━
|
||||||
|
# Personal access token for gitea_ssh_setup.sh — registers this server's SSH public key
|
||||||
|
# with Gitea so git operations use key auth instead of passwords.
|
||||||
|
# Create in Gitea: Settings → Applications → Generate Token → scope: write:user
|
||||||
|
HOST1_GITEA_API_TOKEN=""
|
||||||
|
|
||||||
# ━━━ Notifications ━━━
|
# ━━━ Notifications ━━━
|
||||||
# Discord webhook — leave blank to disable.
|
# Discord webhook — leave blank to disable.
|
||||||
# Per-host so HOST1 and HOST2 can post to different channels or only one server notifies.
|
# Per-host so HOST1 and HOST2 can post to different channels or only one server notifies.
|
||||||
@@ -121,6 +127,8 @@
|
|||||||
"my-Authelia-Secondary.xml"
|
"my-Authelia-Secondary.xml"
|
||||||
"my-NginxProxyManager.xml"
|
"my-NginxProxyManager.xml"
|
||||||
"my-Lldap-Gmer4Lfe.xml"
|
"my-Lldap-Gmer4Lfe.xml"
|
||||||
|
# Source of truth — must be available on HOST2 independently of the auth stack
|
||||||
|
"my-Gitea.xml"
|
||||||
)
|
)
|
||||||
|
|
||||||
# XML templates pushed to mirror for the arr stack during onboard.
|
# XML templates pushed to mirror for the arr stack during onboard.
|
||||||
|
|||||||
@@ -337,6 +337,7 @@
|
|||||||
# Higher tiers activate after HOST1_TIER*_DELAY minutes (set in host1.conf).
|
# Higher tiers activate after HOST1_TIER*_DELAY minutes (set in host1.conf).
|
||||||
FALLBACK_HOST2_COVERS_HOST1_TIER1=(
|
FALLBACK_HOST2_COVERS_HOST1_TIER1=(
|
||||||
"Gmer4Lfe.com"
|
"Gmer4Lfe.com"
|
||||||
|
"Gitea" # source of truth — must be reachable even when HOST1 auth stack is down
|
||||||
"Emby"
|
"Emby"
|
||||||
"VaultWarden-Gmer4Lfe"
|
"VaultWarden-Gmer4Lfe"
|
||||||
"Dispatcharr"
|
"Dispatcharr"
|
||||||
|
|||||||
@@ -249,6 +249,7 @@
|
|||||||
TARGET_DIR="/mnt/user/appdata/unraid_scripts"
|
TARGET_DIR="/mnt/user/appdata/unraid_scripts"
|
||||||
GITEA_SSH_KEY="/root/.ssh/unraid_gitea"
|
GITEA_SSH_KEY="/root/.ssh/unraid_gitea"
|
||||||
SSH_PORT=221 # Gitea SSH port (default 22, Gitea often uses 221/222)
|
SSH_PORT=221 # Gitea SSH port (default 22, Gitea often uses 221/222)
|
||||||
|
GITEA_HTTP_PORT=3000 # Gitea web/API port — used by gitea_ssh_setup.sh
|
||||||
|
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
# ── ORCHESTRATORS ─────────────────────────────────────────────────────────────────────────────
|
# ── ORCHESTRATORS ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user