#!/bin/bash # # ServerKit CLI - Management tool for ServerKit # Usage: ./serverkit [options] # set -e # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration INSTALL_DIR="${SERVERKIT_DIR:-/opt/serverkit}" CONTAINER_NAME="serverkit-backend" COMPOSE_FILE="docker-compose.yml" # 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_docker() { if ! command -v docker &> /dev/null; then print_error "Docker is not installed" exit 1 fi if ! docker info &> /dev/null; then print_error "Docker is not running or you don't have permission" exit 1 fi } check_installed() { if [ ! -f "$INSTALL_DIR/$COMPOSE_FILE" ]; then print_error "ServerKit is not installed in $INSTALL_DIR" print_info "Run: ./serverkit install" exit 1 fi } run_cli() { docker exec -it $CONTAINER_NAME python cli.py "$@" } # Commands cmd_help() { print_header echo "" echo "Usage: serverkit [options]" echo "" echo "Service Commands:" echo " install Install ServerKit" 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 " shell Open a shell in the backend container" echo " config Edit configuration" echo "" echo "Examples:" echo " serverkit install" echo " serverkit reset-password" echo " serverkit logs backend" echo "" } cmd_install() { print_header echo "" print_info "Installing ServerKit..." check_docker # Check if already installed if [ -d "$INSTALL_DIR" ] && [ -f "$INSTALL_DIR/$COMPOSE_FILE" ]; then print_warning "ServerKit is already installed in $INSTALL_DIR" read -p "Reinstall? (y/N) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 0 fi fi # Create install directory sudo mkdir -p "$INSTALL_DIR" # Clone or copy files if [ -d ".git" ]; then print_info "Copying files to $INSTALL_DIR..." sudo cp -r . "$INSTALL_DIR/" else print_info "Cloning repository..." sudo git clone https://github.com/jhd3197/serverkit.git "$INSTALL_DIR" fi cd "$INSTALL_DIR" # Generate .env if not exists if [ ! -f ".env" ]; then print_info "Generating configuration..." SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))" 2>/dev/null || openssl rand -hex 32) JWT_SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))" 2>/dev/null || openssl rand -hex 32) cat > .env << EOF # ServerKit Configuration # Generated on $(date) # Security Keys (auto-generated) SECRET_KEY=$SECRET_KEY JWT_SECRET_KEY=$JWT_SECRET_KEY # Database DATABASE_URL=sqlite:///serverkit.db # CORS Origins (your domain) CORS_ORIGINS=http://localhost # Ports PORT=80 SSL_PORT=443 # Environment FLASK_ENV=production EOF print_success "Configuration file created" fi # Create SSL directory mkdir -p nginx/ssl # Generate self-signed cert for initial setup if [ ! -f "nginx/ssl/fullchain.pem" ]; then print_info "Generating self-signed SSL certificate..." openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout nginx/ssl/privkey.pem \ -out nginx/ssl/fullchain.pem \ -subj "/CN=localhost" 2>/dev/null print_warning "Self-signed certificate created. Replace with real certificate for production." fi # Build and start print_info "Building containers..." docker compose build print_info "Starting services..." docker compose up -d # Wait for services print_info "Waiting for services to be ready..." sleep 10 # Check status if docker compose ps | grep -q "running"; then echo "" print_success "ServerKit installed successfully!" echo "" echo "Next steps:" echo " 1. Open http://localhost in your browser" echo " 2. Create your admin account: serverkit create-admin" echo " 3. Configure SSL certificate for production" echo "" else print_error "Installation failed. Check logs with: serverkit logs" exit 1 fi } cmd_start() { check_installed cd "$INSTALL_DIR" print_info "Starting ServerKit..." docker compose up -d print_success "ServerKit started" } cmd_stop() { check_installed cd "$INSTALL_DIR" print_info "Stopping ServerKit..." docker compose down print_success "ServerKit stopped" } cmd_restart() { check_installed cd "$INSTALL_DIR" print_info "Restarting ServerKit..." docker compose restart print_success "ServerKit restarted" } cmd_status() { check_installed cd "$INSTALL_DIR" print_header echo "" docker compose ps echo "" # Health check if curl -s http://localhost/api/v1/health > /dev/null 2>&1; then print_success "API is healthy" else print_warning "API health check failed" fi } cmd_logs() { check_installed cd "$INSTALL_DIR" service="${1:-}" if [ -n "$service" ]; then docker compose logs -f "$service" else docker compose logs -f fi } cmd_update() { check_installed cd "$INSTALL_DIR" print_info "Updating ServerKit..." # Pull latest changes if [ -d ".git" ]; then git pull fi # Rebuild and restart docker compose build docker compose up -d print_success "ServerKit updated" } cmd_uninstall() { 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 if [ -d "$INSTALL_DIR" ]; then cd "$INSTALL_DIR" docker compose down -v 2>/dev/null || true cd / sudo rm -rf "$INSTALL_DIR" fi 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 cd "$INSTALL_DIR" BACKUP_FILE="backup/serverkit-$(date +%Y%m%d-%H%M%S).db" mkdir -p backup docker cp $CONTAINER_NAME:/app/instance/serverkit.db "$BACKUP_FILE" print_success "Database backed up to $BACKUP_FILE" } cmd_restore_db() { check_installed cd "$INSTALL_DIR" if [ -z "$1" ]; then echo "Available backups:" ls -la backup/*.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 docker cp "$BACKUP_FILE" $CONTAINER_NAME:/app/instance/serverkit.db docker compose restart backend print_success "Database restored" fi } cmd_generate_keys() { check_docker print_header echo "" echo "Add these to your .env file:" echo "" SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))" 2>/dev/null || openssl rand -hex 32) JWT_SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))" 2>/dev/null || openssl rand -hex 32) echo "SECRET_KEY=$SECRET_KEY" echo "JWT_SECRET_KEY=$JWT_SECRET_KEY" echo "" } cmd_shell() { check_installed docker exec -it $CONTAINER_NAME /bin/bash } cmd_config() { check_installed ${EDITOR:-nano} "$INSTALL_DIR/.env" print_info "Restart ServerKit to apply changes: serverkit restart" } # Main case "${1:-help}" in help|--help|-h) cmd_help ;; install) cmd_install ;; 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 ;; shell) cmd_shell ;; config) cmd_config ;; *) print_error "Unknown command: $1" echo "Run 'serverkit help' for usage" exit 1 ;; esac