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
# This script sets up your entire website on a VPS with domain configuration
# 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
@@ -92,7 +93,7 @@ create_systemd_service() {
local working_dir="$4"
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]
Description=$description
After=network.target
@@ -110,31 +111,31 @@ Environment=NODE_ENV=production
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable "$service_name"
$SUDO_CMD systemctl daemon-reload
$SUDO_CMD systemctl enable "$service_name"
}
# Function to setup firewall
setup_firewall() {
print_step "Setting up UFW firewall..."
sudo ufw --force reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
$SUDO_CMD ufw --force reset
$SUDO_CMD ufw default deny incoming
$SUDO_CMD ufw default allow outgoing
# Allow SSH
sudo ufw allow ssh
sudo ufw allow 22
$SUDO_CMD ufw allow ssh
$SUDO_CMD ufw allow 22
# Allow HTTP and HTTPS
sudo ufw allow 80
sudo ufw allow 443
$SUDO_CMD ufw allow 80
$SUDO_CMD ufw allow 443
# Allow specific ports for development (optional)
sudo ufw allow $FRONTEND_PORT
sudo ufw allow $BACKEND_PORT
$SUDO_CMD ufw allow $FRONTEND_PORT
$SUDO_CMD ufw allow $BACKEND_PORT
sudo ufw --force enable
$SUDO_CMD ufw --force enable
print_success "Firewall configured"
}
@@ -143,14 +144,14 @@ setup_firewall() {
setup_nginx() {
print_step "Setting up Nginx..."
sudo apt update
sudo apt install -y nginx
$SUDO_CMD apt update
$SUDO_CMD apt install -y nginx
# Remove default configuration
sudo rm -f /etc/nginx/sites-enabled/default
$SUDO_CMD rm -f /etc/nginx/sites-enabled/default
# 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 frontend {
server 127.0.0.1:$FRONTEND_PORT;
@@ -245,10 +246,10 @@ server {
EOF
# 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
sudo nginx -t
$SUDO_CMD nginx -t
print_success "Nginx configured"
}
@@ -258,20 +259,20 @@ setup_ssl() {
print_step "Setting up SSL certificate with Let's Encrypt..."
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
$SUDO_CMD apt install -y certbot python3-certbot-nginx
# Stop Nginx temporarily
sudo systemctl stop nginx
$SUDO_CMD systemctl stop nginx
# 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
sudo systemctl start nginx
sudo systemctl enable nginx
$SUDO_CMD systemctl start nginx
$SUDO_CMD systemctl enable nginx
# 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"
}
@@ -280,12 +281,12 @@ setup_ssl() {
setup_postgresql() {
print_step "Setting up PostgreSQL..."
sudo apt update
sudo apt install -y postgresql postgresql-contrib
$SUDO_CMD apt update
$SUDO_CMD apt install -y postgresql postgresql-contrib
# Start and enable PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql
$SUDO_CMD systemctl start postgresql
$SUDO_CMD systemctl enable postgresql
# Generate database password if not provided
if [ -z "$DB_PASSWORD" ]; then
@@ -294,13 +295,23 @@ setup_postgresql() {
fi
# Create database and user
sudo -u postgres psql <<EOF
if [ "$CURRENT_USER" = "root" ]; then
su - postgres -c "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
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"
}
@@ -309,14 +320,14 @@ EOF
setup_redis() {
print_step "Setting up Redis..."
sudo apt update
sudo apt install -y redis-server
$SUDO_CMD apt update
$SUDO_CMD apt install -y redis-server
# 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 systemctl enable redis.service
$SUDO_CMD systemctl restart redis.service
$SUDO_CMD systemctl enable redis.service
print_success "Redis configured"
}
@@ -326,11 +337,11 @@ install_nodejs() {
print_step "Installing Node.js..."
# Install Node.js 18.x
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
curl -fsSL https://deb.nodesource.com/setup_18.x | $SUDO_CMD -E bash -
$SUDO_CMD apt-get install -y nodejs
# Install PM2 globally
sudo npm install -g pm2
$SUDO_CMD npm install -g pm2
print_success "Node.js and PM2 installed"
}
@@ -340,12 +351,12 @@ setup_project() {
print_step "Setting up project files..."
# Create project directory
sudo mkdir -p "$PROJECT_DIR"
sudo mkdir -p "$BACKUP_DIR"
$SUDO_CMD mkdir -p "$PROJECT_DIR"
$SUDO_CMD mkdir -p "$BACKUP_DIR"
# Copy files to project directory (assuming current directory has the project)
sudo cp -r ./* "$PROJECT_DIR/" 2>/dev/null || true
sudo chown -R "$CURRENT_USER:$CURRENT_USER" "$PROJECT_DIR"
$SUDO_CMD cp -r ./* "$PROJECT_DIR/" 2>/dev/null || true
$SUDO_CMD chown -R "$SERVICE_USER:$SERVICE_USER" "$PROJECT_DIR"
cd "$PROJECT_DIR"
@@ -447,7 +458,9 @@ module.exports = {
out_file: '/var/log/pm2/laca-city-backend-out.log',
log_file: '/var/log/pm2/laca-city-backend.log',
max_restarts: 10,
min_uptime: '10s'
min_uptime: '10s',
uid: '$SERVICE_USER',
gid: '$SERVICE_USER'
},
{
name: 'laca-city-frontend',
@@ -464,15 +477,17 @@ module.exports = {
out_file: '/var/log/pm2/laca-city-frontend-out.log',
log_file: '/var/log/pm2/laca-city-frontend.log',
max_restarts: 10,
min_uptime: '10s'
min_uptime: '10s',
uid: '$SERVICE_USER',
gid: '$SERVICE_USER'
}
]
};
EOF
# Create log directory
sudo mkdir -p /var/log/pm2
sudo chown -R "$CURRENT_USER:$CURRENT_USER" /var/log/pm2
$SUDO_CMD mkdir -p /var/log/pm2
$SUDO_CMD chown -R "$SERVICE_USER:$SERVICE_USER" /var/log/pm2
# Start applications with PM2
pm2 start ecosystem.config.js
@@ -487,10 +502,10 @@ setup_monitoring() {
print_step "Setting up monitoring..."
# 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
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 {
daily
missingok
@@ -498,7 +513,7 @@ setup_monitoring() {
compress
delaycompress
notifempty
create 644 $CURRENT_USER $CURRENT_USER
create 644 $SERVICE_USER $SERVICE_USER
postrotate
pm2 reloadLogs
endscript
@@ -512,7 +527,7 @@ EOF
create_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
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"
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
(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"
# Check if running as root
if [ "\$(whoami)" = "root" ]; then
SUDO_CMD=""
else
SUDO_CMD="sudo"
fi
echo "🚀 Starting deployment update..."
# Stop applications
@@ -589,9 +611,10 @@ npm run build
pm2 restart all
# Reload Nginx
sudo systemctl reload nginx
\$SUDO_CMD systemctl reload nginx
echo "✅ Deployment update completed!"
EOF
EOF
chmod +x "$PROJECT_DIR/deploy-update.sh"
@@ -641,16 +664,20 @@ final_checks() {
main() {
print_header "🚀 LACA CITY WEBSITE - VPS DEPLOYMENT"
# Check if running as root
# Check execution context and setup appropriate commands
if [ "$CURRENT_USER" = "root" ]; then
print_error "Please don't run this script as root. Run as a regular user with sudo access."
exit 1
fi
# Check if sudo is available
if ! sudo -n true 2>/dev/null; then
print_error "This script requires sudo access. Please ensure you can run sudo commands."
exit 1
print_warning "Running as root user. Some operations will be adjusted accordingly."
SUDO_CMD=""
# Set a default non-root user for services
SERVICE_USER="www-data"
else
# Check if sudo is available
if ! sudo -n true 2>/dev/null; then
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
# Collect configuration
@@ -685,11 +712,11 @@ main() {
# Update system
print_step "Updating system packages..."
sudo apt update && sudo apt upgrade -y
$SUDO_CMD apt update && $SUDO_CMD apt upgrade -y
# Install 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
@@ -750,8 +777,8 @@ main() {
echo -e " pm2 list # View running processes"
echo -e " pm2 restart all # Restart all applications"
echo -e " pm2 logs # View application logs"
echo -e " sudo systemctl status nginx # Check Nginx status"
echo -e " sudo certbot renew --dry-run # Test SSL renewal"
echo -e " $SUDO_CMD systemctl status nginx # Check Nginx status"
echo -e " $SUDO_CMD certbot renew --dry-run # Test SSL renewal"
print_success "Setup completed! Your website should be accessible at https://$DOMAIN_NAME"
}