Prepare Ubuntu 22.04 Server for Production Deployment
Setting up an Ubuntu 22.04 server for production requires careful configuration to ensure security, performance, and reliability. This guide covers essential hardening steps including disabling cloud-init, managing automatic updates, and optimizing SSH configuration for production environments.
Whether you’re deploying on cloud infrastructure, bare metal, or virtual machines, these foundational steps will prepare your Ubuntu server for reliable production use. The procedures outlined here focus on creating a stable, secure baseline that can be further customized based on your specific application requirements.
Prerequisites
Before beginning this setup, ensure you have:
- Fresh Ubuntu 22.04 server installation
- Root or sudo access to the server
- Basic familiarity with command line operations
- SSH access to the server (if configuring remotely)
For comprehensive initial server setup including user management and basic security, reference Digital Ocean’s excellent Initial Server Setup with Ubuntu 22.04 guide, which complements the production-specific configurations covered here.
System Update and Preparation
Start by ensuring your system has the latest packages and security updates. This creates a clean baseline for production configuration.
Update System Packages
# Update package list and upgrade all packages
apt update && apt upgrade -y
# Remove unnecessary packages and clean up
apt autoremoveThe apt autoremove command removes packages that were automatically installed as dependencies but are no longer needed, helping maintain a clean system.
Disable Cloud-Init
Cloud-init is useful during initial provisioning but can interfere with production operations by making unexpected configuration changes. Disabling it prevents unwanted modifications to your carefully configured production environment.
Create Disable File
# Create the disable file to prevent cloud-init from running
touch /etc/cloud/cloud-init.disabledThis simple file creation permanently disables cloud-init on subsequent boots. The service will detect this file and skip all cloud-init operations, giving you full control over system configuration.
Configure Automatic Updates
While keeping systems updated is crucial for security, automatic updates in production environments can cause unexpected downtime or compatibility issues. Configure automatic updates according to your maintenance schedule and change management policies.
Disable Automatic Updates
For production systems where you want to control update timing:
# Edit the automatic update configuration
vim /etc/apt/apt.conf.d/20auto-upgradesConfigure the file with these settings:
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "0";
APT::Periodic::Unattended-Upgrade "0";# disable
systemctl disable --now unattended-upgrades.serviceVerify Configuration
After making changes, verify the configuration is applied correctly:
# Check that automatic updates are disabled
apt-config dump APT::Periodic::Update-Package-Lists && apt-config dump APT::Periodic::Unattended-UpgradeBoth commands should return “0” confirming that automatic updates are disabled.
Alternative: Controlled Automatic Updates
If you prefer to enable security-only automatic updates:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";Then configure /etc/apt/apt.conf.d/50unattended-upgrades to only install security updates automatically.
Optimize SSH Configuration
SSH performance can be significantly improved by disabling DNS lookups, which often cause connection delays in production environments.
Disable SSH DNS Lookups
# Edit SSH daemon configuration
vim /etc/ssh/sshd_configAdd or modify this line:
UseDNS noThis prevents the SSH daemon from performing reverse DNS lookups on connecting clients, which can cause significant connection delays, especially when DNS resolution is slow or unavailable.
Apply SSH Configuration Changes
# Restart SSH daemon to apply changes
systemctl restart sshdImportant: Ensure you have an active SSH session or console access before restarting the SSH daemon, in case of configuration errors.
Additional Production Hardening
Configure Timezone
Set the appropriate timezone for your production environment:
# Set timezone (example: UTC for servers)
timedatectl set-timezone UTC
# Verify timezone setting
timedatectl statusConfigure System Limits
For applications with high resource requirements, adjust system limits:
# Edit limits configuration
vim /etc/security/limits.conf
# Example: Increase file descriptor limits
* soft nofile 65536
* hard nofile 65536Disable Unnecessary Services
Review and disable services not needed in your production environment:
# List all enabled services
systemctl list-unit-files --state=enabled
# Disable unnecessary services (example)
systemctl disable snapd
systemctl disable ModemManagerVerification and Testing
System Status Check
Verify all configurations are applied correctly:
# Check cloud-init status
ls -la /etc/cloud/cloud-init.disabled
# Verify SSH configuration
sshd -t
# Check automatic update settings
apt-config dump APT::PeriodicPerformance Testing
Test SSH connection performance to verify DNS lookup disable is working:
# Time SSH connection from client
time ssh user@your-server-ipConnection should establish quickly without DNS-related delays.
Post-Configuration Steps
After completing these foundational steps:
- Document Changes: Record all configuration changes for your infrastructure documentation
- Create System Snapshot: Take a backup or snapshot of your configured system
- Test Applications: Deploy and test your applications with the new configuration
- Monitor Systems: Implement monitoring to track system performance and security
- Schedule Maintenance: Plan regular maintenance windows for manual updates
Troubleshooting Common Issues
Cloud-Init Still Running
If cloud-init continues to run despite the disable file:
# Check cloud-init status
cloud-init status
# Manually disable all cloud-init services
systemctl disable cloud-init
systemctl disable cloud-config
systemctl disable cloud-final
systemctl disable cloud-init-localSSH Connection Issues
If SSH connections become problematic after configuration changes:
# Check SSH daemon status
systemctl status sshd
# Test SSH configuration syntax
sshd -t
# View SSH daemon logs
journalctl -u sshd -fAutomatic Update Issues
If automatic updates aren’t properly disabled:
# Check for additional update configurations
ls -la /etc/apt/apt.conf.d/
# Verify unattended-upgrades status
systemctl status unattended-upgradesSecurity Considerations
Firewall Configuration
Configure UFW (Uncomplicated Firewall) for additional security - see our UFW cheatsheet for detailed firewall management, including IP restrictions, port configuration, and application rules.
Regular Security Updates
Even with automatic updates disabled, establish a schedule for manual security updates:
# Check for security updates
apt list --upgradable | grep -i security
# Install security updates only
unattended-upgrade -d --dry-runMonitoring and Logging
Implement comprehensive logging and monitoring solutions to track system changes and potential security issues.
References and Resources
- Digital Ocean Initial Server Setup Guide - Comprehensive server setup including user management and basic security
- Ubuntu Server Guide - Official Ubuntu server documentation
- SSH Hardening Guide - Advanced SSH security configuration
- APT Configuration Reference - Detailed APT configuration options
Questions Answered in This Document
Q: How do I disable cloud-init on Ubuntu 22.04?
A: Create a disable file using touch /etc/cloud/cloud-init.disabled. This prevents cloud-init from running on subsequent boots.
Q: Should I disable automatic updates on production servers? A: Generally yes, to maintain control over update timing and prevent unexpected downtime. Configure manual updates during planned maintenance windows instead.
Q: Why disable SSH DNS lookups in production?
A: DNS lookups can cause significant connection delays, especially when DNS resolution is slow. Disabling with UseDNS no improves SSH connection speed.
Q: How do I verify automatic updates are properly disabled?
A: Run apt-config dump APT::Periodic::Update-Package-Lists && apt-config dump APT::Periodic::Unattended-Upgrade. Both should return “0”.
Q: What’s the difference between apt update and apt upgrade?
A: apt update refreshes the package list from repositories, while apt upgrade actually installs available package updates. Always run update before upgrade.
Q: Can I re-enable cloud-init later if needed?
A: Yes, simply remove the /etc/cloud/cloud-init.disabled file and reboot. Cloud-init will resume normal operation.
Q: How do I check if my SSH configuration changes are valid?
A: Use sshd -t to test SSH configuration syntax before restarting the service. This prevents locking yourself out due to configuration errors.
Q: What services should I disable on a production Ubuntu server? A: Commonly disabled services include snapd, ModemManager, and cloud-init services. Review your specific needs as requirements vary by use case.