03 January 2025
ยท

How to Harden Ubuntu 24.04 for Docker: A Step-by-Step Guide

This guide is intended for developers and system administrators who want to set up a secure environment for deploying applications with Docker on Ubuntu 24.04. Follow these steps to configure your system, install necessary tools, and secure your server.

First, you need SSH

First, you need to install and enable SSH if it is not yet set up. SSH allows secure remote access to your server.

sudo apt update
sudo apt install openssh-server
sudo systemctl enable ssh

Edit your files with vi

:set paste in Vi toggles paste mode, disabling auto-indentation and formatting to preserve your code's exact structure when pasting.

Disable cloud-init

If you are not using cloud services or want to avoid automatic configurations, you can disable cloud-init.

sudo touch /etc/cloud/cloud-init.disabled
sudo reboot

Get into the Root Shell

The sudo -i command in Ubuntu is a powerful way to obtain root-level access to your system. Unlike regular sudo commands, this variant provides you with a complete root shell environment.

UFW (firewall)

Configure the Uncomplicated Firewall (UFW) to secure your server. By default, deny all incoming connections and allow outgoing connections. Only allow SSH, HTTP, and HTTPS.

sudo ufw --force reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw --force enable

Optional: Allow Access to a Rails Application

sudo ufw allow 3000/tcp

To check the current UFW rules and their status, use:

sudo ufw status verbose

Packages for dev

Install essential development packages:

sudo apt install -y build-essential rustc libssl-dev libyaml-dev zlib1g-dev libgmp-dev tmux

Install additional packages for managing repositories and certificates:

sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

Install Ruby, Node using Mise

Mise is a version manager that allows you to easily switch between different versions of Ruby and Node.js. Install Mise and set it up:

curl https://mise.run | sh
echo 'eval "$(~/.local/bin/mise activate)"' >> ~/.bashrc
source ~/.bashrc

Install the latest Ruby version using Mise:

mise use --global ruby@3

Confirm that Ruby is installed and works:

ruby --version
#=> ruby 3.4.1

Update Rubygems to the latest version:

gem update --system

Optionally, install Node.js using Mise:

mise use --global node@22.12.0

Verify the Node.js installation:

node -v
#=> 22.12.0

Configuring Git

Set up Git for version control. Replace the placeholders with your GitHub name and email.

git config --global color.ui true
git config --global user.name "YOUR NAME"
git config --global user.email "YOUR@EMAIL.com"
ssh-keygen -t ed25519 -C "your@email.tld"
chmod 600 ~/.ssh/id_ed25519

Add the newly generated SSH key to your GitHub account:

cat ~/.ssh/id_ed25519.pub

Paste the output here.

Test the SSH connection to GitHub:

ssh -T git@github.com

You should see a message like this:

Hi <user.name>! You've successfully authenticated, but GitHub does not provide shell access.

Let's secure ssh console!

Allow your public key for SSH authentication:

cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys

Edit the SSH configuration to disable password authentication and enable public key authentication:

# File: /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes

Copy your private key on your Windows host, run a cmd and type:

cd desktop
scp <your_user>@<your_server>:.ssh/id_ed25519 .

Finally, restart the SSH service:

sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf
systemctl restart ssh

Installing Rails

Install the specified version of Rails:

gem install rails -v 8.0.1

Verify the Rails installation:

rails -v

Install Kamal

Kamal is a tool for deploying any applications. Install it with:

gem install kamal

Automatic Unattended Upgrades

Automate system updates to ensure your server is always up-to-date with security patches.

Installation

Install the necessary packages:

sudo apt update
sudo apt install unattended-upgrades apt-listchanges bsd-mailx

Enable unattended security updates:

sudo dpkg-reconfigure -plow unattended-upgrades

Answer 'yes'.

Check the service status:

systemctl status unattended-upgrades

Configuration

Edit the configuration file for unattended upgrades:

sudo vi /etc/apt/apt.conf.d/50unattended-upgrades

Configure allowed origins, automatic reboots, and email notifications:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
    // "${distro_id}:${distro_codename}-updates";
    // "${distro_id}:${distro_codename}-proposed";
    // "${distro_id}:${distro_codename}-backports";
};

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

Unattended-Upgrade::Mail "your_email@domain.com";
Unattended-Upgrade::MailReport "on-change";

Why updates Are Not Enabled by Default?

The updates repository includes non-critical updates like bug fixes and feature improvements. While generally stable, these updates can occasionally cause regressions or compatibility issues. For production servers, stability is prioritized over having the latest features.

By excluding updates from unattended-upgrades, you minimize the risk of unexpected problems. Instead, apply these updates manually during planned maintenance windows.

Scheduling Updates

Configure how often updates are checked and installed:

sudo vi /etc/apt/apt.conf.d/20auto-upgrades

Add or modify:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";

Testing Your Setup

Verify your setup without installing updates:

sudo unattended-upgrades --dry-run --debug

Check logs for actual update activities:

sudo cat /var/log/unattended-upgrades/unattended-upgrades.log

How to Apply Updates Manually

To apply updates from the updates repository, follow these steps:

Check for Available Updates

First, update the package list to ensure you have the latest information about available updates:

sudo apt update

Then, list the packages that can be upgraded:

sudo apt list --upgradable

Apply Updates

To install the available updates, use the following command:

sudo apt upgrade

This command will upgrade all packages that can be upgraded without removing or installing additional packages.

If there are packages that require additional actions (e.g., removing or installing new packages), use:

sudo apt full-upgrade

Handle Configuration File Changes

During the upgrade process, you may be prompted to handle changes in configuration files. You can choose to:

  • Keep the current version of the file.
  • Install the maintainer's version.
  • Compare the differences and decide manually.

To avoid interruptions, you can pre-select the option to keep the current version of configuration files:

sudo apt upgrade -o Dpkg::Options::="--force-confold"

Reboot if Necessary

Some updates, such as kernel updates, may require a reboot. Check if a reboot is needed:

[ -f /var/run/reboot-required ] && echo "Reboot required" || echo "No reboot required"

If a reboot is required, schedule it during a maintenance window:

sudo reboot

Installing and Configuring Samba

Install Samba:

sudo apt install samba

Firewall Configuration

Allow Samba through the Ubuntu firewall:

sudo ufw allow samba

Configuration

  1. Create a backup of the original Samba configuration file:
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.backup
  1. Edit the Samba configuration file:
sudo nano /etc/samba/smb.conf
  1. Replace the content with the following configuration:
[global]
   workgroup = WORKGROUP
   server string = %h server (Samba, Ubuntu)
   log file = /var/log/samba/log.%m
   max log size = 1000
   logging = file
   panic action = /usr/share/samba/panic-action %d
   server role = standalone server
   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
   pam password change = yes
   map to guest = bad user
   usershare allow guests = yes

[sabrina]
   comment = Home Directories
   browseable = yes
   guest ok = no
   read only = no
   writable = yes
   create mask = 0775
   directory mask = 0775
   valid users = tolga
   path = /home/tolga/sabrina

Setting Up User Access

  1. Create a Samba user (replace 'tolga' with your system username):
sudo smbpasswd -a tolga
  1. Enter and confirm your password when prompted.

Starting the Service

  1. Check if the configuration is valid:
testparm
  1. Restart Samba services to apply the changes:
sudo systemctl restart smbd nmbd

Accessing the Share

From Windows: Open File Explorer and enter \\server-ip\sabrina. Replace server-ip with your Ubuntu machine's IP address.

Docker installation

Add GPG Docker key

Add Docker's GPG key:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Add the Docker repository

Add the Docker repository to your system:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Update your packages

Update your package list:

sudo apt update

Install Docker and its components

Install Docker and related components:

sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Check the Docker installation

Verify that Docker is running:

sudo systemctl status docker

Check Docker version

Check the installed Docker version:

docker --version

Run a test container

Run a test container to verify the installation:

sudo docker run hello-world

Add your user to the Docker group

Add your user to the Docker group to avoid using sudo for Docker commands:

sudo usermod -aG docker $USER

Disconnect and reconnect to apply the changes.

Docker Hub

What is it?

Docker Hub is the official cloud-based registry for Docker container images - like GitHub for Docker images.

Why use it?

  • Store your Docker images online
  • Download official images
  • Share images with teams/public
  • Free for basic use
  • Automated builds from GitHub

Getting Started

  1. Register at hub.docker.com
  2. Login:
docker login

Basic Commands

# Download image
docker pull ubuntu:latest

# Upload your image
docker push yourusername/imagename:tag

Free Plan Includes

  • Unlimited public repos
  • 1 private repo
  • 200 pulls/6h

That's it! Simple and ready to use.

Clean Up Unnecessary Packages

To remove unused packages and clean up the APT cache, run:

sudo apt autoremove -y && sudo apt autoclean

Shutdown the box

sudo halt -p

Reboot the box

sudo reboot

Conclusion

By following this guide, you have set up a secure environment for deploying applications with Docker on Ubuntu 24.04. Regularly update your system and monitor security logs to maintain a secure and efficient server.