Table of Contents
Introduction
The Apache HTTP Server, or Apache, is one of the most widely used web servers in the world. Since its release in 1995, it has remained popular because it is open source, reliable, and easy to customize. Even in 2025, Apache continues to be a dependable choice for hosting websites and applications on Linux servers such as Ubuntu.
Apache uses a modular design that allows you to enable only the features you need, such as SSL encryption, caching, or URL rewriting. On Ubuntu 24.04, Apache is included with the event MPM as the default processing module, offering improved performance for busy servers.
In this tutorial, you will install Apache on an Ubuntu server, configure the firewall, set up virtual hosts, enable HTTPS with Let's Encrypt, and learn how to manage and troubleshoot the service. This guide follows an HTTPS-first approach, helping you configure SSL early so your Apache server is secure and ready for production use.
Key Takeaways:
- Default Architecture: Ubuntu 24.04 installs Apache with the event MPM (Multi-Processing Module) by default, offering better performance for high-concurrency environments compared to the older prefork model.
- Firewall Integration: You must explicitly permit traffic through the firewall; using the 'Apache Full' profile in UFW automatically opens both port 80 (HTTP) and 443 (HTTPS) simultaneously.
- Virtual Host Strategy: To host multiple domains, avoid using the default
/var/www/htmlroot; instead, create dedicated directories for each domain and assign permissions to the non-root user.
- Configuration Management: Apache separates configuration files (
sites-available) from active sites (sites-enabled); usea2ensiteto enable a site (creating a symbolic link) anda2dissiteto disable it without deleting the file.
- HTTPS Automation: Security is mandatory, not optional. The
python3-certbot-apacheplugin automates the acquisition of Let's Encrypt SSL certificates and handles the configuration of HTTPS redirects.
- Systemd Timers: You do not need to manually renew SSL certificates; Certbot installs a systemd timer that checks for expiration twice daily and renews certificates automatically.
- Security Hardening: A production-ready server requires disabling directory indexing (to hide file lists) and implementing security headers like
X-Content-Type-OptionsandX-Frame-Optionsto prevent browser-based attacks.
- Troubleshooting Protocol: Always verify configuration syntax with
sudo apache2ctl configtestbefore restarting the service to prevent downtime, and checkjournalctl -u apache2if the service fails to start.
[info]
Simplify deploying applications to servers with an app platform. Deploy directly from GitHub in minutes.
Prerequisites
Before you begin this guide, you should have a regular, non-root user with sudo privileges configured on your server. Additionally, you will need to enable a basic firewall to block non-essential ports. You can learn how to configure a regular user account and set up a firewall for your server by following our Initial server setup guide for Ubuntu.
Once you have created a non-root user with sudo privileges, log in as that user to begin.
Note: This guide has been tested on Ubuntu 24.04 LTS, the latest stable release at the time of writing. The commands and steps will also work on other recent Ubuntu versions, such as 22.04 LTS. However, it is recommended to use the latest stable version to ensure compatibility, security, and access to updated software packages.
Installing Apache
Apache is included in Ubuntu's default package repositories, so you can install it using standard package management tools. Let's start by updating your server's local package index to make sure you're installing the latest available version.
sudo apt update
Once the update is complete, install the apache2 package:
sudo apt install apache2
When prompted, confirm the installation. The package manager will install Apache along with all required dependencies.
After installation, you can verify that Apache was installed correctly and check the version currently running on your system:
apache2 -v
You'll see output similar to this:
Server version: Apache/2.4.58 (Ubuntu)
Server built: 2025-08-11T11:10:09
Ubuntu may ship the prefork MPM by default if libapache2-mod-php is installed, because mod_php is not thread safe. To confirm which MPM (Multi-Processing Module) your system is using, run:
apache2ctl -M | grep mpm
Expected output:
mpm_event_module (shared)
That confirms that Apache is installed and configured with the default event-based processing model.
If you want to switch to the event MPM (recommended when using PHP-FPM instead of mod_php), run:
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo systemctl restart apache2
Note: mpm_event works best with PHP-FPM (php-fpm package). It does not work with mod_php because mod_php requires the prefork MPM.
[info]
Tip: You can extend Apache's functionality by installing additional modules. For example, use sudo apt install apache2-utils for common administrative tools or sudo apt install libapache2-mod-security2 to enable a web application firewall for added security.
Configuring the Firewall for Apache (HTTP and HTTPS)
Before testing Apache, you'll need to adjust your firewall to allow web traffic. If you followed the Initial Server Setup for Ubuntu guide, you should already have UFW (Uncomplicated Firewall) configured to restrict access to only essential services like SSH.
When Apache is installed, it automatically registers a few application profiles with UFW that define which ports to open for different traffic types. To view these profiles, run:
sudo ufw app list
You should see output similar to this:
Available applications:
Apache
Apache Full
Apache Secure
OpenSSH
Each profile allows different levels of access:
| Profile | Ports Opened | Description |
| —————– | ———— | ———————————- |
| Apache | 80/tcp | Allows unencrypted HTTP traffic |
| Apache Secure | 443/tcp | Allows encrypted HTTPS traffic |
| Apache Full | 80, 443/tcp | Allows both HTTP and HTTPS traffic |
Since most websites today use HTTPS by default, it's best to enable the Apache Full profile to allow both HTTP and HTTPS connections:
sudo ufw allow 'Apache Full'
Next, verify that the rule was added successfully:
sudo ufw status
You should see output similar to this:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Apache Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Apache Full (v6) ALLOW Anywhere (v6)
Note: If your servers are running on the cloud provider, you can optionally use the cloud provider Cloud Firewalls instead of the UFW firewall. We recommend using only one firewall at a time to avoid conflicting rules that may be difficult to debug.
Checking Apache Status
After installation, Apache starts automatically. Let's verify that it's running and serving web pages correctly.
Check Apache Service Status
Apache on Ubuntu is managed by systemd, which controls how services start, stop, and restart. To check whether Apache is active, run:
sudo systemctl status apache2
You should see output similar to this:
● apache2.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
Active: active (running) since Wed 2025-12-03 06:22:48 UTC; 2min 6s ago
Docs: https://httpd.apache.org/docs/2.4/
Main PID: 2085 (apache2)
Tasks: 55 (limit: 4656)
Memory: 5.3M (peak: 5.5M)
CPU: 57ms
CGroup: /system.slice/apache2.service
├─2085 /usr/sbin/apache2 -k start
├─2087 /usr/sbin/apache2 -k start
└─2088 /usr/sbin/apache2 -k start
If you see Active: active (running), Apache is up and running.
If Apache isn't active, you can start it manually with:
sudo systemctl start apache2
Test Apache Using Your Server's Public IP
You can confirm Apache is serving web content by visiting your server's public IP address.
First, find your server's IP address:
hostname -I
This command will return one or more IP addresses. You can also get your public IPv4 address using:
curl -4 icanhazip.com
Copy the IPv4 address and enter it in your browser's address bar:
http://your_server_ip
For example:
http://203.0.113.10
If Apache is working correctly, you'll see the default Apache welcome page, which confirms your web server is running and serving requests from /var/www/html.
Access Apache via Hostname (Optional)
If you've already configured a domain name for your server, you can also test access using your domain:
http://your_domain
Make sure your DNS records are correctly pointed to your server's public IP. DNS changes can take a few minutes to propagate depending on your registrar.
IPv6 Access
Most modern Ubuntu servers, including those on the cloud provider, come with IPv6 enabled by default. To check whether Apache is listening on both IPv4 and IPv6 addresses, run:
sudo ss -tuln | grep :80
You should see both of these lines if IPv6 is enabled:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 [::]:80 [::]:*
To test locally over IPv6, open this address in your browser:
http://[::1]
Or, if your server has a public IPv6 address, use that address in brackets:
http://[your_ipv6_address]
Tip: If you're testing on a remote cloud instance, make sure your provider's networking setup supports both IPv4 and IPv6. On the cloud provider, you can verify this under Networking -> IP Addresses in your control panel.
Managing the Apache Process
Now that Apache is installed and running, it's helpful to know how to control the service. Ubuntu uses systemd to manage background services, including Apache. This means you can use the systemctl command to start, stop, restart, and check the status of the web server.
Starting, Stopping, and Restarting Apache
To stop the web server, run:
sudo systemctl stop apache2
To start Apache again, run:
sudo systemctl start apache2
If you've made configuration changes and need to apply them, you can restart the service:
sudo systemctl restart apache2
Restarting stops and then restarts Apache, which briefly interrupts any active connections. For configuration updates that don't require a full restart, you can instead reload the service to apply changes gracefully:
sudo systemctl reload apache2
Reloading tells Apache to re-read its configuration files without closing existing connections. This is useful when you're updating virtual hosts, enabling modules, or changing log settings.
Enable or Disable Apache at Boot
By default, Apache is set to start automatically when your system boots. You can confirm this behavior by checking its enablement status:
sudo systemctl is-enabled apache2
To disable Apache from starting automatically on boot:
sudo systemctl disable apache2
To enable it again:
sudo systemctl enable apache2
This control is useful for testing environments or servers where you only want Apache running on demand.
Checking Apache's Status
At any time, you can view the current status of the Apache service:
sudo systemctl status apache2
This command displays whether the service is running, its uptime, and recent log entries. You'll also see the Main PID, which identifies the process Apache is using to serve requests.
For a simple confirmation without full log output, you can use:
sudo systemctl is-active apache2
If it returns active, Apache is running as expected.
Viewing Apache Logs
Apache keeps detailed logs that can help you monitor performance and diagnose issues. These logs are stored in /var/log/apache2/ by default:
- Access logs (
/var/log/apache2/access.log): records every request to your server.
- Error logs (
/var/log/apache2/error.log): records warnings, errors, and startup messages.
To view the most recent entries in the error log, use:
sudo tail -f /var/log/apache2/error.log
For a broader look at Apache's activity through systemd's journal, use the modern log viewer:
sudo journalctl -u apache2 --no-pager
You can also view only the latest events:
sudo journalctl -u apache2 -n 20
And to follow logs in real time:
sudo journalctl -u apache2 -f
Using journalctl is often the best way to view live logs and service messages in modern Ubuntu systems, since it combines traditional logging with system-level information.
Tip: For production servers, consider setting up log rotation and retention policies using logrotate, which is installed by default on Ubuntu. This prevents log files from growing too large and ensures older logs are archived automatically.
Setting Up Virtual Hosts
When using the Apache web server, you can configure virtual hosts (similar to server blocks in Nginx) to define separate configurations for each website hosted on the same server. Virtual hosts make it easy to serve different domains or subdomains from a single machine, each with its own document root, log files, and configuration options.
In this example, we'll set up a domain called example.com, but you should replace this with your actual domain name. If you're setting up a new domain with the cloud provider, refer to our Networking Documentation for steps on creating DNS records that point to your server.
Creating the Web Root Directory
Apache on Ubuntu includes one default site that serves content from /var/www/html. While this works for a single website, it's better to create a separate directory for each domain you host. This structure keeps files organized and prevents conflicts when managing multiple sites.
Create a new directory for your domain under /var/www:
sudo mkdir /var/www/example.com
Assign ownership of the directory to your current user to make it easier to edit web files:
sudo chown -R $USER:$USER /var/www/example.com
By default, Ubuntu sets a umask value that assigns secure permissions, but you can verify the correct settings using:
sudo chmod -R 755 /var/www/example.com
This gives the owner full read/write/execute access, while allowing others to read and execute files, the standard for web content.
Now, let's create a simple test page that will confirm your virtual host works correctly:
sudo nano /var/www/example.com/index.html
Add the following HTML content:
<html>
<head>
<title>Welcome to example.com!</title>
</head>
<body>
<h1>Success! The example.com virtual host is working!</h1>
<p>This page is being served from /var/www/example.com on Ubuntu 24.04.</p>
</body>
</html>
Save and close the file when finished.
Creating the HTTP Virtual Host
Apache's virtual host configuration files are stored in the /etc/apache2/sites-available/ directory. These files define how Apache should respond to incoming HTTP requests for a given domain.
Let's create a new configuration file for your domain:
sudo nano /etc/apache2/sites-available/example.com.conf
Insert the following configuration block:
<VirtualHost *:80>
ServerAdmin webmaster@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>
Here's what each directive does:
- ServerAdmin: The email address Apache should display on error pages.
- ServerName: The main domain name for this virtual host.
- ServerAlias: Additional domain names that should point to the same site (for example,
www.example.com).
- DocumentRoot: The directory where your site's files are stored.
- ErrorLog and CustomLog: Define separate log files for tracking errors and access requests.
Save and close the file. This configuration will handle all requests to http://example.com.
Enabling and Testing Your Sites
Now that your configuration files are ready, you can enable your site using the a2ensite command:
sudo a2ensite example.com.conf
To prevent the default site from serving unintended traffic, disable it:
sudo a2dissite 000-default.conf
Before applying any changes, always test your Apache configuration for syntax errors:
sudo apache2ctl configtest
You should see this output:
Syntax OK
If there are no syntax errors, reload Apache to apply the configuration changes:
sudo systemctl reload apache2
This command gracefully reloads the service, applying new settings without disconnecting existing users.
You can confirm that both virtual hosts are active by listing the enabled sites:
sudo apache2ctl -S
You'll see an output that includes your domain and the associated configuration file paths.
Now, open your browser and visit your site:
http://example.com
If everything is set up correctly, you should see the sample page you created earlier.
Installing TLS/SSL with Let's Encrypt
Using HTTPS has become the standard for all modern websites, not only to secure user data but also to improve search rankings and user trust. The easiest way to obtain and manage free SSL/TLS certificates is through Let's Encrypt, a certificate authority that provides automated, no-cost certificates.
Let's Encrypt works together with Certbot, a lightweight command-line tool that handles certificate creation, installation, and renewal automatically.
In this section, you'll install Certbot, generate a certificate for your domain, and verify that automatic renewal is configured correctly.
Installing Certbot and the Apache Plugin
Certbot is included in Ubuntu's default repositories, along with a plugin that integrates directly with Apache.
Update your package index and install both packages:
sudo apt update
sudo apt install certbot python3-certbot-apache
- The certbot package handles certificate requests and renewals.
- The python3-certbot-apache plugin automates the Apache configuration process for HTTPS.
Once installed, you can verify Certbot's version with:
certbot --version
Generating a Let's Encrypt Certificate
With Certbot installed, you can request and install a certificate for your domain in a single step. Replace example.com and www.example.com with your actual domain names:
sudo certbot --apache -d example.com -d www.example.com
Certbot will:
- Communicate with Let's Encrypt's servers to verify domain ownership.
- Generate a valid SSL/TLS certificate.
- Automatically update your Apache virtual host to use HTTPS.
- Reload Apache to apply the changes.
You'll be asked to provide an email address for renewal notices and agree to the Let's Encrypt Terms of Service. When prompted, you can also choose whether to redirect HTTP traffic to HTTPS. Selecting "Redirect" is recommended, as it enforces secure connections for all visitors.
After the setup completes, Certbot will display a message confirming that the certificate was successfully installed.
You can verify your certificate's expiration date with:
sudo certbot certificates
The output should list your domain name and indicate that your certificate is valid for 90 days.
Automatic Certificate Renewal
Let's Encrypt certificates are valid for 90 days, but Certbot includes a built-in systemd timer that automatically renews them before they expire.
You can confirm that the renewal timer is active with:
sudo systemctl status certbot.timer
You should see output similar to this:
● certbot.timer - Run certbot twice daily
Loaded: loaded (/lib/systemd/system/certbot.timer; enabled)
Active: active (waiting) since Tue 2025-12-02 15:00:00 UTC; 1h ago
Trigger: Wed 2025-12-03 00:00:00 UTC; 8h left
This means that Certbot will automatically check for expiring certificates twice per day and renew them if necessary.
Note: If you installed Certbot via snap/distro packaging, the mechanism may be a systemd timer or a cron job. You can check this with systemctl list-timers.
To manually test the renewal process without making changes, use:
sudo certbot renew --dry-run
If you see "Congratulations! Your certificate and chain have been saved successfully.", automatic renewal is working as expected.
Testing Your HTTPS Configuration
After your certificate is installed, open your site in a web browser and verify that it loads securely:
https://example.com
You should see the padlock icon in the browser's address bar, indicating that HTTPS is active and the connection is encrypted.
You can also verify the configuration using the command line with:
curl -I https://example.com
A valid response should include:
HTTP/2 200
content-type: text/html
strict-transport-security: max-age=31536000; includeSubDomains
If you see this response, your site is correctly serving HTTPS traffic.
Getting Familiar with Important Apache Files and Directories
Now that Apache is installed, configured, and serving your site, it's helpful to understand where key files and directories are located. Knowing how Apache's configuration is organized will make it easier to manage multiple sites, enable modules, and troubleshoot issues later.
/var/www/ — Web Root Directories
This is where your website content lives. By default, Apache serves files from /var/www/html, which contains the default Apache landing page you saw after installation.
When hosting multiple sites, it's common to create a dedicated directory for each one, such as:
/var/www/example.com
/var/www/myblog.com
/var/www/api.example.com
Each virtual host you configure can point to its own directory inside /var/www. This structure keeps your projects organized and allows you to apply permissions or ownership separately per site.
/etc/apache2/ — Apache Configuration Directory
This directory contains all of Apache's configuration files. Most of your administrative work, including enabling sites, changing ports, or managing modules, happens here.
The key files and subdirectories include:
| Location | Description |
| —————————- | ————————————————————————————————————————————————————————————————— |
/etc/apache2/apache2.conf |
The main configuration file. It loads the other configuration files and sets global options that affect the entire server. |
/etc/apache2/ports.conf |
Defines which ports Apache listens on. By default, Apache listens on port 80 (HTTP) and port 443 (HTTPS) when SSL is enabled. |
/etc/apache2/envvars |
Contains environment variable settings used by Apache, such as the user and group under which it runs (www-data by default). |
/etc/apache2/conf-enabled/ |
Contains symbolic links to active configuration fragments found in /etc/apache2/conf-available/. Used for settings that apply to all sites (for example, security headers or timeout directives). |
sites-available/ and sites-enabled/ — Virtual Host Configurations
Apache separates virtual host configurations into two directories:
/etc/apache2/sites-available/contains all virtual host configuration files. These files define how Apache serves each site, including the document root, domain names, and logging directives.
/etc/apache2/sites-enabled/contains symbolic links to the active site configurations found insites-available/.
To activate a site, use:
sudo a2ensite example.com.conf
To deactivate it:
sudo a2dissite example.com.conf
This approach makes it easy to manage multiple websites without editing global configuration files. You can quickly enable or disable sites as needed, and Apache will only load configurations that are linked in sites-enabled/.
mods-available/ and mods-enabled/ — Apache Modules
Apache's functionality is modular, meaning most features, such as SSL, rewrite rules, or compression, are implemented as modules that can be loaded dynamically.
/etc/apache2/mods-available/contains configuration (.conf) and load (.load) files for all available modules.
/etc/apache2/mods-enabled/contains symbolic links to the modules that are currently enabled.
You can enable or disable modules using these commands:
sudo a2enmod module_name
sudo a2dismod module_name
For example, to enable the rewrite and ssl modules (common for HTTPS sites):
sudo a2enmod rewrite ssl
After enabling or disabling modules, reload Apache to apply the changes:
sudo systemctl reload apache2
conf-available/ and conf-enabled/ — Configuration Fragments
These directories are similar to the site directories but are used for global configuration snippets that don't belong to a specific virtual host.
For example, a configuration file that sets default security headers or MIME types might live in /etc/apache2/conf-available/, and when enabled, a symbolic link is created in /etc/apache2/conf-enabled/.
You can enable or disable these configuration fragments with:
sudo a2enconf config_name
sudo a2disconf config_name
Like site configurations, these fragments are only active when linked in conf-enabled/.
/var/log/apache2/ — Log Files
Apache logs nearly every event, from client requests to errors, in the /var/log/apache2/ directory. Monitoring these logs is one of the best ways to understand how your server is performing and to troubleshoot problems.
The two most common log files are:
| File | Description |
| —————————– | ——————————————————————————————————————- |
/var/log/apache2/access.log |
Records every request to the web server, including the client IP, requested URL, status code, and user agent. |
/var/log/apache2/error.log |
Captures startup messages, warnings, and errors. Useful for diagnosing configuration issues or site-level problems. |
You can view the most recent log entries with:
sudo tail -f /var/log/apache2/access.log
or
sudo tail -f /var/log/apache2/error.log
For a broader view across all Apache logs, you can use:
sudo journalctl -u apache2 --no-pager
This command shows recent service messages collected by systemd, combining traditional logs with service-level events.
Tip: On high-traffic sites, log files can grow quickly. Ubuntu includes logrotate, which automatically compresses and rotates Apache logs to prevent them from filling up disk space. You can view its configuration at /etc/logrotate.d/apache2.
Security Best Practices
Once Apache is installed and serving your websites, the next step is securing your web server. Even a correctly configured Apache installation can expose unnecessary information or become vulnerable if not hardened properly. The following best practices will help protect your system against common attacks, reduce information exposure, and keep your web environment stable and up to date.
Disable Directory Listing
By default, Apache may display the contents of a directory if it does not contain an index file. This can unintentionally expose sensitive information, such as backup files, configuration scripts, or version numbers.
To disable directory listing, open your site's configuration file:
sudo nano /etc/apache2/sites-available/example.com.conf
Inside the <Directory> block or the virtual host configuration, ensure the Options directive does not include Indexes. For example:
<Directory /var/www/example.com>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Save the file and reload Apache to apply your changes:
sudo systemctl reload apache2
Now, if a directory does not contain an index.html file, Apache will return a 403 Forbidden error instead of listing its contents.
Restrict File Permissions and Ownership
File and directory permissions should always follow the principle of least privilege.
- The owner of each web root should be the user who manages the files.
- The group should typically remain
www-data, which is the default user that Apache runs as.
You can set these permissions with the following commands:
sudo chown -R $USER:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
These commands ensure that directories are readable and executable by everyone but writable only by the owner, while files are readable by everyone and writable only by the owner.
Avoid granting 777 permissions, as they allow any user on the system to modify web files.
Enable Security Headers
Security headers help protect browsers from common web vulnerabilities like cross-site scripting (XSS), clickjacking, and content-type sniffing.
If you have not already done so, enable the headers module:
sudo a2enmod headers
Then, open your site's virtual host configuration file:
sudo nano /etc/apache2/sites-available/example.com.conf
Inside the <VirtualHost> block, add the following headers:
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"
You can also apply a basic Content Security Policy (CSP) to control which resources the browser can load:
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self';"
This policy allows only local scripts and styles to load from the same domain.
Save your changes and reload Apache:
sudo systemctl reload apache2
To confirm that the headers are active, you can test your site with curl:
curl -I https://example.com
Look for the headers in the response. You can also use securityheaders.com to analyze your configuration.
Harden SSL and TLS Configuration
Apache 2.4.58 on Ubuntu 24.04 supports TLS 1.3 by default, provided your OpenSSL version is 1.1.1 or later (check with openssl version). To ensure strong encryption and compatibility, open the SSL configuration file:
sudo nano /etc/apache2/mods-available/ssl.conf
Verify or update the following settings:
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder on
These settings disable older, insecure protocols and ciphers.
After saving the file, reload Apache:
sudo systemctl reload apache2
For stricter or more compatible configurations (Modern or Old profiles), you can generate templates at: SSL Configuration Generator. You can also test your site's SSL configuration using Qualys SSL Labs to verify that it scores at least an "A" rating.
Disable Unused Apache Modules
Every enabled module increases Apache's attack surface. To reduce potential vulnerabilities, disable any modules that are not required for your site.
List enabled modules with:
apache2ctl -M
If you see a module you are not using, disable it with:
sudo a2dismod module_name
For example, if your site does not use CGI scripts:
sudo a2dismod cgi
After disabling modules, reload Apache:
sudo systemctl reload apache2
Keep essential modules such as ssl, rewrite, headers, and mpm_event active, as they are commonly used for secure, high-performance websites.
Keep the System Updated Automatically
Keeping your server updated is one of the most effective ways to prevent vulnerabilities. Security patches are released regularly for both Ubuntu and Apache. To ensure your server always receives updates, enable unattended-upgrades, which installs security updates automatically.
Install the package:
sudo apt install unattended-upgrades
Then enable automatic updates:
sudo dpkg-reconfigure --priority=low unattended-upgrades
By default, the service runs daily and applies available security updates silently. You can check the status of the timer with:
systemctl status apt-daily-upgrade.timer
Logs are stored in /var/log/unattended-upgrades/.
To apply updates manually at any time, run:
sudo apt update && sudo apt upgrade
Additional Recommendations
To further improve security and server reliability:
- Use strong passwords or SSH keys for administrative access.
- Restrict SSH access to known IP addresses using UFW or cloud firewalls.
- Set up fail2ban to automatically block repeated failed login attempts.
- Regularly back up your
/etc/apache2/and/var/www/directories.
- Monitor logs for unusual activity using tools like
goaccessorjournalctl.
Basic Troubleshooting
Even a correctly configured Apache server can occasionally fail to start, reload, or serve web pages. Common issues usually involve syntax errors, missing permissions, or blocked ports.
1. Check Apache Service Logs
When Apache does not start or reload properly, the first place to look is the service log. Apache integrates with systemd, so logs are managed by the journalctl command.
To view recent log entries:
sudo journalctl -u apache2 --no-pager
This displays Apache-related messages, including startup logs, configuration warnings, and module errors.
If you want to see live log updates while restarting or reloading Apache, use:
sudo journalctl -u apache2 -f
The log output can reveal valuable details such as:
AH00526: Syntax error on line 14 of /etc/apache2/sites-enabled/example.com.conf:
Invalid command 'Redirectt'
or
(13)Permission denied: AH00072: make_sock: could not bind to address [::]:80
In these cases:
- The first indicates a typo or syntax issue in a configuration file.
- The second means Apache cannot bind to port 80, usually because another process is using it or UFW or a cloud firewall is blocking it.
Checking logs is often the quickest way to pinpoint why Apache isn't starting or responding.
2. Test Apache Configuration Syntax
A common mistake is reloading Apache after editing a configuration file without testing it first. Apache includes a built-in syntax checker that scans all configuration files for errors.
Run the following:
sudo apache2ctl configtest
If your configuration is valid, you'll see:
Syntax OK
If not, the command will show the file and line number containing the issue. For example:
AH00526: Syntax error on line 25 of /etc/apache2/sites-enabled/example.com.conf:
Invalid command 'ServerNme', perhaps misspelled or defined by a module not included in the server configuration
This tells you exactly where the problem is located. Once you fix the issue, test again until the syntax passes.
Finally, reload Apache to apply the working configuration:
sudo systemctl reload apache2
Tip: Always run configtest before reloading Apache, especially on production servers. It prevents accidental downtime caused by broken configurations.
3. Check Listening Ports and Conflicting Services
If your Apache service starts but your site doesn't load, it may not be listening on the expected ports (80 for HTTP, 443 for HTTPS), or another application could be using those ports.
Check which ports Apache is currently listening on:
sudo ss -tuln | grep apache
You should see output similar to:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("apache2",pid=1534,fd=4))
LISTEN 0 511 [::]:443 [::]:* users:(("apache2",pid=1535,fd=6))
This confirms Apache is listening on both HTTP and HTTPS.
If no entries appear, check that your virtual hosts and SSL module are enabled:
sudo a2enmod ssl
sudo a2ensite example.com.conf
sudo a2ensite example.com-le-ssl.conf
sudo systemctl reload apache2
If another process is using port 80 or 443, identify it:
sudo ss -tulpn | grep ':80\|:443'
This will show which process ID (PID) and program name are bound to the ports. For example:
nginx 1920 root 6u IPv4 37221 0t0 TCP *:80 (LISTEN)
4. Fix Common Permission and Ownership Errors
If Apache starts correctly but returns a "403 Forbidden" error or fails to load your site, it often means that file permissions or ownership are incorrect. Apache must be able to read the files under your site's web root, and they must be owned by the right user and group.
To fix ownership and permissions, run:
sudo chown -R $USER:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
These commands set:
- The current user as the owner (so you can edit files easily).
- The
www-datagroup for Apache.
- Secure permissions for files and directories.
You can confirm the permissions using:
ls -ld /var/www/example.com
The output should look like this:
drwxr-xr-x 3 user www-data 4096 Jan 10 12:34 /var/www/example.com
If your site uses uploads or caching (like WordPress), you may need to give Apache write access to specific directories:
sudo chmod 775 /var/www/example.com/wp-content/uploads
Be cautious not to apply global write access, as it can open serious security risks.
5. Check DNS Configuration and Propagation
If your site works when accessed via its IP address but not through the domain name, it is usually a DNS or propagation issue.
First, check that your domain points to the correct server IP:
dig example.com +short
Compare the result with your server's public IP address:
curl -4 icanhazip.com
If they don't match, update your DNS records at your registrar or DNS provider.
You can also check global DNS propagation using a tool such as whatsmydns.net.
If you recently updated DNS records, remember that propagation can take several hours depending on the TTL (time-to-live) values configured for your domain.
If you're hosting your DNS on the cloud provider, make sure your A (IPv4) and AAAA (IPv6) records are correctly configured in the Networking -> Domains section of the control panel.
6. Verify Cloud and Local Firewall Rules
Sometimes Apache runs correctly but is inaccessible from the internet because traffic is being blocked by a firewall. Ubuntu uses UFW by default.
Check your firewall status:
sudo ufw status
You should see entries like this:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Apache Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Apache Full (v6) ALLOW Anywhere (v6)
If the Apache Full profile is missing, enable it:
sudo ufw allow 'Apache Full'
Then reload UFW:
sudo ufw reload
If you're running Apache on a cloud provider such as the cloud provider, confirm that the cloud firewall also allows inbound connections on ports 80 and 443.
For example, in the the cloud provider Control Panel:
- Go to Networking -> Firewalls.
- Select your Droplet's firewall.
- Ensure inbound rules for HTTP (80) and HTTPS (443) are both allowed.
If you're using a load balancer or CDN, confirm that it is properly forwarding requests to your Droplet's IP address and ports.
7. Identify and Fix Broken Virtual Host Configurations
Apache uses virtual hosts to map domain names to specific directories and configurations. A broken or conflicting virtual host file is one of the most common problems beginners face.
To list all active virtual hosts, use:
sudo apache2ctl -S
This command shows each domain's configuration file and port. Look for:
- The correct
ServerName(must match your domain).
- A valid
DocumentRootpath (should point to your web directory).
- No duplicate entries for the same port.
If you see this warning:
AH00558: apache2: Could not reliably determine the server's fully qualified domain name
Add a global ServerName directive to fix it:
echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/servername.conf
sudo a2enconf servername.conf
sudo systemctl reload apache2
If one of your site configurations is broken and prevents Apache from starting, disable it temporarily:
sudo a2dissite example.com.conf
sudo systemctl reload apache2
Then review the file in /etc/apache2/sites-available/ for issues such as:
- Missing
</VirtualHost>closing tags
- Incorrect indentation or misplaced directives
- Wrong log or document paths
Once fixed, re-enable the site:
sudo a2ensite example.com.conf
sudo systemctl reload apache2
Your site should now load correctly.
Tip: When troubleshooting Apache, isolate each issue step-by-step. Start by confirming that the service is running, then check the configuration syntax, permissions, ports, and DNS. Apache's error logs (journalctl and /var/log/apache2/error.log) almost always contain the clues you need.
FAQs
1. How do I install Apache on Ubuntu?
You can install Apache from Ubuntu's default repositories. Update your package index and install Apache with:
sudo apt update
sudo apt install apache2
Once installed, Apache starts automatically. You can verify it with:
sudo systemctl status apache2
2. How do I start, stop, or restart Apache?
Use the systemctl command to control the Apache service:
sudo systemctl start apache2
sudo systemctl stop apache2
sudo systemctl restart apache2
To reload configuration changes without interrupting active connections, use:
sudo systemctl reload apache2
You can also check if it starts automatically at boot using:
sudo systemctl is-enabled apache2
3. How do I configure virtual hosts in Apache?
Virtual hosts let you host multiple sites on one server. Create a new configuration file in /etc/apache2/sites-available/:
sudo nano /etc/apache2/sites-available/example.com.conf
Add a basic configuration block:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
</VirtualHost>
Save the file, enable the site, and reload Apache:
sudo a2ensite example.com.conf
sudo systemctl reload apache2
4. How do I allow HTTP and HTTPS traffic through the Ubuntu firewall?
If you're using UFW, list the available application profiles with:
sudo ufw app list
Then allow full Apache access (both HTTP and HTTPS):
sudo ufw allow 'Apache Full'
Check your firewall status to confirm:
sudo ufw status
5. How can I test if Apache is working correctly?
Open your browser and visit your server's public IP address:
http://your_server_ip
You should see the default Apache welcome page. You can also check the service status with:
sudo systemctl status apache2
If the page does not load, review the firewall settings and confirm that Apache is active.
6. Where is the default web root directory in Ubuntu?
By default, Apache serves content from /var/www/html.
You can replace or modify the index.html file in this directory to change what appears on your site's home page. When hosting multiple domains, you can create additional directories such as /var/www/example.com.
7. How do I troubleshoot Apache not starting?
Start by checking for syntax errors:
sudo apache2ctl configtest
If you see anything other than "Syntax OK," fix the listed issue. Then review service logs for errors:
sudo journalctl -u apache2 --no-pager
If ports 80 or 443 are already in use, identify the conflicting service with:
sudo ss -tulpn | grep ':80\|:443'
Permission issues can also prevent Apache from reading files in /var/www/. Make sure your user and group ownership are correct and that directories are readable.
8. How do I enable SSL on Apache in Ubuntu?
Enable the SSL and headers modules first:
sudo a2enmod ssl
sudo a2enmod headers
You can then install Let's Encrypt to get a free SSL certificate:
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com
Certbot will automatically configure HTTPS and handle renewals. Once installed, you can test renewal with:
sudo certbot renew --dry-run
Summary
In this tutorial, you installed and configured the Apache web server on an Ubuntu server. You verified that Apache was running, allowed HTTP and HTTPS traffic through the firewall, and created virtual hosts for both protocols. You secured your site with Let's Encrypt SSL certificates, applied key security settings, and learned how to manage Apache modules, logs, and configurations.
Your server is now fully configured and ready to host production websites. To continue exploring, check out the following articles: