fix: forgejo ip
This commit is contained in:
@@ -102,6 +102,7 @@
|
|||||||
"/snapcast.cloonar.com/${config.networkPrefix}.97.21"
|
"/snapcast.cloonar.com/${config.networkPrefix}.97.21"
|
||||||
"/lms.cloonar.com/${config.networkPrefix}.97.21"
|
"/lms.cloonar.com/${config.networkPrefix}.97.21"
|
||||||
"/git.cloonar.com/${config.networkPrefix}.97.50"
|
"/git.cloonar.com/${config.networkPrefix}.97.50"
|
||||||
|
"/forgejo.cloonar.com/${config.networkPrefix}.97.55"
|
||||||
"/feeds.cloonar.com/188.34.191.144"
|
"/feeds.cloonar.com/188.34.191.144"
|
||||||
"/nukibridge1a753f72.cloonar.smart/${config.networkPrefix}.100.112"
|
"/nukibridge1a753f72.cloonar.smart/${config.networkPrefix}.100.112"
|
||||||
"/allywatch.cloonar.com/${config.networkPrefix}.97.5"
|
"/allywatch.cloonar.com/${config.networkPrefix}.97.5"
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ in
|
|||||||
users.groups.forgejo = group;
|
users.groups.forgejo = group;
|
||||||
|
|
||||||
# Reuse the existing git.cloonar.com ACME cert from gitea.nix
|
# Reuse the existing git.cloonar.com ACME cert from gitea.nix
|
||||||
|
security.acme.certs."forgejo.cloonar.com" = {
|
||||||
|
group = "nginx";
|
||||||
|
};
|
||||||
|
|
||||||
containers.forgejo = {
|
containers.forgejo = {
|
||||||
autoStart = false; # Don't start until migration is complete
|
autoStart = false; # Don't start until migration is complete
|
||||||
@@ -27,14 +30,15 @@ in
|
|||||||
privateNetwork = true;
|
privateNetwork = true;
|
||||||
hostBridge = "server";
|
hostBridge = "server";
|
||||||
hostAddress = "${networkPrefix}.97.1";
|
hostAddress = "${networkPrefix}.97.1";
|
||||||
localAddress = "${networkPrefix}.97.51/24"; # Different from gitea's .50
|
localAddress = "${networkPrefix}.97.55/24"; # Different from gitea's .50
|
||||||
bindMounts = {
|
bindMounts = {
|
||||||
"/var/lib/forgejo" = {
|
"/var/lib/forgejo" = {
|
||||||
hostPath = "/var/lib/forgejo/";
|
hostPath = "/var/lib/forgejo/";
|
||||||
isReadOnly = false;
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
"/var/lib/acme/forgejo/" = {
|
"/var/lib/acme/forgejo/" = {
|
||||||
hostPath = config.security.acme.certs.${domain}.directory;
|
# hostPath = config.security.acme.certs.${domain}.directory;
|
||||||
|
hostPath = config.security.acme.certs."forgejo.cloonar.com".directory;
|
||||||
isReadOnly = true;
|
isReadOnly = true;
|
||||||
};
|
};
|
||||||
"/run/secrets/forgejo-mailer-password" = {
|
"/run/secrets/forgejo-mailer-password" = {
|
||||||
|
|||||||
@@ -7,6 +7,15 @@
|
|||||||
proxyPass = "https://git.cloonar.com/";
|
proxyPass = "https://git.cloonar.com/";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
services.nginx.virtualHosts."forgejo.cloonar.com" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
acmeRoot = null;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://${config.networkPrefix}.97.55:3001/";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
services.nginx.virtualHosts."foundry-vtt.cloonar.com" = {
|
services.nginx.virtualHosts."foundry-vtt.cloonar.com" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
|
|||||||
19
scripts/migrate-gitea-to-forgejo.env.example
Normal file
19
scripts/migrate-gitea-to-forgejo.env.example
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Gitea to Forgejo Migration - Environment Configuration
|
||||||
|
#
|
||||||
|
# Copy this file to migrate-gitea-to-forgejo.env and adjust values.
|
||||||
|
# Then run: ./scripts/migrate-gitea-to-forgejo.sh
|
||||||
|
#
|
||||||
|
# IMPORTANT: Ensure Gitea is stopped before running migration.
|
||||||
|
|
||||||
|
# Source (Gitea) - READ ONLY, never modified
|
||||||
|
# This is the original Gitea data directory
|
||||||
|
SOURCE_DATA=/var/lib/gitea
|
||||||
|
|
||||||
|
# Target (Forgejo) - where data will be copied
|
||||||
|
# Must be on a filesystem with enough space (1.2x source size)
|
||||||
|
TARGET_DATA=/var/lib/forgejo
|
||||||
|
|
||||||
|
# User/group for target files
|
||||||
|
# These should match your Forgejo service user
|
||||||
|
TARGET_USER=forgejo
|
||||||
|
TARGET_GROUP=forgejo
|
||||||
497
scripts/migrate-gitea-to-forgejo.sh
Executable file
497
scripts/migrate-gitea-to-forgejo.sh
Executable file
@@ -0,0 +1,497 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Gitea 1.25.4 to Forgejo Migration Script
|
||||||
|
#
|
||||||
|
# This script copies data from Gitea to Forgejo and rolls back the database
|
||||||
|
# schema from version 322/323 to 304, allowing Forgejo to run its own migrations.
|
||||||
|
#
|
||||||
|
# IMPORTANT: This script NEVER modifies source data. All operations work on copies,
|
||||||
|
# so the original Gitea instance can be restarted as a rollback.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# 1. Copy migrate-gitea-to-forgejo.env.example to migrate-gitea-to-forgejo.env
|
||||||
|
# 2. Edit the .env file with your paths
|
||||||
|
# 3. Stop Gitea
|
||||||
|
# 4. Run: ./scripts/migrate-gitea-to-forgejo.sh
|
||||||
|
# 5. Update NixOS config and deploy
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="${SCRIPT_DIR}/migrate-gitea-to-forgejo.env"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
log_info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
||||||
|
log_success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||||
|
|
||||||
|
# Load environment file
|
||||||
|
if [[ ! -f "$ENV_FILE" ]]; then
|
||||||
|
log_error "Environment file not found: $ENV_FILE"
|
||||||
|
log_info "Copy migrate-gitea-to-forgejo.env.example to migrate-gitea-to-forgejo.env and configure it."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$ENV_FILE"
|
||||||
|
|
||||||
|
# Verify required variables
|
||||||
|
: "${SOURCE_DATA:?SOURCE_DATA must be set in $ENV_FILE}"
|
||||||
|
: "${TARGET_DATA:?TARGET_DATA must be set in $ENV_FILE}"
|
||||||
|
: "${TARGET_USER:?TARGET_USER must be set in $ENV_FILE}"
|
||||||
|
: "${TARGET_GROUP:?TARGET_GROUP must be set in $ENV_FILE}"
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo "Gitea to Forgejo Migration Script"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "Source: $SOURCE_DATA (read-only)"
|
||||||
|
echo "Target: $TARGET_DATA"
|
||||||
|
echo "User: $TARGET_USER:$TARGET_GROUP"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 1: Pre-flight Checks
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 1: Pre-flight checks..."
|
||||||
|
|
||||||
|
# Check if running as root (needed for chown)
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
log_error "This script must be run as root (for chown operations)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify SQLite version >= 3.35 (required for DROP COLUMN)
|
||||||
|
if ! command -v sqlite3 &> /dev/null; then
|
||||||
|
log_error "sqlite3 command not found. Please install SQLite."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sqlite_version=$(sqlite3 --version | cut -d' ' -f1)
|
||||||
|
sqlite_major=$(echo "$sqlite_version" | cut -d'.' -f1)
|
||||||
|
sqlite_minor=$(echo "$sqlite_version" | cut -d'.' -f2)
|
||||||
|
if [[ "$sqlite_major" -lt 3 ]] || { [[ "$sqlite_major" -eq 3 ]] && [[ "$sqlite_minor" -lt 35 ]]; }; then
|
||||||
|
log_error "SQLite $sqlite_version is too old. Need 3.35+ for DROP COLUMN support."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "SQLite version: $sqlite_version"
|
||||||
|
|
||||||
|
# Verify rsync is available (needed for incremental copying)
|
||||||
|
if ! command -v rsync &> /dev/null; then
|
||||||
|
log_error "rsync command not found. Please install rsync."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "rsync available"
|
||||||
|
|
||||||
|
# Verify source exists
|
||||||
|
if [[ ! -d "$SOURCE_DATA" ]]; then
|
||||||
|
log_error "Source directory not found: $SOURCE_DATA"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Source directory exists"
|
||||||
|
|
||||||
|
# Find source database (could be gitea.db or forgejo.db depending on setup)
|
||||||
|
SOURCE_DB=""
|
||||||
|
if [[ -f "$SOURCE_DATA/data/gitea.db" ]]; then
|
||||||
|
SOURCE_DB="$SOURCE_DATA/data/gitea.db"
|
||||||
|
elif [[ -f "$SOURCE_DATA/gitea.db" ]]; then
|
||||||
|
SOURCE_DB="$SOURCE_DATA/gitea.db"
|
||||||
|
else
|
||||||
|
log_error "Source database not found in $SOURCE_DATA/data/ or $SOURCE_DATA/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Source database found: $SOURCE_DB"
|
||||||
|
|
||||||
|
# Verify source app.ini exists
|
||||||
|
SOURCE_INI=""
|
||||||
|
if [[ -f "$SOURCE_DATA/custom/conf/app.ini" ]]; then
|
||||||
|
SOURCE_INI="$SOURCE_DATA/custom/conf/app.ini"
|
||||||
|
elif [[ -f "$SOURCE_DATA/conf/app.ini" ]]; then
|
||||||
|
SOURCE_INI="$SOURCE_DATA/conf/app.ini"
|
||||||
|
else
|
||||||
|
log_error "Source app.ini not found in $SOURCE_DATA/custom/conf/ or $SOURCE_DATA/conf/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Source app.ini found: $SOURCE_INI"
|
||||||
|
|
||||||
|
# Check disk space (need 1.2x source size)
|
||||||
|
source_size=$(du -sb "$SOURCE_DATA" | cut -f1)
|
||||||
|
required=$((source_size * 12 / 10))
|
||||||
|
target_parent=$(dirname "$TARGET_DATA")
|
||||||
|
mkdir -p "$target_parent"
|
||||||
|
available=$(df --output=avail -B1 "$target_parent" | tail -1)
|
||||||
|
if [[ "$available" -lt "$required" ]]; then
|
||||||
|
log_error "Not enough disk space. Need $(numfmt --to=iec $required), have $(numfmt --to=iec $available)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Disk space OK: need $(numfmt --to=iec $required), have $(numfmt --to=iec $available)"
|
||||||
|
|
||||||
|
# Warn if target exists (rsync will sync incrementally)
|
||||||
|
if [[ -d "$TARGET_DATA" ]]; then
|
||||||
|
log_warn "Target directory exists: $TARGET_DATA"
|
||||||
|
log_info "rsync will perform incremental sync (only copying changed files)"
|
||||||
|
read -p "Continue with incremental sync? (y/N) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
log_error "Aborted by user"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 2: Copy All Data
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 2: Copying data..."
|
||||||
|
|
||||||
|
mkdir -p "$TARGET_DATA/data"
|
||||||
|
mkdir -p "$TARGET_DATA/custom/conf"
|
||||||
|
|
||||||
|
# Copy database
|
||||||
|
log_info "Copying database..."
|
||||||
|
rsync -a --info=progress2 "$SOURCE_DB" "$TARGET_DATA/data/forgejo.db"
|
||||||
|
log_success "Database copied"
|
||||||
|
|
||||||
|
# Copy all data directories (preserve attributes, sync incrementally)
|
||||||
|
for dir in repositories avatars attachments packages lfs custom queues indexers; do
|
||||||
|
if [[ -d "$SOURCE_DATA/$dir" ]]; then
|
||||||
|
log_info "Syncing $dir..."
|
||||||
|
mkdir -p "$TARGET_DATA/$dir"
|
||||||
|
rsync -a --delete --info=progress2 "$SOURCE_DATA/$dir/" "$TARGET_DATA/$dir/"
|
||||||
|
log_success "Synced $dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Also check data/ subdirectory structure
|
||||||
|
for dir in repositories avatars attachments packages lfs; do
|
||||||
|
if [[ -d "$SOURCE_DATA/data/$dir" ]]; then
|
||||||
|
log_info "Syncing data/$dir..."
|
||||||
|
mkdir -p "$TARGET_DATA/data/$dir"
|
||||||
|
rsync -a --delete --info=progress2 "$SOURCE_DATA/data/$dir/" "$TARGET_DATA/data/$dir/"
|
||||||
|
log_success "Synced data/$dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 3: Database Schema Rollback
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 3: Rolling back database schema..."
|
||||||
|
|
||||||
|
TARGET_DB="$TARGET_DATA/data/forgejo.db"
|
||||||
|
|
||||||
|
# Show current schema version
|
||||||
|
current_version=$(sqlite3 "$TARGET_DB" "SELECT version FROM version WHERE id=1;")
|
||||||
|
log_info "Current Gitea schema version: $current_version"
|
||||||
|
log_info "Target version: 304"
|
||||||
|
|
||||||
|
# Create rollback SQL script
|
||||||
|
ROLLBACK_SQL=$(mktemp)
|
||||||
|
cat > "$ROLLBACK_SQL" << 'ROLLBACK_EOF'
|
||||||
|
-- ================================================================
|
||||||
|
-- Gitea 1.25.4 to Forgejo Rollback Script
|
||||||
|
-- Rolls back migrations 305-322 to allow Forgejo to migrate cleanly
|
||||||
|
-- ================================================================
|
||||||
|
|
||||||
|
-- Enable foreign keys check after we're done
|
||||||
|
PRAGMA foreign_keys = OFF;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 305: Drop repo_license table
|
||||||
|
-- ============================================
|
||||||
|
DROP TABLE IF EXISTS repo_license;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 308 & 317: Drop action table indices
|
||||||
|
-- (These are the main conflict source)
|
||||||
|
-- ============================================
|
||||||
|
DROP INDEX IF EXISTS IDX_action_r_u_d;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_au_r_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_c_u;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_au_c_u;
|
||||||
|
-- Alternative naming conventions
|
||||||
|
DROP INDEX IF EXISTS UQE_action_r_u_d;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_au_r_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_c_u;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_au_c_u;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 309: Drop notification table indices
|
||||||
|
-- ============================================
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_u_s_uu;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_user_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_repo_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_status;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_source;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_issue_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_commit_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_updated_by;
|
||||||
|
DROP INDEX IF EXISTS UQE_notification_u_s_uu;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 313: Drop issue_pin table
|
||||||
|
-- (pin_order restoration handled separately)
|
||||||
|
-- ============================================
|
||||||
|
DROP TABLE IF EXISTS issue_pin;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 306: Drop protected_branch column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE protected_branch DROP COLUMN IF EXISTS block_admin_merge_override;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 310: Drop protected_branch column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE protected_branch DROP COLUMN IF EXISTS priority;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 311: Drop issue column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE issue DROP COLUMN IF EXISTS time_estimate;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 312: Drop pull_auto_merge column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE pull_auto_merge DROP COLUMN IF EXISTS delete_branch_after_merge;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 315: Drop action_runner column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE action_runner DROP COLUMN IF EXISTS ephemeral;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 316: Drop description columns
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE secret DROP COLUMN IF EXISTS description;
|
||||||
|
ALTER TABLE action_variable DROP COLUMN IF EXISTS description;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 318: Drop repo_unit column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE repo_unit DROP COLUMN IF EXISTS anonymous_access_mode;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 319: Drop label column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE label DROP COLUMN IF EXISTS exclusive_order;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- MIGRATION 320: Drop login_source column
|
||||||
|
-- ============================================
|
||||||
|
ALTER TABLE login_source DROP COLUMN IF EXISTS two_factor_policy;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- SET VERSION TO 304
|
||||||
|
-- ============================================
|
||||||
|
UPDATE version SET version = 304 WHERE id = 1;
|
||||||
|
|
||||||
|
PRAGMA foreign_keys = ON;
|
||||||
|
ROLLBACK_EOF
|
||||||
|
|
||||||
|
log_info "Executing schema rollback..."
|
||||||
|
|
||||||
|
# SQLite doesn't support DROP COLUMN IF EXISTS, so we need to handle errors gracefully
|
||||||
|
# Execute each ALTER TABLE separately to handle missing columns
|
||||||
|
sqlite3 "$TARGET_DB" << 'SQL_PART1'
|
||||||
|
PRAGMA foreign_keys = OFF;
|
||||||
|
|
||||||
|
-- Drop tables
|
||||||
|
DROP TABLE IF EXISTS repo_license;
|
||||||
|
DROP TABLE IF EXISTS issue_pin;
|
||||||
|
|
||||||
|
-- Drop indices (these always work, even if index doesn't exist)
|
||||||
|
DROP INDEX IF EXISTS IDX_action_r_u_d;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_au_r_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_c_u;
|
||||||
|
DROP INDEX IF EXISTS IDX_action_au_c_u;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_r_u_d;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_au_r_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_c_u_d;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_c_u;
|
||||||
|
DROP INDEX IF EXISTS UQE_action_au_c_u;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_u_s_uu;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_user_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_repo_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_status;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_source;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_issue_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_commit_id;
|
||||||
|
DROP INDEX IF EXISTS IDX_notification_updated_by;
|
||||||
|
DROP INDEX IF EXISTS UQE_notification_u_s_uu;
|
||||||
|
SQL_PART1
|
||||||
|
|
||||||
|
# Function to drop column if it exists
|
||||||
|
drop_column_if_exists() {
|
||||||
|
local table="$1"
|
||||||
|
local column="$2"
|
||||||
|
local exists
|
||||||
|
exists=$(sqlite3 "$TARGET_DB" "SELECT COUNT(*) FROM pragma_table_info('$table') WHERE name='$column';")
|
||||||
|
if [[ "$exists" -gt 0 ]]; then
|
||||||
|
log_info "Dropping column $table.$column..."
|
||||||
|
sqlite3 "$TARGET_DB" "ALTER TABLE $table DROP COLUMN $column;"
|
||||||
|
log_success "Dropped $table.$column"
|
||||||
|
else
|
||||||
|
log_info "Column $table.$column does not exist, skipping"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Drop columns added in migrations 306-320
|
||||||
|
drop_column_if_exists "protected_branch" "block_admin_merge_override"
|
||||||
|
drop_column_if_exists "protected_branch" "priority"
|
||||||
|
drop_column_if_exists "issue" "time_estimate"
|
||||||
|
drop_column_if_exists "pull_auto_merge" "delete_branch_after_merge"
|
||||||
|
drop_column_if_exists "action_runner" "ephemeral"
|
||||||
|
drop_column_if_exists "secret" "description"
|
||||||
|
drop_column_if_exists "action_variable" "description"
|
||||||
|
drop_column_if_exists "repo_unit" "anonymous_access_mode"
|
||||||
|
drop_column_if_exists "label" "exclusive_order"
|
||||||
|
drop_column_if_exists "login_source" "two_factor_policy"
|
||||||
|
|
||||||
|
# Check if pin_order column needs to be added back to issue table (migration 313 removed it)
|
||||||
|
log_info "Checking if pin_order column needs to be restored to issue table..."
|
||||||
|
has_pin_order=$(sqlite3 "$TARGET_DB" "SELECT COUNT(*) FROM pragma_table_info('issue') WHERE name='pin_order';")
|
||||||
|
if [[ "$has_pin_order" -eq 0 ]]; then
|
||||||
|
log_info "Adding pin_order column back to issue table..."
|
||||||
|
sqlite3 "$TARGET_DB" "ALTER TABLE issue ADD COLUMN pin_order INTEGER DEFAULT 0;"
|
||||||
|
log_success "Added pin_order column to issue table"
|
||||||
|
else
|
||||||
|
log_info "pin_order column already exists in issue table"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set version to 304 (allows Forgejo to run migration 305 which converts two_factor.secret from TEXT to BLOB)
|
||||||
|
sqlite3 "$TARGET_DB" "UPDATE version SET version = 304 WHERE id = 1;"
|
||||||
|
log_success "Database version set to 304"
|
||||||
|
|
||||||
|
rm -f "$ROLLBACK_SQL"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 4: Clear Regeneratable Data
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 4: Clearing regeneratable data..."
|
||||||
|
|
||||||
|
# Remove indexers (will be rebuilt on first start)
|
||||||
|
if [[ -d "$TARGET_DATA/indexers" ]]; then
|
||||||
|
rm -rf "$TARGET_DATA/indexers"
|
||||||
|
log_success "Removed indexers (will be rebuilt)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove queues (will be recreated)
|
||||||
|
if [[ -d "$TARGET_DATA/queues" ]]; then
|
||||||
|
rm -rf "$TARGET_DATA/queues"
|
||||||
|
log_success "Removed queues (will be recreated)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 5: Update Configuration
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 5: Updating configuration..."
|
||||||
|
|
||||||
|
# Copy app.ini
|
||||||
|
rsync -a --info=progress2 "$SOURCE_INI" "$TARGET_DATA/custom/conf/app.ini"
|
||||||
|
log_success "Copied app.ini"
|
||||||
|
|
||||||
|
# Update paths from gitea to forgejo
|
||||||
|
sed -i 's|/var/lib/gitea|/var/lib/forgejo|g' "$TARGET_DATA/custom/conf/app.ini"
|
||||||
|
log_success "Updated paths in app.ini"
|
||||||
|
|
||||||
|
# Check if WAL mode is already configured
|
||||||
|
if ! grep -q "SQLITE_JOURNAL_MODE" "$TARGET_DATA/custom/conf/app.ini"; then
|
||||||
|
# Add WAL mode after [database] section
|
||||||
|
sed -i '/^\[database\]/a SQLITE_JOURNAL_MODE = WAL' "$TARGET_DATA/custom/conf/app.ini"
|
||||||
|
log_success "Enabled SQLite WAL mode"
|
||||||
|
else
|
||||||
|
log_info "SQLite journal mode already configured"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 6: Set Permissions
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 6: Setting permissions..."
|
||||||
|
|
||||||
|
chown -R "$TARGET_USER:$TARGET_GROUP" "$TARGET_DATA"
|
||||||
|
chmod 750 "$TARGET_DATA"
|
||||||
|
chmod 640 "$TARGET_DATA/data/forgejo.db"
|
||||||
|
log_success "Permissions set for $TARGET_USER:$TARGET_GROUP"
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 7: Verify Database Integrity
|
||||||
|
# ============================================
|
||||||
|
log_info "Phase 7: Verifying database integrity..."
|
||||||
|
|
||||||
|
sqlite3 "$TARGET_DB" << 'VERIFY_SQL'
|
||||||
|
.headers off
|
||||||
|
.mode list
|
||||||
|
|
||||||
|
-- Verify version was set correctly
|
||||||
|
SELECT 'Version: ' || CASE WHEN version = 304 THEN 'PASS (304)' ELSE 'FAIL (version=' || version || ')' END
|
||||||
|
FROM version WHERE id = 1;
|
||||||
|
|
||||||
|
-- Check critical tables exist
|
||||||
|
SELECT 'Users: ' || CASE WHEN COUNT(*) > 0 THEN 'PASS (' || COUNT(*) || ' users)' ELSE 'WARN (empty)' END FROM user;
|
||||||
|
SELECT 'Repositories: ' || CASE WHEN COUNT(*) > 0 THEN 'PASS (' || COUNT(*) || ' repos)' ELSE 'WARN (empty)' END FROM repository;
|
||||||
|
SELECT 'Secrets: PASS (' || COUNT(*) || ' secrets)' FROM secret;
|
||||||
|
SELECT 'Runners: PASS (' || COUNT(*) || ' runners)' FROM action_runner;
|
||||||
|
SELECT 'Variables: PASS (' || COUNT(*) || ' variables)' FROM action_variable;
|
||||||
|
VERIFY_SQL
|
||||||
|
|
||||||
|
# Verify dropped tables are gone
|
||||||
|
repo_license_exists=$(sqlite3 "$TARGET_DB" "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='repo_license';")
|
||||||
|
issue_pin_exists=$(sqlite3 "$TARGET_DB" "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='issue_pin';")
|
||||||
|
|
||||||
|
if [[ "$repo_license_exists" -eq 0 ]]; then
|
||||||
|
log_success "repo_license table: DROPPED"
|
||||||
|
else
|
||||||
|
log_warn "repo_license table: STILL EXISTS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$issue_pin_exists" -eq 0 ]]; then
|
||||||
|
log_success "issue_pin table: DROPPED"
|
||||||
|
else
|
||||||
|
log_warn "issue_pin table: STILL EXISTS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# PHASE 8: Print Next Steps
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "========================================"
|
||||||
|
echo -e "${GREEN}Migration complete!${NC}"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "Data copied to: $TARGET_DATA"
|
||||||
|
echo "Database schema rolled back to version 304"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Update NixOS configuration:"
|
||||||
|
echo " - Create hosts/fw/modules/forgejo.nix based on gitea.nix"
|
||||||
|
echo " - Change services.gitea to services.forgejo"
|
||||||
|
echo " - Update bind mount paths in container config"
|
||||||
|
echo " - Update runner configuration for Forgejo"
|
||||||
|
echo ""
|
||||||
|
echo "2. Deploy:"
|
||||||
|
echo " nixos-rebuild switch"
|
||||||
|
echo ""
|
||||||
|
echo "3. Monitor first startup:"
|
||||||
|
echo " journalctl -u container@git -f"
|
||||||
|
echo ""
|
||||||
|
echo "4. Verify functionality:"
|
||||||
|
echo " [ ] Forgejo starts without errors"
|
||||||
|
echo " [ ] Login via OpenID (auth.cloonar.com)"
|
||||||
|
echo " [ ] All repositories visible"
|
||||||
|
echo " [ ] Can push/pull to repositories"
|
||||||
|
echo " [ ] CI/CD runners connect"
|
||||||
|
echo " [ ] Workflow with secrets runs"
|
||||||
|
echo " [ ] Packages registry accessible"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}ROLLBACK:${NC} If anything fails, original Gitea data is untouched."
|
||||||
|
echo "Just revert NixOS config and restart Gitea container."
|
||||||
|
echo "========================================"
|
||||||
Reference in New Issue
Block a user