By Erin Glass and Manikandan Kurup

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:
/var/www/html root; instead, create dedicated directories for each domain and assign permissions to the non-root user.sites-available) from active sites (sites-enabled); use a2ensite to enable a site (creating a symbolic link) and a2dissite to disable it without deleting the file.python3-certbot-apache plugin automates the acquisition of Let’s Encrypt SSL certificates and handles the configuration of HTTPS redirects.X-Content-Type-Options and X-Frame-Options to prevent browser-based attacks.sudo apache2ctl configtest before restarting the service to prevent downtime, and check journalctl -u apache2 if the service fails to start.Simplify deploying applications to servers with DigitalOcean App Platform. Deploy directly from GitHub in minutes.
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.
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.
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.
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)
This confirms that Apache is now allowed through the firewall for both IPv4 and IPv6 traffic.
Note: If your servers are running on DigitalOcean, you can optionally use DigitalOcean 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.
After installation, Apache starts automatically. Let’s verify that it’s running and serving web pages correctly.
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
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.
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.
Most modern Ubuntu servers, including those on DigitalOcean, 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 DigitalOcean, you can verify this under Networking -> IP Addresses in your control panel.
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.
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.
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.
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.
Apache keeps detailed logs that can help you monitor performance and diagnose issues. These logs are stored in /var/log/apache2/ by default:
/var/log/apache2/access.log): records every request to your server./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.
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 DigitalOcean, refer to our Networking Documentation for steps on creating DNS records that point to your server.
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.
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:
www.example.com).Save and close the file. This configuration will handle all requests to http://example.com.
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.
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.
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
Once installed, you can verify Certbot’s version with:
- certbot --version
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:
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.
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.
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.
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 DirectoriesThis 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 DirectoryThis 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 ConfigurationsApache 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 in sites-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 ModulesApache’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 FragmentsThese 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 FilesApache 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.
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.
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.
File and directory permissions should always follow the principle of least privilege.
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.
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.
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.
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.
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
To further improve security and server reliability:
/etc/apache2/ and /var/www/ directories.goaccess or journalctl.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.
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:
Checking logs is often the quickest way to pinpoint why Apache isn’t starting or responding.
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.
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)
If another web server like Nginx or a development process (for example, Node.js) is using the same port, you can either stop that service or reconfigure one of them to use a different port.
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:
www-data group for Apache.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.
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 DigitalOcean, make sure your A (IPv4) and AAAA (IPv6) records are correctly configured in the Networking -> Domains section of the control panel.
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 DigitalOcean, confirm that the cloud firewall also allows inbound connections on ports 80 and 443.
For example, in the DigitalOcean Control Panel:
If you’re using a load balancer or CDN, confirm that it is properly forwarding requests to your Droplet’s IP address and ports.
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:
ServerName (must match your domain).DocumentRoot path (should point to your web directory).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:
</VirtualHost> closing tagsOnce 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.
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
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
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
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
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.
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.
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.
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
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:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Open source advocate and lover of education, culture, and community.
With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Thank you very much for your easy instructions on installing Apache2 server. it still proves that it takes a woman to get things right. I just switched over from centos 7 to the ubuntu 20.04 server due to vestacp problems and no kind of support for why my add on domains would not work but yet the main admin one would. still baffels me, but i’m a glutten for punishment so thought i would try it out on ubuntu 20.04. any way thanks for the excellent info and help the enternet needs more like you.
Hello!
Thanks for sharing this information. Here is a question
I have a website(example.com) already running in /var/www/html can i add another website (newdomain.com) by creating directory /var/www/newdomain.com and use it. Without changing the location of example.com as you know it will take time to transfer from /var/www/html to /var/www/example.com
Yes, i’m using Apache Web Server on Ubuntu 20.04 (LTS) x64
Please reply me ASAP
Now it’s easy, you can use easy-apache to set up everything for you, all you have to do is copy-paste below lines into your terminal, and enter your domain name when asked, it will also install SSL if you want
sudo add-apt-repository ppa:realpvn/easy-apache
sudo apt-get update
sudo apt-get install easy-apache
#to install Apache server
easy-apache -a
#to install SSL
easy-apache -s
#full setup, Apache and SSL
easy-apache -f
A very nice piece of Information. Nicely written. Thanks a lot. I was wondering for basic apache server setup. I will remember your name as my teacher. GBY.
Issue: Error AH00558: Could not reliably determine the server’s fully qualified domain name
Solution: Add a line containing ServerName 127.0.0.1 to the end of the file:
sudo nano /etc/apache2/apache2.conf
Restart apache2
sudo systemctl restart apache2
=========================================================
Issue: can access the website via IP but not Domain Solution:
sudo nano /etc/hosts
add this code:
127.0.0.1 www.YOURDOMAIN.com
Restart apache2
sudo systemctl restart apache2
Do we need to add /public_html to the directory if we want to add more than one virtual host site? If I add one using the above method it works fine but if I add a second one the second one won’t show up.
Thanks Erin!
Just a comment, that could help people. When following your tutorial after doing the configtest of apache I found ERROR AH00558. Since I was starting from scratch from a Desktop 20.04 Ubuntu distribution, I assume that it will happen to anybody doing the same thing.
The fix is easy, just add to your tutorial that if they find this error all they need to do is to add this line to their /etc/apache2/apache2.conf file using sudo nano /etc/apache2/apache2.conf, going to the end of the file and adding it, then <Ctrl>S, followed by <Ctrl>X
ServerName 127.0.0.1
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.