Forked from rameerez/kamal-production-server-setup.sh
Created
November 21, 2024 11:48
-
-
Save johan--/b2523ef77dd92bd963417652c20fece9 to your computer and use it in GitHub Desktop.
Revisions
-
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 1 addition and 11 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -300,15 +300,6 @@ curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh rm get-docker.sh # --- Docker Configuration --- print_message "${YELLOW}" "Configuring Docker..." mkdir -p /etc/docker @@ -319,11 +310,10 @@ cat <<EOF > /etc/docker/daemon.json "max-size": "10m", "max-file": "3" }, "icc": true, "live-restore": true, "userland-proxy": false, "no-new-privileges": true, "default-ulimits": { "nofile": { "Name": "nofile", -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -403,7 +403,7 @@ LogLevel VERBOSE LoginGraceTime 30 PermitRootLogin prohibit-password StrictModes yes MaxAuthTries 10 MaxSessions 5 PubkeyAuthentication yes @@ -456,7 +456,7 @@ cat <<EOF > /etc/fail2ban/jail.local [DEFAULT] bantime = 3600 findtime = 600 maxretry = 10 banaction = ufw banaction_allports = ufw @@ -465,7 +465,7 @@ enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 10 bantime = 3600 [docker] -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -373,7 +373,6 @@ usermod -aG docker docker # --- SSH Configuration --- print_message "${YELLOW}" "Configuring SSH..." mkdir -p /home/docker/.ssh chown -R docker:docker /home/docker -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -371,12 +371,22 @@ print_message "${YELLOW}" "Creating docker user..." adduser --system --group --shell /bin/bash --home /home/docker --disabled-password docker usermod -aG docker docker # --- SSH Configuration --- # --- SSH Configuration --- print_message "${YELLOW}" "Configuring SSH..." mkdir -p /home/docker/.ssh chown -R docker:docker /home/docker chmod 755 /home/docker # Copy root's authorized keys to docker user if they exist if [ -f /root/.ssh/authorized_keys ]; then cp /root/.ssh/authorized_keys /home/docker/.ssh/authorized_keys chown -R docker:docker /home/docker/.ssh chmod 700 /home/docker/.ssh chmod 600 /home/docker/.ssh/authorized_keys fi cat <<EOF > /etc/ssh/sshd_config Include /etc/ssh/sshd_config.d/*.conf -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -447,7 +447,7 @@ cat <<EOF > /etc/fail2ban/jail.local [DEFAULT] bantime = 3600 findtime = 600 maxretry = 6 banaction = ufw banaction_allports = ufw @@ -456,7 +456,7 @@ enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 6 bantime = 3600 [docker] -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 4 additions and 3 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -87,7 +87,7 @@ verify_security_settings() { # Check kernel parameters local params=( "kernel.unprivileged_bpf_disabled=1" "net.ipv4.conf.all.log_martians=0" "net.ipv4.ip_forward=1" "fs.protected_hardlinks=1" "fs.protected_symlinks=1" @@ -273,13 +273,14 @@ fs.protected_symlinks = 1 fs.suid_dumpable = 0 # Additional network hardening net.ipv4.conf.all.log_martians = 0 net.ipv4.conf.default.log_martians = 0 net.ipv6.conf.all.accept_ra = 0 net.ipv6.conf.default.accept_ra = 0 EOF sysctl -p /etc/sysctl.d/99-security.conf sysctl --system # This loads all configs including the new one # Configure system limits cat <<EOF > /etc/security/limits.d/docker.conf -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 5 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -336,7 +336,6 @@ cat <<EOF > /etc/docker/daemon.json "experimental": false, "default-runtime": "runc", "storage-driver": "overlay2", "metrics-addr": "127.0.0.1:9323", "builder": { "gc": { @@ -356,7 +355,11 @@ if ! docker info &>/dev/null; then fi systemctl enable docker systemctl restart docker || { print_error "Docker failed to start. Logs:" journalctl -u docker.service --no-pager | tail -n 50 exit 1 } # Verify Docker configuration print_message "${YELLOW}" "Verifying Docker configuration..." -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 17 additions and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -299,6 +299,15 @@ curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh rm get-docker.sh # --- Docker User Namespace Setup --- print_message "${YELLOW}" "Setting up Docker user namespaces..." # Create dockremap user and group addgroup --system dockremap adduser --system --ingroup dockremap dockremap # Set up subuid and subgid mappings echo "dockremap:100000:65536" >> /etc/subuid echo "dockremap:100000:65536" >> /etc/subgid # --- Docker Configuration --- print_message "${YELLOW}" "Configuring Docker..." mkdir -p /etc/docker @@ -338,6 +347,14 @@ cat <<EOF > /etc/docker/daemon.json } EOF # After Docker daemon.json configuration print_message "${YELLOW}" "Testing Docker configuration..." if ! docker info &>/dev/null; then print_error "Docker failed to start. Checking configuration..." journalctl -u docker.service --no-pager | tail -n 50 exit 1 fi systemctl enable docker systemctl restart docker -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 67 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -110,6 +110,11 @@ verify_security_settings() { failed=1 fi if [[ "$(stat -c %a /var/run/docker.sock)" != "660" ]]; then print_error "Docker socket has incorrect permissions" failed=1 fi # Check services local services=( "docker" @@ -348,7 +353,8 @@ usermod -aG docker docker # --- SSH Configuration --- print_message "${YELLOW}" "Configuring SSH..." mkdir -p /home/docker/.ssh chown -R docker:docker /home/docker chmod 755 /home/docker cat <<EOF > /etc/ssh/sshd_config Include /etc/ssh/sshd_config.d/*.conf @@ -395,6 +401,8 @@ Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh. MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com EOF systemctl reload ssh # --- Firewall Configuration --- print_message "${YELLOW}" "Configuring firewall..." ufw --force reset @@ -407,6 +415,13 @@ ufw --force enable # --- fail2ban Configuration --- print_message "${YELLOW}" "Configuring fail2ban..." cat <<EOF > /etc/fail2ban/filter.d/docker.conf [Definition] failregex = failed login attempt from <HOST> ignoreregex = EOF cat <<EOF > /etc/fail2ban/jail.local [DEFAULT] bantime = 3600 @@ -444,6 +459,57 @@ else print_warning "Some security checks failed. Please review the warnings above." fi # Add logging configuration print_message "${YELLOW}" "Configuring system logging..." cat <<EOF > /etc/logrotate.d/docker-logs /var/lib/docker/containers/*/*.log { rotate 7 daily compress size=100M missingok delaycompress copytruncate } EOF # Automated cleanup to prevent residual files print_message "${YELLOW}" "Setting up maintenance tasks..." cat <<EOF > /etc/cron.daily/docker-cleanup #!/bin/bash docker system prune -af --volumes docker builder prune -af --keep-storage=20GB EOF chmod +x /etc/cron.daily/docker-cleanup # Configure auditd cat <<EOF > /etc/audit/rules.d/audit.rules # Docker daemon configuration -w /usr/bin/dockerd -k docker -w /var/lib/docker -k docker -w /etc/docker -k docker -w /usr/lib/systemd/system/docker.service -k docker -w /etc/default/docker -k docker -w /etc/docker/daemon.json -k docker -w /usr/bin/docker -k docker-bin EOF # Reload audit rules auditctl -R /etc/audit/rules.d/audit.rules # Configure unattended-upgrades for automated security updates print_message "${YELLOW}" "Configuring automatic updates..." cat <<EOF > /etc/apt/apt.conf.d/50unattended-upgrades Unattended-Upgrade::Allowed-Origins { "\${distro_id}:\${distro_codename}-security"; "\${distro_id}ESMApps:\${distro_codename}-apps-security"; "\${distro_id}ESM:\${distro_codename}-infra-security"; }; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Automatic-Reboot "false"; EOF # --- Final Cleanup --- apt-get autoremove -y apt-get clean -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 36 additions and 4 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -126,6 +126,34 @@ verify_security_settings() { fi done # Check AIDE database if [ ! -f /var/lib/aide/aide.db ]; then print_error "AIDE database not initialized" failed=1 fi # Check Chrony sync if ! chronyc tracking &>/dev/null; then print_error "Chrony is not syncing time" failed=1 fi # Additional security checks if ! ufw status | grep -q "Status: active"; then print_error "UFW firewall is not active" failed=1 fi if ! grep -q "PasswordAuthentication no" /etc/ssh/sshd_config; then print_error "SSH password authentication is not disabled" failed=1 fi if ! apparmor_status | grep -q "apparmor module is loaded."; then print_error "AppArmor is not loaded" failed=1 fi return $failed } @@ -181,9 +209,12 @@ systemctl stop systemd-timesyncd || true systemctl disable systemd-timesyncd || true apt-get remove -y systemd-timesyncd || true DEBIAN_FRONTEND=noninteractive apt-get install -y chrony if systemctl -q is-enabled systemd-timesyncd 2>/dev/null; then systemctl disable systemd-timesyncd systemctl stop systemd-timesyncd fi systemctl enable chrony.service || true # use .service to avoid alias issues systemctl start chrony.service # --- System Hardening --- print_message "${YELLOW}" "Configuring system security..." @@ -192,7 +223,8 @@ systemctl enable apparmor systemctl start apparmor # Initialize AIDE aide --config=/etc/aide/aide.conf --init mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Configure kernel parameters cat <<EOF > /etc/sysctl.d/99-security.conf -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 183 additions and 124 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,44 +1,156 @@ #!/bin/bash # Production Docker Host Hardening Script v2 # For Ubuntu Server 24.04 LTS (Noble) # Suitable for both Kamal deployment and builder hosts set -euo pipefail IFS=$'\n\t' # --- Constants --- REQUIRED_OS="Ubuntu" REQUIRED_VERSION="24.04" MIN_RAM_MB=1024 MIN_DISK_GB=20 # --- Aesthetics --- GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' ALIEN='\xF0\x9F\x91\xBD' NC='\033[0m' # --- Functions --- print_message() { local color=$1 local message=$2 echo -e "${color}${ALIEN} ${message}${NC}" } print_error() { print_message "${RED}" "ERROR: $1" } print_warning() { print_message "${YELLOW}" "WARNING: $1" } print_success() { print_message "${GREEN}" "SUCCESS: $1" } check_root() { if [[ $EUID -ne 0 ]]; then print_error "This script must be run as root" exit 1 fi } check_os() { if ! command -v lsb_release >/dev/null 2>&1; then print_error "lsb_release command not found. Is this Ubuntu?" exit 1 fi local os_name=$(lsb_release -is) local os_version=$(lsb_release -rs) if [[ "$os_name" != "$REQUIRED_OS" ]]; then print_error "This script requires $REQUIRED_OS (found $os_name)" exit 1 fi if [[ "$os_version" != "$REQUIRED_VERSION" ]]; then print_error "This script requires Ubuntu $REQUIRED_VERSION (found $os_version)" exit 1 fi } check_resources() { local total_ram_mb=$(free -m | awk '/^Mem:/{print $2}') local total_disk_gb=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') if (( total_ram_mb < MIN_RAM_MB )); then print_error "Insufficient RAM. Required: ${MIN_RAM_MB}MB, Found: ${total_ram_mb}MB" exit 1 fi if (( total_disk_gb < MIN_DISK_GB )); then print_error "Insufficient disk space. Required: ${MIN_DISK_GB}GB, Found: ${total_disk_gb}GB" exit 1 fi } verify_security_settings() { local failed=0 # Check kernel parameters local params=( "kernel.unprivileged_bpf_disabled=1" "net.ipv4.conf.all.log_martians=1" "net.ipv4.ip_forward=1" "fs.protected_hardlinks=1" "fs.protected_symlinks=1" ) for param in "${params[@]}"; do local name=${param%=*} local expected=${param#*=} local actual=$(sysctl -n "$name" 2>/dev/null || echo "NOT_FOUND") if [[ "$actual" != "$expected" ]]; then print_error "Kernel parameter $name = $actual (expected $expected)" failed=1 fi done # Check Docker settings if ! docker info 2>/dev/null | grep -q "Cgroup Driver: systemd"; then print_error "Docker is not using systemd cgroup driver" failed=1 fi # Check services local services=( "docker" "fail2ban" "ufw" "auditd" "chrony" ) for service in "${services[@]}"; do if ! systemctl is-active --quiet "$service"; then print_error "Service $service is not running" failed=1 fi done return $failed } handle_error() { local line_number=$1 print_error "Script failed on line ${line_number}" print_error "Please check the logs above for more information" exit 1 } # Set up error handling trap 'handle_error ${LINENO}' ERR # --- Pre-flight Checks --- print_message "${YELLOW}" "Performing pre-flight checks..." check_root check_os check_resources # --- System Updates --- print_message "${YELLOW}" "Updating system packages..." apt-get update DEBIAN_FRONTEND=noninteractive apt-get upgrade -y # --- Essential Packages --- print_message "${YELLOW}" "Installing essential packages..." DEBIAN_FRONTEND=noninteractive apt-get install -y \ ufw \ @@ -55,50 +167,34 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y \ audispd-plugins \ unattended-upgrades \ acl \ apparmor \ apparmor-utils \ aide \ rkhunter \ logwatch \ git \ python3-pyinotify # --- Time Synchronization --- print_message "${YELLOW}" "Configuring time synchronization..." systemctl stop systemd-timesyncd || true systemctl disable systemd-timesyncd || true apt-get remove -y systemd-timesyncd || true DEBIAN_FRONTEND=noninteractive apt-get install -y chrony systemctl enable chrony systemctl start chrony # --- System Hardening --- print_message "${YELLOW}" "Configuring system security..." # Configure AppArmor systemctl enable apparmor systemctl start apparmor # Initialize AIDE aide --init # Configure kernel parameters cat <<EOF > /etc/sysctl.d/99-security.conf # Network security net.ipv4.conf.all.send_redirects = 0 @@ -148,12 +244,25 @@ EOF sysctl -p /etc/sysctl.d/99-security.conf # Configure system limits cat <<EOF > /etc/security/limits.d/docker.conf * soft nproc 10000 * hard nproc 10000 * soft nofile 1048576 * hard nofile 1048576 * soft core 0 * hard core 0 * soft stack 8192 * hard stack 8192 EOF # --- Docker Installation --- print_message "${YELLOW}" "Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh rm get-docker.sh # --- Docker Configuration --- print_message "${YELLOW}" "Configuring Docker..." mkdir -p /etc/docker cat <<EOF > /etc/docker/daemon.json @@ -180,9 +289,6 @@ cat <<EOF > /etc/docker/daemon.json }, "experimental": false, "default-runtime": "runc", "storage-driver": "overlay2", "storage-opts": ["overlay2.override_kernel_check=true"], "metrics-addr": "127.0.0.1:9323", @@ -195,12 +301,19 @@ cat <<EOF > /etc/docker/daemon.json } EOF systemctl enable docker systemctl restart docker # Verify Docker configuration print_message "${YELLOW}" "Verifying Docker configuration..." docker info | grep -E "Cgroup Driver|Storage Driver|Logging Driver" # --- User Setup --- print_message "${YELLOW}" "Creating docker user..." adduser --system --group --shell /bin/bash --home /home/docker --disabled-password docker usermod -aG docker docker # --- SSH Configuration --- print_message "${YELLOW}" "Configuring SSH..." mkdir -p /home/docker/.ssh chmod 700 /home/docker/.ssh @@ -248,8 +361,6 @@ AllowUsers docker root KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com EOF # --- Firewall Configuration --- @@ -262,7 +373,7 @@ ufw allow http ufw allow https ufw --force enable # --- fail2ban Configuration --- print_message "${YELLOW}" "Configuring fail2ban..." cat <<EOF > /etc/fail2ban/jail.local [DEFAULT] @@ -286,89 +397,37 @@ filter = docker logpath = /var/log/auth.log maxretry = 5 bantime = 3600 EOF # --- Enable and Start Services --- print_message "${YELLOW}" "Enabling services..." systemctl enable docker fail2ban auditd chrony systemctl restart docker fail2ban auditd chrony # --- Verify Setup --- print_message "${YELLOW}" "Verifying security settings..." if verify_security_settings; then print_success "Security verification passed" else print_warning "Some security checks failed. Please review the warnings above." fi # --- Final Cleanup --- apt-get autoremove -y apt-get clean print_success "Setup complete! System hardening successful." print_message "${YELLOW}" "Important next steps:" print_message "${YELLOW}" "1. Add your SSH public key to /home/docker/.ssh/authorized_keys" print_message "${YELLOW}" "2. Configure your deployment tools (Kamal, etc.)" print_message "${YELLOW}" "3. REBOOT THE SYSTEM to apply all security settings" print_message "${YELLOW}" "4. Review logs in /var/log/ regularly" print_message "${YELLOW}" "5. Set up external monitoring and alerting" # Additional verification info print_message "${GREEN}" "System Information:" echo "Docker Version: $(docker --version)" echo "Kernel Version: $(uname -r)" echo "AppArmor Status: $(aa-status --enabled && echo 'Enabled' || echo 'Disabled')" echo "UFW Status: $(ufw status | grep Status)" echo "fail2ban Status: $(fail2ban-client status | grep "Number of jail:")" -
rameerez revised this gist
Oct 23, 2024 . 1 changed file with 210 additions and 132 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,51 +1,44 @@ #!/bin/bash # Production Docker Host Hardening Script # Suitable for both Kamal deployment and builder hosts # For Ubuntu Server 24.04 LTS set -euo pipefail IFS=$'\n\t' # --- Aesthetics and Error Handling --- GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' ALIEN='\xF0\x9F\x91\xBD' NC='\033[0m' print_message() { local color=$1 local message=$2 echo -e "${color}${ALIEN} ${message}${NC}" } handle_error() { local line_number=$1 print_message "${RED}" "Error on line ${line_number}" exit 1 } trap 'handle_error ${LINENO}' ERR # Check if script is run as root if [[ $EUID -ne 0 ]]; then print_message "${RED}" "This script must be run as root" exit 1 fi # --- System Updates and Essential Packages --- print_message "${YELLOW}" "Updating system packages..." apt-get update DEBIAN_FRONTEND=noninteractive apt-get upgrade -y print_message "${YELLOW}" "Installing essential packages..." DEBIAN_FRONTEND=noninteractive apt-get install -y \ ufw \ @@ -61,48 +54,106 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y \ auditd \ audispd-plugins \ unattended-upgrades \ acl \ openssh-server \ apparmor \ apparmor-utils \ chrony \ aide \ rkhunter \ logwatch \ git # --- System Hardening --- print_message "${YELLOW}" "Configuring system security..." # AppArmor systemctl enable apparmor systemctl start apparmor # AIDE initialization aideinit # Configure chrony for secure time sync cat <<EOF > /etc/chrony/chrony.conf pool pool.ntp.org iburst maxsources 4 keyfile /etc/chrony/chrony.keys driftfile /var/lib/chrony/chrony.drift logdir /var/log/chrony maxupdateskew 100.0 rtcsync makestep 1 3 leapsectz right/UTC EOF # Configure system limits cat <<EOF > /etc/security/limits.d/docker.conf * soft nproc 10000 * hard nproc 10000 * soft nofile 1048576 * hard nofile 1048576 * soft core 0 * hard core 0 * soft stack 8192 * hard stack 8192 EOF # Kernel hardening cat <<EOF > /etc/sysctl.d/99-security.conf # Network security 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 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 5 # Docker needs IPv4 forwarding net.ipv4.ip_forward = 1 # System limits fs.file-max = 1048576 kernel.pid_max = 65536 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.tcp_tw_reuse = 1 vm.max_map_count = 262144 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 # File system hardening fs.protected_hardlinks = 1 fs.protected_symlinks = 1 fs.suid_dumpable = 0 # Additional network hardening net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1 net.ipv6.conf.all.accept_ra = 0 net.ipv6.conf.default.accept_ra = 0 EOF sysctl -p /etc/sysctl.d/99-security.conf # --- Docker Installation and Configuration --- print_message "${YELLOW}" "Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh rm get-docker.sh print_message "${YELLOW}" "Configuring Docker..." mkdir -p /etc/docker cat <<EOF > /etc/docker/daemon.json @@ -116,76 +167,74 @@ cat <<EOF > /etc/docker/daemon.json "live-restore": true, "userland-proxy": false, "no-new-privileges": true, "userns-remap": "default", "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 64000, "Soft": 64000 } }, "features": { "buildkit": true }, "experimental": false, "default-runtime": "runc", "seccomp-profile": "/etc/docker/seccomp.json", "selinux-enabled": true, "userns-remap": "default", "storage-driver": "overlay2", "storage-opts": ["overlay2.override_kernel_check=true"], "metrics-addr": "127.0.0.1:9323", "builder": { "gc": { "enabled": true, "defaultKeepStorage": "20GB" } } } EOF # --- User Setup --- print_message "${YELLOW}" "Creating docker user..." adduser --system --group --shell /bin/bash --home /home/docker --disabled-password docker usermod -aG docker docker # --- SSH Hardening --- print_message "${YELLOW}" "Configuring SSH..." mkdir -p /home/docker/.ssh chmod 700 /home/docker/.ssh cat <<EOF > /etc/ssh/sshd_config Include /etc/ssh/sshd_config.d/*.conf Port 22 AddressFamily inet Protocol 2 HostKey /etc/ssh/ssh_host_ed25519_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_rsa_key SyslogFacility AUTH LogLevel VERBOSE LoginGraceTime 30 PermitRootLogin prohibit-password StrictModes yes MaxAuthTries 3 MaxSessions 5 PubkeyAuthentication yes HostbasedAuthentication no IgnoreRhosts yes PasswordAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no UsePAM yes AllowAgentForwarding no AllowTcpForwarding yes # Required for Docker forwarding X11Forwarding no PermitTTY yes PrintMotd no @@ -199,63 +248,66 @@ AllowUsers docker root KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com Subsystem sftp internal-sftp EOF # --- Firewall Configuration --- print_message "${YELLOW}" "Configuring firewall..." ufw --force reset ufw default deny incoming ufw default allow outgoing ufw allow ssh ufw allow http ufw allow https ufw --force enable # --- Fail2ban Configuration --- print_message "${YELLOW}" "Configuring fail2ban..." cat <<EOF > /etc/fail2ban/jail.local [DEFAULT] bantime = 3600 findtime = 600 maxretry = 3 banaction = ufw banaction_allports = ufw [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 3600 [docker] enabled = true filter = docker logpath = /var/log/auth.log maxretry = 5 bantime = 3600 [docker-api] enabled = true port = 2375,2376 filter = docker-api logpath = /var/log/docker.log maxretry = 3 bantime = 3600 EOF # Create custom Docker fail2ban filter cat <<EOF > /etc/fail2ban/filter.d/docker.conf [Definition] failregex = failed login attempt from <HOST> ignoreregex = EOF # --- Logging and Monitoring --- print_message "${YELLOW}" "Configuring logging and monitoring..." # Docker log rotation cat <<EOF > /etc/logrotate.d/docker /var/lib/docker/containers/*/*.log { rotate 7 daily @@ -267,11 +319,21 @@ cat <<EOF > /etc/logrotate.d/docker-logs } EOF # Configure auditd cat <<EOF > /etc/audit/rules.d/docker.rules # Docker daemon configuration -w /usr/bin/dockerd -k docker -w /var/lib/docker -k docker -w /etc/docker -k docker -w /usr/lib/systemd/system/docker.service -k docker -w /etc/systemd/system/docker.service -k docker -w /usr/lib/systemd/system/docker.socket -k docker -w /etc/default/docker -k docker -w /etc/docker/daemon.json -k docker EOF # --- Automatic Updates --- print_message "${YELLOW}" "Configuring automatic updates..." cat <<EOF > /etc/apt/apt.conf.d/50unattended-upgrades Unattended-Upgrade::Allowed-Origins { "\${distro_id}:\${distro_codename}"; @@ -283,14 +345,30 @@ Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; Unattended-Upgrade::AutoFixInterruptedDpkg "true"; Unattended-Upgrade::MinimalSteps "true"; Unattended-Upgrade::InstallOnShutdown "false"; EOF # --- System Maintenance --- print_message "${YELLOW}" "Setting up maintenance tasks..." cat <<EOF > /etc/cron.daily/docker-cleanup #!/bin/bash docker system prune -af --volumes docker builder prune -af --keep-storage=20GB EOF chmod +x /etc/cron.daily/docker-cleanup # Enable and start services systemctl enable docker fail2ban auditd chronyd systemctl restart docker fail2ban auditd chronyd # Final cleanup apt-get autoremove -y apt-get clean print_message "${GREEN}" "Setup complete! System hardening successful." print_message "${YELLOW}" "Important next steps:" print_message "${YELLOW}" "1. Add your SSH public key to /home/docker/.ssh/authorized_keys" print_message "${YELLOW}" "2. Configure your deployment tools (Kamal, etc.)" print_message "${YELLOW}" "3. REBOOT THE SYSTEM to apply all security settings" print_message "${YELLOW}" "4. Review logs in /var/log/ regularly" print_message "${YELLOW}" "5. Set up external monitoring and alerting" -
rameerez revised this gist
Oct 22, 2024 . 1 changed file with 10 additions and 7 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -168,14 +168,13 @@ HostKey /etc/ssh/ssh_host_ed25519_key SyslogFacility AUTH LogLevel VERBOSE LoginGraceTime 60 PermitRootLogin prohibit-password StrictModes yes MaxAuthTries 6 MaxSessions 10 PubkeyAuthentication yes HostbasedAuthentication no IgnoreRhosts yes @@ -184,7 +183,7 @@ PasswordAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no UsePAM yes AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no @@ -195,13 +194,17 @@ ClientAliveInterval 300 ClientAliveCountMax 2 TCPKeepAlive no AllowUsers docker root KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com EOF # Ensure proper ownership and permissions of the entire /home/docker directory chown -R docker:docker /home/docker chmod 755 /home/docker # Restart SSH service - now using correct service name if systemctl is-active --quiet ssh; then systemctl restart ssh -
rameerez revised this gist
Oct 22, 2024 . 1 changed file with 9 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -202,7 +202,15 @@ Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh. MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com EOF # Restart SSH service - now using correct service name if systemctl is-active --quiet ssh; then systemctl restart ssh elif systemctl is-active --quiet sshd; then systemctl restart sshd else print_message "${RED}" "SSH service not found. Please check your SSH installation." exit 1 fi # Kamal-specific sudo permissions print_message "${YELLOW}" "Configuring sudo for Kamal..." -
rameerez revised this gist
Oct 22, 2024 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -61,8 +61,7 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y \ auditd \ audispd-plugins \ unattended-upgrades \ acl # Configure UFW print_message "${YELLOW}" "Configuring firewall..." -
rameerez created this gist
Oct 22, 2024 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,286 @@ #!/bin/bash # Production Kamal Docker Host Setup Script # Sets up a secure, production-ready Docker host on Ubuntu Server 24.04 LTS # Ready for Kamal 2.x deployments set -euo pipefail # --- AESTHETICS --- # Define color codes for echo messages GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' # Define the escape sequence for the alien emoji (U+1F47D) ALIEN='\xF0\x9F\x91\xBD' # Define the variable for resetting the color back to the default NC='\033[0m' # Function to print colorized output with alien emoji print_message() { local color=$1 local message=$2 echo -e "${color}${ALIEN} ${message}${NC}" } # Function to handle errors handle_error() { print_message "${RED}" "An error occurred. Exiting..." exit 1 } # Set up error handling trap 'handle_error' ERR # Check if script is run as root if [[ $EUID -ne 0 ]]; then print_message "${RED}" "This script must be run as root" exit 1 fi # System Updates print_message "${YELLOW}" "Updating system packages..." apt-get update && DEBIAN_FRONTEND=noninteractive apt-get upgrade -y # Install essential packages print_message "${YELLOW}" "Installing essential packages..." DEBIAN_FRONTEND=noninteractive apt-get install -y \ ufw \ fail2ban \ curl \ wget \ gnupg \ lsb-release \ ca-certificates \ apt-transport-https \ software-properties-common \ sysstat \ auditd \ audispd-plugins \ unattended-upgrades \ acl \ netcat # Configure UFW print_message "${YELLOW}" "Configuring firewall..." ufw --force reset ufw default deny incoming ufw default allow outgoing ufw allow ssh ufw allow http ufw allow https echo "y" | ufw enable # Configure fail2ban with aggressive settings print_message "${YELLOW}" "Configuring fail2ban..." cat <<EOF > /etc/fail2ban/jail.local [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 3600 findtime = 600 [docker-login] enabled = true port = http,https filter = apache-auth logpath = /var/log/auth.log maxretry = 3 bantime = 3600 EOF systemctl enable fail2ban systemctl restart fail2ban # Install Docker print_message "${YELLOW}" "Installing Docker..." curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh rm get-docker.sh # Docker Configuration print_message "${YELLOW}" "Configuring Docker..." mkdir -p /etc/docker cat <<EOF > /etc/docker/daemon.json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "icc": false, "live-restore": true, "userland-proxy": false, "no-new-privileges": true, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 64000, "Soft": 64000 } }, "metrics-addr": "0.0.0.0:9323", "experimental": true, "features": { "buildkit": true } } EOF systemctl enable docker systemctl restart docker # Set up Docker user print_message "${YELLOW}" "Creating docker user..." adduser --system --group --shell /bin/bash --home /home/docker --disabled-password docker usermod -aG docker docker # Set up SSH for docker user print_message "${YELLOW}" "Configuring SSH..." mkdir -p /home/docker/.ssh chmod 700 /home/docker/.ssh if [ -f /root/.ssh/authorized_keys ]; then cp /root/.ssh/authorized_keys /home/docker/.ssh/ chmod 600 /home/docker/.ssh/authorized_keys chown -R docker:docker /home/docker/.ssh else print_message "${RED}" "No SSH key found in /root/.ssh/authorized_keys" exit 1 fi # SSH Hardening cat <<EOF > /etc/ssh/sshd_config Include /etc/ssh/sshd_config.d/*.conf Port 22 AddressFamily inet Protocol 2 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key SyslogFacility AUTH LogLevel VERBOSE LoginGraceTime 20 PermitRootLogin no StrictModes yes MaxAuthTries 3 MaxSessions 2 PubkeyAuthentication yes AuthenticationMethods publickey HostbasedAuthentication no IgnoreRhosts yes PasswordAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no UsePAM no AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no PermitTTY yes PrintMotd no ClientAliveInterval 300 ClientAliveCountMax 2 TCPKeepAlive no AllowUsers docker KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com EOF systemctl restart sshd # Kamal-specific sudo permissions print_message "${YELLOW}" "Configuring sudo for Kamal..." cat <<EOF > /etc/sudoers.d/docker-user docker ALL=(ALL) NOPASSWD: /usr/sbin/service docker restart docker ALL=(ALL) NOPASSWD: /bin/systemctl restart docker EOF chmod 440 /etc/sudoers.d/docker-user # System hardening print_message "${YELLOW}" "Hardening system..." cat <<EOF >> /etc/sysctl.conf # Network security 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 # Docker needs IPv4 forwarding net.ipv4.ip_forward = 1 # System limits for Kamal/Docker fs.file-max = 65535 kernel.pid_max = 65536 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.tcp_tw_reuse = 1 vm.max_map_count = 262144 EOF sysctl -p # Log rotation for Docker cat <<EOF > /etc/logrotate.d/docker-logs /var/lib/docker/containers/*/*.log { rotate 7 daily compress missingok delaycompress copytruncate size 100M } EOF # Enable security services systemctl enable sysstat auditd systemctl start sysstat auditd # Configure unattended upgrades cat <<EOF > /etc/apt/apt.conf.d/50unattended-upgrades Unattended-Upgrade::Allowed-Origins { "\${distro_id}:\${distro_codename}"; "\${distro_id}:\${distro_codename}-security"; "\${distro_id}ESMApps:\${distro_codename}-apps-security"; "\${distro_id}ESM:\${distro_codename}-infra-security"; }; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; Unattended-Upgrade::AutoFixInterruptedDpkg "true"; Unattended-Upgrade::MinimalSteps "true"; EOF # Clean up apt-get autoremove -y apt-get clean print_message "${GREEN}" "Setup complete! Please reboot the system." print_message "${YELLOW}" "Important next steps:" print_message "${YELLOW}" "1. Configure your load balancer to point to this host" print_message "${YELLOW}" "2. Set up your .kamal/secrets file on your deployment machine" print_message "${YELLOW}" "3. Run 'kamal deploy' to deploy your application"