How To

Install Apache HTTP Server on openSUSE Leap 16

openSUSE Leap 16 ships Apache 2.4.66 with the prefork MPM, and the module set is driven entirely from /etc/sysconfig/apache2, not from the main httpd.conf. That single design choice is what trips up admins arriving from Debian or RHEL: editing httpd.conf to load a module does nothing here, because the SUSE helper scripts regenerate the load list from the sysconfig file. This guide shows how to install Apache on openSUSE Leap 16, open the firewall, serve content, enable modules the SUSE way, and ends with the numbers that decide how you tune it.

Original content from computingforgeeks.com - post 169177

Every command below was run on a live Leap 16 box: a 2 vCPU, 2 GB virtual machine. The throughput and memory figures in the tuning section come from that machine, not from documentation.

Tested June 2026 on Apache 2.4.66 (openSUSE Leap 16.0).

Prerequisites

Apache’s footprint is set by the MPM and the workload, not by the binary. The prefork MPM forks one process per connection, and on the test box each worker measured at 6.9 MB resident. Multiply that by your expected concurrency to size memory: 256 simultaneous prefork workers is roughly 1.8 GB before the application behind Apache uses a byte. For a static site or a reverse proxy front end, 1 vCPU and 1 GB is enough; for a PHP application server under real load, start at 2 vCPU and 2 GB and scale memory with MaxRequestWorkers.

  • An openSUSE Leap 16 server with sudo access. The reference box was 2 vCPU / 2 GB, which is a floor for following along, not a production target.
  • A non-root user in the wheel group. The initial server setup and hardening guide covers that groundwork.
  • Network access to the openSUSE CDN for zypper.

Step 1: Install Apache from the OSS repository

Apache is packaged as apache2 in the default repositories. Installing it pulls in the prefork MPM and the utilities package:

sudo zypper refresh
sudo zypper install apache2

The control binaries land in /usr/sbin, which is not on a normal user’s PATH, so confirm the version through sudo. Note the control command on openSUSE is apachectl:

sudo apachectl -v

The build identifies itself as the SUSE flavor:

Server version: Apache/2.4.66 (Linux/SUSE)
Server built:   2026-05-13 23:29:22.000000000 +0000

Step 2: Start Apache and enable it at boot

The service unit is apache2, with httpd and apache registered as aliases. Enable and start it in one command:

sudo systemctl enable --now apache2

Confirm the daemon is up. The main process reports as httpd-prefork, which names the active MPM:

systemctl status apache2 --no-pager

The status block shows it running and processing requests:

● apache2.service - The Apache Webserver
     Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: disabled)
     Active: active (running) since Fri 2026-06-19 01:20:35 CEST
   Main PID: 7167 (httpd-prefork)
     Status: "Processing requests..."

Step 3: Open the firewall

Leap 16 runs firewalld. Add the HTTP and HTTPS services and reload:

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

List the active services to confirm both are allowed:

sudo firewall-cmd --list-services

The output includes http and https:

cockpit dhcpv6-client http https ssh

With the firewall open, the server is reachable. All that remains to serve a page is content in the document root.

Step 4: Serve a page from the document root

Apache’s document root on openSUSE is /srv/www/htdocs, set in /etc/apache2/default-server.conf, not the /var/www/html you may know from other distributions. Drop an index file there and Apache serves it:

echo '<h1>Apache is running on openSUSE Leap 16</h1>' | sudo tee /srv/www/htdocs/index.html

Open the server’s address in a browser and the page loads.

Apache web server welcome page in browser on openSUSE Leap 16

Step 5: Enable modules the SUSE way

This is the part that behaves differently from every other distribution. The list of loaded modules lives in the APACHE_MODULES variable inside /etc/sysconfig/apache2. You do not edit that file by hand; the a2enmod and a2dismod helpers edit it for you, then a restart regenerates the load directives. Enable the rewrite module:

sudo a2enmod rewrite
sudo systemctl restart apache2

Verifying that the module loaded exposes a real trap. Running httpd -M directly returns nothing useful, because the raw binary does not source the SUSE environment that defines the module paths. Use apachectl -M instead, which sources /etc/sysconfig/apache2 first:

sudo apachectl -M | grep rewrite

With the environment sourced, the module shows as loaded:

rewrite_module (shared)

Step 6: Configure a name-based virtual host

Apache reads per-site configuration from /etc/apache2/vhosts.d/*.conf, pulled in by IncludeOptional /etc/apache2/vhosts.d/*.conf in the main config. The directory ships with vhost.template and vhost-ssl.template as starting points.

The site name and web root repeat across the next commands, so set them once as variables and adjust to your real domain:

export SITE_DOMAIN="site1.example.com"
export WEB_ROOT="/srv/www/vhosts/${SITE_DOMAIN}"

Create the document root and a landing page:

sudo mkdir -p "${WEB_ROOT}"
echo "<h1>${SITE_DOMAIN} on Apache / openSUSE Leap 16</h1>" | sudo tee "${WEB_ROOT}/index.html"

Open a new virtual host file:

sudo vim /etc/apache2/vhosts.d/site1.example.com.conf

Add the virtual host. Keep the paths in line with the variables set above:

<VirtualHost *:80>
    ServerName site1.example.com
    ServerAlias www.site1.example.com
    DocumentRoot /srv/www/vhosts/site1.example.com

    <Directory /srv/www/vhosts/site1.example.com>
        Require all granted
        Options FollowSymLinks
        AllowOverride All
    </Directory>

    ErrorLog /var/log/apache2/site1.example.com-error.log
    CustomLog /var/log/apache2/site1.example.com-access.log combined
</VirtualHost>

Validate the syntax before restarting:

sudo apachectl configtest

A clean configuration reports Syntax OK. On a fresh install it also prints one warning that confuses people:

AH00558: httpd-prefork: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain. Set the 'ServerName' directive globally to suppress this message
Syntax OK

The warning is harmless, but suppress it by setting a global ServerName. Create a small drop-in:

echo "ServerName localhost" | sudo tee /etc/apache2/conf.d/servername.conf

Restart to apply the virtual host:

sudo systemctl restart apache2

Confirm the virtual host answers for its name by sending a matching Host header:

curl -s -H "Host: ${SITE_DOMAIN}" http://127.0.0.1/

Apache returns the virtual host’s page:

<h1>site1.example.com on Apache / openSUSE Leap 16</h1>
Apache version, systemctl status and a2enmod on openSUSE Leap 16 terminal

A note on SELinux

Leap 16 ships SELinux in enforcing mode, and Apache runs in the confined httpd_t domain. In practice the targeted policy shipped with Leap is far more permissive than the RHEL equivalent: getsebool -a returns an empty list, so there are none of the httpd_* toggles you would flip on Rocky or RHEL, and content under /srv/www serves without any relabeling. Keep document roots under /srv/www and SELinux stays out of the way. If a future policy update tightens this, relabel a custom path with semanage fcontext -a -t httpd_sys_content_t followed by restorecon.

Performance: the numbers that set the tuning

The default prefork MPM forks one process per connection. On the 2 vCPU test box, ab -n 5000 -c 50 against the static document root measured 11,507 requests per second with zero failed requests, a 4.3 ms mean response time, and a 10.2 MB/s transfer rate. Each prefork worker held 6.9 MB resident. Those two numbers, requests per second and memory per worker, are what you tune against.

ab -n 5000 -c 50 http://127.0.0.1/

The relevant lines from the run:

Complete requests:      5000
Failed requests:        0
Requests per second:    11507.72 [#/sec] (mean)
Time per request:       4.345 [ms] (mean)
Transfer rate:          10159.16 [Kbytes/sec] received

Two levers move those figures. First, MaxRequestWorkers in /etc/apache2/server-tuning.conf caps concurrency; with prefork at 6.9 MB per worker, set it from your available RAM, not from a round number, or a traffic spike will push the box into swap. Second, the MPM itself. Prefork trades memory for stability and is the safe default for non-thread-safe modules like older PHP handlers. For high-concurrency keep-alive traffic, the event MPM holds far more idle connections per megabyte; swap it in by installing apache2-event (which replaces apache2-prefork) and restarting. Measure both on your own workload before committing, because the right MPM depends on whether your bottleneck is memory or thread safety.

With Apache serving and the MPM chosen, the next steps are usually putting it behind TLS and managing it from the browser. Cockpit exposes the service state and logs, and the post-install guide plus the zypper reference cover the surrounding setup.

Keep reading

Use Let’s Encrypt on Private Network with Cloudflare Security Use Let’s Encrypt on Private Network with Cloudflare Deploy Static Sites to Cloudflare Pages (Free Hosting) DevOps Deploy Static Sites to Cloudflare Pages (Free Hosting) How To Install GLPI on Ubuntu 24.04 / 26.04 LTS Debian How To Install GLPI on Ubuntu 24.04 / 26.04 LTS Install Nginx Web Server on openSUSE Leap 16 Web Hosting Install Nginx Web Server on openSUSE Leap 16 FileBrowser Quantum: OIDC, LDAP and Multi-Source File Manager Containers FileBrowser Quantum: OIDC, LDAP and Multi-Source File Manager How to Use Ahrefs Web Hosting How to Use Ahrefs

Leave a Comment

Press ESC to close