Server: Ubuntu 22.04 / 24.04 (DigitalOcean)
Goal: Safely migrate SSH from default port 22 → custom port 2222 for non-root user demo, with IPv4 & IPv6 listening addresses, cloud-init protection, firewall updates, and rollback.
Step 0 – Prepare Variables
NEW_PORT=2222
SSH_USER=demo
SERVER_IP=your_server_ip
LISTEN_IPV4=0.0.0.0
LISTEN_IPV6=::
Keep a root or console session open.
Ensure demo user has sudo privileges:
sudo adduser demo
sudo usermod -aG sudo demoStep 1 – Backup All SSH Configs
sudo mkdir -p /root/ssh-migration-backups
sudo cp /etc/ssh/sshd_config /root/ssh-migration-backups/sshd_config.bak
sudo cp -r /etc/ssh/sshd_config.d /root/ssh-migration-backups/
sudo tar -czf /root/ssh-migration-backups/ssh-configs-$(date +%F-%T).tar.gz /etc/sshStep 2 – Disable ssh.socket (if active)
sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket
sudo systemctl mask ssh.socket
sudo systemctl daemon-reloadStep 3 – Update /etc/ssh/sshd_config
sudo nano /etc/ssh/sshd_configAdd or update:
Allow only non-root user login
PermitRootLogin no
AllowUsers demo
Custom SSH port
Port 2222
Listen on IPv4 & IPv6
ListenAddress 0.0.0.0
ListenAddress :
Step 4 – Create /etc/ssh/sshd_config.d/
custom_port.conf (Test)
sudo touch /etc/ssh/sshd_config.d/custom_port.conf
sudo chmod 644 /etc/ssh/sshd_config.d/custom_port.conf
sudo bash -c "cat > /etc/ssh/sshd_config.d/custom_port.conf <<EOF
# Temporary test config
Port 2222
ListenAddress 0.0.0.0
ListenAddress ::
EOF"Step 5 – Update Cloud-Init /etc/ssh/sshd_config.d/50-cloud-init.conf
sudo nano /etc/ssh/sshd_config.d/50-cloud-init.confUpdate contents:
Prevent cloud-init from forcing port 22
Port 22
Custom port & listen addresses
Port 2222
ListenAddress 0.0.0.0
ListenAddress ::
Step 6 – Create Permanent Override /etc/ssh/sshd_config.d/99-force-port.conf
sudo touch /etc/ssh/sshd_config.d/99-force-port.conf
sudo chmod 644 /etc/ssh/sshd_config.d/99-force-port.conf
sudo bash -c "cat > /etc/ssh/sshd_config.d/99-force-port.conf <<EOF
# Permanent enforced SSH configuration
Port 2222
ListenAddress 0.0.0.0
ListenAddress ::
EOF"Forces port 2222 and prevents overrides from other configs.
Step 7 – Restart SSH & Verify Ports
sudo systemctl daemon-reload
sudo systemctl restart ssh
sudo ss -tulpn | grep ssh✅ Port 2222 should appear on both IPv4 & IPv6.
Step 8 — Test SSH Connection (Non-Root User)
ssh -p 2222 demo@your_server_ip✅ Confirm login works; keep emergency root session open.
Step 9 – Update Firewalls
UFW:
sudo ufw allow 2222/tcp
sudo ufw statusDigitalOcean Cloud Firewall:
Add TCP port 2222 inbound rule.
Keep port 22 temporarily until confirmed.
Step 10 — Remove Old Port 22 (After Confirmation)
UFW:
sudo ufw delete allow 22/tcpDigitalOcean: Remove port 22 inbound rule.
Step 11- Remove Temporary Test File
sudo rm -f /etc/ssh/sshd_config.d/custom_port.confStep 12 – Final Verification
ssh -p 2222 demo@your_server_ip
sudo ss -tulpn | grep ssh
sudo systemctl status ssh
sudo journalctl -u ssh -n 50✅ Only port 2222 active.
✅ Non-root user login works.
✅ Firewall and cloud-init configs verified.
Step 13 – Rollback Plan
If locked out, use DigitalOcean console:
sudo mv /root/ssh-migration-backups/sshd_config.bak /etc/ssh/sshd_config
sudo mv /root/ssh-migration-backups/sshd_config.d/50-cloud-init.conf /etc/ssh/sshd_config.d/
sudo rm -f /etc/ssh/sshd_config.d/99-force-port.conf
sudo systemctl restart ssh
sudo ufw allow 22/tcp
sudo ufw reload✅ Step 14 – Final Checklist
| File | Purpose | IPv4 & IPv6 | Notes |
| /etc/ssh/sshd_config | Main config | ✅ | Port 2222 Allow non-root user demo |
| /etc/ssh/sshd_config.d/custom_port.conf | Temporary test | ✅ | Removed after verification |
| /etc/ssh/sshd_config.d/50-cloud-init.conf | Prevent cloud-init override | ✅ | Keep custom port |
| /etc/ssh/sshd_config.d/99-force-port.conf | Permanent enforced port & listen | ✅ | Forces port 2222 & ListenAddress |