Tujuan panduan ini adalah membawa sebuah server Ubuntu 24 dari kondisi awal menjadi siap melayani website dengan HTTPS secara otomatis. Anda akan: (1) menginstal paket dasar, (2) membuat server block Nginx untuk domain, (3) menerbitkan sertifikat Let’s Encrypt, dan (4) melakukan verifikasi. Seluruh perintah disiapkan agar copy-paste friendly.
Prasyarat & Catatan Keamanan
- Server Ubuntu 24.04 LTS dengan IP publik dan akses root (
sudo -i). - Domain yang Anda miliki (misal
example.com). - Firewall membuka port 80/tcp dan 443/tcp.
- Gunakan SSH key untuk produksi; hindari kata sandi lemah.
Arsitektur Singkat (LEMP)
- Linux (Ubuntu 24) sebagai OS.
- Nginx melayani HTTP/HTTPS dan meneruskan request ke PHP-FPM.
- MariaDB sebagai RDBMS.
- PHP-FPM memproses skrip PHP.
- Certbot mengotomasi sertifikat Let’s Encrypt + pembaruan otomatis.
Penting: Arahkan DNS ke Server Ini
Auntukexample.com→IP_PUBLIK_SERVERAuntukwww.example.com→IP_PUBLIK_SERVER- (Opsional IPv6)
AAAAuntuk keduanya →IPv6_SERVER
Setelah itu, cek:
dig +short A example.com
dig +short A www.example.comSkrip Utama: bootstrap-lemp-ubuntu24.sh
Skrip ini: menyiapkan UFW, memasang Nginx + PHP-FPM + MariaDB + Certbot, membuat vhost & direktori web, menambahkan index.php, memeriksa DNS → IP server, dan menerbitkan SSL.
/root/bootstrap-lemp-ubuntu24.sh#!/usr/bin/env bash
# File: /root/bootstrap-lemp-ubuntu24.sh
# OS : Ubuntu 24.04 LTS
# Goal : Automate LEMP + domain + HTTPS (Let's Encrypt) end-to-end
set -euo pipefail
# ---------------- Helpers ----------------
log() { echo -e "[\e[32mINFO\e[0m] $*"; }
warn(){ echo -e "[\e[33mWARN\e[0m] $*"; }
err() { echo -e "[\e[31mERROR\e[0m] $*" 1>&2; }
require_root() {
if [[ $EUID -ne 0 ]]; then
err "Jalankan sebagai root. Gunakan: sudo -i"
exit 1
fi
}
get_server_ip() {
local ip4
ip4="$(curl -4s https://api.ipify.org || true)"
echo "$ip4"
}
resolve_domain_ip() {
local d="$1"
local ip
ip="$(getent ahostsv4 "$d" | awk '/STREAM/ {print $1; exit}' || true)"
if [[ -z "$ip" ]]; then
ip="$(dig +short A "$d" 2>/dev/null | head -n1 || true)"
fi
echo "$ip"
}
random_password() {
tr -dc 'A-Za-z0-9_@#%+=' < /dev/urandom | head -c 24 } # ---------------- Inputs ------------------ DOMAIN="${DOMAIN:-}" ADMIN_EMAIL="${ADMIN_EMAIL:-}" DB_NAME="${DB_NAME:-}" DB_USER="${DB_USER:-}" DB_PASS="${DB_PASS:-}" STAGING="${STAGING:-false}" # true|false # -------------- Pre-flight ---------------- require_root command -v curl >/dev/null 2>&1 || apt-get update -y && apt-get install -y curl
log "Memulai bootstrap LEMP Ubuntu 24..."
if [[ -z "$DOMAIN" ]]; then
read -rp "Masukkan DOMAIN (contoh: example.com): " DOMAIN
fi
if [[ -z "$ADMIN_EMAIL" ]]; then
read -rp "Masukkan EMAIL admin untuk Let's Encrypt: " ADMIN_EMAIL
fi
if [[ -n "$DB_NAME" || -n "$DB_USER" || -n "$DB_PASS" ]]; then
log "Mode DB: pembuatan kredensial untuk ${DB_NAME:-}"
if [[ -z "${DB_NAME}" ]]; then read -rp "Masukkan DB_NAME: " DB_NAME; fi
if [[ -z "${DB_USER}" ]]; then read -rp "Masukkan DB_USER: " DB_USER; fi
if [[ -z "${DB_PASS}" ]]; then
read -rp "Masukkan DB_PASS (kosongkan untuk acak): " DB_PASS || true
if [[ -z "${DB_PASS}" ]]; then DB_PASS="$(random_password)"; fi
fi
fi
SERVER_IP="$(get_server_ip || true)"
if [[ -z "$SERVER_IP" ]]; then
warn "Gagal mendeteksi IP publik via api.ipify.org. Pastikan koneksi internet tersedia."
else
log "IP publik server terdeteksi: $SERVER_IP"
fi
DNS_IP_ROOT="$(resolve_domain_ip "$DOMAIN" || true)"
DNS_IP_WWW="$(resolve_domain_ip "www.${DOMAIN}" || true)"
if [[ -z "$DNS_IP_ROOT" || "$DNS_IP_ROOT" != "$SERVER_IP" ]]; then
warn "A record untuk ${DOMAIN} belum mengarah ke IP server ($SERVER_IP). Deteksi: ${DNS_IP_ROOT:-}"
fi
if [[ -z "$DNS_IP_WWW" || "$DNS_IP_WWW" != "$SERVER_IP" ]]; then
warn "A record untuk www.${DOMAIN} belum mengarah ke IP server ($SERVER_IP). Deteksi: ${DNS_IP_WWW:-}"
fi
# -------------- System Prep ----------------
log "Update & upgrade paket..."
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get upgrade -y
log "Instal paket umum..."
apt-get install -y software-properties-common unzip ca-certificates gnupg ufw
log "Set firewall (UFW)..."
ufw allow OpenSSH >/dev/null 2>&1 || true
ufw allow 80/tcp >/dev/null 2>&1 || true
ufw allow 443/tcp >/dev/null 2>&1 || true
echo "y" | ufw enable >/dev/null 2>&1 || true
# -------------- Install LEMP ---------------
log "Instal Nginx, PHP-FPM, ekstensi, MariaDB, Certbot..."
apt-get install -y nginx \
php-fpm php-cli php-mysql php-curl php-xml php-mbstring php-zip php-gd php-intl \
mariadb-server \
certbot python3-certbot-nginx
systemctl enable --now nginx
systemctl enable --now mariadb
# PHP-FPM service name and socket autodetect
if systemctl list-units | grep -q 'php8.3-fpm'; then
systemctl enable --now php8.3-fpm
else
systemctl enable --now php-fpm || true
fi
PHP_SOCK="$(find /run/php -maxdepth 1 -type s -name 'php*-fpm.sock' | head -n1)"
if [[ -z "$PHP_SOCK" ]]; then
PHP_SOCK="/run/php/php8.3-fpm.sock"
fi
log "Menggunakan PHP-FPM socket: ${PHP_SOCK}"
# --------- (Optional) Create DB ------------
create_db_user() {
local dbn="$1" dbu="$2" dbp="$3"
log "Membuat database & user MariaDB untuk ${DOMAIN}..."
mysql < "/root/${DOMAIN}-db.txt" < "${WEBROOT}/index.php" <<'PHP'
#!/usr/bin/env bash
# File: /root/add-site.sh
# Add a new domain vhost + webroot + Let's Encrypt (Nginx)
set -euo pipefail
DOMAIN="${DOMAIN:-}"
ADMIN_EMAIL="${ADMIN_EMAIL:-}"
STAGING="${STAGING:-false}"
if [[ -z "$DOMAIN" || -z "$ADMIN_EMAIL" ]]; then
echo "Usage: DOMAIN=example.com ADMIN_EMAIL=admin@example.com [STAGING=true] /root/add-site.sh"
exit 1
fi
WEBROOT="/var/www/${DOMAIN}/public"
mkdir -p "$WEBROOT"
cat > "${WEBROOT}/index.php" <<'PHP'
PHP
chown -R www-data:www-data "/var/www/${DOMAIN}"
find "/var/www/${DOMAIN}" -type f -exec chmod 0644 {} \;
find "/var/www/${DOMAIN}" -type d -exec chmod 0755 {} \;
# Autodetect PHP-FPM socket
PHP_SOCK="$(find /run/php -maxdepth 1 -type s -name 'php*-fpm.sock' | head -n1)"
if [[ -z "$PHP_SOCK" ]]; then PHP_SOCK="/run/php/php8.3-fpm.sock"; fi
VHOST="/etc/nginx/sites-available/${DOMAIN}.conf"
cat > "$VHOST" <chmod +x /root/add-site.sh
DOMAIN=sub.example.com ADMIN_EMAIL=admin@example.com /root/add-site.shVerifikasi & Uji Cepat
systemctl status nginx php8.3-fpm mariadbcurl -I https://example.com
curl -s https://example.com | headsudo certbot renew --dry-runtail -n 50 /var/log/nginx/example.com.access.log
tail -n 50 /var/log/nginx/example.com.error.logTroubleshooting Ringkas
- Sertifikat gagal diterbitkan → Pastikan DNS
A/AAAAuntukexample.comdanwww.example.commengarah ke IP server; tunggu propagasi. Jalankan ulang Certbot:certbot --nginx -d example.com -d www.example.com \ -m admin@example.com --agree-tos --redirect --non-interactive - Konfigurasi Nginx error → Uji sintaks, lalu reload.
nginx -t && systemctl reload nginx - PHP tidak dieksekusi → Pastikan blok
location ~ \.php$ada danfastcgi_passmenunjuk ke soket FPM yang benar. - 403/404 → Pastikan
rootmengarah ke/var/www/<domain>/public, fileindex.phpada, dan izin/owner sesuai (www-data). - Kredensial DB → Tersimpan di
/root/<domain>-db.txtbila pembuatan DB diaktifkan.
Matriks Perbandingan: Nginx vs Apache
| Aspek | Nginx | Apache |
|---|---|---|
| Kinerja Static | Event-driven, sangat efisien | Baik, modul luas |
| Reverse Proxy | Native kuat (HTTP/2/3) | Bisa via mod_proxy |
| Konfigurasi PHP | via PHP-FPM | mod_php/PHP-FPM |
| Konsumsi Memori | Umumnya lebih hemat | Cenderung lebih tinggi |
| Ekosistem Modul | Ringkas | Sangat banyak |
Kesimpulan
Dengan skrip bootstrap-lemp-ubuntu24.sh, proses dari server kosong hingga situs aktif dengan HTTPS menjadi ringkas, konsisten, dan mudah diaudit. Pastikan DNS sudah mengarah ke IP publik sebelum meminta sertifikat. Untuk domain tambahan, gunakan add-site.sh agar administrasi tetap rapi dan berulang dengan cepat.
Sumber/Referensi
- https://nginx.org/en/linux_packages.html
- https://www.php.net/manual/en/install.fpm.php
- https://mariadb.com/kb/en/documentation/
- https://certbot.eff.org/
- https://ubuntu.com/server/docs
- https://letsencrypt.org/docs/

