mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-28 15:47:50 +09:00
- Add 'serverkit update --branch <name>' to switch branches - Add 'serverkit branch' command to show current branch - Skip version check for non-main branches (dev mode) - Show commit hash and branch in update output - Warn users when running on non-main branch Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1020 lines
26 KiB
Bash
1020 lines
26 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
|
|
|
|
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!"
|
|
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
|
|
|
|
# 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
|
|
|
|
systemctl daemon-reload
|
|
|
|
print_success "ServerKit uninstalled"
|
|
echo ""
|
|
echo "To reinstall, run:"
|
|
echo " cd ~ && curl -fsSL https://raw.githubusercontent.com/jhd3197/ServerKit/main/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
|