feat: add systemd sync solution to eliminate repo/active gap
Some checks failed
systemd-sync / sync-systemd (push) Failing after 2s
security-scanning / audit (push) Successful in 1m36s

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:
2026-03-27 22:55:55 +01:00
parent 36a5bd229a
commit 35fc07977f
3 changed files with 376 additions and 0 deletions

View 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
View 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
View 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"