mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-26 13:06:57 +09:00
Added calls to serverkit.ai to track successful installation, update, and uninstall events with the current version. This helps monitor usage and improve support.
1055 lines
27 KiB
Bash
1055 lines
27 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 "$@"
|
|
}
|
|
|
|
# Version management
|
|
VERSION_FILE="$INSTALL_DIR/VERSION"
|
|
REMOTE_VERSION_URL="https://raw.githubusercontent.com/jhd3197/serverkit/main/VERSION"
|
|
|
|
get_local_version() {
|
|
if [ -f "$VERSION_FILE" ]; then
|
|
cat "$VERSION_FILE" | tr -d '\n\r '
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
get_remote_version() {
|
|
curl -sf "$REMOTE_VERSION_URL" 2>/dev/null | tr -d '\n\r ' || echo "unknown"
|
|
}
|
|
|
|
compare_versions() {
|
|
# Returns: 0 if equal, 1 if v1 > v2, 2 if v1 < v2
|
|
local v1="$1"
|
|
local v2="$2"
|
|
|
|
if [ "$v1" = "$v2" ]; then
|
|
return 0
|
|
fi
|
|
|
|
# Compare version components
|
|
local v1_major=$(echo "$v1" | cut -d. -f1)
|
|
local v1_minor=$(echo "$v1" | cut -d. -f2)
|
|
local v1_patch=$(echo "$v1" | cut -d. -f3)
|
|
|
|
local v2_major=$(echo "$v2" | cut -d. -f1)
|
|
local v2_minor=$(echo "$v2" | cut -d. -f2)
|
|
local v2_patch=$(echo "$v2" | cut -d. -f3)
|
|
|
|
if [ "$v1_major" -gt "$v2_major" ] 2>/dev/null; then return 1; fi
|
|
if [ "$v1_major" -lt "$v2_major" ] 2>/dev/null; then return 2; fi
|
|
if [ "$v1_minor" -gt "$v2_minor" ] 2>/dev/null; then return 1; fi
|
|
if [ "$v1_minor" -lt "$v2_minor" ] 2>/dev/null; then return 2; fi
|
|
if [ "$v1_patch" -gt "$v2_patch" ] 2>/dev/null; then return 1; fi
|
|
if [ "$v1_patch" -lt "$v2_patch" ] 2>/dev/null; then return 2; fi
|
|
|
|
return 0
|
|
}
|
|
|
|
cmd_version() {
|
|
local version=$(get_local_version)
|
|
echo "ServerKit version $version"
|
|
}
|
|
|
|
cmd_check_update() {
|
|
print_info "Checking for updates..."
|
|
|
|
local local_version=$(get_local_version)
|
|
local remote_version=$(get_remote_version)
|
|
|
|
echo ""
|
|
echo " Installed version: $local_version"
|
|
echo " Latest version: $remote_version"
|
|
echo ""
|
|
|
|
if [ "$remote_version" = "unknown" ]; then
|
|
print_warning "Could not check remote version (network error?)"
|
|
return 1
|
|
fi
|
|
|
|
set +e # Temporarily disable exit on error
|
|
compare_versions "$local_version" "$remote_version"
|
|
local result=$?
|
|
set -e # Re-enable exit on error
|
|
|
|
if [ $result -eq 2 ]; then
|
|
print_success "Update available! Run 'sudo serverkit update' to upgrade."
|
|
return 0
|
|
elif [ $result -eq 0 ]; then
|
|
print_success "You are running the latest version."
|
|
return 0
|
|
else
|
|
print_info "You are running a newer version than released."
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# 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 [options] Update ServerKit"
|
|
echo " --branch <name> Switch to specific branch (e.g., dev)"
|
|
echo " --force Skip version check"
|
|
echo " branch Show current branch"
|
|
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 " migrate-db Apply database migrations"
|
|
echo " backup-db Backup the database"
|
|
echo " restore-db Restore database from backup"
|
|
echo ""
|
|
echo "Cleanup Commands:"
|
|
echo " cleanup-apps Delete all apps and containers"
|
|
echo " factory-reset Complete reset (delete everything)"
|
|
echo ""
|
|
echo "App Management:"
|
|
echo " create-app Show how to create apps (via web UI)"
|
|
echo " list-apps [--all] List deployed apps (--all shows Docker containers)"
|
|
echo " start-app Start an app"
|
|
echo " stop-app Stop an app"
|
|
echo " app-logs View app logs"
|
|
echo ""
|
|
echo "Site Management:"
|
|
echo " setup-proxy Setup host nginx as reverse proxy (run once)"
|
|
echo " add-site Add a new site/domain"
|
|
echo " list-sites List all configured sites"
|
|
echo " remove-site Remove a site"
|
|
echo ""
|
|
echo "Version Commands:"
|
|
echo " version Show current version"
|
|
echo " check-update Check if updates are available"
|
|
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 " sudo serverkit add-site test.mysite.com 3000"
|
|
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_branch() {
|
|
check_installed
|
|
cd "$INSTALL_DIR"
|
|
|
|
local current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
local current_commit=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
|
|
echo ""
|
|
echo " Current branch: $current_branch"
|
|
echo " Current commit: $current_commit"
|
|
echo " Version: $(get_local_version)"
|
|
echo ""
|
|
|
|
# Show available remote branches
|
|
print_info "Available branches:"
|
|
git branch -r 2>/dev/null | grep -v HEAD | sed 's/origin\// /' | head -10
|
|
echo ""
|
|
}
|
|
|
|
cmd_update() {
|
|
local force_update=false
|
|
local target_branch=""
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--force|-f)
|
|
force_update=true
|
|
shift
|
|
;;
|
|
--branch|-b)
|
|
target_branch="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
check_root
|
|
check_installed
|
|
print_header
|
|
echo ""
|
|
|
|
cd "$INSTALL_DIR"
|
|
|
|
# Get current branch
|
|
local current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
|
|
# If no branch specified, use current branch (or main if detached)
|
|
if [ -z "$target_branch" ]; then
|
|
target_branch="$current_branch"
|
|
if [ "$target_branch" = "HEAD" ]; then
|
|
target_branch="main"
|
|
fi
|
|
fi
|
|
|
|
# Get versions
|
|
CURRENT_VERSION=$(get_local_version)
|
|
|
|
# For non-main branches, skip version comparison
|
|
if [ "$target_branch" != "main" ]; then
|
|
force_update=true
|
|
print_warning "Updating to branch: $target_branch (dev mode)"
|
|
echo ""
|
|
else
|
|
REMOTE_VERSION=$(get_remote_version)
|
|
echo " Installed version: $CURRENT_VERSION"
|
|
echo " Latest version: $REMOTE_VERSION"
|
|
echo ""
|
|
fi
|
|
|
|
# Check if update is needed (skip if --force or non-main branch)
|
|
if [ "$force_update" = false ] && [ "$REMOTE_VERSION" != "unknown" ]; then
|
|
set +e # Temporarily disable exit on error
|
|
compare_versions "$CURRENT_VERSION" "$REMOTE_VERSION"
|
|
local result=$?
|
|
set -e # Re-enable exit on error
|
|
if [ $result -eq 0 ]; then
|
|
print_success "Already running the latest version."
|
|
echo ""
|
|
read -p "Force update anyway? [y/N] " -n 1 -r
|
|
echo ""
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
exit 0
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
print_info "Updating ServerKit to branch: $target_branch..."
|
|
|
|
# Stop services
|
|
print_info "Stopping services..."
|
|
systemctl stop $BACKEND_SERVICE || true
|
|
docker compose down || true
|
|
|
|
# Fetch all branches and pull changes
|
|
print_info "Fetching latest changes..."
|
|
git fetch origin --prune
|
|
|
|
# Checkout target branch
|
|
print_info "Switching to branch: $target_branch..."
|
|
git checkout "$target_branch" 2>/dev/null || git checkout -b "$target_branch" "origin/$target_branch"
|
|
git reset --hard "origin/$target_branch"
|
|
|
|
# Restore executable permissions
|
|
chmod +x "$INSTALL_DIR/serverkit"
|
|
chmod +x "$INSTALL_DIR/scripts/"*.sh 2>/dev/null || true
|
|
|
|
# Get new version from VERSION file
|
|
NEW_VERSION=$(get_local_version)
|
|
NEW_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
|
|
# Update Python dependencies
|
|
print_info "Updating Python dependencies..."
|
|
source "$VENV_DIR/bin/activate"
|
|
pip install -r "$INSTALL_DIR/backend/requirements.txt" --quiet
|
|
|
|
# Sync app templates
|
|
print_info "Syncing app templates..."
|
|
mkdir -p /etc/serverkit/templates
|
|
cp -r "$INSTALL_DIR/backend/templates/"*.yaml /etc/serverkit/templates/ 2>/dev/null || true
|
|
cp -r "$INSTALL_DIR/backend/templates/"*.yml /etc/serverkit/templates/ 2>/dev/null || true
|
|
|
|
# Clean up Docker to prevent networking issues
|
|
print_info "Cleaning up Docker..."
|
|
docker network prune -f 2>/dev/null || true
|
|
docker system prune -f 2>/dev/null || true
|
|
|
|
# Rebuild frontend (no cache to ensure fresh build)
|
|
print_info "Rebuilding frontend..."
|
|
docker compose build --no-cache
|
|
|
|
# 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
|
|
|
|
# Track successful update
|
|
curl -s "https://serverkit.ai/track/update?v=${NEW_VERSION}" >/dev/null 2>&1 || true
|
|
|
|
echo ""
|
|
print_success "ServerKit updated!"
|
|
echo " Branch: $target_branch"
|
|
echo " Commit: $NEW_COMMIT"
|
|
echo " Version: $NEW_VERSION"
|
|
echo ""
|
|
|
|
if [ "$target_branch" != "main" ]; then
|
|
print_warning "Running on '$target_branch' branch. Use 'serverkit update --branch main' to return to stable."
|
|
fi
|
|
|
|
cmd_status_brief
|
|
}
|
|
|
|
cmd_uninstall() {
|
|
check_root
|
|
print_header
|
|
echo ""
|
|
print_warning "This will remove ServerKit and all data!"
|
|
echo ""
|
|
echo "The following will be removed:"
|
|
echo " - ServerKit backend service (systemd)"
|
|
echo " - Frontend Docker container and images"
|
|
echo " - Installation directory ($INSTALL_DIR)"
|
|
echo " - Configuration (/etc/serverkit)"
|
|
echo " - App data (/var/serverkit)"
|
|
echo " - Logs (/var/log/serverkit)"
|
|
echo " - Nginx site configs for ServerKit"
|
|
echo " - CLI symlink (/usr/local/bin/serverkit)"
|
|
echo ""
|
|
read -p "Are you sure? (y/N) " -n 1 -r
|
|
echo
|
|
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
# Track uninstall before removing files
|
|
UNINSTALL_VERSION=$(get_local_version)
|
|
curl -s "https://serverkit.ai/track/uninstall?v=${UNINSTALL_VERSION}" >/dev/null 2>&1 || true
|
|
|
|
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
|
|
|
|
# Move to safe directory before deleting install dir
|
|
cd /tmp 2>/dev/null || cd / || 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
|
|
|
|
# Remove ServerKit config and app data
|
|
rm -rf /etc/serverkit
|
|
rm -rf /var/serverkit
|
|
|
|
# Remove nginx site configs installed by ServerKit
|
|
print_info "Removing nginx configs..."
|
|
rm -f /etc/nginx/sites-enabled/serverkit.conf
|
|
rm -f /etc/nginx/sites-available/serverkit.conf
|
|
rm -f /etc/nginx/sites-available/example.conf.template
|
|
# Reload nginx if it's still running (don't stop it — user may use it for other sites)
|
|
if systemctl is-active --quiet nginx 2>/dev/null; then
|
|
systemctl reload nginx 2>/dev/null || true
|
|
fi
|
|
|
|
systemctl daemon-reload
|
|
|
|
print_success "ServerKit uninstalled"
|
|
echo ""
|
|
echo "Note: System packages (Docker, Node.js, nginx, Python) were NOT removed."
|
|
echo "Remove them manually if no longer needed."
|
|
echo ""
|
|
echo "To reinstall, run:"
|
|
echo " cd ~ && curl -fsSL https://serverkit.ai/install.sh | sudo bash"
|
|
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_migrate_db() {
|
|
check_installed
|
|
run_cli migrate-db
|
|
}
|
|
|
|
cmd_cleanup_apps() {
|
|
check_root
|
|
check_installed
|
|
|
|
DELETE_VOLUMES=""
|
|
KEEP_DB=""
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--delete-volumes|-v)
|
|
DELETE_VOLUMES="--delete-volumes"
|
|
shift
|
|
;;
|
|
--keep-db|-k)
|
|
KEEP_DB="--keep-db"
|
|
shift
|
|
;;
|
|
*)
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
run_cli cleanup-apps $DELETE_VOLUMES $KEEP_DB
|
|
}
|
|
|
|
cmd_factory_reset() {
|
|
check_root
|
|
check_installed
|
|
run_cli factory-reset
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
cmd_setup_proxy() {
|
|
check_root
|
|
check_installed
|
|
print_info "Setting up host nginx as reverse proxy..."
|
|
|
|
if [ -f "$INSTALL_DIR/scripts/setup-nginx-proxy.sh" ]; then
|
|
chmod +x "$INSTALL_DIR/scripts/setup-nginx-proxy.sh"
|
|
"$INSTALL_DIR/scripts/setup-nginx-proxy.sh"
|
|
else
|
|
print_error "Setup script not found. Run 'serverkit update' first."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
cmd_create_app() {
|
|
print_header
|
|
echo ""
|
|
echo "To create a new app, use the ServerKit web interface:"
|
|
echo ""
|
|
echo " 1. Open ServerKit in your browser"
|
|
echo " 2. Go to Templates in the sidebar"
|
|
echo " 3. Choose from 60+ available templates:"
|
|
echo " - PHP Application (custom PHP projects)"
|
|
echo " - Python Application (Flask, FastAPI, Django)"
|
|
echo " - Node.js Application (Express, Next.js)"
|
|
echo " - WordPress, Ghost, Nextcloud, and many more"
|
|
echo " 4. Click Install and configure your app"
|
|
echo ""
|
|
echo "The web interface provides:"
|
|
echo " ✓ One-click installation"
|
|
echo " ✓ Automatic port assignment"
|
|
echo " ✓ Configuration UI"
|
|
echo " ✓ Update management"
|
|
echo ""
|
|
}
|
|
|
|
cmd_list_apps() {
|
|
check_installed
|
|
# Pass --all flag if provided
|
|
if [ "$1" = "--all" ] || [ "$1" = "-a" ]; then
|
|
run_cli list-apps --all
|
|
else
|
|
run_cli list-apps
|
|
fi
|
|
}
|
|
|
|
cmd_start_app() {
|
|
check_root
|
|
NAME="$1"
|
|
|
|
if [ -z "$NAME" ]; then
|
|
echo "Usage: serverkit start-app <name>"
|
|
cmd_list_apps
|
|
exit 1
|
|
fi
|
|
|
|
APP_DIR="/var/www/$NAME"
|
|
if [ ! -d "$APP_DIR" ]; then
|
|
print_error "App not found: $NAME"
|
|
exit 1
|
|
fi
|
|
|
|
print_info "Starting $NAME..."
|
|
cd "$APP_DIR"
|
|
docker compose up -d
|
|
print_success "$NAME started"
|
|
}
|
|
|
|
cmd_stop_app() {
|
|
check_root
|
|
NAME="$1"
|
|
|
|
if [ -z "$NAME" ]; then
|
|
echo "Usage: serverkit stop-app <name>"
|
|
cmd_list_apps
|
|
exit 1
|
|
fi
|
|
|
|
APP_DIR="/var/www/$NAME"
|
|
if [ ! -d "$APP_DIR" ]; then
|
|
print_error "App not found: $NAME"
|
|
exit 1
|
|
fi
|
|
|
|
print_info "Stopping $NAME..."
|
|
cd "$APP_DIR"
|
|
docker compose down
|
|
print_success "$NAME stopped"
|
|
}
|
|
|
|
cmd_app_logs() {
|
|
NAME="$1"
|
|
|
|
if [ -z "$NAME" ]; then
|
|
echo "Usage: serverkit app-logs <name>"
|
|
cmd_list_apps
|
|
exit 1
|
|
fi
|
|
|
|
APP_DIR="/var/www/$NAME"
|
|
if [ ! -d "$APP_DIR" ]; then
|
|
print_error "App not found: $NAME"
|
|
exit 1
|
|
fi
|
|
|
|
cd "$APP_DIR"
|
|
docker compose logs -f
|
|
}
|
|
|
|
cmd_add_site() {
|
|
check_root
|
|
|
|
DOMAIN="$1"
|
|
PORT="${2:-3000}"
|
|
|
|
if [ -z "$DOMAIN" ]; then
|
|
echo "Usage: serverkit add-site <domain> [port]"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " serverkit add-site test.builditdesign.com"
|
|
echo " serverkit add-site myapp.builditdesign.com 3000"
|
|
exit 1
|
|
fi
|
|
|
|
SITE_FILE="/etc/nginx/sites-available/${DOMAIN}.conf"
|
|
|
|
if [ -f "$SITE_FILE" ]; then
|
|
print_warning "Site config already exists: $SITE_FILE"
|
|
read -p "Overwrite? (y/N) " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
print_info "Creating site config for $DOMAIN..."
|
|
|
|
cat > "$SITE_FILE" << EOF
|
|
# Site: $DOMAIN
|
|
# Created: $(date)
|
|
|
|
server {
|
|
listen 80;
|
|
server_name $DOMAIN;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:$PORT;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
}
|
|
EOF
|
|
|
|
# Enable the site
|
|
ln -sf "$SITE_FILE" /etc/nginx/sites-enabled/
|
|
|
|
# Test and reload nginx
|
|
if nginx -t 2>/dev/null; then
|
|
systemctl reload nginx
|
|
print_success "Site added: $DOMAIN → localhost:$PORT"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Add DNS record in Cloudflare:"
|
|
echo " Type: A, Name: ${DOMAIN%%.*}, Content: $(curl -s ifconfig.me)"
|
|
echo " 2. Start your app on port $PORT"
|
|
echo ""
|
|
else
|
|
print_error "Nginx config error. Check: $SITE_FILE"
|
|
rm -f "/etc/nginx/sites-enabled/${DOMAIN}.conf"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
cmd_list_sites() {
|
|
print_header
|
|
echo ""
|
|
echo "Configured Sites:"
|
|
echo "─────────────────────────────────────────"
|
|
|
|
if [ -d /etc/nginx/sites-enabled ]; then
|
|
for site in /etc/nginx/sites-enabled/*.conf; do
|
|
if [ -f "$site" ]; then
|
|
DOMAIN=$(grep -m1 "server_name" "$site" | awk '{print $2}' | tr -d ';')
|
|
PORT=$(grep -m1 "proxy_pass" "$site" | grep -oP ':\K[0-9]+' || echo "static")
|
|
ENABLED="✓"
|
|
printf " %s %-35s → port %s\n" "$ENABLED" "$DOMAIN" "$PORT"
|
|
fi
|
|
done
|
|
else
|
|
echo " No sites configured. Run 'serverkit setup-proxy' first."
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
cmd_remove_site() {
|
|
check_root
|
|
|
|
DOMAIN="$1"
|
|
|
|
if [ -z "$DOMAIN" ]; then
|
|
echo "Usage: serverkit remove-site <domain>"
|
|
cmd_list_sites
|
|
exit 1
|
|
fi
|
|
|
|
SITE_FILE="/etc/nginx/sites-available/${DOMAIN}.conf"
|
|
ENABLED_FILE="/etc/nginx/sites-enabled/${DOMAIN}.conf"
|
|
|
|
if [ ! -f "$SITE_FILE" ]; then
|
|
print_error "Site not found: $DOMAIN"
|
|
exit 1
|
|
fi
|
|
|
|
print_warning "This will remove the site config for $DOMAIN"
|
|
read -p "Continue? (y/N) " -n 1 -r
|
|
echo
|
|
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
rm -f "$ENABLED_FILE"
|
|
rm -f "$SITE_FILE"
|
|
systemctl reload nginx
|
|
print_success "Site removed: $DOMAIN"
|
|
fi
|
|
}
|
|
|
|
# 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)
|
|
shift
|
|
cmd_update "$@"
|
|
;;
|
|
branch)
|
|
cmd_branch
|
|
;;
|
|
version|--version|-v)
|
|
cmd_version
|
|
;;
|
|
check-update)
|
|
cmd_check_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
|
|
;;
|
|
migrate-db)
|
|
cmd_migrate_db
|
|
;;
|
|
cleanup-apps)
|
|
shift
|
|
cmd_cleanup_apps "$@"
|
|
;;
|
|
factory-reset)
|
|
cmd_factory_reset
|
|
;;
|
|
backup-db)
|
|
cmd_backup_db
|
|
;;
|
|
restore-db)
|
|
cmd_restore_db "$2"
|
|
;;
|
|
generate-keys)
|
|
cmd_generate_keys
|
|
;;
|
|
config)
|
|
cmd_config
|
|
;;
|
|
setup-proxy)
|
|
cmd_setup_proxy
|
|
;;
|
|
create-app)
|
|
cmd_create_app "$2" "$3" "$4"
|
|
;;
|
|
list-apps)
|
|
cmd_list_apps "$2"
|
|
;;
|
|
start-app)
|
|
cmd_start_app "$2"
|
|
;;
|
|
stop-app)
|
|
cmd_stop_app "$2"
|
|
;;
|
|
app-logs)
|
|
cmd_app_logs "$2"
|
|
;;
|
|
add-site)
|
|
cmd_add_site "$2" "$3"
|
|
;;
|
|
list-sites)
|
|
cmd_list_sites
|
|
;;
|
|
remove-site)
|
|
cmd_remove_site "$2"
|
|
;;
|
|
*)
|
|
print_error "Unknown command: $1"
|
|
echo "Run 'serverkit help' for usage"
|
|
exit 1
|
|
;;
|
|
esac
|