308 lines
10 KiB
Bash
308 lines
10 KiB
Bash
#!/bin/bash
|
|
|
|
# =============================================================================
|
|
# Mnemo Cards Web App - Deployment Configuration
|
|
# =============================================================================
|
|
# This file contains all deployment variables and settings.
|
|
# Modify these values according to your environment.
|
|
|
|
# =============================================================================
|
|
# SERVER CONFIGURATION
|
|
# =============================================================================
|
|
|
|
# Server connection details
|
|
export SERVER_IP="147.45.152.129"
|
|
export SERVER_USER="root"
|
|
|
|
# Domain configuration
|
|
export DOMAIN="mnemo-cards.online"
|
|
|
|
# =============================================================================
|
|
# APPLICATION CONFIGURATION
|
|
# =============================================================================
|
|
|
|
# Application details
|
|
export APP_NAME="mnemo_cards"
|
|
export APP_TITLE="Mnemo Cards Web App"
|
|
|
|
# Web root directory on server
|
|
export WEB_ROOT="/var/www/$APP_NAME"
|
|
|
|
# Nginx configuration paths
|
|
export NGINX_CONFIG="/etc/nginx/sites-available/$APP_NAME"
|
|
export NGINX_ENABLED="/etc/nginx/sites-enabled/$APP_NAME"
|
|
|
|
# =============================================================================
|
|
# API CONFIGURATION
|
|
# =============================================================================
|
|
|
|
# API endpoints (via nginx reverse proxy on port 443)
|
|
export API_BASE_URL="https://api.mnemo-cards.online"
|
|
#export API_BASE_URL_DEV="http://localhost:8000"
|
|
export API_BASE_URL_DEV="https://api.mnemo-cards.online"
|
|
|
|
# =============================================================================
|
|
# SSL CONFIGURATION
|
|
# =============================================================================
|
|
|
|
# SSL certificate paths (Let's Encrypt)
|
|
export SSL_CERT_PATH="/etc/letsencrypt/live/$DOMAIN/fullchain.pem"
|
|
export SSL_KEY_PATH="/etc/letsencrypt/live/$DOMAIN/privkey.pem"
|
|
|
|
# Self-signed certificate paths (fallback)
|
|
export SSL_SELF_CERT="/etc/ssl/certs/nginx-selfsigned.crt"
|
|
export SSL_SELF_KEY="/etc/ssl/private/nginx-selfsigned.key"
|
|
|
|
# SSL configuration
|
|
export SSL_PROTOCOLS="TLSv1.2 TLSv1.3"
|
|
export SSL_CIPHERS="ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384"
|
|
|
|
# =============================================================================
|
|
# NGINX CONFIGURATION
|
|
# =============================================================================
|
|
|
|
# Security headers
|
|
export CSP_POLICY="default-src 'self' http: https: data: blob: 'unsafe-inline' 'unsafe-eval'"
|
|
export X_FRAME_OPTIONS="SAMEORIGIN"
|
|
export X_XSS_PROTECTION="1; mode=block"
|
|
export X_CONTENT_TYPE_OPTIONS="nosniff"
|
|
export REFERRER_POLICY="no-referrer-when-downgrade"
|
|
export STRICT_TRANSPORT_SECURITY="max-age=31536000; includeSubDomains"
|
|
|
|
# CORS headers for Flutter web assets (disabled to avoid conflicts with API CORS)
|
|
export COOP_POLICY="same-origin"
|
|
export COEP_POLICY="require-corp"
|
|
# Note: COEP/COOP headers are disabled in nginx.conf to allow CORS requests to API
|
|
|
|
# Cache settings
|
|
export CACHE_EXPIRES="1y"
|
|
export CACHE_CONTROL="public, immutable"
|
|
|
|
# =============================================================================
|
|
# DEPLOYMENT CONFIGURATION
|
|
# =============================================================================
|
|
|
|
# Build configuration
|
|
export FLUTTER_BUILD_MODE="--release"
|
|
export FLUTTER_BUILD_TARGET="web"
|
|
|
|
# Backup configuration
|
|
export BACKUP_DIR="/var/www/$APP_NAME.backup"
|
|
export BACKUP_TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
|
|
# File permissions
|
|
export WEB_USER="www-data"
|
|
export WEB_GROUP="www-data"
|
|
export WEB_PERMISSIONS="755"
|
|
|
|
# =============================================================================
|
|
# EMAIL CONFIGURATION (for Let's Encrypt)
|
|
# =============================================================================
|
|
|
|
export LETSENCRYPT_EMAIL="admin@mnemo-cards.online"
|
|
|
|
# =============================================================================
|
|
# FIREWALL CONFIGURATION
|
|
# =============================================================================
|
|
|
|
export FIREWALL_ALLOW_NGINX="Nginx Full"
|
|
export FIREWALL_ALLOW_SSH="ssh"
|
|
|
|
# =============================================================================
|
|
# CRON CONFIGURATION (for certificate renewal)
|
|
# =============================================================================
|
|
|
|
export CRON_RENEWAL_TIMES="0 12 * * * 0 0 * * *"
|
|
export CRON_RENEWAL_COMMAND="certbot renew --quiet --post-hook \"systemctl reload nginx\" --cert-name mnemo-cards.online"
|
|
export CRON_API_RENEWAL_COMMAND="certbot renew --quiet --cert-name api.mnemo-cards.online"
|
|
export CRON_ADMIN_RENEWAL_COMMAND="certbot renew --quiet --cert-name admin.mnemo-cards.online"
|
|
export CRON_FORGEJO_RENEWAL_COMMAND="certbot renew --quiet --cert-name code.mnemo-cards.online"
|
|
|
|
# =============================================================================
|
|
# COLORS FOR OUTPUT
|
|
# =============================================================================
|
|
|
|
export RED='\033[0;31m'
|
|
export GREEN='\033[0;32m'
|
|
export YELLOW='\033[1;33m'
|
|
export BLUE='\033[0;34m'
|
|
export NC='\033[0m' # No Color
|
|
|
|
# =============================================================================
|
|
# HELPER FUNCTIONS
|
|
# =============================================================================
|
|
|
|
# Function to print colored output
|
|
print_status() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
print_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
# Function to check if running from correct directory
|
|
check_project_root() {
|
|
if [ ! -f "pubspec.yaml" ]; then
|
|
print_error "Please run this script from the Flutter project root directory"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to check if build directory exists
|
|
check_build_directory() {
|
|
if [ ! -d "build/web" ]; then
|
|
print_error "Build directory not found. Please run 'flutter build web --release' first"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to build Flutter web app for production
|
|
build_flutter_app() {
|
|
print_status "Building Flutter web app for production..."
|
|
flutter build $FLUTTER_BUILD_TARGET $FLUTTER_BUILD_MODE \
|
|
--dart-define=API_BASE_URL=$API_BASE_URL \
|
|
--dart2js-optimization=O4
|
|
|
|
if [ $? -ne 0 ]; then
|
|
print_error "Flutter build failed"
|
|
exit 1
|
|
fi
|
|
|
|
print_success "Flutter build completed successfully"
|
|
}
|
|
|
|
# Function to create backup
|
|
create_backup() {
|
|
if [ -d "$WEB_ROOT" ] && [ "$(ls -A $WEB_ROOT 2>/dev/null)" ]; then
|
|
print_status "Creating backup of existing deployment..."
|
|
cp -r "$WEB_ROOT" "${BACKUP_DIR}.${BACKUP_TIMESTAMP}"
|
|
print_success "Backup created: ${BACKUP_DIR}.${BACKUP_TIMESTAMP}"
|
|
fi
|
|
}
|
|
|
|
# Function to set file permissions
|
|
set_permissions() {
|
|
print_status "Setting proper permissions..."
|
|
chown -R $WEB_USER:$WEB_GROUP "$WEB_ROOT"
|
|
chmod -R $WEB_PERMISSIONS "$WEB_ROOT"
|
|
print_success "Permissions set successfully"
|
|
}
|
|
|
|
# Function to test nginx configuration
|
|
test_nginx() {
|
|
print_status "Testing nginx configuration..."
|
|
nginx -t
|
|
if [ $? -ne 0 ]; then
|
|
print_error "Nginx configuration test failed"
|
|
exit 1
|
|
fi
|
|
print_success "Nginx configuration is valid"
|
|
}
|
|
|
|
# Function to restart nginx
|
|
restart_nginx() {
|
|
print_status "Restarting nginx..."
|
|
systemctl restart nginx
|
|
systemctl enable nginx
|
|
print_success "Nginx restarted successfully"
|
|
}
|
|
|
|
# Function to setup swap if needed
|
|
setup_swap() {
|
|
print_status "Checking swap configuration..."
|
|
|
|
# Check current swap
|
|
CURRENT_SWAP=$(free -m | awk '/^Swap:/ {print $2}')
|
|
RECOMMENDED_SWAP=2048 # 2GB
|
|
|
|
if [ "$CURRENT_SWAP" -lt "$RECOMMENDED_SWAP" ]; then
|
|
print_warning "Current swap is ${CURRENT_SWAP}MB, recommended is ${RECOMMENDED_SWAP}MB"
|
|
print_status "Setting up temporary swap file..."
|
|
|
|
# Create swap file if it doesn't exist
|
|
if [ ! -f /swapfile ]; then
|
|
dd if=/dev/zero of=/swapfile bs=1M count=$RECOMMENDED_SWAP status=progress
|
|
chmod 600 /swapfile
|
|
mkswap /swapfile
|
|
swapon /swapfile
|
|
|
|
# Optimize swap usage (don't add to fstab - it's temporary)
|
|
sysctl vm.swappiness=10
|
|
|
|
print_success "Temporary swap file created and activated (${RECOMMENDED_SWAP}MB)"
|
|
# Mark that we created it for cleanup
|
|
touch /tmp/.swap_created_by_deploy
|
|
else
|
|
# Swap exists, activate it if not active
|
|
if ! swapon --show | grep -q '/swapfile'; then
|
|
swapon /swapfile
|
|
print_info "Existing swap file activated"
|
|
else
|
|
print_info "Swap file already active"
|
|
fi
|
|
fi
|
|
else
|
|
print_success "Swap is already configured (${CURRENT_SWAP}MB)"
|
|
fi
|
|
}
|
|
|
|
# Function to remove temporary swap after deployment
|
|
remove_swap() {
|
|
print_status "Checking if temporary swap needs cleanup..."
|
|
|
|
# Only remove swap if we created it during this deployment
|
|
if [ -f /tmp/.swap_created_by_deploy ]; then
|
|
print_status "Removing temporary swap file..."
|
|
|
|
# Deactivate swap
|
|
if swapon --show | grep -q '/swapfile'; then
|
|
swapoff /swapfile
|
|
print_info "Swap deactivated"
|
|
fi
|
|
|
|
# Remove swap file
|
|
if [ -f /swapfile ]; then
|
|
rm -f /swapfile
|
|
print_success "Temporary swap file removed"
|
|
fi
|
|
|
|
# Remove fstab entry if exists
|
|
if grep -q '/swapfile' /etc/fstab 2>/dev/null; then
|
|
sed -i '/\/swapfile/d' /etc/fstab
|
|
print_info "Removed swap entry from fstab"
|
|
fi
|
|
|
|
# Remove marker file
|
|
rm -f /tmp/.swap_created_by_deploy
|
|
else
|
|
print_info "No temporary swap to remove (swap was pre-existing or already cleaned)"
|
|
fi
|
|
}
|
|
|
|
# =============================================================================
|
|
# EXPORT ALL VARIABLES
|
|
# =============================================================================
|
|
|
|
# Make sure all variables are exported
|
|
export -f print_status print_warning print_error print_success print_info
|
|
export -f check_project_root check_build_directory build_flutter_app
|
|
export -f create_backup set_permissions test_nginx restart_nginx setup_swap remove_swap
|
|
|
|
print_info "Configuration loaded successfully"
|
|
print_info "Server: $SERVER_USER@$SERVER_IP"
|
|
print_info "Domain: $DOMAIN"
|
|
print_info "API URL: $API_BASE_URL"
|
|
print_info "Web Root: $WEB_ROOT"
|