debian-post-install.sh
· 6.8 KiB · Bash
原始文件
#!/bin/bash
#
# debian-post-install.sh
#
# Bootstrap Debian fresh install:
# - sudo + add user to sudo group
# - vnStat
# - Vim
# - sync global .bashrc / shell prompt / Fastfetch config
# - UFW firewall
# - Fail2ban for SSH
#
# Jalankan sebagai root setelah:
# su -
#
# Contoh:
# chmod +x bootstrap-debian.sh
# ./debian-post-install.sh
#
# Aman dijalankan ulang (idempotent).
set -Eeuo pipefail
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
ADMIN_USER="${ADMIN_USER:-darto}"
SYNC_BASHRC_URL="https://gist.darto.id/dartokloning/82f93f1f0a294d55bd5f1a0abcb7f63f/download/HEAD/sync-bashrc-all.sh"
SYNC_BASHRC_FILE="/usr/local/sbin/sync-bashrc-all.sh"
FAIL2BAN_JAIL="/etc/fail2ban/jail.d/sshd.local"
# Port web yang biasa dibuka.
ALLOW_HTTP="${ALLOW_HTTP:-yes}"
ALLOW_HTTPS="${ALLOW_HTTPS:-yes}"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
log() {
printf '\n== %s ==\n' "$*"
}
ok() {
printf ' -> %s\n' "$*"
}
die() {
printf 'ERROR: %s\n' "$*" >&2
exit 1
}
if [[ "$(id -u)" -ne 0 ]]; then
die "Jalankan script ini sebagai root. Gunakan: su -"
fi
if [[ ! -r /etc/os-release ]]; then
die "/etc/os-release tidak ditemukan."
fi
. /etc/os-release
if [[ "${ID:-}" != "debian" ]]; then
die "Script ini khusus Debian. Sistem terdeteksi: ${PRETTY_NAME:-unknown}"
fi
if ! id "$ADMIN_USER" >/dev/null 2>&1; then
die "User '$ADMIN_USER' tidak ditemukan."
fi
export DEBIAN_FRONTEND=noninteractive
# ---------------------------------------------------------------------------
# 1. Update + packages
# ---------------------------------------------------------------------------
log "1. Update repository dan install paket dasar"
apt-get update
apt-get install -y \
sudo \
curl \
ca-certificates \
vnstat \
vim \
vim-common \
ufw \
fail2ban
ok "Paket dasar sudah terinstall."
# ---------------------------------------------------------------------------
# 2. Sudo access
# ---------------------------------------------------------------------------
log "2. Pastikan $ADMIN_USER masuk group sudo"
if id -nG "$ADMIN_USER" | tr ' ' '\n' | grep -qx sudo; then
ok "$ADMIN_USER sudah menjadi anggota group sudo."
else
usermod -aG sudo "$ADMIN_USER"
ok "$ADMIN_USER ditambahkan ke group sudo."
fi
printf ' -> Group %s: %s\n' "$ADMIN_USER" "$(id -nG "$ADMIN_USER")"
# ---------------------------------------------------------------------------
# 3. vnStat
# ---------------------------------------------------------------------------
log "3. Aktifkan vnStat"
systemctl enable --now vnstat
systemctl is-active --quiet vnstat \
&& ok "vnstat aktif." \
|| die "vnstat gagal aktif."
# ---------------------------------------------------------------------------
# 4. Vim
# ---------------------------------------------------------------------------
log "4. Verifikasi Vim"
if command -v vim >/dev/null 2>&1; then
ok "Vim tersedia: $(vim --version | head -n1)"
else
die "Vim tidak ditemukan setelah instalasi."
fi
# ---------------------------------------------------------------------------
# 5. Sync .bashrc / prompt / Fastfetch
# ---------------------------------------------------------------------------
log "5. Download dan jalankan sync-bashrc-all.sh"
tmp_sync="$(mktemp)"
trap 'rm -f "$tmp_sync"' EXIT
curl -fL --silent --show-error "$SYNC_BASHRC_URL" -o "$tmp_sync"
if [[ ! -s "$tmp_sync" ]]; then
die "sync-bashrc-all.sh hasil download kosong."
fi
install -o root -g root -m 0755 "$tmp_sync" "$SYNC_BASHRC_FILE"
ok "sync-bashrc-all.sh disimpan di $SYNC_BASHRC_FILE"
"$SYNC_BASHRC_FILE"
ok "Konfigurasi Bash/Fastfetch selesai disinkronkan."
# ---------------------------------------------------------------------------
# 6. Detect SSH port
# ---------------------------------------------------------------------------
log "6. Deteksi port SSH"
SSH_PORT="22"
if command -v sshd >/dev/null 2>&1; then
detected_port="$(sshd -T 2>/dev/null | awk '$1=="port" {print $2; exit}' || true)"
if [[ "$detected_port" =~ ^[0-9]+$ ]]; then
SSH_PORT="$detected_port"
fi
fi
ok "Port SSH terdeteksi: $SSH_PORT/tcp"
# ---------------------------------------------------------------------------
# 7. UFW
# ---------------------------------------------------------------------------
log "7. Konfigurasi UFW"
# Jangan reset UFW agar rule custom yang mungkin sudah ada tidak hilang.
ufw allow "${SSH_PORT}/tcp" comment 'SSH'
if [[ "$ALLOW_HTTP" == "yes" ]]; then
ufw allow 80/tcp comment 'HTTP'
fi
if [[ "$ALLOW_HTTPS" == "yes" ]]; then
ufw allow 443/tcp comment 'HTTPS'
fi
# ufw --force enable aman untuk noninteractive.
ufw --force enable
systemctl enable --now ufw
ok "UFW aktif."
ufw status verbose
# ---------------------------------------------------------------------------
# 8. Fail2ban
# ---------------------------------------------------------------------------
log "8. Konfigurasi Fail2ban"
mkdir -p /etc/fail2ban/jail.d
cat > "$FAIL2BAN_JAIL" <<EOF
[sshd]
enabled = true
backend = systemd
port = ${SSH_PORT}
bantime = 4w
maxretry = 2
banaction = ufw
EOF
chmod 0644 "$FAIL2BAN_JAIL"
ok "Konfigurasi dibuat: $FAIL2BAN_JAIL"
# Validasi konfigurasi sebelum restart.
if ! fail2ban-client -t; then
die "Validasi konfigurasi Fail2ban gagal."
fi
systemctl enable --now fail2ban
systemctl restart fail2ban
sleep 1
systemctl is-active --quiet fail2ban \
&& ok "Fail2ban aktif." \
|| die "Fail2ban gagal aktif."
# ---------------------------------------------------------------------------
# 9. Summary
# ---------------------------------------------------------------------------
log "9. Ringkasan"
printf 'User admin : %s\n' "$ADMIN_USER"
printf 'Group : %s\n' "$(id -nG "$ADMIN_USER")"
printf 'SSH port : %s/tcp\n' "$SSH_PORT"
printf 'vnStat : %s\n' "$(systemctl is-active vnstat || true)"
printf 'UFW : %s\n' "$(systemctl is-active ufw || true)"
printf 'Fail2ban : %s\n' "$(systemctl is-active fail2ban || true)"
printf 'Fail2ban jail : %s\n' "$FAIL2BAN_JAIL"
printf 'Bash sync : %s\n' "$SYNC_BASHRC_FILE"
echo
echo "Fail2ban SSH jail:"
fail2ban-client status sshd 2>/dev/null || true
echo
echo "============================================================"
echo "BOOTSTRAP DEBIAN SELESAI"
echo "============================================================"
echo
echo "PENTING:"
echo "User '$ADMIN_USER' baru memperoleh group sudo pada login session berikutnya."
echo "Disconnect SSH lalu login kembali sebagai '$ADMIN_USER'."
echo
echo "Setelah login ulang, cek:"
echo " sudo -v"
echo " groups"
echo " fastfetch --config /etc/fastfetch/config.jsonc"
echo " sudo ufw status verbose"
echo " sudo fail2ban-client status sshd"
echo
| 1 | #!/bin/bash |
| 2 | # |
| 3 | # debian-post-install.sh |
| 4 | # |
| 5 | # Bootstrap Debian fresh install: |
| 6 | # - sudo + add user to sudo group |
| 7 | # - vnStat |
| 8 | # - Vim |
| 9 | # - sync global .bashrc / shell prompt / Fastfetch config |
| 10 | # - UFW firewall |
| 11 | # - Fail2ban for SSH |
| 12 | # |
| 13 | # Jalankan sebagai root setelah: |
| 14 | # su - |
| 15 | # |
| 16 | # Contoh: |
| 17 | # chmod +x bootstrap-debian.sh |
| 18 | # ./debian-post-install.sh |
| 19 | # |
| 20 | # Aman dijalankan ulang (idempotent). |
| 21 | |
| 22 | set -Eeuo pipefail |
| 23 | |
| 24 | # --------------------------------------------------------------------------- |
| 25 | # Configuration |
| 26 | # --------------------------------------------------------------------------- |
| 27 | |
| 28 | ADMIN_USER="${ADMIN_USER:-darto}" |
| 29 | |
| 30 | SYNC_BASHRC_URL="https://gist.darto.id/dartokloning/82f93f1f0a294d55bd5f1a0abcb7f63f/download/HEAD/sync-bashrc-all.sh" |
| 31 | SYNC_BASHRC_FILE="/usr/local/sbin/sync-bashrc-all.sh" |
| 32 | |
| 33 | FAIL2BAN_JAIL="/etc/fail2ban/jail.d/sshd.local" |
| 34 | |
| 35 | # Port web yang biasa dibuka. |
| 36 | ALLOW_HTTP="${ALLOW_HTTP:-yes}" |
| 37 | ALLOW_HTTPS="${ALLOW_HTTPS:-yes}" |
| 38 | |
| 39 | # --------------------------------------------------------------------------- |
| 40 | # Helpers |
| 41 | # --------------------------------------------------------------------------- |
| 42 | |
| 43 | log() { |
| 44 | printf '\n== %s ==\n' "$*" |
| 45 | } |
| 46 | |
| 47 | ok() { |
| 48 | printf ' -> %s\n' "$*" |
| 49 | } |
| 50 | |
| 51 | die() { |
| 52 | printf 'ERROR: %s\n' "$*" >&2 |
| 53 | exit 1 |
| 54 | } |
| 55 | |
| 56 | if [[ "$(id -u)" -ne 0 ]]; then |
| 57 | die "Jalankan script ini sebagai root. Gunakan: su -" |
| 58 | fi |
| 59 | |
| 60 | if [[ ! -r /etc/os-release ]]; then |
| 61 | die "/etc/os-release tidak ditemukan." |
| 62 | fi |
| 63 | |
| 64 | . /etc/os-release |
| 65 | |
| 66 | if [[ "${ID:-}" != "debian" ]]; then |
| 67 | die "Script ini khusus Debian. Sistem terdeteksi: ${PRETTY_NAME:-unknown}" |
| 68 | fi |
| 69 | |
| 70 | if ! id "$ADMIN_USER" >/dev/null 2>&1; then |
| 71 | die "User '$ADMIN_USER' tidak ditemukan." |
| 72 | fi |
| 73 | |
| 74 | export DEBIAN_FRONTEND=noninteractive |
| 75 | |
| 76 | # --------------------------------------------------------------------------- |
| 77 | # 1. Update + packages |
| 78 | # --------------------------------------------------------------------------- |
| 79 | |
| 80 | log "1. Update repository dan install paket dasar" |
| 81 | |
| 82 | apt-get update |
| 83 | |
| 84 | apt-get install -y \ |
| 85 | sudo \ |
| 86 | curl \ |
| 87 | ca-certificates \ |
| 88 | vnstat \ |
| 89 | vim \ |
| 90 | vim-common \ |
| 91 | ufw \ |
| 92 | fail2ban |
| 93 | |
| 94 | ok "Paket dasar sudah terinstall." |
| 95 | |
| 96 | # --------------------------------------------------------------------------- |
| 97 | # 2. Sudo access |
| 98 | # --------------------------------------------------------------------------- |
| 99 | |
| 100 | log "2. Pastikan $ADMIN_USER masuk group sudo" |
| 101 | |
| 102 | if id -nG "$ADMIN_USER" | tr ' ' '\n' | grep -qx sudo; then |
| 103 | ok "$ADMIN_USER sudah menjadi anggota group sudo." |
| 104 | else |
| 105 | usermod -aG sudo "$ADMIN_USER" |
| 106 | ok "$ADMIN_USER ditambahkan ke group sudo." |
| 107 | fi |
| 108 | |
| 109 | printf ' -> Group %s: %s\n' "$ADMIN_USER" "$(id -nG "$ADMIN_USER")" |
| 110 | |
| 111 | # --------------------------------------------------------------------------- |
| 112 | # 3. vnStat |
| 113 | # --------------------------------------------------------------------------- |
| 114 | |
| 115 | log "3. Aktifkan vnStat" |
| 116 | |
| 117 | systemctl enable --now vnstat |
| 118 | systemctl is-active --quiet vnstat \ |
| 119 | && ok "vnstat aktif." \ |
| 120 | || die "vnstat gagal aktif." |
| 121 | |
| 122 | # --------------------------------------------------------------------------- |
| 123 | # 4. Vim |
| 124 | # --------------------------------------------------------------------------- |
| 125 | |
| 126 | log "4. Verifikasi Vim" |
| 127 | |
| 128 | if command -v vim >/dev/null 2>&1; then |
| 129 | ok "Vim tersedia: $(vim --version | head -n1)" |
| 130 | else |
| 131 | die "Vim tidak ditemukan setelah instalasi." |
| 132 | fi |
| 133 | |
| 134 | # --------------------------------------------------------------------------- |
| 135 | # 5. Sync .bashrc / prompt / Fastfetch |
| 136 | # --------------------------------------------------------------------------- |
| 137 | |
| 138 | log "5. Download dan jalankan sync-bashrc-all.sh" |
| 139 | |
| 140 | tmp_sync="$(mktemp)" |
| 141 | trap 'rm -f "$tmp_sync"' EXIT |
| 142 | |
| 143 | curl -fL --silent --show-error "$SYNC_BASHRC_URL" -o "$tmp_sync" |
| 144 | |
| 145 | if [[ ! -s "$tmp_sync" ]]; then |
| 146 | die "sync-bashrc-all.sh hasil download kosong." |
| 147 | fi |
| 148 | |
| 149 | install -o root -g root -m 0755 "$tmp_sync" "$SYNC_BASHRC_FILE" |
| 150 | |
| 151 | ok "sync-bashrc-all.sh disimpan di $SYNC_BASHRC_FILE" |
| 152 | |
| 153 | "$SYNC_BASHRC_FILE" |
| 154 | |
| 155 | ok "Konfigurasi Bash/Fastfetch selesai disinkronkan." |
| 156 | |
| 157 | # --------------------------------------------------------------------------- |
| 158 | # 6. Detect SSH port |
| 159 | # --------------------------------------------------------------------------- |
| 160 | |
| 161 | log "6. Deteksi port SSH" |
| 162 | |
| 163 | SSH_PORT="22" |
| 164 | |
| 165 | if command -v sshd >/dev/null 2>&1; then |
| 166 | detected_port="$(sshd -T 2>/dev/null | awk '$1=="port" {print $2; exit}' || true)" |
| 167 | if [[ "$detected_port" =~ ^[0-9]+$ ]]; then |
| 168 | SSH_PORT="$detected_port" |
| 169 | fi |
| 170 | fi |
| 171 | |
| 172 | ok "Port SSH terdeteksi: $SSH_PORT/tcp" |
| 173 | |
| 174 | # --------------------------------------------------------------------------- |
| 175 | # 7. UFW |
| 176 | # --------------------------------------------------------------------------- |
| 177 | |
| 178 | log "7. Konfigurasi UFW" |
| 179 | |
| 180 | # Jangan reset UFW agar rule custom yang mungkin sudah ada tidak hilang. |
| 181 | ufw allow "${SSH_PORT}/tcp" comment 'SSH' |
| 182 | |
| 183 | if [[ "$ALLOW_HTTP" == "yes" ]]; then |
| 184 | ufw allow 80/tcp comment 'HTTP' |
| 185 | fi |
| 186 | |
| 187 | if [[ "$ALLOW_HTTPS" == "yes" ]]; then |
| 188 | ufw allow 443/tcp comment 'HTTPS' |
| 189 | fi |
| 190 | |
| 191 | # ufw --force enable aman untuk noninteractive. |
| 192 | ufw --force enable |
| 193 | systemctl enable --now ufw |
| 194 | |
| 195 | ok "UFW aktif." |
| 196 | |
| 197 | ufw status verbose |
| 198 | |
| 199 | # --------------------------------------------------------------------------- |
| 200 | # 8. Fail2ban |
| 201 | # --------------------------------------------------------------------------- |
| 202 | |
| 203 | log "8. Konfigurasi Fail2ban" |
| 204 | |
| 205 | mkdir -p /etc/fail2ban/jail.d |
| 206 | |
| 207 | cat > "$FAIL2BAN_JAIL" <<EOF |
| 208 | [sshd] |
| 209 | enabled = true |
| 210 | backend = systemd |
| 211 | port = ${SSH_PORT} |
| 212 | bantime = 4w |
| 213 | maxretry = 2 |
| 214 | banaction = ufw |
| 215 | EOF |
| 216 | |
| 217 | chmod 0644 "$FAIL2BAN_JAIL" |
| 218 | |
| 219 | ok "Konfigurasi dibuat: $FAIL2BAN_JAIL" |
| 220 | |
| 221 | # Validasi konfigurasi sebelum restart. |
| 222 | if ! fail2ban-client -t; then |
| 223 | die "Validasi konfigurasi Fail2ban gagal." |
| 224 | fi |
| 225 | |
| 226 | systemctl enable --now fail2ban |
| 227 | systemctl restart fail2ban |
| 228 | |
| 229 | sleep 1 |
| 230 | |
| 231 | systemctl is-active --quiet fail2ban \ |
| 232 | && ok "Fail2ban aktif." \ |
| 233 | || die "Fail2ban gagal aktif." |
| 234 | |
| 235 | # --------------------------------------------------------------------------- |
| 236 | # 9. Summary |
| 237 | # --------------------------------------------------------------------------- |
| 238 | |
| 239 | log "9. Ringkasan" |
| 240 | |
| 241 | printf 'User admin : %s\n' "$ADMIN_USER" |
| 242 | printf 'Group : %s\n' "$(id -nG "$ADMIN_USER")" |
| 243 | printf 'SSH port : %s/tcp\n' "$SSH_PORT" |
| 244 | printf 'vnStat : %s\n' "$(systemctl is-active vnstat || true)" |
| 245 | printf 'UFW : %s\n' "$(systemctl is-active ufw || true)" |
| 246 | printf 'Fail2ban : %s\n' "$(systemctl is-active fail2ban || true)" |
| 247 | printf 'Fail2ban jail : %s\n' "$FAIL2BAN_JAIL" |
| 248 | printf 'Bash sync : %s\n' "$SYNC_BASHRC_FILE" |
| 249 | |
| 250 | echo |
| 251 | echo "Fail2ban SSH jail:" |
| 252 | fail2ban-client status sshd 2>/dev/null || true |
| 253 | |
| 254 | echo |
| 255 | echo "============================================================" |
| 256 | echo "BOOTSTRAP DEBIAN SELESAI" |
| 257 | echo "============================================================" |
| 258 | echo |
| 259 | echo "PENTING:" |
| 260 | echo "User '$ADMIN_USER' baru memperoleh group sudo pada login session berikutnya." |
| 261 | echo "Disconnect SSH lalu login kembali sebagai '$ADMIN_USER'." |
| 262 | echo |
| 263 | echo "Setelah login ulang, cek:" |
| 264 | echo " sudo -v" |
| 265 | echo " groups" |
| 266 | echo " fastfetch --config /etc/fastfetch/config.jsonc" |
| 267 | echo " sudo ufw status verbose" |
| 268 | echo " sudo fail2ban-client status sshd" |
| 269 | echo |
| 270 |