Files
Alphaeus Mote be6d358086 Initial Commit
2025-11-19 08:09:34 -05:00

653 lines
23 KiB
Bash

#!/bin/bash
#
# Depl0y - Automated VM Deployment Panel Installer
# Complete automated installation - no manual steps required!
# One-line install: curl -fsSL http://deploy.agit8or.net/downloads/install.sh | sudo bash
#
set -e
# Installer version for tracking
INSTALLER_VERSION="1.1.0"
INSTALLER_BUILD="$(date +%Y%m%d%H%M%S)"
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ ██████╗ ███████╗██████╗ ██╗ ██████╗ ██╗ ██╗ ║"
echo "║ ██╔══██╗██╔════╝██╔══██╗██║ ██╔═████╗╚██╗ ██╔╝ ║"
echo "║ ██║ ██║█████╗ ██████╔╝██║ ██║██╔██║ ╚████╔╝ ║"
echo "║ ██║ ██║██╔══╝ ██╔═══╝ ██║ ████╔╝██║ ╚██╔╝ ║"
echo "║ ██████╔╝███████╗██║ ███████╗╚██████╔╝ ██║ ║"
echo "║ ╚═════╝ ╚══════╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ║"
echo "║ ║"
echo "║ Automated VM Deployment Panel for Proxmox VE ║"
echo "║ https://deploy.agit8or.net ║"
echo "║ Version 1.1.5 ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════╝"
echo ""
echo "This installer will:"
echo " ✓ Install all dependencies"
echo " ✓ Set up Depl0y application"
echo " ✓ Configure cloud images (optional)"
echo " ✓ Configure inter-node SSH (optional)"
echo " ✓ No manual steps required!"
echo ""
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "ERROR: Please run as root (use sudo)"
exit 1
fi
echo "🚀 Starting Depl0y installation..."
echo ""
# Check if Depl0y is already installed
UPGRADE_MODE=false
if [ -d "/opt/depl0y" ] && [ -f "/etc/systemd/system/depl0y-backend.service" ]; then
UPGRADE_MODE=true
echo "📦 Existing Depl0y installation detected"
echo " This will upgrade your installation while preserving your database"
echo ""
fi
# Detect OS
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
VER=$VERSION_ID
else
echo "ERROR: Cannot detect OS"
exit 1
fi
echo "✓ Detected OS: $OS $VER"
# Check if Ubuntu/Debian
if [[ "$OS" != "ubuntu" && "$OS" != "debian" ]]; then
echo "ERROR: This installer currently only supports Ubuntu and Debian"
exit 1
fi
# Update system
echo ""
echo "📦 Updating system packages..."
apt-get update -qq
# Install ALL dependencies
echo "📦 Installing dependencies..."
echo " This includes: Python, Node.js, nginx, SQLite, PDF libraries, and more"
apt-get install -y -qq \
python3 \
python3-pip \
python3-venv \
python3-dev \
build-essential \
nginx \
nodejs \
npm \
sqlite3 \
curl \
wget \
git \
sshpass \
openssh-client \
at \
ca-certificates \
gnupg \
lsb-release \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libgdk-pixbuf2.0-0 \
libffi-dev \
shared-mime-info
echo "✓ Dependencies installed"
# Create depl0y user
echo ""
echo "👤 Creating depl0y system user..."
if ! id -u depl0y > /dev/null 2>&1; then
useradd -r -m -d /opt/depl0y -s /bin/bash depl0y
echo "✓ User 'depl0y' created"
else
echo "✓ User 'depl0y' already exists"
fi
# If upgrading, stop the backend service and backup encryption keys
if [ "$UPGRADE_MODE" = true ]; then
echo "🔄 Preparing for upgrade..."
# Clear any stale Python cache first
echo "🗑️ Clearing old Python cache..."
find /opt/depl0y/backend -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find /opt/depl0y/backend -type f -name "*.pyc" -delete 2>/dev/null || true
echo "✓ Cache cleared"
if systemctl is-active --quiet depl0y-backend; then
systemctl stop depl0y-backend
echo "✓ Stopped backend service"
fi
# Backup encryption keys from existing service
KEYS_VALID=false
if [ -f /etc/systemd/system/depl0y-backend.service ]; then
echo "🔍 Extracting existing encryption keys..."
EXISTING_SECRET=$(grep "SECRET_KEY=" /etc/systemd/system/depl0y-backend.service | sed 's/.*SECRET_KEY=\([^"]*\).*/\1/')
EXISTING_ENCRYPTION=$(grep "ENCRYPTION_KEY=" /etc/systemd/system/depl0y-backend.service | sed 's/.*ENCRYPTION_KEY=\([^"]*\).*/\1/')
if [ -n "$EXISTING_SECRET" ] && [ -n "$EXISTING_ENCRYPTION" ]; then
echo " Found existing keys, validating..."
# Validate the encryption key
if python3 -c "from cryptography.fernet import Fernet; Fernet('${EXISTING_ENCRYPTION}'.encode())" 2>/dev/null; then
echo "✓ Existing encryption keys are valid and will be preserved"
KEYS_VALID=true
else
echo "⚠️ Existing encryption keys are INVALID (wrong format)"
echo " Will generate new keys - you'll need to re-enter Proxmox credentials"
fi
else
echo "⚠️ Could not extract existing keys from service file"
echo " Will generate new keys"
fi
fi
fi
# Download latest Depl0y
echo ""
echo "⬇️ Downloading Depl0y from deploy.agit8or.net..."
cd /tmp
rm -f depl0y-latest.tar.gz
# Add cache-busting timestamp to ensure fresh download
CACHE_BUST=$(date +%s)
curl -fsSL "http://deploy.agit8or.net/api/v1/system-updates/download?v=${CACHE_BUST}" -o depl0y-latest.tar.gz
echo "📦 Extracting Depl0y..."
rm -rf /tmp/depl0y-install
mkdir -p /tmp/depl0y-install
cd /tmp/depl0y-install
tar -xzf /tmp/depl0y-latest.tar.gz
# Install backend
echo ""
echo "🔧 Installing backend..."
mkdir -p /opt/depl0y
chmod 755 /opt/depl0y # Allow nginx to traverse
cp -r backend /opt/depl0y/
chown -R depl0y:depl0y /opt/depl0y/backend
chmod -R 755 /opt/depl0y/backend
# Create Python virtual environment
echo "🐍 Setting up Python environment..."
cd /opt/depl0y/backend
sudo -u depl0y python3 -m venv venv
sudo -u depl0y venv/bin/pip install --upgrade pip -q
sudo -u depl0y venv/bin/pip install -r requirements.txt -q
# Install additional Python packages for features
echo " Installing additional Python packages..."
sudo -u depl0y venv/bin/pip install -q weasyprint markdown requests
echo "✓ Backend installed"
# Install scripts
echo ""
echo "📜 Installing scripts..."
if [ -d "/tmp/depl0y-install/scripts" ]; then
mkdir -p /opt/depl0y/scripts
cp -r /tmp/depl0y-install/scripts/* /opt/depl0y/scripts/
chmod -R 755 /opt/depl0y/scripts
echo "✓ Scripts installed"
else
echo "⚠️ No scripts directory found in package"
fi
# Install frontend
echo ""
echo "🎨 Installing frontend..."
if [ "$UPGRADE_MODE" = true ]; then
# During upgrade, use pre-built frontend from package (much faster!)
echo " Using pre-built frontend from package..."
if [ -d "/tmp/depl0y-install/frontend/dist" ]; then
mkdir -p /opt/depl0y/frontend/dist
chmod 755 /opt/depl0y/frontend
cp -r /tmp/depl0y-install/frontend/dist/* /opt/depl0y/frontend/dist/
chown -R www-data:www-data /opt/depl0y/frontend/dist
chmod -R 755 /opt/depl0y/frontend/dist
echo "✓ Frontend installed (pre-built)"
else
echo "⚠️ Pre-built frontend not found, building from source..."
cd /tmp/depl0y-install/frontend
npm install --silent
npm run build
mkdir -p /opt/depl0y/frontend/dist
chmod 755 /opt/depl0y/frontend
cp -r dist/* /opt/depl0y/frontend/dist/
chown -R www-data:www-data /opt/depl0y/frontend/dist
chmod -R 755 /opt/depl0y/frontend/dist
echo "✓ Frontend installed (built from source)"
fi
else
# Fresh install - build frontend from source
cd /tmp/depl0y-install/frontend
npm install --silent
npm run build
mkdir -p /opt/depl0y/frontend/dist
chmod 755 /opt/depl0y/frontend
cp -r dist/* /opt/depl0y/frontend/dist/
chown -R www-data:www-data /opt/depl0y/frontend/dist
chmod -R 755 /opt/depl0y/frontend/dist
echo "✓ Frontend installed"
fi
# Create database directory
echo ""
echo "💾 Setting up database..."
mkdir -p /var/lib/depl0y/db
mkdir -p /var/lib/depl0y/cloud-images
mkdir -p /var/lib/depl0y/isos
mkdir -p /var/lib/depl0y/ssh_keys
mkdir -p /var/log/depl0y
chown -R depl0y:depl0y /var/lib/depl0y
chown -R depl0y:depl0y /var/log/depl0y
chmod -R 755 /var/lib/depl0y
echo "✓ Database directories created"
# Copy documentation
echo ""
echo "📚 Installing documentation..."
if [ -d "/tmp/depl0y-install/docs" ]; then
mkdir -p /opt/depl0y/docs
cp -r /tmp/depl0y-install/docs/* /opt/depl0y/docs/
chown -R depl0y:depl0y /opt/depl0y/docs
echo "✓ Documentation installed"
fi
# Generate or reuse encryption keys
echo ""
if [ "$UPGRADE_MODE" = true ] && [ "$KEYS_VALID" = true ]; then
echo "🔐 Reusing existing encryption keys..."
SECRET_KEY="$EXISTING_SECRET"
ENCRYPTION_KEY="$EXISTING_ENCRYPTION"
echo "✓ Existing encryption keys preserved"
else
echo "🔐 Generating new encryption keys..."
SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')
ENCRYPTION_KEY=$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')
echo "✓ New encryption keys generated"
if [ "$UPGRADE_MODE" = true ]; then
echo ""
echo "⚠️ IMPORTANT: New encryption keys have been generated"
echo " This means you will need to:"
echo " • Log in again (previous sessions are now invalid)"
echo " • Re-enter all Proxmox host credentials"
echo " • Your database and settings are preserved"
fi
fi
# Create systemd service
echo ""
echo "⚙️ Creating systemd service..."
cat > /etc/systemd/system/depl0y-backend.service << SVCEOF
[Unit]
Description=Depl0y Backend API
After=network.target
[Service]
Type=simple
User=depl0y
Group=depl0y
WorkingDirectory=/opt/depl0y/backend
Environment="PATH=/opt/depl0y/backend/venv/bin"
Environment="SECRET_KEY=${SECRET_KEY}"
Environment="ENCRYPTION_KEY=${ENCRYPTION_KEY}"
ExecStart=/opt/depl0y/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
SVCEOF
# Clear Python cache to ensure new code is loaded
if [ "$UPGRADE_MODE" = true ]; then
echo "🗑️ Clearing Python cache again (ensuring fresh code)..."
else
echo "🗑️ Clearing Python cache..."
fi
find /opt/depl0y/backend -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find /opt/depl0y/backend -type f -name "*.pyc" -delete 2>/dev/null || true
systemctl daemon-reload
systemctl enable depl0y-backend
# Use restart to ensure service loads new code (important for upgrades)
if [ "$UPGRADE_MODE" = true ]; then
echo "🔄 Restarting backend service with new code..."
systemctl restart depl0y-backend
else
echo "🚀 Starting backend service..."
systemctl start depl0y-backend
fi
echo "✓ Backend service started"
# Configure nginx
echo ""
echo "🌐 Configuring nginx..."
cat > /etc/nginx/sites-available/depl0y << 'NGEOF'
server {
listen 80;
server_name _;
client_max_body_size 10G;
# Frontend
location / {
root /opt/depl0y/frontend/dist;
try_files $uri $uri/ /index.html;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# Backend API
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
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_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
access_log /var/log/nginx/depl0y_access.log;
error_log /var/log/nginx/depl0y_error.log;
}
NGEOF
ln -sf /etc/nginx/sites-available/depl0y /etc/nginx/sites-enabled/depl0y
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl restart nginx
echo "✓ Nginx configured"
# Setup sudoers for depl0y user
echo ""
echo "🔐 Configuring permissions..."
cat > /etc/sudoers.d/depl0y << 'SUDOEOF'
# Depl0y user sudo permissions
depl0y ALL=(ALL) NOPASSWD: /usr/bin/apt-get install -y -qq sshpass
depl0y ALL=(ALL) NOPASSWD: /usr/bin/which sshpass
depl0y ALL=(depl0y) NOPASSWD: /usr/bin/mkdir -p /opt/depl0y/.ssh
depl0y ALL=(depl0y) NOPASSWD: /usr/bin/ssh-keygen *
depl0y ALL=(depl0y) NOPASSWD: /usr/bin/sshpass *
depl0y ALL=(depl0y) NOPASSWD: /usr/bin/ssh *
depl0y ALL=(depl0y) NOPASSWD: /usr/bin/ssh-copy-id *
depl0y ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart depl0y-backend
depl0y ALL=(ALL) NOPASSWD: /bin/systemctl restart depl0y-backend
depl0y ALL=(ALL) NOPASSWD: /usr/bin/systemctl status depl0y-backend
depl0y ALL=(ALL) NOPASSWD: /bin/bash /tmp/depl0y-update-install.sh
depl0y ALL=(ALL) NOPASSWD: /opt/depl0y/scripts/update-wrapper.sh *
depl0y ALL=(ALL) NOPASSWD: /usr/bin/journalctl -u depl0y-backend *
SUDOEOF
chmod 440 /etc/sudoers.d/depl0y
visudo -c
echo "✓ Permissions configured"
# Wait for backend to start
echo ""
echo "⏳ Waiting for backend to start..."
sleep 5
# Check if backend is running
if systemctl is-active --quiet depl0y-backend; then
echo "✓ Backend is running"
else
echo ""
echo "❌ ERROR: Backend failed to start!"
echo ""
echo "Last 30 lines of backend logs:"
journalctl -u depl0y-backend -n 30 --no-pager
echo ""
echo "Installation failed. Please check the logs above for errors."
exit 1
fi
# Create default admin user
echo ""
echo "👤 Creating default admin user..."
cd /opt/depl0y/backend
if sudo -u depl0y /opt/depl0y/backend/venv/bin/python3 create_admin.py; then
echo "✓ Default credentials: admin / admin"
else
echo "❌ ERROR: Failed to create admin user!"
echo "Check permissions and database connection."
exit 1
fi
# Initialize system settings in database
echo ""
echo "⚙️ Initializing system settings..."
sudo -u depl0y sqlite3 /var/lib/depl0y/db/depl0y.db "CREATE TABLE IF NOT EXISTS system_settings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key VARCHAR(100) UNIQUE NOT NULL,
value TEXT NOT NULL,
description TEXT,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);" 2>/dev/null || true
sudo -u depl0y sqlite3 /var/lib/depl0y/db/depl0y.db "INSERT OR REPLACE INTO system_settings (key, value, description) VALUES
('app_version', '1.1.9', 'Current application version'),
('app_name', 'Depl0y', 'Application name');" 2>/dev/null || true
echo "✓ System settings initialized"
# Optional Proxmox setup
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Optional: Proxmox Integration Setup"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Would you like to configure Proxmox integration now?"
echo "This will:"
echo " • Set up cloud images for fast VM deployment"
echo " • Configure inter-node SSH for multi-node clusters"
echo ""
read -p "Configure Proxmox now? (y/N): " -n 1 -r SETUP_PROXMOX < /dev/tty || SETUP_PROXMOX="N"
echo ""
if [[ $SETUP_PROXMOX =~ ^[Yy]$ ]]; then
echo ""
echo "📋 Proxmox Configuration"
echo ""
# Get Proxmox details
read -p "Enter Proxmox hostname or IP: " PROXMOX_HOST < /dev/tty
read -p "Enter Proxmox root username [root]: " PROXMOX_USER < /dev/tty
PROXMOX_USER=${PROXMOX_USER:-root}
echo ""
echo "⚠️ Note: Password will be used to set up SSH keys only"
read -s -p "Enter Proxmox root password: " PROXMOX_PASSWORD < /dev/tty
echo ""
echo ""
# Setup SSH keys for depl0y user
echo "🔑 Setting up SSH keys..."
if [ ! -f "/opt/depl0y/.ssh/id_rsa" ]; then
sudo -u depl0y mkdir -p /opt/depl0y/.ssh
sudo -u depl0y ssh-keygen -t rsa -b 4096 -f /opt/depl0y/.ssh/id_rsa -N "" -q
echo "✓ SSH keys generated"
else
echo "✓ SSH keys already exist"
fi
# Copy SSH key to Proxmox
echo "📤 Copying SSH key to Proxmox..."
sudo -u depl0y sshpass -p "$PROXMOX_PASSWORD" ssh-copy-id -o StrictHostKeyChecking=no "${PROXMOX_USER}@${PROXMOX_HOST}" 2>/dev/null || {
echo "⚠️ Failed to copy SSH key. You may need to do this manually later."
}
# Test SSH connection
if sudo -u depl0y ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=no "${PROXMOX_USER}@${PROXMOX_HOST}" "echo SSH_OK" 2>/dev/null | grep -q "SSH_OK"; then
echo "✓ SSH connection verified"
# Setup cloud images
echo ""
echo "☁️ Setting up cloud images..."
sudo -u depl0y ssh -o StrictHostKeyChecking=no "${PROXMOX_USER}@${PROXMOX_HOST}" 'bash -s' << 'CLOUDEOF'
# Check if cloud-init is available
if ! which cloud-init >/dev/null 2>&1; then
apt-get update -qq
apt-get install -y -qq cloud-init
fi
# Create cloud-init snippet storage if needed
mkdir -p /var/lib/vz/snippets
chmod 755 /var/lib/vz/snippets
echo "✓ Cloud images configured"
CLOUDEOF
# Setup inter-node SSH for cluster
echo ""
echo "🔗 Setting up inter-node SSH for cluster..."
sudo -u depl0y ssh -o StrictHostKeyChecking=no "${PROXMOX_USER}@${PROXMOX_HOST}" 'bash -s' << 'SSHEOF'
# Get cluster nodes
NODES=$(pvesh get /cluster/status --output-format json 2>/dev/null | grep -o '"name":"[^"]*"' | cut -d'"' -f4 | grep -v "^$" || echo "")
if [ -n "$NODES" ]; then
echo " Found cluster nodes: $NODES"
# Generate SSH key on this node if needed
if [ ! -f ~/.ssh/id_rsa ]; then
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "" -q
fi
# Copy key to other nodes
for node in $NODES; do
if [ "$node" != "$(hostname)" ]; then
echo " Setting up SSH to $node..."
ssh-copy-id -o StrictHostKeyChecking=no "root@$node" 2>/dev/null || true
fi
done
echo "✓ Inter-node SSH configured"
else
echo " Single node or cluster not configured, skipping"
fi
SSHEOF
echo ""
echo "✓ Proxmox integration complete!"
else
echo "⚠️ SSH connection failed. You can set this up later via Settings in the web interface."
fi
else
echo ""
echo "⏭️ Skipping Proxmox setup. You can configure this later via:"
echo " Settings → Cloud Images"
echo " Settings → Proxmox Cluster SSH"
fi
# Cleanup
echo ""
echo "🧹 Cleaning up..."
cd /
rm -rf /tmp/depl0y-install
rm -f /tmp/depl0y-latest.tar.gz
# Final restart for upgrades to ensure new code is loaded
if [ "$UPGRADE_MODE" = true ]; then
echo ""
echo "🔄 Final restart to load new code..."
find /opt/depl0y/backend -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
find /opt/depl0y/backend -type f -name "*.pyc" -delete 2>/dev/null || true
systemctl restart depl0y-backend
sleep 3
if systemctl is-active --quiet depl0y-backend; then
echo "✓ Backend restarted successfully"
else
echo "⚠️ Backend restart may have issues, check logs"
fi
fi
# Get IP address
IP=$(hostname -I | awk '{print $1}')
echo ""
if [ "$UPGRADE_MODE" = true ]; then
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ ✅ UPGRADE COMPLETE ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════╝"
echo ""
echo "🎉 Depl0y v1.1.9 has been successfully upgraded!"
echo ""
echo "📍 Access Depl0y at:"
echo " http://$IP"
echo ""
echo "✨ What's new in v1.1.9:"
echo " • Automatic backend restart after upgrades"
echo " • No manual restart needed - updates apply immediately"
echo " • Fixed JavaScript error (version not defined)"
echo " • One-click automatic updates from Settings"
echo ""
echo "📚 Note:"
echo " • Your database has been preserved"
echo " • Your encryption keys have been preserved"
echo " • All users and settings retained"
else
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ ✅ INSTALLATION COMPLETE ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════╝"
echo ""
echo "🎉 Depl0y v1.1.9 has been successfully installed!"
echo ""
echo "📍 Access Depl0y at:"
echo " http://$IP"
echo ""
echo "👤 Default Credentials:"
echo " Username: admin"
echo " Password: admin"
echo " 🔐 2FA: Disabled (enable in Settings after login)"
echo " ⚠️ CHANGE PASSWORD IMMEDIATELY AFTER FIRST LOGIN!"
echo ""
echo "✨ Features:"
echo " • High Availability wizard"
echo " • Cloud image management"
echo " • Automated VM deployment"
echo ""
echo "📚 Next Steps:"
echo " 1. Access the web interface"
echo " 2. Change the default password"
echo " 3. Add your Proxmox host in Settings (if not done)"
echo " 4. Try the HA Setup Wizard!"
fi
echo ""
echo "📖 Documentation: http://$IP → Documentation"
echo "🆘 Support: Check /opt/depl0y/docs/"
echo ""
echo "Thank you for using Depl0y! 🚀"
echo ""