Before running production workloads, it’s critical to secure your server and install the right foundations.
This Bash script prepares a fresh Ubuntu server with:
- Docker + Docker Compose
- UFW firewall
- Fail2Ban (SSH protection)
- Fish shell (optional but nice 🐟)
🎯 What This Script Does
- 🔄 Updates the system
- 🐳 Installs Docker & Docker Compose
- 🔐 Secures SSH with UFW + rate limiting
- 🚫 Protects against brute-force attacks using Fail2Ban
- 🧑💻 Improves shell experience with Fish
🧾 Bash Script
bash
#!/usr/bin/env bash
set -euo pipefail
sudo apt update && sudo apt upgrade -y
sudo apt install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
software-properties-common \
ufw \
fail2ban
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
sudo apt install -y fish
chsh -s /usr/bin/fish
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw limit OpenSSH
sudo ufw --force enable
sudo tee /etc/fail2ban/jail.local > /dev/null << 'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = ufw
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
backend = systemd
EOF
sudo systemctl enable --now fail2ban
Top comments (2)
Nice setup. After you get this running, throw some monitoring on there. Something like fivenines.io to keep an eye on those Docker containers and get alerts when fail2ban triggers.
Security setup's solid but blind servers bite you later.
Thanks appreciate the suggestion something like that can definitely be added but there are a lot of tools in this space and I wanted to keep things simple so I didn’t go into monitoring here, might cover it separately later on.