Skip to content

Instantly share code, notes, and snippets.

@owainlewis
Created July 28, 2026 20:44
Show Gist options
  • Select an option

  • Save owainlewis/510592948d5950a985f25bb13b0c8d82 to your computer and use it in GitHub Desktop.

Select an option

Save owainlewis/510592948d5950a985f25bb13b0c8d82 to your computer and use it in GitHub Desktop.
Harden VM
#!/usr/bin/env bash
set -euo pipefail
[[ "$EUID" -eq 0 ]] || {
echo "Run with sudo"
exit 1
}
# Refuse to continue unless root already has an SSH key.
[[ -s /root/.ssh/authorized_keys ]] || {
echo "Root has no SSH key. Stopping."
exit 1
}
apt-get update
apt-get install -y ufw unattended-upgrades
# Create a separate user for Codex and Push.
if ! id push >/dev/null 2>&1; then
useradd --create-home --shell /bin/bash push
passwd --lock push
fi
# Keep root access, but require an SSH key.
cat > /etc/ssh/sshd_config.d/00-basic-hardening.conf <<'EOF'
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
X11Forwarding no
EOF
# Validate SSH before changing the firewall or reloading.
sshd -t
SSH_PORT="$(sshd -T | awk '$1 == "port" { print $2; exit }')"
# Block inbound traffic except rate-limited SSH.
ufw default deny incoming
ufw default allow outgoing
ufw limit "${SSH_PORT}/tcp"
ufw --force enable
# Enable daily security updates.
cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
systemctl enable --now apt-daily.timer apt-daily-upgrade.timer
systemctl reload ssh
echo
echo "Hardening complete."
echo "Root key login remains enabled on port $SSH_PORT."
echo "Root password login is disabled."
echo "Run Codex and Push as the 'push' user."
echo
echo "Keep this session open and test a second root SSH connection now."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment