Minimal Debian 13 VPS Setup
Isi Tulisan
VPS baru sering memberi kesan aman karena isinya masih sedikit. Kenyataannya justru sebaliknya. Pada fase inilah kita belum tahu konfigurasi apa yang ditinggalkan image provider, service apa yang mendengarkan jaringan, atau metode login apa yang masih terbuka. Panduan ini menyiapkan baseline Debian yang sederhana. Sistem diperbarui, waktu disinkronkan, firewall diaktifkan, SSH dipaksa memakai key, pembaruan keamanan dibuat otomatis, lalu seluruh hasilnya diperiksa lagi.
Fokus utamanya adalah Debian 13 Trixie. Sebagian besar langkah juga tetap berlaku untuk Debian 12 Bookworm, tetapi contoh di bawah mengikuti perilaku Debian 13. Semua perintah server dijalankan sebagai root. Model ini cocok untuk VPS milik satu administrator, meskipun server bersama atau lingkungan produksi yang lebih besar sebaiknya memakai akun admin terpisah dengan sudo.
1. Perbarui sistem lebih dulu
Jangan mengeraskan konfigurasi di atas paket yang sudah tertinggal. Mulailah dari package index yang baru dan selesaikan upgrade sistem sebelum mengubah firewall atau SSH.
apt update
apt full-upgrade -y
apt autoremove --purge -y
apt cleanJika kernel, libc, systemd, atau komponen inti ikut berubah, reboot lebih awal biasanya lebih bersih daripada melanjutkan konfigurasi di atas proses lama yang belum dimuat ulang.
2. Sinkronkan waktu
Waktu server bukan sekadar kosmetik. Log insiden, sertifikat TLS, TOTP, rotasi log, dan banyak mekanisme autentikasi bergantung pada jam yang konsisten. Untuk server, UTC biasanya paling mudah dipelihara karena tidak terpengaruh daylight-saving atau lokasi operator.
timedatectl set-timezone UTC
timedatectl set-ntp true
timedatectl statusJika image provider tidak memasang layanan sinkronisasi waktu, instal systemd-timesyncd atau gunakan daemon NTP lain yang memang sudah menjadi bagian dari stack Anda. Jangan menjalankan dua daemon waktu sekaligus.
3. Pasang alat dasar
VPS minimal sengaja datang dengan sedikit utilitas. Beberapa paket berikut cukup untuk administrasi sehari-hari tanpa mengubah server menjadi gudang software.
apt install -y curl wget git unzip htop ca-certificates gnupg lsb-release needrestartneedrestart membantu menunjukkan service atau proses yang masih memakai library lama setelah upgrade. Ia bukan alat keamanan dengan sendirinya, tetapi berguna untuk mengetahui kapan sebuah update belum benar-benar aktif hanya karena paketnya sudah selesai dipasang.
4. Batasi pintu masuk dengan UFW
Firewall yang sehat dimulai dari prinsip sederhana. Koneksi masuk ditolak kecuali ada alasan jelas untuk membukanya. Untuk SSH, gunakan rate limit agar koneksi berulang dari sumber yang sama diperlambat. HTTP dan HTTPS baru dibuka ketika server memang menjalankan web service.
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw limit 22/tcp
# Buka hanya bila memang diperlukan:
# ufw allow 80/tcp
# ufw allow 443/tcp
ufw enable
ufw status verbose5. Tambahkan Fail2Ban
Setelah password login dimatikan, Fail2Ban bukan lagi garis pertahanan utama SSH. Namun ia tetap berguna untuk menahan scanner yang berulang, mengurangi noise pada log, dan memperlambat sumber yang terus mencoba autentikasi.
apt install -y fail2banBuat konfigurasi lokal agar perubahan tidak menyentuh file bawaan paket:
cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1w
[sshd]
enabled = true
backend = systemd
EOFfail2ban-client -t
systemctl enable --now fail2ban
fail2ban-client status
fail2ban-client status sshdProgressive banning membuat pelanggar berulang menerima masa ban yang semakin panjang. Tetap anggap ini sebagai rem tambahan, bukan pengganti public-key authentication atau firewall.
6. Aktifkan pembaruan keamanan otomatis
Server yang hanya diam di internet tetap menua. Celah keamanan baru muncul pada software yang kemarin dianggap aman. Karena itu patch rutin lebih berharga daripada konfigurasi hardening yang rumit tetapi tidak pernah diperbarui.
apt install -y unattended-upgrades apt-listchanges
cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOFsystemctl list-timers apt-daily.timer apt-daily-upgrade.timer
unattended-upgrade --dry-rununattended-upgrades bekerja melalui mekanisme APT dan timer systemd. Dry run memberi kesempatan untuk melihat perilakunya sebelum kita mempercayakan update otomatis kepada server.
7. Hardening kernel dan jaringan—secukupnya
Internet penuh dengan daftar sysctl yang menjanjikan “hardening maksimal”. Masalahnya, sebagian parameter itu hanya benar untuk topologi tertentu. Baseline yang baik seharusnya mengurangi perilaku jaringan yang tidak dibutuhkan tanpa mematahkan routing, VPN, container, atau service yang kelak dipasang.
Simpan pengaturan lokal di /etc/sysctl.d/. Ini lebih jelas pada sistem modern yang memakai systemd-sysctl saat boot.
cat > /etc/sysctl.d/90-nthl-hardening.conf <<'EOF'
# TCP SYN flood fallback
net.ipv4.tcp_syncookies = 1
# Do not accept ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# Do not send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Reject source-routed packets
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Ignore broadcast ICMP echo requests
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Do not create setuid core dumps
fs.suid_dumpable = 0
EOF
sysctl --systemnet.ipv4.ip_forward=0, net.ipv6.conf.all.forwarding=0, dan strict rp_filter=1 dapat menjadi masalah pada WireGuard, container networking, multi-homed host, NAT, atau routing asimetris. Gunakan hanya jika Anda memahami topologi server.8. Kunci SSH menjadi key-only
Di tahap ini firewall sudah aktif dan server sudah diperbarui. Sekarang kita menghapus bagian paling mudah diserang dari SSH yaitu password login. Root masih boleh masuk, tetapi hanya dengan public key. Ini mempertahankan workflow VPS sederhana sambil menutup autentikasi password dan keyboard-interactive.
Pastikan key bekerja sebelum menyentuh konfigurasi
Jalankan bagian ini dari komputer lokal. Jika provider sudah memasang key Anda saat provisioning, cukup uji login. Jika belum, buat key Ed25519 dan salin public key ke server.
ssh-keygen -t ed25519
ssh-copy-id root@your-server-ip
ssh root@your-server-ipssh-copy-id mungkin tidak dapat dipakai. Dalam kasus itu, pasang public key melalui control panel provider, cloud-init, recovery console, atau mekanisme provisioning yang tersedia. Untuk create SSH Keys disini saya menggunakan windows powershell.Periksa konfigurasi efektif OpenSSH
Debian memuat file /etc/ssh/sshd_config.d/*.conf di awal konfigurasi. OpenSSH memakai nilai pertama yang ditemukan untuk sebagian besar directive, sehingga nama file bukan sekadar kosmetik. Drop-in yang datang lebih awal dapat mengalahkan file yang datang belakangan.
ls -la /etc/ssh/sshd_config.d/
grep -RniE '^(PermitRootLogin|PasswordAuthentication|KbdInteractiveAuthentication|X11Forwarding)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null
sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|x11forwarding)'Buat policy NTHL sebagai drop-in awal. Nama 00-nthl-hardening.conf dipilih agar biasanya dibaca sebelum drop-in provider seperti 50-cloud-init.conf. Hasil akhirnya tetap harus diverifikasi dengan sshd -T. Jangan mengandalkan nama file saja.
cat > /etc/ssh/sshd_config.d/00-nthl-hardening.conf <<'EOF'
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
EOFsshd -t
sshd -T | grep -E '^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|x11forwarding|clientaliveinterval|clientalivecountmax)'
systemctl reload sshNilai efektif yang kita harapkan setidaknya mencakup:
permitrootlogin prohibit-password
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
maxauthtries 3
x11forwarding no
clientaliveinterval 300
clientalivecountmax 2sshd -t sebelum reload.9. Audit permukaan serangan
Hardening sering terlalu fokus pada file konfigurasi dan lupa melihat kenyataan yang paling sederhana. Proses apa yang benar-benar berjalan, dan port apa yang benar-benar mendengarkan jaringan. Satu service yang tidak dibutuhkan lebih baik dimatikan daripada “diamankan” dengan sepuluh parameter tambahan.
ss -tulpen
systemctl --type=service --state=running --no-pager
systemctl --failed --no-pager
ufw status numberedPada VPS minimal, idealnya hanya service yang memang digunakan yang terlihat listening. Jangan mematikan service hanya karena namanya asing. Cari tahu fungsinya lebih dulu, terutama service yang berasal dari image atau agent provider.
10. Buat VPS Check
Setelah hardening selesai, kita membutuhkan satu cara untuk melihat keadaan server tanpa harus mengingat belasan command. Script berikut hanya membaca status. Ia tidak mengubah konfigurasi. Tujuannya bukan menggantikan monitoring, melainkan memberi pemeriksaan cepat setelah reboot, upgrade besar, atau perubahan jaringan.
cat > /usr/local/sbin/vps-check <<'SCRIPT'
#!/usr/bin/env bash
set -u
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
has_cmd() {
command -v "$1" >/dev/null 2>&1
}
section() {
printf '\n%b== %s ==%b\n' "$YELLOW" "$1" "$NC"
}
status_pct() {
local value="${1:-0}"
if [ "$value" -ge 90 ]; then
printf '%bHIGH%b' "$RED" "$NC"
elif [ "$value" -ge 70 ]; then
printf '%bMODERATE%b' "$YELLOW" "$NC"
else
printf '%bNORMAL%b' "$GREEN" "$NC"
fi
}
section 'SYSTEM'
printf 'Hostname: %s\n' "$(hostname)"
printf 'Kernel: %s\n' "$(uname -r)"
printf 'Uptime: %s\n' "$(uptime -p)"
section 'RESOURCES'
MEM_TOTAL=$(free -m | awk '/^Mem:/ {print $2}')
MEM_USED=$(free -m | awk '/^Mem:/ {print $3}')
MEM_PCT=$((MEM_USED * 100 / MEM_TOTAL))
ROOT_USE=$(df -P / | awk 'NR==2 {gsub(/%/,"",$5); print $5}')
CPU_USAGE=$(LC_ALL=C top -bn1 | awk '
/Cpu\(s\)/ {
for (i=1; i<=NF; i++) {
if ($i ~ /^id/) {
printf "%.0f", 100-$(i-1)
exit
}
}
}')
printf 'CPU: %s%% - %s\n' "$CPU_USAGE" "$(status_pct "$CPU_USAGE")"
printf 'RAM: %s%% - %s\n' "$MEM_PCT" "$(status_pct "$MEM_PCT")"
printf 'Root disk: %s%% - %s\n' "$ROOT_USE" "$(status_pct "$ROOT_USE")"
section 'FIREWALL & FAIL2BAN'
if has_cmd ufw; then
ufw status
else
echo 'UFW: not installed'
fi
if has_cmd fail2ban-client; then
fail2ban-client status
fail2ban-client status sshd 2>/dev/null | grep -E 'Currently banned|Total banned' || true
else
echo 'Fail2Ban: not installed'
fi
section 'SSH POLICY'
if has_cmd sshd; then
sshd -T 2>/dev/null | grep -E \
'^(permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|maxauthtries|x11forwarding)'
else
echo 'sshd: not found'
fi
section 'TIME'
if has_cmd timedatectl; then
printf 'NTP synchronized: %s\n' "$(timedatectl show -p NTPSynchronized --value)"
fi
section 'FAILED UNITS'
FAILED_UNITS=$(systemctl --failed --no-legend --no-pager 2>/dev/null || true)
if [ -n "$FAILED_UNITS" ]; then
echo "$FAILED_UNITS"
else
echo 'None'
fi
section 'LISTENING PORTS'
ss -tulpen
section 'APT'
if systemctl list-unit-files apt-daily-upgrade.timer >/dev/null 2>&1; then
printf 'apt-daily-upgrade.timer: %s / %s\n' \
"$(systemctl is-enabled apt-daily-upgrade.timer 2>/dev/null || true)" \
"$(systemctl is-active apt-daily-upgrade.timer 2>/dev/null || true)"
fi
PENDING=$(apt-get -s upgrade 2>/dev/null | awk '/^Inst/ {count++} END {print count+0}')
printf 'Pending package upgrades: %s\n' "$PENDING"
SCRIPT
chmod 750 /usr/local/sbin/vps-check
vps-checkAngka CPU, RAM, dan disk pada script ini adalah indikator cepat, bukan sistem observability. Untuk server yang benar-benar penting, gunakan monitoring dengan histori, alert, dan metrik yang dapat dibandingkan dari waktu ke waktu.
11. Reboot dan periksa sekali lagi
Konfigurasi belum benar-benar selesai sebelum kita tahu ia tetap bekerja setelah boot baru. Reboot server, login kembali menggunakan SSH key, lalu jalankan pemeriksaan.
rebootSetelah server kembali:
vps-check- SSH key berhasil login dan password authentication tetap mati.
- UFW aktif dengan hanya port yang memang diperlukan.
- Fail2Ban berjalan tanpa configuration error.
- Jam server tersinkronisasi.
- Tidak ada failed systemd unit yang tidak dijelaskan.
- Daftar listening port sesuai fungsi server.
- Timer pembaruan otomatis aktif.
Penutup
Tidak ada konfigurasi yang membuat VPS kebal. Hardening hanya mengubah keadaan awal yang longgar menjadi sistem yang lebih disiplin. Lebih sedikit pintu, lebih sedikit cara masuk, lebih sedikit service yang dibiarkan tanpa alasan, dan lebih banyak jejak ketika sesuatu berjalan tidak semestinya.

Komentar
Posting Komentar