How To

Install Apache Web Server on Ubuntu 26.04 LTS

Apache is still the workhorse behind most of the internet. Despite Nginx gaining ground over the past decade, Apache HTTP Server powers roughly a third of all websites and remains the default in most Linux distributions, LAMP stacks, and hosting control panels. It’s battle-tested, flexible with .htaccess, and well-documented.

Original content from computingforgeeks.com - post 165987

This guide walks through a clean Apache 2.4.66 install on Ubuntu 26.04 LTS, covering virtual hosts, essential modules, security hardening, and log management. If you need Nginx instead, see the Nginx on Ubuntu 26.04 guide.

Current as of April 2026. Tested on Ubuntu 26.04 LTS with Apache 2.4.66

Prerequisites

Before starting, make sure you have:

  • Ubuntu 26.04 LTS server with root or sudo access (initial server setup guide)
  • Tested on: Ubuntu 26.04 LTS (kernel 7.0.0-10-generic), Apache 2.4.66
  • A registered domain name (for virtual host configuration)
  • Port 80 and 443 open in your firewall

Install Apache on Ubuntu 26.04

Apache is available in Ubuntu’s default repositories as the apache2 package. Update the package index and install it:

sudo apt update
sudo apt install -y apache2

After installation completes, Apache starts automatically and is enabled to start on boot. Verify the installed version:

apache2 -v

The output confirms Apache 2.4.66 built for Ubuntu:

Server version: Apache/2.4.66 (Ubuntu)
Server built:   2026-03-05T17:18:22

Check the service status:

systemctl status apache2

You should see active (running):

● apache2.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-04-14 00:25:17 UTC; 10s ago
       Docs: https://httpd.apache.org/docs/2.4/
   Main PID: 2755 (apache2)
     Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec:   0 B/sec"
      Tasks: 55 (limit: 3522)
     Memory: 5.7M (peak: 5.9M)
        CPU: 98ms

Configure the Firewall

Ubuntu 26.04 ships with UFW (Uncomplicated Firewall). Apache registers three UFW application profiles during installation. List them:

sudo ufw app list

The available Apache profiles are:

Available applications:
  Apache
  Apache Full
  Apache Secure
  OpenSSH

Apache opens port 80 only, Apache Secure opens port 443 only, and Apache Full opens both. Allow Apache Full since you’ll want HTTPS later:

sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
sudo ufw enable

Confirm the rules are active:

sudo ufw status

Both OpenSSH and Apache Full should show ALLOW:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Apache Full                ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Apache Full (v6)           ALLOW       Anywhere (v6)

Apache Directory Structure on Ubuntu

Ubuntu organizes Apache’s configuration differently from upstream. Understanding the layout saves time when troubleshooting:

/etc/apache2/
├── apache2.conf          # Main config (includes everything below)
├── ports.conf            # Listen directives (80, 443)
├── mods-available/       # All available module configs
├── mods-enabled/         # Symlinks to active modules
├── conf-available/       # Extra config snippets
├── conf-enabled/         # Symlinks to active configs
├── sites-available/      # All virtual host configs
└── sites-enabled/        # Symlinks to active virtual hosts

The a2ensite / a2dissite commands manage symlinks in sites-enabled/, and a2enmod / a2dismod do the same for modules. This is Debian/Ubuntu-specific. RHEL-based distros use a flat config layout instead.

Enable Essential Modules

A fresh Apache install on Ubuntu 26.04 comes with 30+ modules loaded. Three common ones that aren’t enabled by default are mod_rewrite (URL rewriting), mod_ssl (HTTPS), and mod_headers (custom response headers). Enable all three:

sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers
sudo systemctl restart apache2

Verify they’re loaded:

apache2ctl -M | grep -E 'rewrite|ssl|headers'

All three should appear in the output:

 headers_module (shared)
 rewrite_module (shared)
 ssl_module (shared)

To see every loaded module, run apache2ctl -M without the grep filter.

Set Up Virtual Hosts

Virtual hosts let you run multiple websites on a single server. Each site gets its own configuration file. Here’s how to set one up from scratch.

Create the document root for your site:

sudo mkdir -p /var/www/example.com/html
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com

Drop a test page in the document root:

echo '<html><head><title>Example Site</title></head><body><h1>Welcome to example.com</h1></body></html>' | sudo tee /var/www/example.com/html/index.html

Now create the virtual host configuration file:

sudo vi /etc/apache2/sites-available/example.com.conf

Add the following configuration:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com/html

    <Directory /var/www/example.com/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>

Key directives in this config:

  • ServerName and ServerAlias match incoming requests by hostname
  • Options -Indexes disables directory listing (security measure)
  • AllowOverride All enables .htaccess files for per-directory config
  • Separate log files per virtual host make troubleshooting easier

Enable the new site and test the configuration syntax:

sudo a2ensite example.com.conf
sudo apache2ctl configtest

You should see “Syntax OK”:

Enabling site example.com.
To activate the new configuration, you need to run:
  systemctl reload apache2
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Syntax OK

The AH00558 warning is harmless. To suppress it, add ServerName localhost to /etc/apache2/apache2.conf. Reload Apache to activate the virtual host:

sudo systemctl reload apache2

Verify the virtual host is registered:

sudo apache2ctl -S

The output lists all configured virtual hosts and their source files:

VirtualHost configuration:
*:80                   is a NameVirtualHost
         default server 127.0.1.1 (/etc/apache2/sites-enabled/000-default.conf:1)
         port 80 namevhost 127.0.1.1 (/etc/apache2/sites-enabled/000-default.conf:1)
         port 80 namevhost example.com (/etc/apache2/sites-enabled/example.com.conf:1)
                 alias www.example.com
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/var/log/apache2/error.log"

Check Apache Configuration Syntax

Always validate your config before restarting Apache. A syntax error in any config file will prevent Apache from starting, taking all your sites offline. Two commands do the same thing:

sudo apache2ctl configtest

Or equivalently:

sudo apache2ctl -t

A clean config returns Syntax OK. Make this a habit before every systemctl restart apache2.

Manage Apache: Start, Stop, Restart, Reload

Apache on Ubuntu 26.04 uses systemd. Here are the essential management commands:

sudo systemctl start apache2      # Start the service
sudo systemctl stop apache2       # Stop the service
sudo systemctl restart apache2    # Full restart (drops active connections)
sudo systemctl reload apache2     # Graceful reload (no downtime)
sudo systemctl enable apache2     # Start on boot
sudo systemctl disable apache2    # Don't start on boot

Use reload instead of restart whenever possible. A reload applies configuration changes without dropping active connections. The only time you need a full restart is when loading or unloading modules, since module changes require the main process to be replaced.

For a graceful stop that waits for active requests to finish:

sudo apachectl graceful-stop

Security Hardening

Apache’s defaults are designed for convenience, not security. A few quick changes reduce your attack surface significantly.

Hide Server Version Information

By default, Apache broadcasts its version number and OS in HTTP response headers and error pages. This gives attackers free reconnaissance. Lock it down in the security config:

sudo vi /etc/apache2/conf-available/security.conf

Change these two directives:

ServerTokens Prod
ServerSignature Off

ServerTokens Prod reduces the Server header from Apache/2.4.66 (Ubuntu) to just Apache. ServerSignature Off removes version info from error pages. The existing TraceEnable Off line is already set correctly (prevents TRACE request abuse). Apply the changes:

sudo systemctl restart apache2

Verify the header now shows only “Apache” with no version:

curl -sI http://localhost | grep Server

The response should show a clean header:

Server: Apache

Disable Directory Listing

If a directory has no index.html, Apache will show a listing of all files by default. This is a security risk. Disable it globally in /etc/apache2/apache2.conf by changing:

# Change this:
Options Indexes FollowSymLinks

# To this:
Options -Indexes +FollowSymLinks

The virtual host config we created earlier already has -Indexes set, but doing it globally catches any site that forgets to set it.

Add Security Headers

With mod_headers enabled, add basic security headers. Create a new config snippet:

sudo vi /etc/apache2/conf-available/security-headers.conf

Add the following lines:

Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

Enable the config and reload:

sudo a2enconf security-headers
sudo systemctl reload apache2

For a detailed look at Apache security best practices, see the official Apache security tips.

Logging: Access Logs, Error Logs, and Rotation

Apache stores its logs under /var/log/apache2/. The two main log files are:

  • access.log records every request (client IP, URL, status code, user agent)
  • error.log captures errors, warnings, and startup messages

When you configure per-virtual-host logging (as we did earlier), each site gets its own pair of log files. Check what’s in the log directory:

ls -la /var/log/apache2/

You should see separate logs for each virtual host:

-rw-r-----  1 root adm      81 Apr 14 00:26 access.log
-rw-r-----  1 root adm    2182 Apr 14 00:26 error.log
-rw-r--r--  1 root root      0 Apr 14 00:26 example.com-access.log
-rw-r--r--  1 root root      0 Apr 14 00:26 example.com-error.log
-rw-r-----  1 root adm       0 Apr 14 00:25 other_vhosts_access.log

Log Rotation

Ubuntu configures log rotation for Apache automatically via /etc/logrotate.d/apache2. The default rotates daily, keeps 14 days of history, and compresses old logs:

cat /etc/logrotate.d/apache2

The default configuration:

/var/log/apache2/*.log {
	daily
	missingok
	rotate 14
	compress
	delaycompress
	notifempty
	create 640 root adm
	sharedscripts
	postrotate
		if pgrep -f ^/usr/sbin/apache2 > /dev/null; then
			invoke-rc.d apache2 reload 2>&1 | logger -t apache2.logrotate
		fi
	endscript
}

The wildcard *.log automatically picks up per-virtual-host log files, so no extra rotation config is needed when you add new sites. For high-traffic servers, consider adjusting rotate to keep more history or adding maxsize 100M to rotate large files mid-day.

Verify Apache Ports

With mod_ssl enabled, Apache listens on both port 80 and 443. Confirm with:

ss -tlnp | grep apache2

Both ports should appear:

LISTEN 0  511  *:80   *:*  users:(("apache2",pid=4090,fd=4),("apache2",pid=4087,fd=4),("apache2",pid=4084,fd=4))
LISTEN 0  511  *:443  *:*  users:(("apache2",pid=4090,fd=6),("apache2",pid=4087,fd=6),("apache2",pid=4084,fd=6))

The port configuration lives in /etc/apache2/ports.conf. By default, port 443 only activates when mod_ssl is loaded.

Apache 2.4.66 version and service status on Ubuntu 26.04 LTS
Apache 2.4.66 running on Ubuntu 26.04 LTS

Ubuntu 26.04 vs 24.04: Apache Comparison

If you’re upgrading from Ubuntu 24.04 or running both in your environment, here are the key differences:

ItemUbuntu 26.04 LTSUbuntu 24.04 LTS
Apache version2.4.662.4.58
Kernel7.06.8
OpenSSL3.4.x3.0.x
MPM defaulteventevent
Config path/etc/apache2//etc/apache2/
Log path/var/log/apache2//var/log/apache2/
PHP defaultPHP 8.4PHP 8.3
Systemd presetenabledenabled
TLS 1.3 supportYes (default)Yes
HTTP/2 supportmod_http2 availablemod_http2 available

The config paths and management commands are identical between releases. The main benefits of 26.04 are a newer Apache with security patches, OpenSSL 3.4 with stronger defaults, and kernel 7.0. If you’re building a LAMP stack, check out the Apache, PHP, and MariaDB on Ubuntu guide for the full stack setup. For container-based deployments, see Docker CE on Ubuntu 26.04. The full Apache 2.4 documentation is available at httpd.apache.org.

Related Articles

Ubuntu Install i-doit Asset Management on Ubuntu 22.04|20.04|18.04 Storage Install Bareos Backup on Ubuntu 24.04 / 22.04 DevOps Deploy Static Sites to Cloudflare Pages (Free Hosting) AlmaLinux Convert Video to MP3 on Linux with FFmpeg

Leave a Comment

Press ESC to close