This is my personal note list for preparing a Ubuntu based linux server. The list is not complete and may contain errors.
Basic Setup
- Install Ubuntu Server (non-minimal) OS as usual or use an image
- Add local user
useradd <username> usermod -aG sudo <username>
Network Setup
- Set hostname
sudo hostnamectl set-hostname <hostname>
- Edit the
/etc/hosts
file - Edit the
/etc/cloud/cloud.cfg
file if exists (preserve_hostname: false to true
) - Set fixed IPv4/IPv6 address
- Open Netplan configuration file under
/etc/netplan/01-netcfg.yaml
or/etc/netplan/50-cloud-init.yaml
- Example configuration
network: version: 2 renderer: networkd ethernets: eth0: dhcp4: no addresses: - 192.168.1.10/24 - 2a03:4000::dead:beef/64 routes: - to: default via: 192.168.1.1 nameservers: addresses: [192.168.1.1] # gateway4: 192.168.1.1 # gateway6: fe80::1
- Adjust file permissions:
sudo chmod 600 /etc/netplan/<name>.yaml
- Apply configuration
sudo netplan apply
- Open Netplan configuration file under
- Set the "Reverse DNS" entry in Control Panel (Root-Server only)
SSH
- Add pubkey to
~/.ssh/authorized_keys
Copy host certs
If you replace a server and keeping the hostname, you may need to update the server“s SSH host keys. This is important for security reasons, as SSH clients use these keys to verify the identity of the server. Alternative you can copy the keys from the old server to the new one. This is not recommended, but it is possible. You should need to copy ssh_host_rsa_key
, ssh_host_ecdsa_key
, and ssh_host_ed25519_key
along with their corresponding public key files (with .pub
extension) under /etc/ssh/
.
sudo cp /etc/ssh/ssh_host_* /path/to/new/server/etc/ssh/
Addition setups for Proxmox VE
Optimization for Virtual Environments
-
For optimal operation, the guest OS should "know" that it is running in a virtual environment. This is achieved by installing some kernel modules:
sudo apt update sudo apt install --install-recommends linux-virtual sudo apt install linux-tools-virtual linux-cloud-tools-virtual
-
Additionally, the I/O scheduler should be configured so that the VM host handles I/O scheduling optimizations rather than the guest itself. To do this, modify the bootloader configuration in the guest operating system:
sudo vim /etc/default/grub
to
GRUB_CMDLINE_LINUX_DEFAULT="elevator=noop"
-
Update the bootloader:
sudo update-grub
Install QEMU Guest Agent
- The QEMU guest agent is a daemon that runs inside the guest OS and communicates with the host. It provides various functionalities, such as:
- Shutdown and reboot commands
- File system freeze and thaw
- Network configuration
- Time synchronization
- To install the QEMU guest agent, run the following command and restart the VM:
sudo apt install qemu-guest-agent sudo systemctl enable qemu-guest-agent sudo systemctl start qemu-guest-agent sudo reboot
(Source)
Ansible
Now the basic setup is done and you can continue with your Ansible Playbook. If not, use the Advanced Setup below.
Advanced Setup
- Disable SSH login with password and permit root login in
/etc/ssh/sshd_config
filePasswordAuthentication no PubkeyAuthentication yes PermitRootLogin no
- Restart SSH Daemon
service sshd restart
VIM
- VIM Color open
and add~/.vimrc
colorsheme desert syntax on
Unattended upgrades
- Enable unattended upgrades
sudo apt-get install unattended-upgrades sudo dpkg-reconfigure unattended-upgrades
Docker
- Install docker-ce with this guide
- add username to docker group (source)
sudo usermod -aG docker $USER
Logrotate for Docker
- Create Logrotate config file for Docker containers under
with the following content:/etc/logrotate.d/docker-container
/var/lib/docker/containers/*/*.log { rotate 8 weekly compress missingok delaycompress copytruncate }
- Test it with:
logrotate -fv /etc/logrotate.d/docker-container
Docker Compose aliases
- Create or append to
~/.bash_aliases
:alias dc='docker compose' alias dcl='docker compose logs -f --tail=200' alias dce='docker compose exec' alias dcb='docker compose up --build -d' alias dcu='docker compose up -d' alias dcul='docker compose up -d && docker-compose logs -f --tail=50' alias dcd='docker compose down --remove-orphans' alias dcdu='docker compose down --remove-orphans && docker compose up -d' alias dcdul='docker compose down --remove-orphans && docker compose up -d && docker compose logs -f --tail=50' alias dcdb='docker compose down --remove-orphans && docker compose up --build -d' alias dcdbl='docker compose down --remove-orphans && docker compose up --build -d && docker compose logs -f --tail=50'
Docker after dist upgrade
- Update key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- Re-enable repo
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- update the package database with the Docker packages from the newly added repo:
sudo apt-get update
- Make sure you are install from the Docker repo instead of the default Ubuntu repo:
apt-cache policy docker-ce
- upgrade packages
sudo apt-get install docker-ce docker-ce-cli containerd.io
- reboot
fail2ban
-
Install fail2ban with
sudo apt-get install fail2ban
-
Create config file
/etc/fail2ban/jail.local
and add a jail for the SSH Deamon[sshd] enabled = true port = <ssh port> filter = sshd logpath = /var/log/auth.log maxretry = 3 [traefik] enabled = true filter = traefik logpath = /var/lib/docker/containers/*/*-json.log banaction = docker-action maxretry = 3 findtime = 900 bantime = 86400 [wplogin] enabled = true filter = wplogin logpath = /var/lib/docker/containers/*/*-json.log banaction = docker-action maxretry = 3 findtime = 900 bantime = 86400 [unifi] enabled = true filter = unifi logpath = /var/lib/docker/containers/*/*-json.log banaction = docker-action maxretry = 3 bantime = 86400 findtime = 900
-
Creat filter for traefik
/etc/fail2ban/filter.d/traefik.conf
[Definition] failregex = ^{"log":"<HOST> - \S+ \[.*\] \\"(GET|POST|HEAD) .+\" 401 .+$ ignoreregex =
-
Create filter for wplogin
/etc/fail2ban/filter.d/wplogin.conf
[Definition] failregex = ^{"log":"<HOST> -.*POST.*wp-login.php.* ignoreregex =
-
Create filter for unifi
/etc/fail2ban/filter.d/unifi.conf
[Definition] failregex = ^{"log":"<HOST> - \S+ \[.*\] \\"POST \/api\/login.+\\" 400 .+$
-
Create action
/etc/fail2ban/action.d/docker-action.conf
Unlike the out-of-the-box action, "actionban" and "actionunban" do not affect the INPUT chain, but the docker FORWARD chain "DOCKER".[Definition] actionstart = iptables -N f2b-docker iptables -A f2b-docker -j RETURN iptables -I FORWARD -p tcp -j f2b-docker actionstop = iptables -D FORWARD -p tcp -j f2b-docker iptables -F f2b-docker iptables -X f2b-docker actioncheck = iptables -n -L FORWARD | grep -q 'f2b-docker[ \t]' actionban = iptables -I f2b-docker -s <ip> -j DROP actionunban = iptables -D f2b-docker -s <ip> -j DROP
(Source)