🌐

Apache2

13 notes  •  Web Hosting

Install an SSL Certificate on Apache

How to install a commercial SSL certificate (e.g., Comodo/Sectigo) on Apache.

Prerequisites

  • Apache with mod_ssl enabled: sudo a2enmod ssl
  • Your domain certificate (.crt), CA bundle, and private key

Step 1 — Prepare Certificate Files

# Copy certificate files to a safe location
sudo mkdir -p /etc/ssl/example.com
sudo cp yourdomain.crt /etc/ssl/example.com/
sudo cp yourdomain.ca-bundle /etc/ssl/example.com/
sudo cp yourdomain.key /etc/ssl/example.com/
sudo chmod 600 /etc/ssl/example.com/*.key

Step 2 — Configure the VirtualHost


    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/html/example.com

    SSLEngine on
    SSLCertificateFile      /etc/ssl/example.com/yourdomain.crt
    SSLCertificateKeyFile   /etc/ssl/example.com/yourdomain.key
    SSLCertificateChainFile /etc/ssl/example.com/yourdomain.ca-bundle

    # Modern SSL settings
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    SSLHonorCipherOrder off

Step 3 — Enable the Site and Restart

sudo a2ensite example.com-ssl.conf
apachectl configtest
sudo systemctl restart apache2

Verify

openssl s_client -connect example.com:443 -brief
curl -I https://example.com

Tune Apache for Performance

Key Apache configuration changes to improve server performance: disabling unneeded modules, selecting the right MPM, and tuning worker settings.

Step 1 — Disable Unused Modules

Every loaded module consumes memory. Disable any you don't need:

# List enabled modules
apache2ctl -M

# Disable common unnecessary modules
sudo a2dismod autoindex   # Directory listing
sudo a2dismod status      # /server-status page
sudo a2dismod userdir     # ~/public_html support
sudo a2dismod info        # /server-info page
sudo systemctl restart apache2

Step 2 — Choose the Right MPM

  • prefork — one process per request; required for mod_php; high memory use
  • worker — multi-threaded; lower memory; requires thread-safe PHP
  • event — best for high concurrency; use with PHP-FPM (not mod_php)
# Switch to event MPM (recommended with PHP-FPM)
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo a2enmod proxy_fcgi setenvif
sudo systemctl restart apache2

Step 3 — Tune MPM Settings

# /etc/apache2/mods-enabled/mpm_event.conf

    StartServers          2
    MinSpareThreads       25
    MaxSpareThreads       75
    ThreadLimit           64
    ThreadsPerChild       25
    MaxRequestWorkers     150
    MaxConnectionsPerChild 0

Step 4 — Enable Compression and Caching

# Enable mod_deflate for gzip
sudo a2enmod deflate
# Enable browser caching
sudo a2enmod expires
sudo a2enmod headers
sudo systemctl reload apache2

Step 5 — Keep-Alive Settings

# /etc/apache2/apache2.conf
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

Serve Jenkins over HTTPS with Apache Reverse Proxy and Let's Encrypt

How to put Jenkins behind Apache as an HTTPS reverse proxy using a Let's Encrypt certificate.

Prerequisites

  • Jenkins running on port 8080 (localhost)
  • Apache installed with mod_proxy, mod_ssl, mod_headers
  • A domain pointing to the server

Step 1 — Enable Required Modules

sudo a2enmod proxy proxy_http ssl headers rewrite
sudo systemctl restart apache2

Step 2 — Obtain SSL Certificate

sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d jenkins.example.com

Step 3 — Create the VirtualHost Config

# /etc/apache2/sites-available/jenkins.conf

    ServerName jenkins.example.com
    Redirect permanent / https://jenkins.example.com/



    ServerName jenkins.example.com

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/jenkins.example.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/jenkins.example.com/privkey.pem

    ProxyRequests     Off
    ProxyPreserveHost On
    AllowEncodedSlashes NoDecode

    ProxyPass         / http://localhost:8080/ nocanon
    ProxyPassReverse  / http://localhost:8080/

    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port  "443"

Step 4 — Enable Site and Restart

sudo a2ensite jenkins.conf
apachectl configtest
sudo systemctl reload apache2

Step 5 — Configure Jenkins URL

In Jenkins: Manage Jenkins → Configure System → Jenkins URL → set to https://jenkins.example.com/

5 Tips to Boost Apache Web Server Performance

Five practical configuration changes to significantly improve Apache throughput and response time.

1. Enable mod_deflate (Gzip Compression)

sudo a2enmod deflate
# /etc/apache2/mods-enabled/deflate.conf

    AddOutputFilterByType DEFLATE text/html text/css application/javascript
    AddOutputFilterByType DEFLATE text/plain application/json application/xml

2. Enable mod_expires (Browser Caching)

sudo a2enmod expires

    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType text/css   "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"

3. Disable .htaccess Lookups (AllowOverride None)

Apache checks for .htaccess in every directory traversal. Set AllowOverride None for directories that don't need it:


    AllowOverride None

4. Switch to Event MPM with PHP-FPM

sudo a2dismod mpm_prefork php8.1
sudo a2enmod mpm_event proxy_fcgi setenvif
sudo a2enconf php8.1-fpm
sudo systemctl restart apache2 php8.1-fpm

5. Enable mod_cache (Content Caching)

sudo a2enmod cache cache_disk

    CacheRoot /var/cache/apache2/mod_cache_disk
    CacheEnable disk /
    CacheDirLevels 2
    CacheDirLength 1

Configure Apache with PHP-FPM (proxy_fcgi)

How to connect Apache to PHP-FPM using Apache's proxy modules for better performance than mod_php.

Prerequisites

  • Apache 2.4+
  • PHP-FPM installed

Step 1 — Install Required Packages

sudo apt-get update
sudo apt-get install -y apache2 php8.1-fpm libapache2-mod-fcgid

Step 2 — Enable Required Modules

sudo a2dismod php8.1             # Disable mod_php if installed
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.1-fpm
sudo systemctl restart apache2 php8.1-fpm

Step 3 — Configure VirtualHost to Use PHP-FPM


    ServerName example.com
    DocumentRoot /var/www/html

    
        SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
    

    
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    

Step 4 — Verify

# Check PHP handler
curl -s http://localhost/info.php | grep -i "Server API"
# Should show: FPM/FastCGI

apachectl -M | grep proxy_fcgi

Install Apache, MySQL, PHP-FPM (LAMP) on Ubuntu

Full LAMP stack installation on Ubuntu using Apache with PHP-FPM for better performance.

Step 1 — Install Packages

sudo apt-get update
sudo apt-get install -y apache2 mysql-server
sudo mysql_secure_installation

sudo apt-get install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt-get update
sudo apt-get install -y php8.1-fpm php8.1-mysql php8.1-curl php8.1-xml     php8.1-zip php8.1-mbstring php8.1-gd php8.1-bcmath php8.1-soap

Step 2 — Enable Apache Modules for PHP-FPM

sudo a2dismod mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif
sudo a2enconf php8.1-fpm
sudo systemctl restart apache2 php8.1-fpm

Step 3 — Install Certbot (Let's Encrypt)

sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com

Step 4 — Install Common Extras

sudo apt-get install -y zip curl imagemagick ffmpeg

Verify

php -v
php8.1-fpm --version
mysql --version
apache2 -v
sudo systemctl status apache2 php8.1-fpm mysql

Apache2 + PHP-FPM Performance Optimization Guide

Step-by-step guide to optimizing Apache 2.4 and PHP-FPM for high-traffic WordPress and PHP applications.

Step 1 — Switch Apache to event MPM

sudo a2dismod mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif

Step 2 — Tune mpm_event

# /etc/apache2/mods-available/mpm_event.conf

    StartServers          2
    MinSpareThreads       25
    MaxSpareThreads       75
    ThreadLimit           64
    ThreadsPerChild       25
    MaxRequestWorkers     150
    MaxConnectionsPerChild 0

Step 3 — Tune PHP-FPM Pool

# /etc/php/8.1/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

Step 4 — Enable OPcache

# /etc/php/8.1/fpm/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.fast_shutdown=1

Step 5 — Restart Services

sudo systemctl restart php8.1-fpm apache2

Step 6 — Verify PHP-FPM is Active

sudo systemctl status php8.1-fpm
php -r "phpinfo();" | grep -i "Server API"

Switch Apache from prefork to event MPM with PHP-FPM

How to switch Apache from the mpm_prefork (used with mod_php) to mpm_event (used with PHP-FPM) on Ubuntu 16.04+ for better performance.

Step 1 — Install PHP-FPM

sudo apt-get install -y php7.4-fpm
sudo systemctl start php7.4-fpm
sudo systemctl enable php7.4-fpm

Step 2 — Disable mod_php and prefork MPM

sudo a2dismod php7.4
sudo a2dismod mpm_prefork

Step 3 — Enable event MPM and PHP-FPM Proxy

sudo a2enmod mpm_event
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php7.4-fpm

Step 4 — Restart Apache

sudo apachectl configtest
sudo systemctl restart apache2

Step 5 — Verify

# Check active MPM
apache2ctl -V | grep -i mpm

# Check PHP handler
apache2ctl -M | grep proxy_fcgi

# Check PHP-FPM is being used
curl -s http://localhost/phpinfo.php | grep "FPM"

Notes

  • With mpm_event, each request uses a thread instead of a process — far more memory-efficient under load.
  • Ensure mod_php is fully disabled: you cannot run mod_php and PHP-FPM simultaneously under event MPM.

Redirect HTTP to HTTPS in Apache VirtualHost

How to force all HTTP traffic to redirect to HTTPS in Apache by modifying the VirtualHost configuration.

Step 1 — Find Your VirtualHost File

# On Ubuntu/Debian:
apachectl -S

# On CentOS/RHEL:
httpd -S

Step 2 — Add Redirect to the HTTP VirtualHost


    ServerName example.com
    ServerAlias www.example.com
    Redirect permanent / https://example.com/



    ServerName example.com
    DocumentRoot /var/www/html/example.com
    SSLEngine on
    SSLCertificateFile    /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

Alternative — Using mod_rewrite


    ServerName example.com
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Step 3 — Test and Reload

apachectl configtest
sudo systemctl reload apache2
curl -I http://example.com
# Should return: HTTP/1.1 301 Moved Permanently

Apache httpd Command Reference (CentOS/RHEL)

Command reference for Apache httpd on CentOS/RHEL systems, including config testing, module listing, aliases, and redirects.

Configuration and Syntax

# Test config file syntax
httpd -t
httpd -t -f /etc/httpd/conf/httpd.conf

# List all loaded modules
httpd -M

# Show virtual host configuration
httpd -S

Service Management

# Start / stop / restart
systemctl start httpd
systemctl stop httpd
systemctl restart httpd

# Graceful restart
apachectl graceful

# Enable on boot
systemctl enable httpd

Aliases

Aliases map a URL path to a filesystem directory, even outside the DocumentRoot:

# /etc/httpd/conf/httpd.conf or a .conf file in conf.d/
Alias /img /var/www/html/images


    Options Indexes FollowSymLinks
    Require all granted

Permanent Redirects

# Redirect a single page
Redirect permanent /oldpage.html /newpage.html

# Redirect an entire directory
Redirect permanent /old-blog/ /blog/

Log Locations

/var/log/httpd/access_log
/var/log/httpd/error_log

Apache mod_rewrite Rules Reference

Common mod_rewrite directives for URL manipulation in Apache VirtualHost configs or .htaccess files.

Enable mod_rewrite

RewriteEngine On

Basic Redirect

# Redirect /oldpage to /newpage
RewriteRule ^oldpage\.html$ /newpage.html [R=301,L]

# Redirect everything starting with "i" and ending with "l" to test.html
RewriteRule ^index\.html$ /test.html [R=301,L]

Force HTTPS

RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Remove www

RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]

Rewrite Flags

  • [L] — Last rule; stop processing after this rule matches
  • [R=301] — Permanent redirect (301)
  • [R=302] — Temporary redirect (302)
  • [NC] — Case-insensitive match
  • [QSA] — Append query string to the result
  • [NE] — Do not escape special chars in the output

Rewrite Conditions

# Only match if request is not a file
RewriteCond %{REQUEST_FILENAME} !-f
# Only match if request is not a directory
RewriteCond %{REQUEST_FILENAME} !-d
# Match based on Host header
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]

Configure Apache Reverse Proxy to a Docker Container

How to use Apache as a reverse proxy to forward requests to an application running inside a Docker container.

Step 1 — Enable Proxy Modules

sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests
sudo systemctl restart apache2

Step 2 — Configure the VirtualHost


    ServerName app.example.com

    ProxyRequests Off
    ProxyPreserveHost On

    ProxyPass        / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    
        Require all granted
    

Step 3 — Enable Site and Reload

sudo a2ensite app-proxy.conf
apachectl configtest
sudo systemctl reload apache2

Step 4 — Run the Docker Container

Map the container port to localhost (not 0.0.0.0 for security):

docker run -d --name myapp -p 127.0.0.1:3000:3000 myapp-image

Verify

curl -I http://app.example.com
docker ps | grep myapp

Notes

  • Bind Docker port to 127.0.0.1 so it's only reachable via Apache, not directly from the internet.
  • Use proxy_wstunnel module if the app uses WebSockets.