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
- Create a backup of the original Samba configuration file:
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.backup
- Edit the Samba configuration file:
sudo nano /etc/samba/smb.conf
- 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
- Create a Samba user (replace 'tolga' with your system username):
sudo smbpasswd -a tolga
- Enter and confirm your password when prompted.
Starting the Service
- Check if the configuration is valid:
testparm
- 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
- Register at
hub.docker.com
- 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.