Introduction
An additional feature during creation of a Hetzner cloud server (CX11 and above) is user data. This allows the execution of a cloud-init configuration for the newly created server.
After following this tutorial, you will be able to adjust the setup of new cloud servers with custom configuration.
Parts of this configuration are based on Securing the SSH service.
Step 1 – Insert first line
The cloud-init config uses YAML (“YAML Ain’t Markup Language”) as markup language.
The file should start with a comment on the first line so that the code is interpreted as cloud-config by the server:
#cloud-config
Step 2 – Create user
After the initial comment, let us start by creating a new admin user with sudo
privileges and pre-configured SSH key.
How to create a SSH key pair?
users:
- name: holu
groups: users, admin
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- <public_ssh_key>
Step 3 – Update packages
The first thing we do is an update of the package lists and installed packages. A fresh copy of Linux may have outdated packages with critical security vulnerabilities.
In this step, you could install necessary packages for your projects too.
If packages are to be installed or upgraded, cloud-init will update
the package lists beforehand.
packages:
- fail2ban
- ufw
package_update: true
package_upgrade: true
Step 4 – Run commands
cloud-init allows us to run CLI (Command Line Interface) commands right after the server has been created.
Start the procedure by typing runcmd:
on a new line.
Step 4.1 – Configure fail2ban
Each command is written to a new line, preceded by a hyphen.
To secure the SSH network protocol a bit, we use fail2ban against brute force attacks. By default, it will ban attackers for 10 minutes – after 5 failed login attempts within 10 minutes.
- printf "[sshd]\nenabled = true\nbanaction = iptables-multiport" > /etc/fail2ban/jail.local
- systemctl enable fail2ban
Step 4.2 – Enable ufw
Uncomplicated Firewall (ufw) is used to lock down the system and allow only used services.
Later you will need to allow services or ports (like 80/443) for any applications that require them.
- ufw allow OpenSSH
- ufw enable
Step 4.3 – Harden SSH
The last sequence of commands is dedicated to securing SSH.
We use the command sed
to customize parts of the sshdconfig_ file.
Changes made:
- Deactivate the root login
- Enable user for SSH
- Automatic disconnection in case of incorrect login
- Deactivate unused functions
- sed -i -e '/^\(#\|\)PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)X11Forwarding/s/^.*$/X11Forwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)MaxAuthTries/s/^.*$/MaxAuthTries 2/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)AllowTcpForwarding/s/^.*$/AllowTcpForwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)AllowAgentForwarding/s/^.*$/AllowAgentForwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh/authorized_keys/' /etc/ssh/sshd_config
- sed -i '$a AllowUsers holu' /etc/ssh/sshd_config
Step 4.4 – Reboot
We have to execute one last command: reboot
Why? Three birds with one stone:
- After package updates, there might be a reboot necessary for patches to work properly.
- fail2ban needs a restart to perform the enabled SSH protection.
- The changed configuration of SSH will be applied after a restart too.
Step 5 – Create the server
Now boot your secured-by-default cloud server.
After the server is created, go to Graphs using the Cloud Console and wait until CPU usage shrinks to zero. All commands have been executed and the server has rebooted. You can now login over SSH with the created user account.
Conclusion
Many words for 21 lines of code, huh?
I hope you learned a lot! For example:
- Build a cloud-init config from scratch.
- Create users with sudo and other properties.
- Run commands during first server boot.
- Utilize
sed
to edit parts of a file.
Now go ahead and build something awesome!
The complete configuration:
#cloud-config
users:
- name: holu
groups: users, admin
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- <public_ssh_key>
packages:
- fail2ban
- ufw
package_update: true
package_upgrade: true
runcmd:
- printf "[sshd]\nenabled = true\nbanaction = iptables-multiport" > /etc/fail2ban/jail.local
- systemctl enable fail2ban
- ufw allow OpenSSH
- ufw enable
- sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
- sed -i -e '/^PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
- sed -i -e '/^X11Forwarding/s/^.*$/X11Forwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^#MaxAuthTries/s/^.*$/MaxAuthTries 2/' /etc/ssh/sshd_config
- sed -i -e '/^#AllowTcpForwarding/s/^.*$/AllowTcpForwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^#AllowAgentForwarding/s/^.*$/AllowAgentForwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^#AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh/authorized_keys/' /etc/ssh/sshd_config
- sed -i '$a AllowUsers holu' /etc/ssh/sshd_config
- reboot
Reprint:https://community.hetzner.com/tutorials/basic-cloud-config
Leave a Reply