Files
ServerKit/serverkit
T
Juan Denis c95d01b2fb Refactor to run backend on host, frontend in Docker
Removed docker-compose.prod.yml and updated docker-compose.yml to only run the frontend in Docker, with the backend now running as a systemd service on the host. Updated nginx and frontend nginx.conf to proxy API requests to the backend on the host. Added serverkit-backend.service for systemd management of the backend. Refactored install.sh and serverkit CLI to support the new architecture, including improved installation, update, and management commands.
2026-01-18 21:15:31 -05:00

484 lines
11 KiB
Bash

#!/bin/bash
#
# ServerKit CLI - Management tool for ServerKit
#
# Architecture:
# - Backend: systemd service (runs directly on host)
# - Frontend: Docker container (nginx)
#
# Usage: serverkit <command> [options]
#
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Configuration
INSTALL_DIR="${SERVERKIT_DIR:-/opt/serverkit}"
VENV_DIR="$INSTALL_DIR/venv"
BACKEND_SERVICE="serverkit"
FRONTEND_CONTAINER="serverkit-frontend"
# Helper functions
print_header() {
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE} ServerKit CLI${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
print_success() { echo -e "${GREEN}✓ $1${NC}"; }
print_error() { echo -e "${RED}✗ $1${NC}"; }
print_warning() { echo -e "${YELLOW}! $1${NC}"; }
print_info() { echo -e "${BLUE}→ $1${NC}"; }
check_root() {
if [ "$EUID" -ne 0 ]; then
print_error "This command requires root privileges. Run with sudo."
exit 1
fi
}
check_installed() {
if [ ! -d "$INSTALL_DIR" ]; then
print_error "ServerKit is not installed in $INSTALL_DIR"
print_info "Run the install script first"
exit 1
fi
}
run_cli() {
# Run CLI commands directly on host using the virtual environment
cd "$INSTALL_DIR/backend"
source "$VENV_DIR/bin/activate"
python cli.py "$@"
}
# Commands
cmd_help() {
print_header
echo ""
echo "Usage: serverkit <command> [options]"
echo ""
echo "Service Commands:"
echo " start Start all services"
echo " stop Stop all services"
echo " restart Restart all services"
echo " status Show service status"
echo " logs [service] View logs (backend, frontend, or all)"
echo " update Update to latest version"
echo " uninstall Uninstall ServerKit"
echo ""
echo "User Management:"
echo " create-admin Create a new admin user"
echo " reset-password Reset a user's password"
echo " unlock-user Unlock a locked user account"
echo " list-users List all users"
echo " make-admin Promote user to admin"
echo " deactivate-user Deactivate a user account"
echo " activate-user Activate a user account"
echo ""
echo "Database Commands:"
echo " init-db Initialize the database"
echo " backup-db Backup the database"
echo " restore-db Restore database from backup"
echo ""
echo "Utility Commands:"
echo " generate-keys Generate secure keys for .env"
echo " config Edit configuration"
echo ""
echo "Examples:"
echo " sudo serverkit start"
echo " sudo serverkit create-admin"
echo " serverkit logs backend"
echo ""
}
cmd_start() {
check_root
check_installed
print_info "Starting ServerKit..."
# Start backend (systemd)
systemctl start $BACKEND_SERVICE
# Start frontend (Docker)
cd "$INSTALL_DIR"
docker compose up -d
sleep 3
print_success "ServerKit started"
cmd_status_brief
}
cmd_stop() {
check_root
check_installed
print_info "Stopping ServerKit..."
# Stop backend (systemd)
systemctl stop $BACKEND_SERVICE || true
# Stop frontend (Docker)
cd "$INSTALL_DIR"
docker compose down || true
print_success "ServerKit stopped"
}
cmd_restart() {
check_root
check_installed
print_info "Restarting ServerKit..."
# Restart backend (systemd)
systemctl restart $BACKEND_SERVICE
# Restart frontend (Docker)
cd "$INSTALL_DIR"
docker compose restart
sleep 3
print_success "ServerKit restarted"
cmd_status_brief
}
cmd_status_brief() {
# Quick status check
echo ""
# Backend status
if systemctl is-active --quiet $BACKEND_SERVICE; then
print_success "Backend: running"
else
print_error "Backend: stopped"
fi
# Frontend status
if docker ps --format '{{.Names}}' | grep -q $FRONTEND_CONTAINER; then
print_success "Frontend: running"
else
print_error "Frontend: stopped"
fi
# API health
if curl -s http://127.0.0.1:5000/api/v1/system/health > /dev/null 2>&1; then
print_success "API: healthy"
else
print_warning "API: not responding"
fi
}
cmd_status() {
check_installed
print_header
echo ""
echo "Backend Service (systemd):"
echo "─────────────────────────────"
systemctl status $BACKEND_SERVICE --no-pager -l 2>/dev/null || print_warning "Backend service not found"
echo ""
echo "Frontend Container (Docker):"
echo "─────────────────────────────"
cd "$INSTALL_DIR"
docker compose ps 2>/dev/null || print_warning "Frontend container not found"
echo ""
cmd_status_brief
}
cmd_logs() {
check_installed
service="${1:-all}"
case "$service" in
backend)
journalctl -u $BACKEND_SERVICE -f
;;
frontend)
cd "$INSTALL_DIR"
docker compose logs -f
;;
all|*)
print_info "Showing backend logs (Ctrl+C to switch to frontend)..."
echo ""
# Show both in split view isn't easy in bash, so show backend first
journalctl -u $BACKEND_SERVICE -n 50 --no-pager
echo ""
print_info "Showing frontend logs..."
echo ""
cd "$INSTALL_DIR"
docker compose logs --tail=50
echo ""
print_info "For live logs, use: serverkit logs backend OR serverkit logs frontend"
;;
esac
}
cmd_update() {
check_root
check_installed
print_header
echo ""
print_info "Updating ServerKit..."
cd "$INSTALL_DIR"
# Store current version
CURRENT_VERSION=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
# Stop services
print_info "Stopping services..."
systemctl stop $BACKEND_SERVICE || true
docker compose down || true
# Pull latest changes
print_info "Pulling latest changes..."
git fetch origin
git reset --hard origin/main
NEW_VERSION=$(git rev-parse --short HEAD)
# Update Python dependencies
print_info "Updating Python dependencies..."
source "$VENV_DIR/bin/activate"
pip install -r "$INSTALL_DIR/backend/requirements.txt" --quiet
# Rebuild frontend
print_info "Rebuilding frontend..."
docker compose build
# Reload systemd in case service file changed
systemctl daemon-reload
# Restart services
print_info "Starting services..."
systemctl start $BACKEND_SERVICE
docker compose up -d
sleep 5
echo ""
print_success "ServerKit updated!"
echo " Previous version: $CURRENT_VERSION"
echo " Current version: $NEW_VERSION"
echo ""
cmd_status_brief
}
cmd_uninstall() {
check_root
print_header
echo ""
print_warning "This will remove ServerKit and all data!"
read -p "Are you sure? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "Stopping services..."
systemctl stop $BACKEND_SERVICE 2>/dev/null || true
systemctl disable $BACKEND_SERVICE 2>/dev/null || true
cd "$INSTALL_DIR" 2>/dev/null && docker compose down -v 2>/dev/null || true
print_info "Removing files..."
rm -f /etc/systemd/system/serverkit.service
rm -f /usr/local/bin/serverkit
rm -rf "$INSTALL_DIR"
rm -rf /var/log/serverkit
rm -rf /var/lib/serverkit
systemctl daemon-reload
print_success "ServerKit uninstalled"
fi
}
cmd_create_admin() {
check_installed
print_info "Creating admin user..."
run_cli create-admin
}
cmd_reset_password() {
check_installed
print_info "Resetting password..."
run_cli reset-password
}
cmd_unlock_user() {
check_installed
run_cli unlock-user
}
cmd_list_users() {
check_installed
run_cli list-users
}
cmd_make_admin() {
check_installed
run_cli make-admin
}
cmd_deactivate_user() {
check_installed
run_cli deactivate-user
}
cmd_activate_user() {
check_installed
run_cli activate-user
}
cmd_init_db() {
check_installed
run_cli init-db
}
cmd_backup_db() {
check_installed
BACKUP_DIR="$INSTALL_DIR/backups"
BACKUP_FILE="$BACKUP_DIR/serverkit-$(date +%Y%m%d-%H%M%S).db"
DB_FILE="$INSTALL_DIR/backend/instance/serverkit.db"
mkdir -p "$BACKUP_DIR"
if [ -f "$DB_FILE" ]; then
cp "$DB_FILE" "$BACKUP_FILE"
print_success "Database backed up to $BACKUP_FILE"
else
print_error "Database file not found: $DB_FILE"
exit 1
fi
}
cmd_restore_db() {
check_root
check_installed
BACKUP_DIR="$INSTALL_DIR/backups"
DB_FILE="$INSTALL_DIR/backend/instance/serverkit.db"
if [ -z "$1" ]; then
echo "Available backups:"
ls -la "$BACKUP_DIR"/*.db 2>/dev/null || echo "No backups found"
echo ""
read -p "Enter backup file path: " BACKUP_FILE
else
BACKUP_FILE="$1"
fi
if [ ! -f "$BACKUP_FILE" ]; then
print_error "Backup file not found: $BACKUP_FILE"
exit 1
fi
print_warning "This will overwrite the current database!"
read -p "Continue? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
# Stop backend before restore
systemctl stop $BACKEND_SERVICE
cp "$BACKUP_FILE" "$DB_FILE"
# Restart backend
systemctl start $BACKEND_SERVICE
print_success "Database restored"
fi
}
cmd_generate_keys() {
print_header
echo ""
echo "Add these to your .env file:"
echo ""
SECRET_KEY=$(openssl rand -hex 32)
JWT_SECRET_KEY=$(openssl rand -hex 32)
echo "SECRET_KEY=$SECRET_KEY"
echo "JWT_SECRET_KEY=$JWT_SECRET_KEY"
echo ""
}
cmd_config() {
check_installed
${EDITOR:-nano} "$INSTALL_DIR/.env"
print_info "Restart ServerKit to apply changes: sudo serverkit restart"
}
# Main
case "${1:-help}" in
help|--help|-h)
cmd_help
;;
start)
cmd_start
;;
stop)
cmd_stop
;;
restart)
cmd_restart
;;
status)
cmd_status
;;
logs)
cmd_logs "$2"
;;
update)
cmd_update
;;
uninstall)
cmd_uninstall
;;
create-admin)
cmd_create_admin
;;
reset-password)
cmd_reset_password
;;
unlock-user)
cmd_unlock_user
;;
list-users)
cmd_list_users
;;
make-admin)
cmd_make_admin
;;
deactivate-user)
cmd_deactivate_user
;;
activate-user)
cmd_activate_user
;;
init-db)
cmd_init_db
;;
backup-db)
cmd_backup_db
;;
restore-db)
cmd_restore_db "$2"
;;
generate-keys)
cmd_generate_keys
;;
config)
cmd_config
;;
*)
print_error "Unknown command: $1"
echo "Run 'serverkit help' for usage"
exit 1
;;
esac