$linuxjunkies
>

How to Install the Apache Web Server

Install Apache on Linux, enable modules, configure named virtual hosts, use .htaccess, and verify your setup — covering Debian, Ubuntu, Fedora, RHEL, and Arch.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • A Linux server with sudo or root access
  • A domain name or local hostname pointed at the server's IP address (for virtual host testing)
  • Basic familiarity with a terminal text editor such as nano or vim

Apache HTTP Server remains one of the most widely deployed web servers on the internet. Its module system, per-directory configuration via .htaccess, and flexible virtual host model make it a solid choice for hosting anything from a single static site to dozens of applications on one machine. This guide walks through a full installation: getting Apache running, enabling useful modules, configuring a named virtual host, and locking things down enough to serve a real site.

Installation

Debian and Ubuntu

Apache's package is called apache2 on Debian-family systems.

sudo apt update && sudo apt install apache2 -y

Fedora and RHEL / Rocky Linux

On Red Hat-family systems the package is httpd.

sudo dnf install httpd -y

Arch Linux

sudo pacman -S apache

Starting and Enabling the Service

Apache is managed by systemd on all modern distributions. Enable it so it starts at boot, then start it immediately.

Debian / Ubuntu

The package enables the service automatically; confirm it is running:

sudo systemctl enable --now apache2
sudo systemctl status apache2

Fedora / RHEL / Rocky / Arch

sudo systemctl enable --now httpd
sudo systemctl status httpd

You should see Active: active (running) in the output. Visit http://localhost in a browser or run curl -I http://localhost to confirm Apache returns a 200 response.

Opening the Firewall

If a firewall is active — and it should be — allow HTTP and HTTPS traffic before going further.

ufw (Debian / Ubuntu)

sudo ufw allow 'Apache Full'
sudo ufw status

firewalld (Fedora / RHEL / Rocky)

sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload

nftables (Arch or manual setup)

sudo nft add rule inet filter input tcp dport { 80, 443 } accept

Make this persistent by saving your ruleset to /etc/nftables.conf and ensuring nftables.service is enabled.

Directory Layout

Understanding where files live saves significant debugging time later.

  • /etc/apache2/ (Debian/Ubuntu) or /etc/httpd/ (RHEL family) — main configuration tree
  • sites-available/ and sites-enabled/ — virtual host definitions (Debian/Ubuntu only; RHEL family uses conf.d/)
  • /var/www/html/ — default document root
  • /var/log/apache2/ or /var/log/httpd/ — access and error logs

Enabling Modules

Apache's power comes from its module system. On Debian/Ubuntu, a2enmod and a2dismod manage modules by creating or removing symlinks under mods-enabled/. On RHEL-family systems, modules are loaded via LoadModule directives in /etc/httpd/conf.modules.d/.

Commonly needed modules

  • rewrite — URL rewriting; required by most CMS software
  • ssl — HTTPS support
  • headers — set and modify HTTP response headers
  • deflategzip compression

Enable on Debian / Ubuntu

sudo a2enmod rewrite ssl headers deflate
sudo systemctl restart apache2

Verify a module is loaded (any distro)

apache2ctl -M 2>/dev/null | grep rewrite
# or on RHEL family:
httpd -M 2>/dev/null | grep rewrite

Expected output (will vary): rewrite_module (shared)

On RHEL-family systems, mod_rewrite and mod_ssl are installed but may need their LoadModule line uncommented in /etc/httpd/conf.modules.d/00-base.conf.

Configuring a Virtual Host

A virtual host lets Apache serve different content depending on the requested hostname. This is how you host example.com and blog.example.com from a single IP.

Create the document root and a test page

sudo mkdir -p /var/www/example.com/public_html
echo '<h1>It works</h1>' | sudo tee /var/www/example.com/public_html/index.html
sudo chown -R www-data:www-data /var/www/example.com   # Debian/Ubuntu
# sudo chown -R apache:apache /var/www/example.com     # RHEL family / Arch

Write the virtual host file (Debian / Ubuntu)

sudo nano /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
    ServerName   example.com
    ServerAlias  www.example.com
    DocumentRoot /var/www/example.com/public_html
    ErrorLog     ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog    ${APACHE_LOG_DIR}/example.com-access.log combined

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

Enable the site and reload

sudo a2ensite example.com.conf
sudo a2dissite 000-default.conf   # optional: disable the default site
sudo systemctl reload apache2

Virtual host on RHEL / Rocky / Arch

Drop the file directly into /etc/httpd/conf.d/example.com.conf using the same <VirtualHost> block above, replacing ${APACHE_LOG_DIR} with /var/log/httpd. Then reload:

sudo systemctl reload httpd

Using .htaccess

AllowOverride All in the <Directory> block above is what permits .htaccess files. Each directory can contain one, and Apache merges the rules downward from the document root. This is convenient but carries a performance cost because Apache checks for a .htaccess file on every request. On a high-traffic server, move the rules into the virtual host block itself and set AllowOverride None.

Example: redirect all HTTP traffic to HTTPS

cat > /var/www/example.com/public_html/.htaccess <<'EOF'
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
EOF

Example: custom 404 page

echo 'ErrorDocument 404 /404.html' | sudo tee -a /var/www/example.com/public_html/.htaccess

Security note: never allow .htaccess files to override AuthConfig or Limit directives on a multi-tenant server unless you fully trust the users writing those files.

Verifying the Configuration

Always test the configuration before reloading Apache. A syntax error will prevent the service from starting.

sudo apache2ctl configtest   # Debian/Ubuntu
sudo apachectl configtest    # RHEL family / Arch

A clean result shows Syntax OK. Any errors printed above that line point to the file and line number causing the problem.

Test the virtual host from the command line by spoofing the Host header if DNS is not yet pointing at the server:

curl -H 'Host: example.com' http://<server-ip>/

Troubleshooting

Apache fails to start

Run journalctl -xeu apache2 (or httpd) for the full systemd log. Most failures are syntax errors caught by configtest, port conflicts (ss -tlnp | grep :80), or missing module files referenced in configuration.

403 Forbidden on the document root

Check two things: file permissions (ls -la /var/www/example.com/public_html/) and SELinux/AppArmor context. On RHEL-family with SELinux enforcing:

sudo restorecon -Rv /var/www/example.com/
sudo chcon -R -t httpd_sys_content_t /var/www/example.com/

Changes to .htaccess not taking effect

Confirm AllowOverride All is set for the directory in the virtual host config, and that mod_rewrite is loaded. Restart (not just reload) Apache after changing module state.

Virtual host serves the wrong site

Apache matches virtual hosts in the order they appear in configuration. The first match wins. List all configured virtual hosts with:

sudo apache2ctl -S   # or apachectl -S

The output shows which VirtualHost block handles each name and highlights any mismatches.

tested on:Ubuntu 24.04Debian 12Fedora 40Arch rolling

Frequently asked questions

What is the difference between apache2 and httpd package names?
They are the same software. Debian and Ubuntu chose the name apache2 when they packaged it; Red Hat-family distributions and Arch have always called it httpd. The binary and configuration behave identically.
Should I use .htaccess or put rules directly in the virtual host config?
Put rules in the virtual host config whenever you can. Apache reads .htaccess files on every single request for every directory in the path, which adds measurable overhead. Reserve .htaccess for shared hosting environments where you do not control the main config.
How do I host multiple sites on one Apache server?
Create a separate VirtualHost block (and its own config file) for each site with a unique ServerName. Apache selects the correct block by matching the Host header in each incoming request against ServerName and ServerAlias values.
Why do I get a 403 Forbidden error even though the file exists?
The most common causes are file permissions that the Apache user cannot read, a missing Require all granted directive in the Directory block, or an SELinux context mismatch on RHEL-family systems. Run apachectl -S and check journalctl for the specific denial.
Does Apache work on systems using Wayland?
Apache is a server daemon with no graphical component, so the display server in use on the desktop is completely irrelevant. It runs identically regardless of whether the system uses Wayland, X11, or no display server at all.

Related guides