224 lines
10 KiB
Bash
Executable File
224 lines
10 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# =============================================================================
|
|
# phase2_gitea_fedora.sh — Deploy Gitea on Fedora (backup instance)
|
|
# Identical to Phase 1 except: targets Fedora, uses BACKUP vars, NO org created.
|
|
# Produces: Running Gitea on Fedora, admin user, backup API token in .env
|
|
# =============================================================================
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
source "${SCRIPT_DIR}/lib/common.sh"
|
|
|
|
load_env
|
|
require_vars FEDORA_IP FEDORA_SSH_USER FEDORA_SSH_PORT FEDORA_GITEA_DATA_PATH \
|
|
FEDORA_COMPOSE_DIR \
|
|
FEDORA_MACVLAN_PARENT FEDORA_MACVLAN_SUBNET FEDORA_MACVLAN_GATEWAY \
|
|
FEDORA_MACVLAN_IP_RANGE FEDORA_GITEA_IP \
|
|
UNRAID_GITEA_IP GITEA_DOMAIN \
|
|
GITEA_ADMIN_USER GITEA_ADMIN_PASSWORD GITEA_ADMIN_EMAIL \
|
|
GITEA_DB_TYPE GITEA_VERSION
|
|
|
|
if [[ "${GITEA_DB_TYPE}" != "sqlite3" ]]; then
|
|
require_vars GITEA_DB_PORT GITEA_DB_NAME GITEA_DB_USER GITEA_DB_PASSWD
|
|
fi
|
|
|
|
phase_header 2 "Gitea on Fedora (Backup)"
|
|
|
|
# Alias for template rendering — same template as Phase 1, different values
|
|
DATA_PATH="$FEDORA_GITEA_DATA_PATH"
|
|
# Compose files live in a centralized project directory on each host.
|
|
COMPOSE_DIR="${FEDORA_COMPOSE_DIR}/gitea"
|
|
FEDORA_DOCKER_NETWORK_NAME="gitea_net"
|
|
|
|
# DB helpers and strip_template_block are in lib/common.sh
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 1: Ensure data directories on Fedora
|
|
# ---------------------------------------------------------------------------
|
|
log_step 1 "Ensuring data directories on Fedora..."
|
|
if [[ "${GITEA_DB_TYPE}" != "sqlite3" ]]; then
|
|
ssh_exec FEDORA "mkdir -p '${DATA_PATH}/data' '${DATA_PATH}/config' '${DATA_PATH}/db'"
|
|
else
|
|
ssh_exec FEDORA "mkdir -p '${DATA_PATH}/data' '${DATA_PATH}/config'"
|
|
fi
|
|
log_success "Data directories ensured"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 2: Create macvlan Docker network (idempotent)
|
|
# ---------------------------------------------------------------------------
|
|
log_step 2 "Creating macvlan Docker network on Fedora..."
|
|
if ssh_exec FEDORA "docker network inspect '${FEDORA_DOCKER_NETWORK_NAME}'" &>/dev/null; then
|
|
log_info "${FEDORA_DOCKER_NETWORK_NAME} network already exists — skipping"
|
|
else
|
|
ssh_exec FEDORA "docker network create \
|
|
--driver macvlan \
|
|
--subnet='${FEDORA_MACVLAN_SUBNET}' \
|
|
--gateway='${FEDORA_MACVLAN_GATEWAY}' \
|
|
--ip-range='${FEDORA_MACVLAN_IP_RANGE}' \
|
|
-o parent='${FEDORA_MACVLAN_PARENT}' \
|
|
'${FEDORA_DOCKER_NETWORK_NAME}'"
|
|
log_success "macvlan network ${FEDORA_DOCKER_NETWORK_NAME} created"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 3: Render + SCP docker-compose file
|
|
# Uses the same template as Phase 1 but with Fedora-specific values.
|
|
# ---------------------------------------------------------------------------
|
|
log_step 3 "Deploying docker-compose.yml..."
|
|
if ssh_exec FEDORA "test -f '${COMPOSE_DIR}/docker-compose.yml'"; then
|
|
log_info "docker-compose.yml already exists — skipping"
|
|
else
|
|
ssh_exec FEDORA "mkdir -p '${COMPOSE_DIR}'"
|
|
TMPFILE=$(mktemp)
|
|
GITEA_CONTAINER_IP="${FEDORA_GITEA_IP}"
|
|
GITEA_NETWORK_NAME="${FEDORA_DOCKER_NETWORK_NAME}"
|
|
# Macvlan containers use Docker's internal DNS (127.0.0.11) which only resolves
|
|
# container names. Set explicit DNS to the LAN gateway for external resolution.
|
|
GITEA_DNS_SERVER="${FEDORA_MACVLAN_GATEWAY}"
|
|
# Map the primary Gitea domain to the Unraid LAN IP so the backup instance
|
|
# can reach it for pull mirrors (public DNS may resolve to Cloudflare/CDN).
|
|
GITEA_MIRROR_SOURCE_HOST="${GITEA_DOMAIN}"
|
|
GITEA_MIRROR_SOURCE_IP="${UNRAID_GITEA_IP}"
|
|
export DATA_PATH GITEA_CONTAINER_IP GITEA_NETWORK_NAME \
|
|
GITEA_DNS_SERVER GITEA_MIRROR_SOURCE_HOST GITEA_MIRROR_SOURCE_IP
|
|
|
|
if [[ "$GITEA_DB_TYPE" == "sqlite3" ]]; then
|
|
# No DB service needed — render template then strip DB + internal network blocks
|
|
render_template "${SCRIPT_DIR}/templates/docker-compose-gitea.yml.tpl" "$TMPFILE" \
|
|
"\${GITEA_VERSION} \${DATA_PATH} \${GITEA_CONTAINER_IP} \${GITEA_NETWORK_NAME} \${GITEA_DNS_SERVER} \${GITEA_MIRROR_SOURCE_HOST} \${GITEA_MIRROR_SOURCE_IP}"
|
|
strip_template_block "$TMPFILE" "DB_SERVICE_START" "DB_SERVICE_END"
|
|
strip_template_block "$TMPFILE" "DB_DEPENDS_START" "DB_DEPENDS_END"
|
|
strip_template_block "$TMPFILE" "INTERNAL_NET_REF_START" "INTERNAL_NET_REF_END"
|
|
strip_template_block "$TMPFILE" "INTERNAL_NET_DEF_START" "INTERNAL_NET_DEF_END"
|
|
else
|
|
# External DB — set DB-specific vars then render
|
|
# DB container uses an internal bridge network (not exposed to LAN)
|
|
set_db_vars
|
|
render_template "${SCRIPT_DIR}/templates/docker-compose-gitea.yml.tpl" "$TMPFILE" \
|
|
"\${GITEA_VERSION} \${DATA_PATH} \${GITEA_CONTAINER_IP} \${GITEA_NETWORK_NAME} \${DB_DOCKER_IMAGE} \${DB_ENV_VARS} \${DB_DATA_DIR} \${DB_HEALTHCHECK} \${GITEA_DNS_SERVER} \${GITEA_MIRROR_SOURCE_HOST} \${GITEA_MIRROR_SOURCE_IP}"
|
|
fi
|
|
|
|
scp_to FEDORA "$TMPFILE" "${COMPOSE_DIR}/docker-compose.yml"
|
|
rm -f "$TMPFILE"
|
|
log_success "docker-compose.yml deployed to ${COMPOSE_DIR}"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 4: Render + SCP app.ini
|
|
# Fedora is internal-only for pull mirrors, so ROOT_URL/DOMAIN use FEDORA_GITEA_IP.
|
|
# API checks in this script use GITEA_BACKUP_INTERNAL_URL (derived in load_env()).
|
|
# ---------------------------------------------------------------------------
|
|
log_step 4 "Deploying app.ini..."
|
|
if ssh_exec FEDORA "test -f '${DATA_PATH}/config/app.ini'"; then
|
|
log_info "app.ini already exists — skipping"
|
|
else
|
|
TMPFILE=$(mktemp)
|
|
GITEA_SECRET_KEY=$(openssl rand -hex 32)
|
|
export GITEA_SECRET_KEY
|
|
# Override GITEA_DOMAIN for the backup instance — use the container IP since
|
|
# the Fedora instance doesn't have a public domain
|
|
GITEA_DOMAIN="${FEDORA_GITEA_IP}"
|
|
export GITEA_DOMAIN
|
|
|
|
if [[ "$GITEA_DB_TYPE" == "sqlite3" ]]; then
|
|
render_template "${SCRIPT_DIR}/templates/app.ini.tpl" "$TMPFILE" \
|
|
"\${GITEA_DOMAIN} \${GITEA_DB_TYPE} \${GITEA_SECRET_KEY}"
|
|
strip_template_block "$TMPFILE" "EXTDB_BLOCK_START" "EXTDB_BLOCK_END"
|
|
else
|
|
render_template "${SCRIPT_DIR}/templates/app.ini.tpl" "$TMPFILE" \
|
|
"\${GITEA_DOMAIN} \${GITEA_DB_TYPE} \${GITEA_SECRET_KEY} \${GITEA_DB_PORT} \${GITEA_DB_NAME} \${GITEA_DB_USER} \${GITEA_DB_PASSWD}"
|
|
strip_template_block "$TMPFILE" "SQLITE_BLOCK_START" "SQLITE_BLOCK_END"
|
|
fi
|
|
|
|
scp_to FEDORA "$TMPFILE" "${DATA_PATH}/config/app.ini"
|
|
rm -f "$TMPFILE"
|
|
log_success "app.ini deployed"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 5: Start Gitea container
|
|
# ---------------------------------------------------------------------------
|
|
log_step 5 "Starting Gitea container..."
|
|
CONTAINER_STATUS=$(ssh_exec FEDORA "docker ps --filter 'name=^/gitea$' --format '{{.Status}}'" 2>/dev/null || true)
|
|
if [[ "$CONTAINER_STATUS" == *"Up"* ]]; then
|
|
log_info "Gitea container already running — skipping"
|
|
else
|
|
# Try "docker compose" plugin first, fall back to standalone
|
|
ssh_exec FEDORA "cd '${COMPOSE_DIR}' && docker compose up -d 2>/dev/null || docker-compose up -d"
|
|
log_success "Gitea container started"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 6: Wait for Gitea to be ready
|
|
# ---------------------------------------------------------------------------
|
|
log_step 6 "Waiting for Gitea to be ready..."
|
|
wait_for_http "${GITEA_BACKUP_INTERNAL_URL}/api/v1/version" 120
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 7: Create admin user (same creds as primary — shared credentials)
|
|
# ---------------------------------------------------------------------------
|
|
log_step 7 "Creating admin user..."
|
|
if curl -sf -u "${GITEA_ADMIN_USER}:${GITEA_ADMIN_PASSWORD}" "${GITEA_BACKUP_INTERNAL_URL}/api/v1/user" -o /dev/null 2>/dev/null; then
|
|
log_info "Admin user already exists — skipping"
|
|
else
|
|
# Create via CLI inside container, same pattern as Phase 1
|
|
ssh_exec FEDORA "docker exec -u git gitea gitea admin user create \
|
|
--username '${GITEA_ADMIN_USER}' \
|
|
--password '${GITEA_ADMIN_PASSWORD}' \
|
|
--email '${GITEA_ADMIN_EMAIL}' \
|
|
--admin \
|
|
--must-change-password=false" || true
|
|
|
|
if curl -sf -u "${GITEA_ADMIN_USER}:${GITEA_ADMIN_PASSWORD}" "${GITEA_BACKUP_INTERNAL_URL}/api/v1/user" -o /dev/null 2>/dev/null; then
|
|
log_success "Admin user created"
|
|
else
|
|
log_error "Failed to create admin user on Fedora"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Step 8: Generate API token and save to .env as GITEA_BACKUP_ADMIN_TOKEN
|
|
# ---------------------------------------------------------------------------
|
|
log_step 8 "Generating backup API token..."
|
|
if [[ -n "${GITEA_BACKUP_ADMIN_TOKEN:-}" ]]; then
|
|
# Verify existing token works
|
|
if curl -sf -H "Authorization: token ${GITEA_BACKUP_ADMIN_TOKEN}" "${GITEA_BACKUP_INTERNAL_URL}/api/v1/user" -o /dev/null 2>/dev/null; then
|
|
log_info "Backup API token already exists and is valid — skipping"
|
|
else
|
|
log_warn "Existing backup token is invalid — generating new one"
|
|
GITEA_BACKUP_ADMIN_TOKEN=""
|
|
fi
|
|
fi
|
|
|
|
if [[ -z "${GITEA_BACKUP_ADMIN_TOKEN:-}" ]]; then
|
|
# Delete any stale token with the same name (idempotent re-run safety).
|
|
curl -sf -u "${GITEA_ADMIN_USER}:${GITEA_ADMIN_PASSWORD}" \
|
|
-X DELETE \
|
|
"${GITEA_BACKUP_INTERNAL_URL}/api/v1/users/${GITEA_ADMIN_USER}/tokens/migration-token" \
|
|
-o /dev/null 2>/dev/null || true
|
|
|
|
# Generate via basic auth — token is only returned once in the .sha1 field
|
|
TOKEN_RESPONSE=$(curl -sf -u "${GITEA_ADMIN_USER}:${GITEA_ADMIN_PASSWORD}" \
|
|
-X POST \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"migration-token","scopes":["all"]}' \
|
|
"${GITEA_BACKUP_INTERNAL_URL}/api/v1/users/${GITEA_ADMIN_USER}/tokens")
|
|
|
|
GITEA_BACKUP_ADMIN_TOKEN=$(printf '%s' "$TOKEN_RESPONSE" | jq -r '.sha1')
|
|
|
|
if [[ -z "$GITEA_BACKUP_ADMIN_TOKEN" ]] || [[ "$GITEA_BACKUP_ADMIN_TOKEN" == "null" ]]; then
|
|
log_error "Failed to generate backup API token"
|
|
exit 1
|
|
fi
|
|
|
|
save_env_var "GITEA_BACKUP_ADMIN_TOKEN" "$GITEA_BACKUP_ADMIN_TOKEN"
|
|
log_success "Backup API token generated and saved to .env"
|
|
fi
|
|
|
|
# NOTE: No organization is created on the Fedora instance.
|
|
# Mirror repos will be stored under the admin user's namespace.
|
|
|
|
log_success "Phase 2 complete — Gitea backup instance is running on Fedora"
|