NOTE:
- please make sure the domain already point into the ip server before run the script so the acme challenge can be accomplished
#!/bin/bash | |
#================================================================ | |
# Ubuntu VPS Server Setup Script | |
# | |
# This script automates the setup of a LEMP stack (Nginx, MariaDB, PHP) | |
# on a fresh Ubuntu server. It also installs Node.js using NVM | |
# and configures a Let's Encrypt SSL certificate. | |
# | |
# Author: Bachrul Uluum | |
#================================================================ | |
# --- Script Configuration --- | |
# Exit immediately if a command exits with a non-zero status. | |
set -e | |
# --- Variables --- | |
# It's recommended to change these default values. | |
DOMAIN="your-domain.web.id" | |
EMAIL="[email protected]" # Required for Let's Encrypt | |
PHP_VERSION="8.2" | |
NODE_VERSION="--lts" | |
DB_ROOT_PASSWORD="your_strong_password_here" # Change this! | |
# --- Helper Functions --- | |
print_info() { | |
echo -e "\n\033[0;34m[INFO]\033[0m $1" | |
} | |
print_success() { | |
echo -e "\033[0;32m[SUCCESS]\033[0m $1" | |
} | |
print_warning() { | |
echo -e "\033[0;33m[WARNING]\033[0m $1" | |
} | |
# --- Check for Root Privilege --- | |
if [ "$(id -u)" != "0" ]; then | |
echo "This script must be run as root. Please use sudo." 1>&2 | |
exit 1 | |
fi | |
#================================================================ | |
# STEP 1: SYSTEM UPDATE | |
#================================================================ | |
print_info "Updating and upgrading system packages..." | |
apt-get update | |
apt-get upgrade -y | |
print_success "System packages updated." | |
#================================================================ | |
# STEP 2: INSTALL NGINX | |
#================================================================ | |
print_info "Installing Nginx web server..." | |
apt-get install -y nginx | |
systemctl start nginx | |
systemctl enable nginx | |
print_success "Nginx installed and enabled." | |
#================================================================ | |
# STEP 3: INSTALL MARIADB | |
#================================================================ | |
print_info "Installing MariaDB database server..." | |
apt-get install -y mariadb-server mariadb-client | |
print_info "Securing MariaDB installation..." | |
# This sets the root password and removes insecure defaults. | |
mysql -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('${DB_ROOT_PASSWORD}');" | |
mysql -e "DELETE FROM mysql.user WHERE User='';" | |
mysql -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');" | |
mysql -e "DROP DATABASE IF EXISTS test;" | |
mysql -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';" | |
mysql -e "FLUSH PRIVILEGES;" | |
print_success "MariaDB installed and secured." | |
print_warning "MariaDB root password set to: ${DB_ROOT_PASSWORD}. Please save it." | |
#================================================================ | |
# STEP 4: INSTALL PHP | |
#================================================================ | |
print_info "Installing PHP ${PHP_VERSION}..." | |
# Add the ondrej/php PPA for the latest PHP versions | |
apt-get install -y software-properties-common | |
add-apt-repository ppa:ondrej/php -y | |
apt-get update | |
# Install PHP-FPM and common extensions | |
apt-get install -y php${PHP_VERSION}-fpm php${PHP_VERSION}-cli php${PHP_VERSION}-mysql php${PHP_VERSION}-gd php${PHP_VERSION}-json php${PHP_VERSION}-curl php${PHP_VERSION}-mbstring php${PHP_VERSION}-xml php${PHP_VERSION}-zip php${PHP_VERSION}-bcmath | |
# Check the PHP-FPM service status | |
systemctl status php${PHP_VERSION}-fpm | |
print_success "PHP ${PHP_VERSION} and extensions installed." | |
#================================================================ | |
# STEP 5: INSTALL NODE.JS VIA NVM | |
#================================================================ | |
print_info "Installing Node.js via NVM..." | |
# Install curl to download NVM installer | |
apt-get install -y curl | |
# Download and run the NVM installer script | |
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash | |
# Source NVM script to make it available in the current shell | |
export NVM_DIR="$HOME/.nvm" | |
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" | |
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" | |
# Install the specified Node.js version (LTS by default) | |
nvm install ${NODE_VERSION} | |
nvm use ${NODE_VERSION} | |
nvm alias default ${NODE_VERSION} | |
print_success "NVM and Node.js $(node -v) installed." | |
print_info "To use NVM in a new terminal, you may need to run: source ~/.bashrc" | |
#================================================================ | |
# STEP 6: CONFIGURE NGINX | |
#================================================================ | |
print_info "Configuring Nginx server block for ${DOMAIN}..." | |
# Create the web root directory | |
mkdir -p /var/www/${DOMAIN}/html | |
# Set appropriate permissions | |
chown -R www-data:www-data /var/www/${DOMAIN} | |
# Create a Nginx server block configuration file | |
cat > /etc/nginx/sites-available/${DOMAIN} <<EOF | |
server { | |
listen 80; | |
listen [::]:80; | |
server_name ${DOMAIN} www.${DOMAIN}; | |
root /var/www/${DOMAIN}/html; | |
index index.php index.html index.htm; | |
location / { | |
try_files \$uri \$uri/ /index.php?\$query_string; | |
} | |
location ~ \.php$ { | |
include snippets/fastcgi-php.conf; | |
fastcgi_pass unix:/var/run/php/php${PHP_VERSION}-fpm.sock; | |
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; | |
include fastcgi_params; | |
} | |
location ~ /\.ht { | |
deny all; | |
} | |
} | |
EOF | |
# Enable the site by creating a symlink | |
ln -s /etc/nginx/sites-available/${DOMAIN} /etc/nginx/sites-enabled/ | |
# Test Nginx configuration | |
nginx -t | |
# Reload Nginx to apply changes | |
systemctl reload nginx | |
print_success "Nginx server block for ${DOMAIN} created and enabled." | |
# Create a test PHP info page | |
echo "<?php phpinfo(); ?>" > /var/www/${DOMAIN}/html/index.php | |
chown www-data:www-data /var/www/${DOMAIN}/html/index.php | |
print_info "A test phpinfo page has been created at http://${DOMAIN}/index.php" | |
#================================================================ | |
# STEP 7: INSTALL LET'S ENCRYPT SSL | |
#================================================================ | |
print_info "Installing Certbot for Let's Encrypt SSL..." | |
apt-get install -y certbot python3-certbot-nginx | |
print_info "Obtaining and installing SSL certificate for ${DOMAIN}..." | |
# The --non-interactive flag accepts the TOS. --agree-tos | |
# The -m flag sets the email for renewal reminders. | |
# The -d flag specifies the domain. | |
# --redirect automatically redirects HTTP to HTTPS. | |
certbot --nginx --non-interactive --agree-tos --email ${EMAIL} -d ${DOMAIN} -d www.${DOMAIN} --redirect | |
print_success "Let's Encrypt SSL certificate has been successfully installed." | |
#================================================================ | |
# FINAL SUMMARY | |
#================================================================ | |
print_success "Server setup is complete!" | |
echo "============================================================" | |
echo " Domain: https://${DOMAIN}" | |
echo " Web Root: /var/www/${DOMAIN}/html" | |
echo " Nginx Config: /etc/nginx/sites-available/${DOMAIN}" | |
echo "------------------------------------------------------------" | |
echo " MariaDB root password: ${DB_ROOT_PASSWORD}" | |
echo "------------------------------------------------------------" | |
echo " PHP Version: $(php -v | head -n 1)" | |
echo " PHP-FPM Service: php${PHP_VERSION}-fpm" | |
echo "------------------------------------------------------------" | |
echo " Node.js Version: $(source ~/.nvm/nvm.sh && node -v)" | |
echo " NVM is installed. Run 'source ~/.bashrc' to use it." | |
echo "============================================================" | |
print_warning "IMPORTANT: For security, please remove the index.php file after testing." | |
echo "rm /var/www/${DOMAIN}/html/index.php" |