Otomatisasi Webserver Ubuntu 24 (LEMP): Nginx, PHP-FPM, MariaDB, Certbot — Domain Siap HTTPS

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.

Pendapat singkat: Otomasi yang baik menghemat waktu dan mencegah salah ketik—musuh alami sesi lembur.

Daftar Isi

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

Wajib sebelum minta sertifikat: Buat record DNS berikut di Cloudflare/penyedia DNS Anda:
  • A untuk example.comIP_PUBLIK_SERVER
  • A untuk www.example.comIP_PUBLIK_SERVER
  • (Opsional IPv6) AAAA untuk keduanya → IPv6_SERVER

Setelah itu, cek:

Copy
dig +short A example.com
dig +short A www.example.com

Skrip 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.

File: /root/bootstrap-lemp-ubuntu24.sh
Copy
#!/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[32mINFOe[0m] $*"; }
warn(){ echo -e "[e[33mWARNe[0m] $*"; }
err() { echo -e "[e[31mERRORe[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'

      Copy
    
#!/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" <
Copy
chmod +x /root/add-site.sh
DOMAIN=sub.example.com ADMIN_EMAIL=admin@example.com /root/add-site.sh

Verifikasi & Uji Cepat

Copy
systemctl status nginx php8.3-fpm mariadb
Copy
curl -I https://example.com
curl -s https://example.com | head
Copy
sudo certbot renew --dry-run
Copy
tail -n 50 /var/log/nginx/example.com.access.log
tail -n 50 /var/log/nginx/example.com.error.log

Troubleshooting Ringkas

  • Sertifikat gagal diterbitkan → Pastikan DNS A/AAAA untuk example.com dan www.example.com mengarah ke IP server; tunggu propagasi. Jalankan ulang Certbot:
    Copy
    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.
    Copy
    nginx -t && systemctl reload nginx
  • PHP tidak dieksekusi → Pastikan blok location ~ .php$ ada dan fastcgi_pass menunjuk ke soket FPM yang benar.
  • 403/404 → Pastikan root mengarah ke /var/www/<domain>/public, file index.php ada, dan izin/owner sesuai (www-data).
  • Kredensial DB → Tersimpan di /root/<domain>-db.txt bila pembuatan DB diaktifkan.

Matriks Perbandingan: Nginx vs Apache

AspekNginxApache
Kinerja StaticEvent-driven, sangat efisienBaik, modul luas
Reverse ProxyNative kuat (HTTP/2/3)Bisa via mod_proxy
Konfigurasi PHPvia PHP-FPMmod_php/PHP-FPM
Konsumsi MemoriUmumnya lebih hematCenderung lebih tinggi
Ekosistem ModulRingkasSangat 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

.table-wrap{overflow:auto;border:1px solid #e2e8f0;border-radius:12px;margin:8px 0}
table{border-collapse:collapse;width:100%}
th,td{padding:10px;border-bottom:1px solid #e2e8f0;text-align:left}

.refs li{margin-left:18px}

/* Code blocks */
.codebox{margin:10px 0}
.codehead{display:flex;justify-content:space-between;align-items:center;background:var(--soft);border:1px solid #e2e8f0;border-bottom:none;border-radius:10px 10px 0 0;padding:8px 10px;font-size:14px;color:var(--ink-2)}
pre{background:var(--bg);color:var(--fg);border:1px solid var(--line);border-radius:10px;padding:12px;overflow:auto;margin:0}
code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:14px;white-space:pre}
.copy{float:right;margin-left:auto;margin-bottom:6px;padding:6px 10px;border-radius:8px;border:1px solid var(--muted);background:#f8fafc;cursor:pointer}
.copy:disabled{opacity:.6;cursor:not-allowed}


Artikel Terkait

wave

Tekan ESC untuk menutup