feat: Update deployment script to support root user execution

- Modified vps-deploy.sh to run as both root and non-root user
- Added dynamic sudo command handling (SUDO_CMD variable)
- Set appropriate service user (www-data for root, current user for non-root)
- Updated all system commands to use dynamic sudo
- Enhanced PostgreSQL setup for root execution
- Updated PM2 configuration with proper user permissions
- Added deployment update script with root support
- Improved security and flexibility for VPS deployment
This commit is contained in:
2025-08-12 07:39:58 +07:00
parent 70a865a974
commit b146127513

View File

@@ -3,6 +3,7 @@
# 🚀 Laca City Website - Complete VPS Deployment Script # 🚀 Laca City Website - Complete VPS Deployment Script
# This script sets up your entire website on a VPS with domain configuration # This script sets up your entire website on a VPS with domain configuration
# Run this script on your VPS after uploading your project files # Run this script on your VPS after uploading your project files
# Can be run as root user or regular user with sudo privileges
set -e set -e
@@ -92,7 +93,7 @@ create_systemd_service() {
local working_dir="$4" local working_dir="$4"
local user="$5" local user="$5"
sudo tee "/etc/systemd/system/$service_name.service" > /dev/null <<EOF $SUDO_CMD tee "/etc/systemd/system/$service_name.service" > /dev/null <<EOF
[Unit] [Unit]
Description=$description Description=$description
After=network.target After=network.target
@@ -110,31 +111,31 @@ Environment=NODE_ENV=production
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
sudo systemctl daemon-reload $SUDO_CMD systemctl daemon-reload
sudo systemctl enable "$service_name" $SUDO_CMD systemctl enable "$service_name"
} }
# Function to setup firewall # Function to setup firewall
setup_firewall() { setup_firewall() {
print_step "Setting up UFW firewall..." print_step "Setting up UFW firewall..."
sudo ufw --force reset $SUDO_CMD ufw --force reset
sudo ufw default deny incoming $SUDO_CMD ufw default deny incoming
sudo ufw default allow outgoing $SUDO_CMD ufw default allow outgoing
# Allow SSH # Allow SSH
sudo ufw allow ssh $SUDO_CMD ufw allow ssh
sudo ufw allow 22 $SUDO_CMD ufw allow 22
# Allow HTTP and HTTPS # Allow HTTP and HTTPS
sudo ufw allow 80 $SUDO_CMD ufw allow 80
sudo ufw allow 443 $SUDO_CMD ufw allow 443
# Allow specific ports for development (optional) # Allow specific ports for development (optional)
sudo ufw allow $FRONTEND_PORT $SUDO_CMD ufw allow $FRONTEND_PORT
sudo ufw allow $BACKEND_PORT $SUDO_CMD ufw allow $BACKEND_PORT
sudo ufw --force enable $SUDO_CMD ufw --force enable
print_success "Firewall configured" print_success "Firewall configured"
} }
@@ -143,14 +144,14 @@ setup_firewall() {
setup_nginx() { setup_nginx() {
print_step "Setting up Nginx..." print_step "Setting up Nginx..."
sudo apt update $SUDO_CMD apt update
sudo apt install -y nginx $SUDO_CMD apt install -y nginx
# Remove default configuration # Remove default configuration
sudo rm -f /etc/nginx/sites-enabled/default $SUDO_CMD rm -f /etc/nginx/sites-enabled/default
# Create Nginx configuration # Create Nginx configuration
sudo tee "/etc/nginx/sites-available/$NGINX_CONFIG_NAME" > /dev/null <<EOF $SUDO_CMD tee "/etc/nginx/sites-available/$NGINX_CONFIG_NAME" > /dev/null <<EOF
# Upstream servers # Upstream servers
upstream frontend { upstream frontend {
server 127.0.0.1:$FRONTEND_PORT; server 127.0.0.1:$FRONTEND_PORT;
@@ -245,10 +246,10 @@ server {
EOF EOF
# Enable the site # Enable the site
sudo ln -sf "/etc/nginx/sites-available/$NGINX_CONFIG_NAME" "/etc/nginx/sites-enabled/" $SUDO_CMD ln -sf "/etc/nginx/sites-available/$NGINX_CONFIG_NAME" "/etc/nginx/sites-enabled/"
# Test Nginx configuration # Test Nginx configuration
sudo nginx -t $SUDO_CMD nginx -t
print_success "Nginx configured" print_success "Nginx configured"
} }
@@ -258,20 +259,20 @@ setup_ssl() {
print_step "Setting up SSL certificate with Let's Encrypt..." print_step "Setting up SSL certificate with Let's Encrypt..."
# Install Certbot # Install Certbot
sudo apt install -y certbot python3-certbot-nginx $SUDO_CMD apt install -y certbot python3-certbot-nginx
# Stop Nginx temporarily # Stop Nginx temporarily
sudo systemctl stop nginx $SUDO_CMD systemctl stop nginx
# Obtain SSL certificate # Obtain SSL certificate
sudo certbot --nginx -d "$DOMAIN_NAME" -d "www.$DOMAIN_NAME" --email "$EMAIL" --agree-tos --non-interactive $SUDO_CMD certbot --nginx -d "$DOMAIN_NAME" -d "www.$DOMAIN_NAME" --email "$EMAIL" --agree-tos --non-interactive
# Start Nginx # Start Nginx
sudo systemctl start nginx $SUDO_CMD systemctl start nginx
sudo systemctl enable nginx $SUDO_CMD systemctl enable nginx
# Setup automatic renewal # Setup automatic renewal
sudo crontab -l 2>/dev/null | { cat; echo "0 3 * * * /usr/bin/certbot renew --quiet"; } | sudo crontab - $SUDO_CMD crontab -l 2>/dev/null | { cat; echo "0 3 * * * /usr/bin/certbot renew --quiet"; } | $SUDO_CMD crontab -
print_success "SSL certificate configured and auto-renewal setup" print_success "SSL certificate configured and auto-renewal setup"
} }
@@ -280,12 +281,12 @@ setup_ssl() {
setup_postgresql() { setup_postgresql() {
print_step "Setting up PostgreSQL..." print_step "Setting up PostgreSQL..."
sudo apt update $SUDO_CMD apt update
sudo apt install -y postgresql postgresql-contrib $SUDO_CMD apt install -y postgresql postgresql-contrib
# Start and enable PostgreSQL # Start and enable PostgreSQL
sudo systemctl start postgresql $SUDO_CMD systemctl start postgresql
sudo systemctl enable postgresql $SUDO_CMD systemctl enable postgresql
# Generate database password if not provided # Generate database password if not provided
if [ -z "$DB_PASSWORD" ]; then if [ -z "$DB_PASSWORD" ]; then
@@ -294,13 +295,23 @@ setup_postgresql() {
fi fi
# Create database and user # Create database and user
sudo -u postgres psql <<EOF if [ "$CURRENT_USER" = "root" ]; then
su - postgres -c "psql" <<EOF
CREATE DATABASE $DB_NAME; CREATE DATABASE $DB_NAME;
CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASSWORD'; CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER; GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
ALTER USER $DB_USER CREATEDB; ALTER USER $DB_USER CREATEDB;
\q \q
EOF EOF
else
sudo -u postgres psql <<EOF
CREATE DATABASE $DB_NAME;
CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;
ALTER USER $DB_USER CREATEDB;
\q
EOF
fi
print_success "PostgreSQL configured" print_success "PostgreSQL configured"
} }
@@ -309,14 +320,14 @@ EOF
setup_redis() { setup_redis() {
print_step "Setting up Redis..." print_step "Setting up Redis..."
sudo apt update $SUDO_CMD apt update
sudo apt install -y redis-server $SUDO_CMD apt install -y redis-server
# Configure Redis # Configure Redis
sudo sed -i 's/^supervised no/supervised systemd/' /etc/redis/redis.conf $SUDO_CMD sed -i 's/^supervised no/supervised systemd/' /etc/redis/redis.conf
sudo systemctl restart redis.service $SUDO_CMD systemctl restart redis.service
sudo systemctl enable redis.service $SUDO_CMD systemctl enable redis.service
print_success "Redis configured" print_success "Redis configured"
} }
@@ -326,11 +337,11 @@ install_nodejs() {
print_step "Installing Node.js..." print_step "Installing Node.js..."
# Install Node.js 18.x # Install Node.js 18.x
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - curl -fsSL https://deb.nodesource.com/setup_18.x | $SUDO_CMD -E bash -
sudo apt-get install -y nodejs $SUDO_CMD apt-get install -y nodejs
# Install PM2 globally # Install PM2 globally
sudo npm install -g pm2 $SUDO_CMD npm install -g pm2
print_success "Node.js and PM2 installed" print_success "Node.js and PM2 installed"
} }
@@ -340,12 +351,12 @@ setup_project() {
print_step "Setting up project files..." print_step "Setting up project files..."
# Create project directory # Create project directory
sudo mkdir -p "$PROJECT_DIR" $SUDO_CMD mkdir -p "$PROJECT_DIR"
sudo mkdir -p "$BACKUP_DIR" $SUDO_CMD mkdir -p "$BACKUP_DIR"
# Copy files to project directory (assuming current directory has the project) # Copy files to project directory (assuming current directory has the project)
sudo cp -r ./* "$PROJECT_DIR/" 2>/dev/null || true $SUDO_CMD cp -r ./* "$PROJECT_DIR/" 2>/dev/null || true
sudo chown -R "$CURRENT_USER:$CURRENT_USER" "$PROJECT_DIR" $SUDO_CMD chown -R "$SERVICE_USER:$SERVICE_USER" "$PROJECT_DIR"
cd "$PROJECT_DIR" cd "$PROJECT_DIR"
@@ -447,7 +458,9 @@ module.exports = {
out_file: '/var/log/pm2/laca-city-backend-out.log', out_file: '/var/log/pm2/laca-city-backend-out.log',
log_file: '/var/log/pm2/laca-city-backend.log', log_file: '/var/log/pm2/laca-city-backend.log',
max_restarts: 10, max_restarts: 10,
min_uptime: '10s' min_uptime: '10s',
uid: '$SERVICE_USER',
gid: '$SERVICE_USER'
}, },
{ {
name: 'laca-city-frontend', name: 'laca-city-frontend',
@@ -464,15 +477,17 @@ module.exports = {
out_file: '/var/log/pm2/laca-city-frontend-out.log', out_file: '/var/log/pm2/laca-city-frontend-out.log',
log_file: '/var/log/pm2/laca-city-frontend.log', log_file: '/var/log/pm2/laca-city-frontend.log',
max_restarts: 10, max_restarts: 10,
min_uptime: '10s' min_uptime: '10s',
uid: '$SERVICE_USER',
gid: '$SERVICE_USER'
} }
] ]
}; };
EOF EOF
# Create log directory # Create log directory
sudo mkdir -p /var/log/pm2 $SUDO_CMD mkdir -p /var/log/pm2
sudo chown -R "$CURRENT_USER:$CURRENT_USER" /var/log/pm2 $SUDO_CMD chown -R "$SERVICE_USER:$SERVICE_USER" /var/log/pm2
# Start applications with PM2 # Start applications with PM2
pm2 start ecosystem.config.js pm2 start ecosystem.config.js
@@ -487,10 +502,10 @@ setup_monitoring() {
print_step "Setting up monitoring..." print_step "Setting up monitoring..."
# Install htop and other monitoring tools # Install htop and other monitoring tools
sudo apt install -y htop iotop nethogs $SUDO_CMD apt install -y htop iotop nethogs
# Setup logrotate for application logs # Setup logrotate for application logs
sudo tee "/etc/logrotate.d/$PROJECT_NAME" > /dev/null <<EOF $SUDO_CMD tee "/etc/logrotate.d/$PROJECT_NAME" > /dev/null <<EOF
/var/log/pm2/*.log { /var/log/pm2/*.log {
daily daily
missingok missingok
@@ -498,7 +513,7 @@ setup_monitoring() {
compress compress
delaycompress delaycompress
notifempty notifempty
create 644 $CURRENT_USER $CURRENT_USER create 644 $SERVICE_USER $SERVICE_USER
postrotate postrotate
pm2 reloadLogs pm2 reloadLogs
endscript endscript
@@ -512,7 +527,7 @@ EOF
create_backup_script() { create_backup_script() {
print_step "Creating backup script..." print_step "Creating backup script..."
sudo tee "/usr/local/bin/backup-$PROJECT_NAME" > /dev/null <<EOF $SUDO_CMD tee "/usr/local/bin/backup-$PROJECT_NAME" > /dev/null <<EOF
#!/bin/bash #!/bin/bash
BACKUP_DATE=\$(date +%Y%m%d_%H%M%S) BACKUP_DATE=\$(date +%Y%m%d_%H%M%S)
@@ -540,7 +555,7 @@ find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete
echo "Backup completed: backup_\$BACKUP_DATE.tar.gz" echo "Backup completed: backup_\$BACKUP_DATE.tar.gz"
EOF EOF
sudo chmod +x "/usr/local/bin/backup-$PROJECT_NAME" $SUDO_CMD chmod +x "/usr/local/bin/backup-$PROJECT_NAME"
# Setup daily backup cron job # Setup daily backup cron job
(crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/backup-$PROJECT_NAME") | crontab - (crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/backup-$PROJECT_NAME") | crontab -
@@ -560,6 +575,13 @@ set -e
PROJECT_DIR="$PROJECT_DIR" PROJECT_DIR="$PROJECT_DIR"
# Check if running as root
if [ "\$(whoami)" = "root" ]; then
SUDO_CMD=""
else
SUDO_CMD="sudo"
fi
echo "🚀 Starting deployment update..." echo "🚀 Starting deployment update..."
# Stop applications # Stop applications
@@ -589,9 +611,10 @@ npm run build
pm2 restart all pm2 restart all
# Reload Nginx # Reload Nginx
sudo systemctl reload nginx \$SUDO_CMD systemctl reload nginx
echo "✅ Deployment update completed!" echo "✅ Deployment update completed!"
EOF
EOF EOF
chmod +x "$PROJECT_DIR/deploy-update.sh" chmod +x "$PROJECT_DIR/deploy-update.sh"
@@ -641,16 +664,20 @@ final_checks() {
main() { main() {
print_header "🚀 LACA CITY WEBSITE - VPS DEPLOYMENT" print_header "🚀 LACA CITY WEBSITE - VPS DEPLOYMENT"
# Check if running as root # Check execution context and setup appropriate commands
if [ "$CURRENT_USER" = "root" ]; then if [ "$CURRENT_USER" = "root" ]; then
print_error "Please don't run this script as root. Run as a regular user with sudo access." print_warning "Running as root user. Some operations will be adjusted accordingly."
exit 1 SUDO_CMD=""
fi # Set a default non-root user for services
SERVICE_USER="www-data"
# Check if sudo is available else
if ! sudo -n true 2>/dev/null; then # Check if sudo is available
print_error "This script requires sudo access. Please ensure you can run sudo commands." if ! sudo -n true 2>/dev/null; then
exit 1 print_error "This script requires sudo access. Please ensure you can run sudo commands."
exit 1
fi
SUDO_CMD="sudo"
SERVICE_USER="$CURRENT_USER"
fi fi
# Collect configuration # Collect configuration
@@ -685,11 +712,11 @@ main() {
# Update system # Update system
print_step "Updating system packages..." print_step "Updating system packages..."
sudo apt update && sudo apt upgrade -y $SUDO_CMD apt update && $SUDO_CMD apt upgrade -y
# Install basic tools # Install basic tools
print_step "Installing basic tools..." print_step "Installing basic tools..."
sudo apt install -y curl wget git unzip software-properties-common apt-transport-https ca-certificates gnupg lsb-release openssl $SUDO_CMD apt install -y curl wget git unzip software-properties-common apt-transport-https ca-certificates gnupg lsb-release openssl
# Setup firewall # Setup firewall
setup_firewall setup_firewall
@@ -750,8 +777,8 @@ main() {
echo -e " pm2 list # View running processes" echo -e " pm2 list # View running processes"
echo -e " pm2 restart all # Restart all applications" echo -e " pm2 restart all # Restart all applications"
echo -e " pm2 logs # View application logs" echo -e " pm2 logs # View application logs"
echo -e " sudo systemctl status nginx # Check Nginx status" echo -e " $SUDO_CMD systemctl status nginx # Check Nginx status"
echo -e " sudo certbot renew --dry-run # Test SSL renewal" echo -e " $SUDO_CMD certbot renew --dry-run # Test SSL renewal"
print_success "Setup completed! Your website should be accessible at https://$DOMAIN_NAME" print_success "Setup completed! Your website should be accessible at https://$DOMAIN_NAME"
} }