A small Ubuntu server can host a real website as soon as Apache is installed, reachable through the firewall, and pointed at the right document root. To install Apache on Ubuntu, use the distro package named apache2, then verify the service before adding virtual hosts or HTTPS.
The workflow uses Ubuntu’s default repositories on Ubuntu 26.04 LTS (Resolute Raccoon), 24.04 LTS (Noble Numbat), and 22.04 LTS (Jammy Jellyfish). It also covers UFW firewall rules on Ubuntu, Apache virtual hosts, and Let’s Encrypt certificates.
Install Apache on Ubuntu
Ubuntu’s default repository provides a stable, well-tested Apache build that receives security patches through Ubuntu’s standard update cycle. Most users should choose this method before considering a third-party PPA or source build.
Ubuntu uses the apache2 package name. Red Hat-family documentation often uses httpd, but apt install httpd and apt install apache do not provide Apache HTTP Server on supported Ubuntu LTS releases.
Users who specifically need a newer upstream Apache branch can review the Ondrej Sury PPA, which tracks upstream more closely than Ubuntu’s standard repositories. See our Apache upgrade guide for detailed PPA installation and rollback instructions.
Default Apache Versions by Ubuntu Release
The default APT repository ships different Apache versions depending on your Ubuntu release. These versions receive security backports throughout the Ubuntu support lifecycle.
| Ubuntu Release | Default Apache Package | Standard Security Maintenance |
|---|---|---|
| Ubuntu 26.04 LTS (Resolute Raccoon) | Apache 2.4.66 | Until May 2031 |
| Ubuntu 24.04 LTS (Noble Numbat) | Apache 2.4.58 | Until May 2029 |
| Ubuntu 22.04 LTS (Jammy Jellyfish) | Apache 2.4.52 | Until May 2027 |
Update Ubuntu Before Apache Installation
Update Ubuntu first so every package pulls in the latest security fixes and dependency changes. Working from a current baseline prevents conflicts once Apache installs.
The Ubuntu package update guide explains the APT workflow in more depth, but the standard update command is enough for this Apache setup.
Run the combined update and upgrade to sync package metadata and apply pending fixes:
sudo apt update && sudo apt upgrade
These commands use
sudofor system administration tasks. If your account cannot run sudo commands yet, add the user to sudoers first or follow the guide on adding a new sudo user on Ubuntu.
Install Apache Using APT
Install Apache from Ubuntu’s official repository:
sudo apt install apache2
After the installation completes, verify Apache is running:
systemctl is-active apache2
Expected output:
active
Check the installed Apache version:
apache2ctl -v
Expected output on Ubuntu 26.04:
Server version: Apache/2.4.66 (Ubuntu) Server built: 2026-03-05T17:18:22
Ubuntu 24.04 currently reports the Apache 2.4.58 series, while Ubuntu 22.04 reports the Apache 2.4.52 series.
Configure UFW Firewall for Apache
After Apache installs, configure the UFW (Uncomplicated Firewall) rules so HTTP and HTTPS traffic can reach the service. Apache registers multiple UFW profiles during installation, making it easy to allow the correct ports in a single step.
Check UFW Installation
Before you add rules, verify that UFW is installed and note whether it is already active:
sudo ufw status
If the command reports that UFW is missing, install the package:
sudo apt install ufw
Do not enable UFW yet; build the allow rules first so you do not cut off SSH or web access mid-session.
Apply the
OpenSSHprofile (and any other required services) before runningsudo ufw enable. If you only have remote access, schedule firewall changes from a console or with out-of-band management so you can recover quickly if a rule is missing.
List Available Application Profiles
List the available profiles so you know which Apache presets UFW exposes:
sudo ufw app list
Relevant output includes the Apache profiles, though your system may list additional applications:
Available applications: Apache Apache Full Apache Secure OpenSSH
The Apache profiles control web traffic ports:
- Apache: opens port 80 (HTTP) only
- Apache Secure: opens port 443 (HTTPS) only
- Apache Full: opens both port 80 and 443
Most servers start with Apache during initial setup and switch to Apache Full after configuring SSL certificates. Use Apache Secure only when your certificate validation path does not need HTTP.
Configure UFW Firewall Rules for Apache
Start by allowing basic HTTP access with the Apache profile while you finish the rest of the setup:
sudo ufw allow 'Apache'
If you manage the server over SSH, also add the OpenSSH profile so port 22 stays reachable:
sudo ufw allow OpenSSH
Example output:
Rule added Rule added (v6)
The rules apply to both IPv4 and IPv6. Later you can swap profiles if you migrate directly to HTTPS.
Allow Specific IP Addresses and Ranges
You can scope access to trusted hosts by allowing only specific IP addresses or ranges while keeping the rules tied to Apache’s HTTP (80) and HTTPS (443) ports. To allow a single remote IP, run (and repeat with port 443 if you want HTTPS too):
sudo ufw allow from <IP_ADDRESS> to any port 80 proto tcp
Replace <IP_ADDRESS> with the actual IP address you want to allow and adjust the port number as needed.
To authorize an entire subnet, adjust the CIDR notation in this rule (duplicate it for port 443 when needed):
sudo ufw allow from <IP_RANGE> to any port 80 proto tcp
Replace <IP_RANGE> with the subnet you want to trust, such as 192.168.1.0/24. Switching the port number lets you create HTTP-only, HTTPS-only, or dual-purpose rules.
For a typical home or lab network, you might run:
sudo ufw allow from 192.168.1.0/24 to any port 80 proto tcp
This example opens HTTP access for every device in the 192.168.1.0/24 subnet; add a matching port 443 rule if HTTPS should stay local-only.
Review the pending rules before enabling the firewall:
sudo ufw status
Expected output:
Status: inactive To Action From -- ------ ---- Apache ALLOW Anywhere OpenSSH ALLOW Anywhere Apache (v6) ALLOW Anywhere (v6) OpenSSH (v6) ALLOW Anywhere (v6)
Enable the firewall to activate these rules:
sudo ufw enable
Confirm the firewall is active:
sudo ufw status verbose
Expected output:
Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- Apache ALLOW IN Anywhere 22/tcp (OpenSSH) ALLOW IN Anywhere Apache (v6) ALLOW IN Anywhere (v6) 22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6)
Verify Apache Installation on Ubuntu
With Apache installed and the firewall configured, confirm the service answers web requests before moving on to custom content.
Find Your Server’s IP Address
To load Apache’s default landing page, you need the server’s IP address. Display the local addresses assigned to the host with:
hostname -I
The command prints one or more internal IP addresses, similar to this output:
192.168.50.15
Test each address until you reach the server, especially if the machine has multiple interfaces.
To view your public (external) IP address, query a simple HTTPS endpoint:
curl -4 https://icanhazip.com
If curl is missing, install it first:
sudo apt install curl
Once curl is installed, explore more practical use cases in our curl command guide for Linux to better understand how it can assist with troubleshooting and automation.
Access the Apache Landing Page
After you have the correct IP address, open it in your browser with the http:// prefix, such as http://192.168.50.15.
Verify the Apache Default Page
Your browser should display the Apache test page:

This page confirms that Apache is installed correctly and responding over the network.
Configure Virtual Hosts for Apache
Apache uses virtual hosts to map domains to directories, similar to how Nginx uses server blocks. The following example builds a site for example.com that you can later replace with your own domain.
Create and Configure Directories for Apache
Ubuntu ships a single enabled virtual host that serves /var/www/html. You can reuse it for a one-site server, but adding more domains is easier when each domain receives its own directory and matching virtual host file.
Leave /var/www/html untouched for the default site and create a dedicated directory for example.com, which becomes the DocumentRoot for that domain:
sudo mkdir /var/www/example.com
Assign ownership to your sudo user so you can edit site files without switching to root:
sudo chown -R $USER:$USER /var/www/example.com
Verify the permissions with ls -l to ensure Apache can read the files:
ls -l /var/www/
Example output:
drwxr-xr-x 2 joshua joshua 4096 Apr 18 15:25 example.com drwxr-xr-x 2 root root 4096 Apr 18 15:23 html
The drwxr-xr-x entry corresponds to chmod 755, which is ideal for a public web root. Fix the permissions if they differ:
sudo chmod -R 755 /var/www/example.com
Create a quick index.html file with your preferred editor (nano in this example):
sudo nano /var/www/example.com/index.html
In the file, copy and paste the following code:
<html>
<head>
<title>Welcome to example.com</title>
</head>
<body>
<h1>example.com Apache test page</h1>
</body>
</html>
Save the file (Ctrl+O), then exit (Ctrl+X).
Create a Virtual Host for Apache
With the document root prepared, create the virtual host file under /etc/apache2/sites-available/, which is where Apache keeps site definitions.
Create a matching virtual host definition in /etc/apache2/sites-available/example.com.conf:
sudo nano /etc/apache2/sites-available/example.com.conf
Paste this template and replace example.com with your actual domain, ensuring the DocumentRoot points to the directory you created earlier:
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
Use an appropriate email address for ServerAdmin and your domain names for the ServerName and ServerAlias entries.
Save the file (Ctrl+O) and exit (Ctrl+X) when the directives match your domain.
Enable Virtual Host for Apache
With the configuration saved, enable it using Apache’s helper utilities instead of creating symlinks manually like you would on Nginx:
Disable the default 000-default.conf site so Apache does not serve two sites on the same port:
sudo a2dissite 000-default.conf
Enable your new site so Apache creates the appropriate symlink under sites-enabled:
sudo a2ensite example.com.conf
Run the Apache syntax check before reloading to catch mistakes:
sudo apache2ctl configtest
You should see the following confirmation:
Syntax OK
If Apache also prints an AH00558 message about the server’s fully qualified domain name, the syntax check still passed. Add a global ServerName later if you want to suppress that warning.
Once apache2ctl configtest returns Syntax OK, reload Apache to load the new site without dropping active connections:
sudo systemctl reload apache2
Apache now serves the example.com landing page. Point DNS or a local hosts-file entry at the server, then visit http://example.com in your browser to confirm the custom index.html file loads:

Secure Apache with Let’s Encrypt Free SSL Certificate
Protect traffic by serving Apache over HTTPS with a trusted SSL/TLS certificate. Let’s Encrypt, a free certificate authority backed by the Internet Security Research Group (ISRG), automates the process so you are never stuck paying for renewals.
Install Certbot for Apache
Install the Certbot Apache plugin, which handles certificate requests and VirtualHost updates automatically:
sudo apt install python3-certbot-apache
Create and Configure SSL Certificate for Apache
Request and install a certificate for your domain, replacing the email address and domain names with your own:
sudo certbot --apache --agree-tos --redirect --email you@example.com -d example.com -d www.example.com
This command uses the Apache installer plugin, accepts the subscriber agreement, requests certificates for both the root domain and the www hostname, and redirects HTTP traffic to HTTPS.
Do not add HSTS until you are certain every hostname on the domain should require HTTPS. HSTS is a browser-cached policy, so enabling it too early can make recovery harder if a subdomain or hostname is not ready for HTTPS.
Provide a monitored email address for ACME account notices and replace the domain arguments with the hostnames assigned to your site.
Verify SSL Configuration with Apache
Your site now answers on https://www.example.com and automatically redirects from http://www.example.com, keeping visitors on encrypted connections.
Visit the site in a browser to confirm the padlock icon appears and that the redirect fires correctly.
Update your firewall now that HTTPS is available. Keep the Apache Full profile for normal Certbot HTTP-01 validation because Let’s Encrypt still needs port 80 for issuance and renewal checks:
sudo ufw allow 'Apache Full'
Use the Apache Secure profile only when your certificate workflow does not require HTTP validation, such as a DNS-01 setup. Closing port 80 after using the standard Apache installer can make future renewals fail.
Automate Certificate Renewal
Let’s Encrypt certificates remain valid for 90 days. Ubuntu’s Certbot package installs a systemd timer automatically, but run a dry run to confirm renewals work:
sudo certbot renew --dry-run
The dry run simulates a renewal without making changes. A successful result means the automated job can refresh the certificate before it expires.
Combine HTTPS with an application firewall by following our ModSecurity with Apache on Ubuntu guide if you want to block malicious traffic before it reaches your apps.
Apache Management on Ubuntu
Keep Apache healthy by monitoring its logs and knowing the service commands you’ll need during routine operations.
Analyze Apache Server Logs
Use these commands to review Apache logs when you troubleshoot errors or monitor traffic patterns.
Display the last few lines of a log file:
The tail command shows the newest log entries, which helps when you are checking recent requests or errors.
tail /var/log/apache2/access.log
tail /var/log/apache2/error.log
Monitor log file in real-time:
Use tail -f to monitor log files in real time while requests are reaching the server.
tail -f /var/log/apache2/access.log
tail -f /var/log/apache2/error.log
Search for specific keywords in log files:
The grep command searches for keywords or patterns in log files. For example, search for 404 entries in the error log:
grep "404" /var/log/apache2/error.log
Count the occurrences of a specific keyword or pattern:
Use grep with -c to count matching lines. For example, count 500 errors in the error log:
grep -c "500" /var/log/apache2/error.log
Display unique IP addresses that have accessed the server:
Use awk to extract unique client IP addresses from the access log:
awk '{print $1}' /var/log/apache2/access.log | sort | uniq
These snippets give you a starting point for tailing logs, searching for errors, and spotting abusive hosts.
Essential Apache Service Management Commands
Keep these service commands handy for common maintenance tasks:
Stop Apache web server:
sudo systemctl stop apache2
Start Apache web server:
sudo systemctl start apache2
Restart Apache web server:
sudo systemctl restart apache2
Reload Apache web server: Use this for minor configuration changes that do not require a complete restart.
sudo systemctl reload apache2
Disable Apache on server boot:
sudo systemctl disable apache2
Enable Apache on server boot: Apache is normally enabled automatically during installation, but this command restores boot startup if it was disabled.
sudo systemctl enable apache2
Update Apache on Ubuntu
Keep Apache patched by running the regular APT update and upgrade cycle:
sudo apt update
sudo apt upgrade
Create backups or server images before upgrading Apache on production systems. Most security updates apply cleanly, but a backup gives you a recovery point if a module, application, or custom configuration reacts badly to the new package build.
For major version changes or when migrating to a new LTS release, follow our step-by-step Apache upgrade guide for Ubuntu so you can plan downtime, confirm module compatibility, and roll back safely if needed.
Troubleshooting Apache on Ubuntu
Use these checks when Apache fails to start, serves the wrong site, or rejects certificate validation.
Apache Fails to Start
When Apache refuses to start, first check the service status for error details:
sudo systemctl status apache2 --no-pager -l
Common causes and fixes:
Port 80 already in use:
(98)Address already in use: AH00072: make_sock: could not bind to address
Another process is using port 80. Find it with:
sudo ss -tlnp 'sport = :80'
Relevant output usually names the process that owns the listener:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=[varies],fd=[varies]))
Stop the conflicting service (often Nginx) or change Apache’s port in /etc/apache2/ports.conf.
Configuration syntax error:
Job for apache2.service failed because the control process exited with error code.
Test the configuration syntax:
sudo apache2ctl configtest
Fix the reported issue, then restart Apache.
Permission Denied Errors
If Apache returns 403 Forbidden errors for a directory, verify the permissions allow Apache to read the files:
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
Keep ownership with your deployment user unless a specific application directory needs Apache write access. Changing the entire web root to www-data makes quick static-site edits harder and is rarely necessary.
Also confirm the Directory block in your virtual host allows access:
<Directory /var/www/example.com>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Virtual Host Not Loading
If Apache serves the default page instead of your virtual host, verify the site is enabled:
ls -l /etc/apache2/sites-enabled/
Confirm your .conf file appears in the list. If not, enable it:
sudo a2ensite example.com.conf
sudo systemctl reload apache2
Also confirm your DNS or /etc/hosts file points the domain to the server’s IP address.
Certbot Certificate Request Fails
Let’s Encrypt validation requires that the domain resolves to your server and port 80 is open. If certificate requests fail:
- Verify DNS A/AAAA records point to the correct public IP
- Confirm UFW allows the Apache profile:
sudo ufw status - Check that no firewall upstream (cloud provider, router) blocks port 80
- Test HTTP access from outside your network before requesting the certificate
OCSP Stapling Errors After HTTPS Setup
If Apache logs OCSP stapling errors after you enable HTTPS, check whether an older hardening snippet or copied configuration enabled stapling manually:
AH02218: ssl_stapling_init_cert: no OCSP URI in certificate and no SSLStaplingForceURL set AH02604: Unable to configure certificate example.com:443:0 for stapling
Let’s Encrypt ended OCSP support in 2025, and current certificates no longer include OCSP URLs. Do not add --staple-ocsp to the Certbot command for new Let’s Encrypt certificates.
Search your Apache configuration for custom stapling directives:
sudo grep -R -E "SSLUseStapling|SSLStapling" /etc/apache2/ || echo "No custom stapling directives found"
For Let’s Encrypt certificates, remove or comment out custom stapling directives such as SSLUseStapling unless you have a separate certificate authority that still publishes OCSP responder URLs. Apache’s mod_ssl documentation also requires a valid SSLStaplingCache whenever stapling is enabled.
sudo apache2ctl configtest
sudo systemctl reload apache2
Remove Apache from Ubuntu
Remove Apache if you are decommissioning the service or migrating to another web server. Choose between a standard removal that keeps configuration files and a purge that removes the package-managed Apache configuration.
Standard removal (keeps config files for reinstallation):
sudo apt remove apache2
Full purge (removes packages and configuration files):
sudo apt purge apache2 apache2-bin apache2-data apache2-utils
If you installed the Certbot Apache plugin and no longer manage Apache certificates on the server, remove that integration package too:
sudo apt purge python3-certbot-apache
Review orphaned dependencies before removing them. The dry run lets you confirm APT is not trying to remove unrelated desktop packages, old kernels, or tools from earlier maintenance:
sudo apt autoremove --dry-run
If the preview only lists Apache-related dependencies you no longer need, run the cleanup:
sudo apt autoremove
This removal does not delete website content in
/var/www/or custom virtual host configurations in/etc/apache2/sites-available/. Back up these directories before deleting them manually if you want a completely clean slate.
Verify no Apache packages remain installed:
dpkg -l 'apache2*' | grep '^ii' || echo "No Apache packages remain installed"
Expected output after removal:
No Apache packages remain installed
Conclusion
Apache is running on Ubuntu with firewall access, a working virtual host layout, and a Certbot-managed HTTPS path. From here, install ModSecurity with Apache on Ubuntu for request filtering, or use the Apache upgrade guide for Ubuntu when you need a newer upstream branch.


I’d like to know how to delete a file created on Apache.
To delete a file from your Apache web server, use the
rmcommand with the full path to the file. For example, if you createdtest.htmlin your document root at/var/www/example_domain/, remove it withsudo rm /var/www/example_domain/test.html. You needsudobecause Apache’s web directories are typically owned by root or the www-data user.To remove an entire directory and its contents, add the
-rflag:sudo rm -r /var/www/example_domain/. Always double-check the path before runningrmcommands since deletions are permanent. You can verify what’s in a directory first withls -la /var/www/example_domain/to confirm you’re targeting the right files.