chore: migrate application to gunicorn server and add deployment configuration files
This commit is contained in:
parent
f7dba1d11c
commit
b0ef319728
@ -2,18 +2,28 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: 'vsphere-backup-manager',
|
name: 'vsphere-backup-manager',
|
||||||
script: 'gui_app.py',
|
// Gunicorn as the production WSGI server
|
||||||
// If you are using a virtual environment (recommended), set the interpreter to:
|
// If using a virtualenv, replace 'gunicorn' with './venv/bin/gunicorn'
|
||||||
// interpreter: './venv/bin/python3',
|
script: 'gunicorn',
|
||||||
interpreter: 'python3',
|
args: [
|
||||||
|
'--workers', '4',
|
||||||
|
'--bind', '127.0.0.1:5000',
|
||||||
|
'--timeout', '300', // long timeout for backup operations
|
||||||
|
'--keep-alive', '5',
|
||||||
|
'--log-level', 'info',
|
||||||
|
'--access-logfile', './logs/gunicorn_access.log',
|
||||||
|
'--error-logfile', './logs/gunicorn_error.log',
|
||||||
|
'gui_app:app'
|
||||||
|
].join(' '),
|
||||||
|
interpreter: 'none', // gunicorn is its own executable
|
||||||
cwd: './',
|
cwd: './',
|
||||||
instances: 1,
|
instances: 1,
|
||||||
autorestart: true,
|
autorestart: true,
|
||||||
watch: false,
|
watch: false,
|
||||||
max_memory_restart: '500M',
|
max_memory_restart: '500M',
|
||||||
env: {
|
env: {
|
||||||
PORT: '5000',
|
|
||||||
SECRET_KEY: 'vsphere-backup-production-key-change-this'
|
SECRET_KEY: 'vsphere-backup-production-key-change-this'
|
||||||
|
// PORT is no longer used; gunicorn binds via --bind above
|
||||||
},
|
},
|
||||||
error_file: './logs/pm2_err.log',
|
error_file: './logs/pm2_err.log',
|
||||||
out_file: './logs/pm2_out.log',
|
out_file: './logs/pm2_out.log',
|
||||||
|
|||||||
73
nginx.conf
Normal file
73
nginx.conf
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# ─── vSphere Backup Manager — Nginx reverse proxy ────────────────────────────
|
||||||
|
#
|
||||||
|
# Place this file at: /etc/nginx/sites-available/vsphere-backup-manager
|
||||||
|
# Then enable it with: sudo ln -s /etc/nginx/sites-available/vsphere-backup-manager \
|
||||||
|
# /etc/nginx/sites-enabled/
|
||||||
|
#
|
||||||
|
# Assumes:
|
||||||
|
# - SSL cert + key are at /etc/ssl/vsphere-backup/
|
||||||
|
# - Gunicorn is running on 127.0.0.1:5000 (via PM2)
|
||||||
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# Redirect plain HTTP → HTTPS
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _; # catches any hostname / IP
|
||||||
|
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main HTTPS block
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
# ── SSL certificate (self-signed, generated by setup.sh) ──────────────────
|
||||||
|
ssl_certificate /etc/ssl/vsphere-backup/cert.pem;
|
||||||
|
ssl_certificate_key /etc/ssl/vsphere-backup/key.pem;
|
||||||
|
|
||||||
|
# ── TLS hardening ─────────────────────────────────────────────────────────
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
ssl_session_timeout 10m;
|
||||||
|
|
||||||
|
# ── Security headers ──────────────────────────────────────────────────────
|
||||||
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header Referrer-Policy strict-origin-when-cross-origin;
|
||||||
|
# Force HTTPS for 1 year — remove this line if you ever need to switch back to HTTP
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||||
|
|
||||||
|
# ── Proxy to Gunicorn ─────────────────────────────────────────────────────
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:5000;
|
||||||
|
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;
|
||||||
|
|
||||||
|
# Long timeouts — backup jobs can run for hours
|
||||||
|
proxy_read_timeout 3600;
|
||||||
|
proxy_connect_timeout 60;
|
||||||
|
proxy_send_timeout 3600;
|
||||||
|
|
||||||
|
# Allow large log downloads
|
||||||
|
client_max_body_size 64M;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Static files served directly by Nginx (faster than Python) ───────────
|
||||||
|
location /static/ {
|
||||||
|
alias /home/rizqiv2/vSphere-Backup-Manager/static/;
|
||||||
|
expires 7d;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Logging ───────────────────────────────────────────────────────────────
|
||||||
|
access_log /var/log/nginx/vsphere-backup-access.log;
|
||||||
|
error_log /var/log/nginx/vsphere-backup-error.log;
|
||||||
|
}
|
||||||
@ -4,3 +4,4 @@ paramiko
|
|||||||
zstandard
|
zstandard
|
||||||
APScheduler>=3.10
|
APScheduler>=3.10
|
||||||
Flask>=2.3
|
Flask>=2.3
|
||||||
|
gunicorn>=21.0
|
||||||
|
|||||||
78
setup.sh
Normal file
78
setup.sh
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# setup.sh — One-time setup for vSphere Backup Manager (Nginx + Gunicorn + HTTPS)
|
||||||
|
# Run as a user with sudo privileges.
|
||||||
|
# Usage: bash setup.sh
|
||||||
|
# =============================================================================
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SSL_DIR="/etc/ssl/vsphere-backup"
|
||||||
|
NGINX_CONF="/etc/nginx/sites-available/vsphere-backup-manager"
|
||||||
|
NGINX_LINK="/etc/nginx/sites-enabled/vsphere-backup-manager"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " vSphere Backup Manager — Setup Script"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ── 1. Install system packages ────────────────────────────────────────────────
|
||||||
|
echo "[1/6] Installing Nginx..."
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y nginx
|
||||||
|
|
||||||
|
# ── 2. Install Python packages ────────────────────────────────────────────────
|
||||||
|
echo "[2/6] Installing Python dependencies (including gunicorn)..."
|
||||||
|
# If you use a virtualenv, activate it first:
|
||||||
|
# source ./venv/bin/activate
|
||||||
|
pip install -r "$APP_DIR/requirements.txt"
|
||||||
|
|
||||||
|
# ── 3. Generate self-signed SSL certificate (10-year validity) ────────────────
|
||||||
|
echo "[3/6] Generating self-signed TLS certificate (10 years)..."
|
||||||
|
sudo mkdir -p "$SSL_DIR"
|
||||||
|
sudo openssl req -x509 -nodes -newkey rsa:4096 \
|
||||||
|
-days 3650 \
|
||||||
|
-keyout "$SSL_DIR/key.pem" \
|
||||||
|
-out "$SSL_DIR/cert.pem" \
|
||||||
|
-subj "/C=XX/ST=Local/L=Local/O=vSphereBackup/CN=vsphere-backup-manager" \
|
||||||
|
-addext "subjectAltName=IP:127.0.0.1,IP:$(hostname -I | awk '{print $1}')"
|
||||||
|
sudo chmod 600 "$SSL_DIR/key.pem"
|
||||||
|
sudo chmod 644 "$SSL_DIR/cert.pem"
|
||||||
|
echo " Certificate saved to: $SSL_DIR"
|
||||||
|
|
||||||
|
# ── 4. Install Nginx config ───────────────────────────────────────────────────
|
||||||
|
echo "[4/6] Installing Nginx config..."
|
||||||
|
sudo cp "$APP_DIR/nginx.conf" "$NGINX_CONF"
|
||||||
|
# Remove default site if it exists
|
||||||
|
sudo rm -f /etc/nginx/sites-enabled/default
|
||||||
|
# Create symlink to enable our site
|
||||||
|
sudo ln -sf "$NGINX_CONF" "$NGINX_LINK"
|
||||||
|
sudo nginx -t # validate config before applying
|
||||||
|
sudo systemctl enable nginx
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
echo " Nginx configured and running."
|
||||||
|
|
||||||
|
# ── 5. Create logs directory ──────────────────────────────────────────────────
|
||||||
|
echo "[5/6] Creating logs directory..."
|
||||||
|
mkdir -p "$APP_DIR/logs"
|
||||||
|
|
||||||
|
# ── 6. (Re)start with PM2 ────────────────────────────────────────────────────
|
||||||
|
echo "[6/6] Starting app with PM2..."
|
||||||
|
cd "$APP_DIR"
|
||||||
|
# Stop old instance if running (ignore error if not)
|
||||||
|
pm2 delete vsphere-backup-manager 2>/dev/null || true
|
||||||
|
pm2 start ecosystem.config.js
|
||||||
|
pm2 save
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Setup complete!"
|
||||||
|
echo ""
|
||||||
|
echo " Access the app at:"
|
||||||
|
echo " https://$(hostname -I | awk '{print $1}')"
|
||||||
|
echo ""
|
||||||
|
echo " First visit: browser will warn about self-signed cert."
|
||||||
|
echo " Click: Advanced → Proceed (one-time per browser)"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
Loading…
Reference in New Issue
Block a user