92bed208e0
ARCHITECTURE ============ Backend: FastAPI + uvicorn (port 8000) - JWT authentication with PAM system users - ZFS CLI wrapper with caching (30-60s TTL) - WebSocket pool status broadcaster (30s interval) - Services: auth, zfs_runner, file_manager, shares, identities, system_info - Routers: pools, datasets, snapshots, shares, identities, navigator, system Frontend: Next.js 15 + TypeScript (static export) - Incremental Static Regeneration (ISR) for weak hardware - Type-safe API client (lib/api.ts) - Dark mode + custom Tailwind theme - Pages: Dashboard, Login, Snapshots, Datasets, Shares, etc. DEPLOYMENT ========== Test Target: 192.168.1.179:8090 (Debian LXC) Production: 10.66.120.3:9090 (Raspberry Pi 4GB ARM64) Updater: Automated Gitea-based deployment (update-test.sh, update-pi.sh) FEATURES COMPLETED ================== Phase 3a: Dashboard Quick Stats (System, CPU, Memory, Storage) - Real-time stats with color-coded progress bars - Responsive grid layout (mobile: 1, tablet: 2, desktop: 4 columns) - ISR-optimized for fast loads on weak hardware REBRANDING ========== Renamed throughout: - Project: 'ZFS Manager' → 'ZMB Webui' - Services: 'zfs-manager' → 'zmb-webui' - Systemd units: zfs-manager-backend → zmb-webui-backend - Configuration files and documentation Co-Authored-By: Patrick <patrick@perlbach24.de>
244 lines
5.4 KiB
Bash
Executable File
244 lines
5.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ZMB Webui Deployment Script
|
|
# Unterstützt Frontend, Backend und Full-Deployment auf Remote-Host
|
|
# Usage: ./deploy.sh [--target HOST] [--backend-only|--frontend-only]
|
|
|
|
set -e
|
|
|
|
# Default values
|
|
TARGET="192.168.1.179"
|
|
DEPLOY_BACKEND=true
|
|
DEPLOY_FRONTEND=true
|
|
BACKEND_SERVICE="zmb-webui-backend"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--target)
|
|
TARGET="$2"
|
|
shift 2
|
|
;;
|
|
--backend-only)
|
|
DEPLOY_FRONTEND=false
|
|
shift
|
|
;;
|
|
--frontend-only)
|
|
DEPLOY_BACKEND=false
|
|
shift
|
|
;;
|
|
*)
|
|
echo -e "${RED}Unknown option: $1${NC}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Helper functions
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
check_prerequisites() {
|
|
log_info "Checking prerequisites..."
|
|
|
|
if ! command -v scp &> /dev/null; then
|
|
log_error "scp not found. Please install openssh-client"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v ssh &> /dev/null; then
|
|
log_error "ssh not found. Please install openssh-client"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v curl &> /dev/null; then
|
|
log_error "curl not found. Please install curl"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$DEPLOY_FRONTEND" = true ] && ! command -v npm &> /dev/null; then
|
|
log_error "npm not found. Please install Node.js/npm"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "All prerequisites met"
|
|
}
|
|
|
|
check_ssh_connection() {
|
|
log_info "Testing SSH connection to $TARGET..."
|
|
|
|
if ! ssh -o ConnectTimeout=5 root@$TARGET "echo 'Connection OK'" > /dev/null 2>&1; then
|
|
log_error "Cannot connect to $TARGET via SSH"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "SSH connection successful"
|
|
}
|
|
|
|
deploy_frontend() {
|
|
log_info "Building frontend..."
|
|
|
|
if [ ! -d "frontend" ]; then
|
|
log_error "frontend directory not found"
|
|
exit 1
|
|
fi
|
|
|
|
cd frontend
|
|
|
|
if [ ! -f "package.json" ]; then
|
|
log_error "package.json not found in frontend directory"
|
|
exit 1
|
|
fi
|
|
|
|
npm run build
|
|
|
|
if [ ! -d "out" ]; then
|
|
log_error "Frontend build failed - 'out' directory not created"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Frontend build successful"
|
|
cd ..
|
|
|
|
log_info "Uploading frontend to $TARGET..."
|
|
|
|
if ! scp -r frontend/out/* root@$TARGET:/opt/zmb-webui/backend/static/ 2>/dev/null; then
|
|
log_error "Failed to upload frontend files"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Frontend deployed successfully"
|
|
}
|
|
|
|
deploy_backend() {
|
|
log_info "Deploying backend services..."
|
|
|
|
if [ ! -d "backend/services" ]; then
|
|
log_error "backend/services directory not found"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "backend/main.py" ]; then
|
|
log_error "backend/main.py not found"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Uploading backend services to $TARGET..."
|
|
|
|
if ! scp backend/services/*.py root@$TARGET:/opt/zmb-webui/backend/services/ 2>/dev/null; then
|
|
log_error "Failed to upload backend services"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Uploading main.py to $TARGET..."
|
|
|
|
if ! scp backend/main.py root@$TARGET:/opt/zmb-webui/backend/ 2>/dev/null; then
|
|
log_error "Failed to upload main.py"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Backend files uploaded successfully"
|
|
}
|
|
|
|
restart_backend() {
|
|
log_info "Restarting backend service on $TARGET..."
|
|
|
|
if ! ssh root@$TARGET "systemctl restart $BACKEND_SERVICE" 2>/dev/null; then
|
|
log_error "Failed to restart backend service"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Backend service restarted"
|
|
|
|
# Wait a moment for service to start
|
|
sleep 2
|
|
}
|
|
|
|
reload_nginx() {
|
|
log_info "Testing Nginx configuration on $TARGET..."
|
|
|
|
if ! ssh root@$TARGET "nginx -t" 2>/dev/null; then
|
|
log_error "Nginx configuration test failed"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Reloading Nginx..."
|
|
|
|
if ! ssh root@$TARGET "systemctl reload nginx" 2>/dev/null; then
|
|
log_error "Failed to reload Nginx"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Nginx reloaded successfully"
|
|
}
|
|
|
|
health_check() {
|
|
log_info "Running health check..."
|
|
|
|
local max_retries=5
|
|
local retry_count=0
|
|
local http_code
|
|
|
|
while [ $retry_count -lt $max_retries ]; do
|
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" "http://$TARGET/api/status" || echo "000")
|
|
|
|
if [ "$http_code" = "200" ]; then
|
|
log_info "Health check passed (HTTP $http_code)"
|
|
return 0
|
|
fi
|
|
|
|
retry_count=$((retry_count + 1))
|
|
if [ $retry_count -lt $max_retries ]; then
|
|
log_warn "Health check returned HTTP $http_code, retrying... ($retry_count/$max_retries)"
|
|
sleep 2
|
|
fi
|
|
done
|
|
|
|
log_error "Health check failed after $max_retries attempts (last HTTP code: $http_code)"
|
|
exit 1
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
log_info "Starting deployment to $TARGET"
|
|
log_info "Frontend: $DEPLOY_FRONTEND | Backend: $DEPLOY_BACKEND"
|
|
|
|
check_prerequisites
|
|
check_ssh_connection
|
|
|
|
if [ "$DEPLOY_FRONTEND" = true ]; then
|
|
deploy_frontend
|
|
fi
|
|
|
|
if [ "$DEPLOY_BACKEND" = true ]; then
|
|
deploy_backend
|
|
restart_backend
|
|
fi
|
|
|
|
if [ "$DEPLOY_BACKEND" = true ] || [ "$DEPLOY_FRONTEND" = true ]; then
|
|
reload_nginx
|
|
fi
|
|
|
|
health_check
|
|
|
|
log_info "Deployment completed successfully!"
|
|
exit 0
|
|
}
|
|
|
|
main
|