Cara Menyiapkan VPS untuk Pemula, dari Seorang Pemula (Bagian 1: Mengamankan Sistem Dasar)
Bagian 1 dari penyiapan VPS pertama saya di Debian 13. Update, memberi nama server, satu pengguna dengan kunci SSH dan sudo, dan konfigurasi SSH yang hanya mengizinkan pengguna itu masuk.
Seri 5 bagian.
- Bagian 1: Mengamankan Sistem Dasar
- Bagian 2: Firewall, Ban & Update
- Bagian 3: Podman Rootless
- Bagian 4: Traefik & HTTPS
- Bagian 5: Deploy, dan Satu Skrip untuk Semuanya
Pendahuluan
Ini VPS pertama saya. Mesin Debian 13 kecil, dan saya mau menjalankan proyek-proyek saya sendiri di sana, mulai dari situs ini.
Server baru belum dikonfigurasi apa-apa, jadi belum ada juga yang melindunginya. Saya mau paham setiap langkahnya sebelum menaruh apa pun di sana, jadi semuanya saya kerjakan manual dan saya catat sambil jalan. Itulah seri ini.
Di akhir, semuanya saya jadikan satu skrip, vps-setup.sh. Kalau cuma mau hasilnya, Bagian 5 menunjukkan cara menjalankannya. Kalau mau tahu apa yang dilakukannya ke server kita, mulai dari sini.
Akses Pertama
Provider memberi IP dan login root. Sambungkan:
ssh root@IP_VPSThe authenticity of host 'IP_VPS (IP_VPS)' can't be established.
ED25519 key fingerprint is SHA256:qL3nR8vT1wX5yZ0aB4cD7eF9gH2jK6mN8pQ1rS3tU5v.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Linux vps 6.12.48+deb13-amd64 #1 SMP Debian 6.12.48-1 x86_64
root@vps:~#Pertanyaan fingerprint itu cuma muncul sekali. Kalau suatu saat muncul lagi untuk server yang sama, berarti ada yang berubah di sisi sana, dan saya mau tahu apa sebelum mengetik yes.
Saya akan pakai root beberapa menit ke depan, lalu tidak pernah login sebagai root lagi.
Update
Server dibuat dari image milik provider, dan image itu tidak pernah benar-benar terbaru:
apt update && apt full-upgrade -yHit:1 http://deb.debian.org/debian trixie InRelease
Get:2 http://security.debian.org/debian-security trixie-security InRelease [48.0 kB]
...
14 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.Saya pakai full-upgrade, bukan upgrade, karena full-upgrade boleh memasang atau menghapus package kalau update-nya butuh, misalnya package kernel baru. upgrade biasa malah menahannya.
Lalu beberapa yang dasar:
apt install -y sudo curl ca-certificates nano lesssudo saya taruh paling depan karena ada alasannya. Image minimal Debian tidak membawa sudo, tapi grup sudo tetap ada, jadi menambahkan pengguna ke grup itu berhasil tanpa pesan apa pun. Kalau login root lalu dimatikan padahal perintah sudo-nya tidak ada, tidak ada lagi akun yang bisa membereskan apa pun.
Bagian-bagian berikutnya memasang yang mereka butuhkan masing-masing.
Nama dan Waktu
Dua hal kecil. Hostname muncul di prompt dan di setiap baris log, dan vps atau debian tidak akan berarti apa-apa buat saya nanti:
hostnamectl set-hostname my-vps
nano /etc/hosts127.0.1.1 my-vpsBaris di /etc/hosts itu harus sama dengan nama baru, kalau tidak sudo akan mengeluh tidak bisa menemukan host-nya.
Beberapa provider mengatur hostname di setiap boot lewat cloud-init. Kalau provider kita begitu, ini mencegah namanya dikembalikan:
echo 'preserve_hostname: true' > /etc/cloud/cloud.cfg.d/99-hostname.cfgLalu zona waktu, supaya waktu di log pakai jam saya, bukan UTC:
timedatectl set-timezone Asia/Jakarta
timedatectl set-ntp true
timedatectl status Local time: Wed 2026-05-20 16:20:33 WIB
Universal time: Wed 2026-05-20 09:20:33 UTC
Time zone: Asia/Jakarta (WIB, +0700)
System clock synchronized: yes
NTP service: activeYang saya cari System clock synchronized: yes. Jam yang salah bikin sertifikat HTTPS gagal dengan cara yang membingungkan. Kalau NTP service bilang n/a, image-nya datang tanpa klien waktu, dan apt install -y systemd-timesyncd membereskannya.
Kunci SSH
Password bisa ditebak. Kunci tidak, setidaknya tidak dengan cara yang masuk akal. Jadi sebelum yang lain, saya buat kunci di laptop (bukan di server):
ssh-keygen -t ed25519 -C "vps-personal"Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519):
Enter passphrase for "/home/you/.ssh/id_ed25519" (empty for no passphrase):
Your identification has been saved in /home/you/.ssh/id_ed25519
Your public key has been saved in /home/you/.ssh/id_ed25519.pubHasilnya dua berkas. id_ed25519 itu privat dan tidak pernah keluar dari laptop. id_ed25519.pub yang saya berikan ke server:
cat ~/.ssh/id_ed25519.pubssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8kR2pQ7mZvN1xW4tYbL9cD0eF3gH5jK7lM2nP4qR6s vps-personalKalau yang muncul diawali -----BEGIN OPENSSH PRIVATE KEY-----, itu berkas yang salah.
Saya pilih Ed25519 karena kuncinya pendek dan cepat, dan semua OpenSSH modern mendukungnya. RSA juga bisa, tapi minimal harus 2048 bit supaya ada gunanya.
Satu Pengguna untuk Semuanya
Saya tidak mau bekerja sebagai root. Saya juga tidak mau punya banyak akun. Jadi server ini dapat tepat satu pengguna biasa, dan pengguna itu yang mengerjakan semuanya: login, pakai sudo, dan nanti memiliki semua kontainer.
Kembali ke server, sebagai root:
useradd --create-home --shell /bin/bash admin
usermod -aG sudo,adm,systemd-journal admin
passwd adminNew password:
Retype new password:
passwd: password updated successfullyGrupnya:
sudountuk menjalankan perintah admin.admdansystemd-journaluntuk membaca log sistem tanpa harus mengetiksudoterus.
Password-nya cuma untuk sudo. Login akan pakai kunci saja beberapa menit lagi.
Cek dulu sudo benar-benar jalan untuk pengguna baru sebelum mengandalkannya:
su - admin -c 'sudo -v'[sudo] password for admin:Kalau ia minta password dan menerimanya, aman. sudo: command not found berarti package-nya belum ada, jadi pasang dulu selagi root masih bisa dipakai.
Memberi Kunci ke Pengguna
Kunci publik harus masuk ke ~/.ssh/authorized_keys milik pengguna baru. Dari laptop:
ssh-copy-id admin@IP_VPS/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
admin@IP_VPS's password:
Number of key(s) added: 1Ia login pakai password untuk terakhir kalinya, dan mengatur izin berkasnya dengan benar.
Kalau image dari provider sudah mematikan login password, cara itu tidak jalan. Kalau begitu, salin kunci milik root di server:
install -d -m 700 -o admin -g admin /home/admin/.ssh
install -m 600 -o admin -g admin /root/.ssh/authorized_keys /home/admin/.ssh/authorized_keysinstall membuat berkasnya dengan pemilik dan izin yang benar sekaligus. cp biasa akan meninggalkannya dimiliki root, dan SSH diam-diam mengabaikan berkas kunci yang bukan milik penggunanya.
Coba dari laptop:
ssh admin@IP_VPSLinux my-vps 6.12.48+deb13-amd64 #1 SMP Debian 6.12.48-1 x86_64
admin@my-vps:~$Tidak ada prompt password, dan prompt-nya diakhiri $, bukan #. Itu pengguna biasa yang login dengan kunci.
Mengunci SSH
Sekarang hardening-nya. Config utama Debian ada di /etc/ssh/sshd_config, tapi saya tidak mengeditnya. Di bagian atas berkas itu ada baris ini:
Include /etc/ssh/sshd_config.d/*.confsshd memakai nilai pertama yang ia temukan untuk setiap pengaturan, dan berkas yang di-include dibaca duluan, urut abjad. Banyak image VPS membawa 50-cloud-init.conf di sana yang isinya PasswordAuthentication yes. Perubahan apa pun yang kita buat di bawah berkas utama kalah dengannya.
Jadi pengaturan saya taruh di berkas yang urutannya paling awal:
sudo nano /etc/ssh/sshd_config.d/00-hardening.confPort 22022
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
AuthenticationMethods publickey
AllowUsers admin
MaxAuthTries 3
MaxSessions 4
LoginGraceTime 20
ClientAliveInterval 300
ClientAliveCountMax 2
PermitUserEnvironment no
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding local
AllowStreamLocalForwarding no
GatewayPorts no
PermitTunnel no
UseDNS no
LogLevel VERBOSE
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,curve25519-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.comBanyak ya, jadi singkatnya:
- Port 22022. Bukan keamanan sungguhan, tapi bot menggempur port 22 seharian dan ini mengurangi bisingnya di log.
- Tanpa root, tanpa password, hanya kunci, dan hanya
admin. Ini baris-baris yang paling penting. DenganAllowUsers, kalaupun suatu hari ada akun lain di server, akun itu tetap tidak bisa login lewat SSH. MaxAuthTries,LoginGraceTime. Cepat menyerah pada koneksi yang tidak ke mana-mana.- Forwarding. Semua saya matikan kecuali
AllowTcpForwarding local, supaya saya masih bisassh -Luntuk menjangkau database di server dari laptop. LogLevel VERBOSEmencatat fingerprint kunci yang dipakai di setiap login, jadi saya bisa lihat kunci mana yang masuk.- Kripto. Hanya key exchange, cipher, dan MAC yang modern. Key exchange pertama,
mlkem768x25519-sha256, tahan komputer kuantum dan baru ada di OpenSSH 10, yang dibawa Debian 13. Host key ECDSA saya buang, Ed25519 dan RSA tetap untuk klien yang lebih tua.
Kalau versi OpenSSH-nya beda, cek dulu apa yang didukung sebelum menyalin baris-baris terakhir itu:
ssh -Q kexSebelum me-restart apa pun, tes berkasnya. Ada salah ketik di sini dan SSH tidak akan kembali:
sudo sshd -tTidak ada output berarti aman. Lalu tanya sshd apa yang benar-benar akan ia pakai, setelah semua berkas include:
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication|allowusers) 'port 22022
permitrootlogin no
passwordauthentication no
allowusers adminItu config yang efektif, dan cuma itu yang saya percaya. Kalau passwordauthentication di sini bilang yes, ada berkas lain yang menang.
Port Harus Diganti di Dua Tempat
Yang ini sempat menjebak saya. Debian 13 bisa menjalankan SSH lewat socket systemd, dan kalau begitu, yang membuka port adalah systemd, bukan sshd. Baris Port di atas diabaikan. Server saya diatur seperti itu:
systemctl is-enabled ssh.socketenabledKalau hasilnya juga enabled, beri tahu socket-nya soal port baru:
sudo mkdir -p /etc/systemd/system/ssh.socket.d
sudo nano /etc/systemd/system/ssh.socket.d/port.conf[Socket]
ListenStream=
ListenStream=22022ListenStream= yang kosong itu menghapus port default 22. Tanpanya, ia mendengarkan di dua port.
sudo systemctl daemon-reload
sudo systemctl restart ssh.socketKalau hasilnya disabled, sshd membuka port sendiri dan cukup di-restart:
sudo systemctl restart sshYang mana pun, cek apa yang sedang mendengarkan:
sudo ss -tlnp | grep 22022LISTEN 0 4096 0.0.0.0:22022 0.0.0.0:* users:(("systemd",pid=1,fd=52))
LISTEN 0 4096 [::]:22022 [::]:* users:(("systemd",pid=1,fd=53))Tes Sebelum Menutup Apa Pun
Jangan tutup sesi yang sedang dipakai. Buka terminal kedua di laptop dan sambungkan ke port baru:
ssh -p 22022 admin@IP_VPSKalau jalan, selesai. Kalau tidak, sesi pertama masih terbuka dan bisa dipakai untuk membetulkannya. Kalau sesi itu ditutup dan config barunya rusak, satu-satunya jalan masuk tinggal konsol web dari provider.
Dan untuk memastikan root benar-benar terkunci:
ssh -p 22022 root@IP_VPSroot@IP_VPS: Permission denied (publickey).Membuat Koneksi Lebih Pendek
Mengetik ssh -p 22022 admin@IP_VPS setiap kali cepat bikin bosan. SSH punya berkas config di sisi laptop untuk ini:
nano ~/.ssh/configHost vps
HostName IP_VPS
User admin
Port 22022
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yeschmod 600 ~/.ssh/config
ssh vpsIdentitiesOnly yes bikin SSH hanya menawarkan satu kunci itu. Tanpanya, ia mencoba semua kunci di agent, dan dengan MaxAuthTries 3 di server, kita bisa ditolak sebelum sampai ke kunci yang benar.
Enaknya, semua yang lain yang pakai SSH juga membaca berkas ini. scp file vps:~/ dan rsync ./dist/ vps:~/site/ langsung jalan, begitu juga Remote-SSH di VS Code.
Bagian Selanjutnya
Sejauh ini: sistem sudah di-update, ada satu pengguna dengan kunci dan sudo, root tidak bisa login, dan SSH hanya menerima kunci pengguna itu di port yang tidak standar.
Itu baru urusan login. Port lain masih terbuka, tidak ada yang mengawasi kegagalan berulang, dan update cuma terjadi kalau saya ingat. Bagian 2 membereskan itu: firewall, fail2ban, update otomatis, dan sedikit tuning.