feat: add systemd sync solution to eliminate repo/active gap
SYSTEMD SYNC: Link active systemd files to repository for automatic sync Problem Solved: ❌ Gap between repository systemd files and active systemd files ❌ Development changes in repo not reflected in running services ❌ Manual sync required to update systemd configuration ❌ Risk of configuration drift between repo and production Solution Implemented: ✅ Symbolic links from /etc/systemd/system/ to /opt/aitbc/systemd ✅ Automatic sync script for manual operations ✅ CI/CD workflow for automatic sync on repository changes ✅ Backup mechanism for safe operations ✅ Verification and status checking Files Created: 1. scripts/link-systemd.sh: - Creates symbolic links for all aitbc-* services - Handles .d directories automatically - Creates backups before making changes - Provides comprehensive status reporting 2. scripts/sync-systemd.sh: - Alternative copy-based sync method - For environments where symbolic links aren't preferred - Maintains file independence while keeping sync 3. .gitea/workflows/systemd-sync.yml: - Automatic CI/CD sync on repository changes - Triggers when systemd files are modified - Verifies link creation and service status - Provides manual instructions Benefits: ✅ Active systemd files always match repository ✅ No configuration drift between repo and production ✅ Changes in repo immediately reflected ✅ Automatic sync on every repository update ✅ Safe operations with backups ✅ CI/CD integration for automation Usage: - Manual: sudo ./scripts/link-systemd.sh - CI/CD: Automatic on systemd file changes - Verification: ls -la /etc/systemd/system/aitbc-* - Status: sudo systemctl status aitbc-* This eliminates the gap between repository and active systemd configuration, ensuring the repository always contains the current running state and changes are immediately reflected.
This commit is contained in:
181
.gitea/workflows/systemd-sync.yml
Normal file
181
.gitea/workflows/systemd-sync.yml
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
name: systemd-sync
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
paths:
|
||||||
|
- 'systemd/**'
|
||||||
|
- '.gitea/workflows/systemd-sync.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Prevent parallel execution - run workflows serially
|
||||||
|
concurrency:
|
||||||
|
group: ci-workflows
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync-systemd:
|
||||||
|
runs-on: debian
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup workspace
|
||||||
|
run: |
|
||||||
|
echo "=== SYSTEMD SYNC SETUP ==="
|
||||||
|
echo "Current PWD: $(pwd)"
|
||||||
|
echo "Forcing absolute workspace path..."
|
||||||
|
|
||||||
|
# Clean and create isolated workspace
|
||||||
|
rm -rf /opt/aitbc/systemd-sync-workspace
|
||||||
|
mkdir -p /opt/aitbc/systemd-sync-workspace
|
||||||
|
cd /opt/aitbc/systemd-sync-workspace
|
||||||
|
|
||||||
|
# Ensure no git lock files exist
|
||||||
|
find . -name "*.lock" -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Workspace PWD: $(pwd)"
|
||||||
|
echo "Cloning repository..."
|
||||||
|
git clone https://gitea.bubuit.net/oib/aitbc.git repo
|
||||||
|
|
||||||
|
cd repo
|
||||||
|
echo "Repo PWD: $(pwd)"
|
||||||
|
echo "Files in repo:"
|
||||||
|
ls -la
|
||||||
|
|
||||||
|
- name: Sync Systemd Files
|
||||||
|
run: |
|
||||||
|
echo "=== SYNCING SYSTEMD FILES ==="
|
||||||
|
cd /opt/aitbc/systemd-sync-workspace/repo
|
||||||
|
|
||||||
|
echo "Repository systemd files:"
|
||||||
|
ls -la systemd/ | head -10
|
||||||
|
echo
|
||||||
|
echo "Active systemd files:"
|
||||||
|
ls -la /etc/systemd/system/aitbc-* | head -5 || echo "No active files found"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if running as root (should be in CI)
|
||||||
|
if [[ $EUID -eq 0 ]]; then
|
||||||
|
echo "✅ Running as root - can sync systemd files"
|
||||||
|
|
||||||
|
# Run the linking script
|
||||||
|
if [[ -f "scripts/link-systemd.sh" ]]; then
|
||||||
|
echo "🔗 Running systemd linking script..."
|
||||||
|
./scripts/link-systemd.sh
|
||||||
|
else
|
||||||
|
echo "❌ Link script not found, creating manual sync..."
|
||||||
|
|
||||||
|
# Manual sync as fallback
|
||||||
|
REPO_SYSTEMD_DIR="/opt/aitbc/systemd-sync-workspace/repo/systemd"
|
||||||
|
ACTIVE_SYSTEMD_DIR="/etc/systemd/system"
|
||||||
|
|
||||||
|
# Create backup
|
||||||
|
BACKUP_DIR="/opt/aitbc/systemd-backup-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
find "$ACTIVE_SYSTEMD_DIR" -name "aitbc-*" -type f -exec cp {} "$BACKUP_DIR/" \; 2>/dev/null || true
|
||||||
|
|
||||||
|
# Create symbolic links
|
||||||
|
for file in "$REPO_SYSTEMD_DIR"/aitbc-*; do
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
filename=$(basename "$file")
|
||||||
|
target="$ACTIVE_SYSTEMD_DIR/$filename"
|
||||||
|
source="$REPO_SYSTEMD_DIR/$filename"
|
||||||
|
|
||||||
|
echo "🔗 Linking: $filename"
|
||||||
|
ln -sf "$source" "$target"
|
||||||
|
|
||||||
|
# Handle .d directories
|
||||||
|
if [[ -d "${file}.d" ]]; then
|
||||||
|
target_dir="${target}.d"
|
||||||
|
source_dir="${file}.d"
|
||||||
|
rm -rf "$target_dir" 2>/dev/null || true
|
||||||
|
ln -sf "$source_dir" "$target_dir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
echo "✅ Manual systemd sync completed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "⚠️ Not running as root - systemd sync requires root privileges"
|
||||||
|
echo " To sync manually: sudo ./scripts/link-systemd.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Verify Sync
|
||||||
|
run: |
|
||||||
|
echo "=== VERIFYING SYSTEMD SYNC ==="
|
||||||
|
cd /opt/aitbc/systemd-sync-workspace/repo
|
||||||
|
|
||||||
|
if [[ $EUID -eq 0 ]]; then
|
||||||
|
echo "🔍 Verifying systemd links..."
|
||||||
|
|
||||||
|
# Check if links exist
|
||||||
|
echo "Checking symbolic links:"
|
||||||
|
for file in systemd/aitbc-*; do
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
filename=$(basename "$file")
|
||||||
|
target="/etc/systemd/system/$filename"
|
||||||
|
|
||||||
|
if [[ -L "$target" ]]; then
|
||||||
|
echo "✅ $filename -> $(readlink "$target")"
|
||||||
|
elif [[ -f "$target" ]]; then
|
||||||
|
echo "⚠️ $filename exists but is not a link (copied file)"
|
||||||
|
else
|
||||||
|
echo "❌ $filename not found in active systemd"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "📊 Summary:"
|
||||||
|
echo " Repository files: $(find systemd -name 'aitbc-*' -type f | wc -l)"
|
||||||
|
echo " Active files: $(find /etc/systemd/system -name 'aitbc-*' -type f | wc -l)"
|
||||||
|
echo " Symbolic links: $(find /etc/systemd/system -name 'aitbc-*' -type l | wc -l)"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "⚠️ Cannot verify without root privileges"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Service Status Check
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
echo "=== SERVICE STATUS CHECK ==="
|
||||||
|
|
||||||
|
if [[ $EUID -eq 0 ]]; then
|
||||||
|
echo "🔍 Checking AITBC service status..."
|
||||||
|
|
||||||
|
# Check if services are enabled
|
||||||
|
echo "Enabled services:"
|
||||||
|
systemctl list-unit-files 'aitbc-*' --state=enabled | head -5 || echo "No enabled services found"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Failed services:"
|
||||||
|
systemctl list-units 'aitbc-*' --state=failed | head -5 || echo "No failed services found"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Running services:"
|
||||||
|
systemctl list-units 'aitbc-*' --state=running | head -5 || echo "No running services found"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "⚠️ Cannot check service status without root privileges"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Instructions
|
||||||
|
run: |
|
||||||
|
echo "=== SYSTEMD SYNC INSTRUCTIONS ==="
|
||||||
|
echo
|
||||||
|
echo "🔧 Manual sync (if needed):"
|
||||||
|
echo " sudo ./scripts/link-systemd.sh"
|
||||||
|
echo
|
||||||
|
echo "🔄 Restart services:"
|
||||||
|
echo " sudo systemctl restart aitbc-blockchain-node"
|
||||||
|
echo " sudo systemctl restart aitbc-coordinator-api"
|
||||||
|
echo " sudo systemctl restart aitbc-*"
|
||||||
|
echo
|
||||||
|
echo "🔍 Check status:"
|
||||||
|
echo " sudo systemctl status aitbc-*"
|
||||||
|
echo
|
||||||
|
echo "🔍 Verify links:"
|
||||||
|
echo " ls -la /etc/systemd/system/aitbc-*"
|
||||||
|
echo " readlink /etc/systemd/system/aitbc-blockchain-node.service"
|
||||||
108
scripts/link-systemd.sh
Executable file
108
scripts/link-systemd.sh
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# AITBC Systemd Link Script
|
||||||
|
# Creates symbolic links from active systemd to repository systemd files
|
||||||
|
# Keeps active systemd always in sync with repository
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_SYSTEMD_DIR="/opt/aitbc/systemd"
|
||||||
|
ACTIVE_SYSTEMD_DIR="/etc/systemd/system"
|
||||||
|
|
||||||
|
echo "=== AITBC SYSTEMD LINKING ==="
|
||||||
|
echo "Repository: $REPO_SYSTEMD_DIR"
|
||||||
|
echo "Active: $ACTIVE_SYSTEMD_DIR"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "❌ This script must be run as root (use sudo)"
|
||||||
|
echo " sudo $0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if repository systemd directory exists
|
||||||
|
if [[ ! -d "$REPO_SYSTEMD_DIR" ]]; then
|
||||||
|
echo "❌ Repository systemd directory not found: $REPO_SYSTEMD_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Creating symbolic links for AITBC systemd files..."
|
||||||
|
|
||||||
|
# Create backup of current active systemd files
|
||||||
|
BACKUP_DIR="/opt/aitbc/systemd-backup-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
echo "📦 Creating backup: $BACKUP_DIR"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
find "$ACTIVE_SYSTEMD_DIR" -name "aitbc-*" -type f -exec cp {} "$BACKUP_DIR/" \; 2>/dev/null || true
|
||||||
|
|
||||||
|
# Remove existing aitbc-* files (but not directories)
|
||||||
|
echo "🧹 Removing existing systemd files..."
|
||||||
|
find "$ACTIVE_SYSTEMD_DIR" -name "aitbc-*" -type f -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
# Create symbolic links
|
||||||
|
echo "🔗 Creating symbolic links..."
|
||||||
|
linked_files=0
|
||||||
|
for file in "$REPO_SYSTEMD_DIR"/aitbc-*; do
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
filename=$(basename "$file")
|
||||||
|
target="$ACTIVE_SYSTEMD_DIR/$filename"
|
||||||
|
source="$REPO_SYSTEMD_DIR/$filename"
|
||||||
|
|
||||||
|
echo " 🔗 Linking: $filename -> $source"
|
||||||
|
|
||||||
|
# Create symbolic link
|
||||||
|
ln -sf "$source" "$target"
|
||||||
|
|
||||||
|
# Handle .d directories
|
||||||
|
if [[ -d "${file}.d" ]]; then
|
||||||
|
target_dir="${target}.d"
|
||||||
|
source_dir="${file}.d"
|
||||||
|
|
||||||
|
echo " 📁 Linking directory: ${filename}.d -> ${source_dir}"
|
||||||
|
|
||||||
|
# Remove existing directory
|
||||||
|
rm -rf "$target_dir" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Create symbolic link for directory
|
||||||
|
ln -sf "$source_dir" "$target_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
((linked_files++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "🔄 Reloading systemd daemon..."
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "✅ Systemd linking completed!"
|
||||||
|
echo
|
||||||
|
echo "📊 Link Summary:"
|
||||||
|
echo " Linked files: $linked_files"
|
||||||
|
echo " Repository: $REPO_SYSTEMD_DIR"
|
||||||
|
echo " Active: $ACTIVE_SYSTEMD_DIR"
|
||||||
|
echo " Backup location: $BACKUP_DIR"
|
||||||
|
echo
|
||||||
|
echo "🎯 Benefits:"
|
||||||
|
echo " ✅ Active systemd files always match repository"
|
||||||
|
echo " ✅ No gap between repo and running services"
|
||||||
|
echo " ✅ Changes in repo immediately reflected"
|
||||||
|
echo " ✅ Automatic sync on every repository update"
|
||||||
|
echo
|
||||||
|
echo "🔧 To restart services:"
|
||||||
|
echo " sudo systemctl restart aitbc-blockchain-node"
|
||||||
|
echo " sudo systemctl restart aitbc-coordinator-api"
|
||||||
|
echo " # ... or restart all AITBC services:"
|
||||||
|
echo " sudo systemctl restart aitbc-*"
|
||||||
|
echo
|
||||||
|
echo "🔍 To check status:"
|
||||||
|
echo " sudo systemctl status aitbc-*"
|
||||||
|
echo
|
||||||
|
echo "🔍 To verify links:"
|
||||||
|
echo " ls -la /etc/systemd/system/aitbc-*"
|
||||||
|
echo " readlink /etc/systemd/system/aitbc-blockchain-node.service"
|
||||||
|
echo
|
||||||
|
echo "⚠️ If you need to restore backup:"
|
||||||
|
echo " sudo cp $BACKUP_DIR/* /etc/systemd/system/"
|
||||||
|
echo " sudo systemctl daemon-reload"
|
||||||
87
scripts/sync-systemd.sh
Executable file
87
scripts/sync-systemd.sh
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# AITBC Systemd Sync Script
|
||||||
|
# Syncs repository systemd files to active systemd configuration
|
||||||
|
# Eliminates gap between repo and running services
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_SYSTEMD_DIR="/opt/aitbc/systemd"
|
||||||
|
ACTIVE_SYSTEMD_DIR="/etc/systemd/system"
|
||||||
|
|
||||||
|
echo "=== AITBC SYSTEMD SYNC ==="
|
||||||
|
echo "Repository: $REPO_SYSTEMD_DIR"
|
||||||
|
echo "Active: $ACTIVE_SYSTEMD_DIR"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "❌ This script must be run as root (use sudo)"
|
||||||
|
echo " sudo $0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if repository systemd directory exists
|
||||||
|
if [[ ! -d "$REPO_SYSTEMD_DIR" ]]; then
|
||||||
|
echo "❌ Repository systemd directory not found: $REPO_SYSTEMD_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Scanning for AITBC systemd files..."
|
||||||
|
|
||||||
|
# Create backup of current active systemd files
|
||||||
|
BACKUP_DIR="/opt/aitbc/systemd-backup-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
echo "📦 Creating backup: $BACKUP_DIR"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
find "$ACTIVE_SYSTEMD_DIR" -name "aitbc-*" -type f -exec cp {} "$BACKUP_DIR/" \;
|
||||||
|
|
||||||
|
# Sync repository files to active systemd
|
||||||
|
echo "🔄 Syncing systemd files..."
|
||||||
|
|
||||||
|
# Copy all aitbc-* files from repo to active systemd
|
||||||
|
for file in "$REPO_SYSTEMD_DIR"/aitbc-*; do
|
||||||
|
if [[ -f "$file" ]]; then
|
||||||
|
filename=$(basename "$file")
|
||||||
|
target="$ACTIVE_SYSTEMD_DIR/$filename"
|
||||||
|
|
||||||
|
echo " 📄 Syncing: $filename"
|
||||||
|
|
||||||
|
# Copy file with proper permissions
|
||||||
|
cp "$file" "$target"
|
||||||
|
chmod 644 "$target"
|
||||||
|
|
||||||
|
# Handle .d directories
|
||||||
|
if [[ -d "${file}.d" ]]; then
|
||||||
|
target_dir="${target}.d"
|
||||||
|
echo " 📁 Syncing directory: ${filename}.d"
|
||||||
|
mkdir -p "$target_dir"
|
||||||
|
cp -r "${file}.d"/* "$target_dir/"
|
||||||
|
chmod 644 "$target_dir"/*
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "🔄 Reloading systemd daemon..."
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "✅ Systemd sync completed!"
|
||||||
|
echo
|
||||||
|
echo "📊 Sync Summary:"
|
||||||
|
echo " Repository files: $(find "$REPO_SYSTEMD_DIR" -name 'aitbc-*' -type f | wc -l)"
|
||||||
|
echo " Active files: $(find "$ACTIVE_SYSTEMD_DIR" -name 'aitbc-*' -type f | wc -l)"
|
||||||
|
echo " Backup location: $BACKUP_DIR"
|
||||||
|
echo
|
||||||
|
echo "🔧 To restart services:"
|
||||||
|
echo " sudo systemctl restart aitbc-blockchain-node"
|
||||||
|
echo " sudo systemctl restart aitbc-coordinator-api"
|
||||||
|
echo " # ... or restart all AITBC services:"
|
||||||
|
echo " sudo systemctl restart aitbc-*"
|
||||||
|
echo
|
||||||
|
echo "🔍 To check status:"
|
||||||
|
echo " sudo systemctl status aitbc-*"
|
||||||
|
echo
|
||||||
|
echo "⚠️ If you need to restore backup:"
|
||||||
|
echo " sudo cp $BACKUP_DIR/* /etc/systemd/system/"
|
||||||
|
echo " sudo systemctl daemon-reload"
|
||||||
Reference in New Issue
Block a user