Forked from rameerez/kamal-production-server-setup.sh
Last active
June 8, 2025 05:47
-
-
Save Rovel/3dfffe212708f8498fa30f24363ee573 to your computer and use it in GitHub Desktop.
Set up a Ubuntu server to deploy Kamal 2.x Docker containers to, hardened security and production ready
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Ubuntu 24.04 Server Hardening Script | |
set -euo pipefail | |
IFS=$'\n\t' | |
# --- Constants --- | |
REQUIRED_OS="Ubuntu" | |
REQUIRED_VERSION="24.04" | |
MIN_RAM_MB=1024 | |
MIN_DISK_GB=20 | |
GREEN='\033[0;32m' | |
YELLOW='\033[1;33m' | |
RED='\033[0;31m' | |
NC='\033[0m' | |
print_message() { echo -e "${1}${2}${NC}"; } | |
print_error() { print_message "${RED}" "ERROR: $1"; } | |
print_success() { print_message "${GREEN}" "SUCCESS: $1"; } | |
check_root() { [[ $EUID -eq 0 ]] || { print_error "Run as root"; exit 1; }; } | |
check_os() { | |
[[ "$(lsb_release -is)" == "$REQUIRED_OS" ]] || { print_error "Requires $REQUIRED_OS"; exit 1; } | |
[[ "$(lsb_release -rs)" == "$REQUIRED_VERSION" ]] || { print_error "Requires $REQUIRED_VERSION"; exit 1; } | |
} | |
check_resources() { | |
(( $(free -m | awk '/^Mem:/{print $2}') >= MIN_RAM_MB )) || { print_error "Insufficient RAM"; exit 1; } | |
(( $(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') >= MIN_DISK_GB )) || { print_error "Insufficient disk"; exit 1; } | |
} | |
trap 'print_error "Failed at line $LINENO"; exit 1' ERR | |
print_message "${YELLOW}" "Pre-flight checks..." | |
check_root | |
check_os | |
check_resources | |
print_message "${YELLOW}" "Updating system..." | |
apt-get update | |
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y | |
print_message "${YELLOW}" "Installing security packages..." | |
DEBIAN_FRONTEND=noninteractive apt-get install -y \ | |
ufw fail2ban auditd apparmor apparmor-utils aide rkhunter logwatch unattended-upgrades | |
print_message "${YELLOW}" "Configuring AppArmor..." | |
systemctl enable --now apparmor | |
print_message "${YELLOW}" "Initializing AIDE..." | |
aide --init | |
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db | |
print_message "${YELLOW}" "Configuring kernel parameters..." | |
cat <<EOF > /etc/sysctl.d/99-hardening.conf | |
net.ipv4.conf.all.send_redirects = 0 | |
net.ipv4.conf.default.send_redirects = 0 | |
net.ipv4.conf.all.accept_redirects = 0 | |
net.ipv4.conf.default.accept_redirects = 0 | |
net.ipv4.conf.all.rp_filter = 1 | |
net.ipv4.conf.default.rp_filter = 1 | |
net.ipv4.icmp_echo_ignore_broadcasts = 1 | |
net.ipv4.icmp_ignore_bogus_error_responses = 1 | |
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 | |
net.ipv4.tcp_syncookies = 1 | |
fs.protected_hardlinks = 1 | |
fs.protected_symlinks = 1 | |
fs.suid_dumpable = 0 | |
kernel.kptr_restrict = 2 | |
kernel.dmesg_restrict = 1 | |
kernel.perf_event_paranoid = 3 | |
kernel.unprivileged_bpf_disabled = 1 | |
net.core.bpf_jit_harden = 2 | |
kernel.yama.ptrace_scope = 2 | |
EOF | |
sysctl --system | |
print_message "${YELLOW}" "Configuring SSH..." | |
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config | |
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config | |
systemctl reload ssh | |
print_message "${YELLOW}" "Configuring firewall..." | |
ufw --force reset | |
ufw default deny incoming | |
ufw default allow outgoing | |
ufw allow ssh | |
ufw --force enable | |
print_message "${YELLOW}" "Configuring fail2ban..." | |
systemctl enable --now fail2ban | |
print_message "${YELLOW}" "Configuring auditd..." | |
systemctl enable --now auditd | |
print_message "${YELLOW}" "Configuring unattended-upgrades..." | |
cat <<EOF > /etc/apt/apt.conf.d/50unattended-upgrades | |
Unattended-Upgrade::Allowed-Origins { | |
"\${distro_id}:\${distro_codename}-security"; | |
}; | |
Unattended-Upgrade::Remove-Unused-Dependencies "true"; | |
Unattended-Upgrade::Automatic-Reboot "false"; | |
EOF | |
apt-get autoremove -y | |
apt-get clean | |
print_success "Hardening complete. Please reboot to apply all settings." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment