Skip to content

Instantly share code, notes, and snippets.

@syntaxlexx
Created June 11, 2026 15:20
Show Gist options
  • Select an option

  • Save syntaxlexx/2236a42621a2cfff8fd46ab80ff41f74 to your computer and use it in GitHub Desktop.

Select an option

Save syntaxlexx/2236a42621a2cfff8fd46ab80ff41f74 to your computer and use it in GitHub Desktop.
vps-hardening script - Dokploy safe
#!/usr/bin/env bash
set -e
echo "====================================="
echo " VPS HARDENING SCRIPT (Dokploy-safe)"
echo "====================================="
NEW_USER="dokploy"
echo "[1/9] Updating system..."
apt update && apt upgrade -y
echo "[2/9] Installing required packages..."
apt install -y \
sudo \
ufw \
fail2ban \
curl \
git \
unattended-upgrades
echo "[3/9] Installing Docker..."
if ! command -v docker &>/dev/null; then
curl -fsSL https://get.docker.com | sh
systemctl enable docker
systemctl start docker
else
echo "Docker already installed, skipping..."
fi
echo "[4/9] Creating non-root user: $NEW_USER"
if id "$NEW_USER" &>/dev/null; then
echo "User already exists, skipping..."
else
adduser --disabled-password --gecos "" $NEW_USER
fi
echo "[5/9] Adding user to sudo and docker groups..."
usermod -aG sudo $NEW_USER
usermod -aG docker $NEW_USER
echo "[6/9] Passwordless sudo for $NEW_USER..."
echo "$NEW_USER ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$NEW_USER
chmod 440 /etc/sudoers.d/$NEW_USER
echo "[7/9] Copying SSH keys to $NEW_USER..."
if [ -f /root/.ssh/authorized_keys ]; then
mkdir -p /home/$NEW_USER/.ssh
cp /root/.ssh/authorized_keys /home/$NEW_USER/.ssh/authorized_keys
chown -R $NEW_USER:$NEW_USER /home/$NEW_USER/.ssh
chmod 700 /home/$NEW_USER/.ssh
chmod 600 /home/$NEW_USER/.ssh/authorized_keys
echo "SSH keys copied from root to $NEW_USER"
else
echo "⚠️ WARNING: No SSH keys found in /root/.ssh/authorized_keys"
echo " You must manually add your public key before disabling password auth!"
echo " Run: ssh-copy-id $NEW_USER@YOUR_IP"
echo " Then re-run this script."
exit 1
fi
echo "[8/9] SSH hardening..."
# Remove ALL conflicting overrides
rm -f /etc/ssh/sshd_config.d/*cloud*.conf 2>/dev/null || true
rm -f /etc/ssh/sshd_config.d/*dokploy*.conf 2>/dev/null || true
rm -f /etc/ssh/sshd_config.d/*hardening*.conf 2>/dev/null || true
# Nuke the specific Hostinger culprit
rm -f /etc/ssh/sshd_config.d/50-cloud-init.conf 2>/dev/null || true
# Create single authoritative config
cat > /etc/ssh/sshd_config.d/99-dokploy-hardening.conf <<EOF
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PubkeyAuthentication yes
AuthenticationMethods publickey
EOF
echo "Validating SSH config..."
sshd -t
echo "Verifying effective config..."
PWAUTH=$(sshd -T | grep "^passwordauthentication")
if [[ "$PWAUTH" == *"yes"* ]]; then
echo "❌ FATAL: Password auth is still enabled after config. Aborting restart."
echo " Run: grep -R PasswordAuthentication /etc/ssh/"
exit 1
fi
echo "[9/9] Configuring firewall (UFW)..."
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw --force enable
echo "Enabling Fail2Ban..."
systemctl enable fail2ban
systemctl restart fail2ban
echo "Restarting SSH..."
systemctl restart ssh
echo "====================================="
echo " HARDENING COMPLETE"
echo "====================================="
echo ""
echo "SECURITY STATUS:"
echo " Root login: DISABLED"
echo " Password auth: DISABLED"
echo " SSH keys only: ENABLED"
echo " Docker group: ENABLED for $NEW_USER"
echo ""
echo "SWARM PORTS OPEN:"
echo " 2377/tcp cluster management"
echo " 7946/tcp node communication"
echo " 7946/udp node communication"
echo " 4789/udp overlay network"
echo ""
echo "⚠️ IMPORTANT: Log out and back in for docker group to take effect"
echo " ssh $NEW_USER@$(curl -s https://api.ipify.org)"
echo ""
echo "VERIFY:"
echo " sshd -T | grep passwordauthentication"
echo " docker ps"
echo "====================================="
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment