Skip to content

One-command Linux server hardening. Configures SSH, firewall, fail2ban, kernel security, auditd, and automatic updates. Works across Ubuntu/Debian, RHEL/CentOS, Fedora, Arch, and SUSE. Designed for production servers.

License

Notifications You must be signed in to change notification settings

poppyszn/lockdown

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔒 Lockdown

One-command Linux server hardening.

Hardens SSH, firewall, fail2ban, kernel, auditd, services, and automatic updates. Works across Ubuntu/Debian, RHEL/CentOS/AlmaLinux/Rocky, Fedora, Arch, and SUSE. Built for production servers and cloud instances (EC2, GCP, DigitalOcean, etc.).


Quick Start

One-liner (review + run):

curl -fsSL https://raw.githubusercontent.com/poppyszn/lockdown/main/harden.sh -o /tmp/harden.sh
sudo bash /tmp/harden.sh --ssh-user deployer --ssh-pubkey ~/.ssh/id_ed25519.pub

Fully automated (CI/CD, cloud-init, Ansible):

curl -fsSL https://raw.githubusercontent.com/poppyszn/lockdown/main/harden.sh | sudo bash -s -- \
  --auto --accept-warning \
  --ssh-user deployer \
  --ssh-port 2222 \
  --ssh-pubkey /tmp/deploy_key.pub \
  --skip-firewall

⚠️ WARNING: This script disables password authentication and changes the SSH port. Make sure you have console access and an SSH key ready before running.


What It Does

Area What Lockdown Configures
SSH Custom port, key-only auth, root login disabled, idle timeout, AllowUsers, no X11/TCP forwarding
Users Creates sudo user with NOPASSWD, locks root, password policy (14+ chars), umask 027, restricts su
Firewall UFW with default deny in/out, rate-limited SSH, only opens ports you specify
Fail2ban SSH jail with aggressive mode, configurable ban time/retries, optional email alerts
Kernel ASLR, SYN flood protection, ICMP hardening, reverse path filtering, source routing disabled, BPF/ptrace lockdown
Logging auditd with 25+ rules, logwatch daily digests, log rotation, optional remote syslog
Services Disables avahi, cups, bluetooth, rpcbind, telnet; provides systemd sandboxing template
Network Disables IPv6 (optional), blocks unused protocols (DCCP, SCTP, RDS, TIPC), disables unused filesystems
Updates Unattended security upgrades (apt/dnf/yum), optional auto-reboot scheduling
Docker no-new-privileges, ICC disabled, log rotation, hardened container run helper script
Maintenance Weekly security audit cron, port checker, SSH key rotation reminders

Usage

Usage: sudo bash harden.sh [OPTIONS]

Options:
  --auto              Non-interactive mode (accept all defaults)
  --dry-run           Preview changes without applying them
  --accept-warning    Skip the critical safety warning prompt
  --ssh-user USER     Set the sudo user and SSH AllowUsers (default: deployer)
  --ssh-port PORT     Set SSH port (default: 2222, range: 1024-65535)
  --ssh-pubkey FILE   Path to SSH public key file for the sudo user
  --skip-firewall     Skip UFW setup (for EC2/GCP with security groups)
  --skip-docker       Skip Docker hardening section
  --help, -h          Show help message

Examples

# Interactive — prompts for confirmation at each step
sudo bash harden.sh --ssh-user myadmin --ssh-pubkey ~/.ssh/id_ed25519.pub

# Fully automated — no prompts
sudo bash harden.sh --auto --accept-warning \
  --ssh-user deployer --ssh-pubkey /tmp/key.pub

# EC2 instance — skip UFW (use Security Groups instead)
sudo bash harden.sh --auto --accept-warning --skip-firewall \
  --ssh-user ec2-user --ssh-pubkey /tmp/key.pub

# Dry run — see what would change without touching anything
sudo bash harden.sh --dry-run --ssh-user deployer --ssh-pubkey ~/.ssh/key.pub

# Custom SSH port
sudo bash harden.sh --ssh-user admin --ssh-port 2200 --ssh-pubkey ~/.ssh/key.pub

Cloud-Init / User Data

Use this in your EC2 launch template, GCP startup script, or cloud-init config:

#cloud-config
write_files:
  - path: /tmp/deploy_key.pub
    content: |
      ssh-ed25519 AAAA... your-key-comment
    permissions: '0644'

runcmd:
  - curl -fsSL https://raw.githubusercontent.com/poppyszn/lockdown/main/harden.sh -o /tmp/harden.sh
  - bash /tmp/harden.sh --auto --accept-warning --skip-firewall --ssh-user deployer --ssh-pubkey /tmp/deploy_key.pub
  - rm -f /tmp/harden.sh /tmp/deploy_key.pub

Ansible

- name: Harden server with Lockdown
  hosts: all
  become: yes
  tasks:
    - name: Copy SSH public key
      copy:
        src: ~/.ssh/id_ed25519.pub
        dest: /tmp/deploy_key.pub
        mode: '0644'

    - name: Download hardening script
      get_url:
        url: https://raw.githubusercontent.com/poppyszn/lockdown/main/harden.sh
        dest: /tmp/harden.sh
        mode: '0755'

    - name: Run hardening
      command: >
        bash /tmp/harden.sh
        --auto --accept-warning
        --ssh-user deployer
        --ssh-port 2222
        --ssh-pubkey /tmp/deploy_key.pub
        --skip-firewall

    - name: Cleanup
      file:
        path: "{{ item }}"
        state: absent
      loop:
        - /tmp/harden.sh
        - /tmp/deploy_key.pub

Verification

After running, verify everything is applied:

curl -fsSL https://raw.githubusercontent.com/poppyszn/lockdown/main/verify-hardening.sh | sudo bash

Or download and run:

curl -fsSL https://raw.githubusercontent.com/poppyszn/lockdown/main/verify-hardening.sh -o /tmp/verify.sh
sudo bash /tmp/verify.sh

Output looks like:

── 1. SSH HARDENING ──
  ✓ PASS  SSH port changed from default (port 2222)
  ✓ PASS  Port 22 is closed
  ✓ PASS  SSH is listening on port 2222
  ✓ PASS  Root login disabled
  ✓ PASS  Password authentication disabled
  ...

══════════════════════════════════════════
  VERIFICATION SUMMARY
══════════════════════════════════════════
  PASS: 42  FAIL: 0  WARN: 3

  Server hardening looks solid! ✓

What Gets Backed Up

Every file modified by the script is backed up to:

/root/hardening-backups/<timestamp>/

Full execution log is saved to:

/var/log/server-hardening-<timestamp>.log

Maintenance Tools Installed

Command Description
sudo /usr/local/bin/security-audit Full security audit (runs weekly via cron)
sudo /usr/local/bin/check-open-ports Quick view of open ports + firewall status

Supported Distributions

Distro Versions Tested
Ubuntu 20.04, 22.04, 24.04
Debian 11, 12
RHEL / CentOS / AlmaLinux / Rocky 8, 9
Amazon Linux 2, 2023
Fedora 38+
Arch Linux Rolling
openSUSE Leap 15+

Important Notes

  • SSH Keys Required: Password authentication is disabled. You must provide an SSH public key or you will be locked out.
  • EC2 / Cloud: Use --skip-firewall if your cloud provider has security groups. Don't double-firewall.
  • Docker: The script does NOT enable userns-remap by default — it breaks existing containers. Enable it manually on fresh installs.
  • Run Once: The script is idempotent — safe to run multiple times.
  • Backups: Every modified file is backed up. Check /root/hardening-backups/ to restore anything.

After Hardening — Next Steps

  1. Test SSH access from a new terminal before closing your current session
  2. Set up TLS for web services (Let's Encrypt / certbot)
  3. Configure a reverse proxy (Nginx) — never expose app ports directly
  4. Set up secrets management — no plaintext keys in config files
  5. Schedule key rotation — SSH keys and API keys on a regular cadence

Contributing

PRs welcome. Please test on at least Ubuntu and one RHEL-based distro before submitting.


License

MIT

About

One-command Linux server hardening. Configures SSH, firewall, fail2ban, kernel security, auditd, and automatic updates. Works across Ubuntu/Debian, RHEL/CentOS, Fedora, Arch, and SUSE. Designed for production servers.

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages