# Setting up the Apache HTTP web server

Features include:

* `HTTP/2` support is now provided by the `mod_http2` package, which is a part of the `httpd` module.
    
* systemd socket activation is supported. See `httpd.socket(8)` man page for more details.
    
* Multiple new modules have been added:
    
    * `mod_proxy_hcheck` - a proxy health-check module
        
    * `mod_proxy_uwsgi` - a Web Server Gateway Interface (WSGI) proxy
        
    * `mod_proxy_fdpass` - provides support for the passing the socket of the client to another process
        
    * `mod_cache_socache` - an HTTP cache using, for example, memcache backend
        
    * `mod_md` - an ACME protocol SSL/TLS certificate service
        
* The following modules now load by default:
    
    * `mod_request`
        
    * `mod_macro`
        
    * `mod_watchdog`
        
* A new subpackage, `httpd-filesystem`, has been added, which contains the basic directory layout for the **Apache HTTP Server** including the correct permissions for the directories.
    
* Instantiated service support, `httpd@.service` has been introduced. See the `httpd.service` man page for more information.
    
* A new `httpd-init.service` replaces the `%post script` to create a self-signed `mod_ssl` key pair.
    
* Automated TLS certificate provisioning and renewal using the Automatic Certificate Management Environment (ACME) protocol is now supported with the `mod_md` package (for use with certificate providers such as `Let’s Encrypt`).
    
* The **Apache HTTP Server** now supports loading TLS certificates and private keys from hardware security tokens directly from `PKCS#11` modules. As a result, a `mod_ssl` configuration can now use `PKCS#11` URLs to identify the TLS private key, and, optionally, the TLS certificate in the `SSLCertificateKeyFile` and `SSLCertificateFile` directives.
    
* A new `ListenFree` directive in the `/etc/httpd/conf/httpd.conf` file is now supported.
    
    Similarly to the `Listen` directive, `ListenFree` provides information about IP addresses, ports, or IP address-and-port combinations that the server listens to. However, with `ListenFree`, the `IP_FREEBIND` socket option is enabled by default. Hence, `httpd` is allowed to bind to a nonlocal IP address or to an IP address that does not exist yet. This allows `httpd` to listen on a socket without requiring the underlying network interface or the specified dynamic IP address to be up at the time when `httpd` is trying to bind to it.
    

## **Updating the configuration**

You can check the configuration for possible errors by using the following command:

```plaintext
# apachectl configtest
Syntax OK
```

**The httpd service configuration files**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690732076678/8ddd1f71-bf0f-46fd-b509-1cc5852a71a0.png align="center")

To check the configuration for possible errors, type the following at a shell prompt:

```plaintext
# apachectl configtest
Syntax OK
```

To make the recovery from mistakes easier, make a copy of the original file before editing it.

## **Managing the httpd service**

This section describes how to start, stop, and restart the `httpd` service.

**Prerequisites**

* The Apache HTTP Server is installed.
    

**Procedure**

* To start the `httpd` service, enter:
    
    ```plaintext
    # systemctl start httpd
    ```
    
* To stop the `httpd` service, enter:
    
    ```plaintext
    # systemctl stop httpd
    ```
    
* To restart the `httpd` service, enter:
    
    ```plaintext
    # systemctl restart httpd
    ```
    
    ## **Setting up a single-instance Apache HTTP Server**
    
* Install the `httpd` package:
    
    ```plaintext
    # yum install httpd or dnf install httpd
    ```
    
* If you use `firewalld`, open the TCP port `80` in the local firewall:
    
    ```plaintext
    # firewall-cmd --permanent --add-port=80/tcp
    # firewall-cmd --reload
    ```
    
* Enable and start the `httpd` service:
    
    ```plaintext
    # systemctl enable --now httpd
    ```
    
* Optional: Add HTML files to the `/var/www/html/` directory.
    
* Connect with a web browser to [`http://server_IP_or_host_name/`](http://server_IP_or_host_name/).
    

## **Configuring Apache name-based virtual hosts**

**Prerequisites**

* Clients and the web server resolve the [`example.com`](http://example.com) and [`example.net`](http://example.net) domain to the IP address of the web server.
    
    Note that you must manually add these entries to your DNS server.
    
* **Procedure**
    
    1. Install the `httpd` package:
        
        ```plaintext
        # yum install httpd
        ```
        
    2. Edit the `/etc/httpd/conf/httpd.conf` file:
        
        1. Append the following virtual host configuration for the [`example.com`](http://example.com) domain:
            
            ```plaintext
            <VirtualHost *:80>
                DocumentRoot "/var/www/example.com/"
                ServerName example.com
                CustomLog /var/log/httpd/example.com_access.log combined
                ErrorLog /var/log/httpd/example.com_error.log
            </VirtualHost>
            ```
            
            These settings configure the following:
            
            * All settings in the `<VirtualHost *:80>` directive are specific for this virtual host.
                
            * `DocumentRoot` sets the path to the web content of the virtual host.
                
            * `ServerName` sets the domains for which this virtual host serves content.
                
                To set multiple domains, add the `ServerAlias` parameter to the configuration and specify the additional domains separated with a space in this parameter.
                
            * `CustomLog` sets the path to the access log of the virtual host.
                
            * `ErrorLog` sets the path to the error log of the virtual host.
                
            * Append a similar virtual host configuration for the [`example.net`](http://example.net) domain:
                
                ```plaintext
                <VirtualHost *:80>
                    DocumentRoot "/var/www/example.net/"
                    ServerName example.net
                    CustomLog /var/log/httpd/example.net_access.log combined
                    ErrorLog /var/log/httpd/example.net_error.log
                </VirtualHost>
                ```
                
            * Create the document roots for both virtual hosts:
                
                ```plaintext
                # mkdir /var/www/example.com/
                # mkdir /var/www/example.net/
                ```
                
            * If you set paths in the `DocumentRoot` parameters that are not within `/var/www/`, set the `httpd_sys_content_t` context on both document roots:
                
                ```plaintext
                # semanage fcontext -a -t httpd_sys_content_t "/srv/example.com(/.*)?"
                # restorecon -Rv /srv/example.com/
                # semanage fcontext -a -t httpd_sys_content_t "/srv/example.net(/.\*)?"
                # restorecon -Rv /srv/example.net/
                ```
                
                These commands set the `httpd_sys_content_t` context on the `/srv/example.com/` and `/srv/example.net/` directory.
                
                Note that you must install the `policycoreutils-python-utils` package to run the `restorecon` command.
                
            * If you use `firewalld`, open port `80` in the local firewall:
                
                ```plaintext
                # firewall-cmd --permanent --add-port=80/tcp
                # firewall-cmd --reload
                ```
                
            * Enable and start the `httpd` service:
                
                ```plaintext
                # systemctl enable --now httpd
                ```
                
            
            **Verification steps**
            
            1. Create a different example file in each virtual host’s document root:
                
                ```plaintext
                # echo "vHost example.com" > /var/www/example.com/index.html
                # echo "vHost example.net" > /var/www/example.net/index.html
                ```
                
            2. Use a browser and connect to [`http://example.com`](http://example.com). The web server shows the example file from the [`example.com`](http://example.com) virtual host.
                
            3. Use a browser and connect to [`http://example.net`](http://example.net). The web server shows the example file from the [`example.net`](http://example.net) virtual host.
                
            
            **ADDITIONAL RESOURCES**
            
            * [Installing the Apache HTTP Server manual - Virtual Hosts](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/deploying_different_types_of_servers/setting-apache-http-server_Deploying-different-types-of-servers#installing-the-apache-http-server-manual_setting-apache-http-server)
                
            
            ## **Configuring Kerberos authentication for the Apache HTTP web server**
            
            **Note**
            
            The `mod_auth_gssapi` module replaces the removed `mod_auth_kerb` module.
            
            **Prerequisites**
            
            * The `httpd` and `gssproxy` packages are installed.
                
            * The Apache web server is set up and the `httpd` service is running.
                
        
        ### Setting up GSS-Proxy in an IdM environment
        
        **Procedure**
        
        1. Enable access to the `keytab` file of HTTP/&lt;SERVER\_NAME&gt;@realm principal by creating the service principal:
            
            ```plaintext
            # ipa service-add HTTP/<SERVER_NAME>
            ```
            
        2. Retrieve the `keytab` for the principal stored in the `/etc/gssproxy/http.keytab` file:
            
            ```plaintext
            # ipa-getkeytab -s $(awk '/^server =/ {print $3}' /etc/ipa/default.conf) -k /etc/gssproxy/http.keytab -p HTTP/$(hostname -f)
            ```
            
            This step sets permissions to 400, thus only the `root` user has access to the `keytab` file. The `apache` user does not.
            
        3. Create the `/etc/gssproxy/80-httpd.conf` file with the following content:
            
            ```plaintext
            [service/HTTP]
              mechs = krb5
              cred_store = keytab:/etc/gssproxy/http.keytab
              cred_store = ccache:/var/lib/gssproxy/clients/krb5cc_%U
              euid = apache
            ```
            
        4. Restart and enable the `gssproxy` service:
            
            ```plaintext
            # systemctl restart gssproxy.service
            # systemctl enable gssproxy.service
            ```
            
        
        **ADDITIONAL RESOURCES**
        
        * `gssproxy(8)` man pages
            
        * `gssproxy-mech(8)` man pages
            
        * `gssproxy.conf(5)` man pages
            
        
        ### 1.8.2. Configuring Kerberos authentication for a directory shared by the Apache HTTP web server
        
        This procedure describes how to configure Kerberos authentication for the `/var/www/html/private/` directory.
        
        **Prerequisites**
        
        * The `gssproxy` service is configured and running.
            
        
        **Procedure**
        
        1. Configure the `mod_auth_gssapi` module to protect the `/var/www/html/private/` directory:
            
            ```plaintext
            <Location /var/www/html/private>
              AuthType GSSAPI
              AuthName "GSSAPI Login"
              Require valid-user
            </Location>
            ```
            
        2. Create the `/etc/systemd/system/httpd.service` file with the following content:
            
            ```plaintext
            .include /lib/systemd/system/httpd.service
            [Service]
            Environment=GSS_USE_PROXY=1
            ```
            
        3. Reload the `systemd` configuration:
            
            ```plaintext
            # systemctl daemon-reload
            ```
            
        4. Restart the `httpd` service:
            
            ```plaintext
            # systemctl restart httpd.service
            ```
            
        
        **Verification steps**
        
        1. Obtain a Kerberos ticket:
            
            ```plaintext
            # kinit
            ```
            
        2. Open the URL to the protected directory in a browser.
            
        
        ## **1.9. Configuring TLS encryption on an Apache HTTP Server**
        
        By default, Apache provides content to clients using an unencrypted HTTP connection. This section describes how to enable TLS encryption and configure frequently used encryption-related settings on an Apache HTTP Server.
        
        **Prerequisites**
        
        * The Apache HTTP Server is installed and running.
            
* ### Adding TLS encryption to an Apache HTTP Server
    

**Procedure**

1. Install the `mod_ssl` package:
    
    ```plaintext
    # yum install mod_ssl
    ```
    
2. Edit the `/etc/httpd/conf.d/ssl.conf` file and add the following settings to the `<VirtualHost _default_:443>` directive:
    
    1. Set the server name:
        
        ```plaintext
        ServerName example.com
        ```
        
        **Important**
        
        The server name must match the entry set in the `Common Name` field of the certificate.
        
    2. Optional: If the certificate contains additional host names in the `Subject Alt Names` (SAN) field, you can configure `mod_ssl` to provide TLS encryption also for these host names. To configure this, add the `ServerAliases` parameter with corresponding names:
        
        ```plaintext
        ServerAlias www.example.com server.example.com
        ```
        
    3. Set the paths to the private key, the server certificate, and the CA certificate:
        
        ```plaintext
        SSLCertificateKeyFile "/etc/pki/tls/private/example.com.key"
        SSLCertificateFile "/etc/pki/tls/certs/example.com.crt"
        SSLCACertificateFile "/etc/pki/tls/certs/ca.crt"
        ```
        
3. For security reasons, configure that only the `root` user can access the private key file:
    
    ```plaintext
    # chown root:root /etc/pki/tls/private/example.com.key
    # chmod 600 /etc/pki/tls/private/example.com.key
    ```
    
    **Warning**
    
    If the private key was accessed by unauthorized users, revoke the certificate, create a new private key, and request a new certificate. Otherwise, the TLS connection is no longer secure.
    
4. If you use `firewalld`, open port `443` in the local firewall:
    
    ```plaintext
    # firewall-cmd --permanent --add-port=443/tcp
    # firewall-cmd --reload
    ```
    
5. Restart the `httpd` service:
    
    ```plaintext
    # systemctl restart httpd
    ```
    
    **Note**
    
    If you protected the private key file with a password, you must enter this password each time when the `httpd` service starts.
    

**Verification steps**

* Use a browser and connect to [`https://example.com`](https://example.com).
    

**ADDITIONAL RESOURCES**

* [SSL/TLS Encryption](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/deploying_different_types_of_servers/setting-apache-http-server_Deploying-different-types-of-servers#installing-the-apache-http-server-manual_setting-apache-http-server)
    
* [Security considerations for TLS in RHEL 8](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/securing_networks/planning-and-implementing-tls_securing-networks#security-considerations-for-tls-in-rhel_planning-and-implementing-tls)
    

### Setting the supported TLS protocol versions on an Apache HTTP Server

**Procedure**

1. Edit the `/etc/httpd/conf/httpd.conf` file, and add the following setting to the `<VirtualHost>` directive for which you want to set the TLS protocol version. For example, to enable only the `TLSv1.3` protocol:
    
    ```plaintext
    SSLProtocol -All TLSv1.3
    ```
    
2. Restart the `httpd` service:
    
    ```plaintext
    # systemctl restart httpd
    ```
    

**Verification steps**

1. Use the following command to verify that the server supports `TLSv1.3`:
    
    ```plaintext
    # openssl s_client -connect example.com:443 -tls1_3
    ```
    
2. Use the following command to verify that the server does not support `TLSv1.2`:
    
    ```plaintext
    # openssl s_client -connect example.com:443 -tls1_2
    ```
    
    If the server does not support the protocol, the command returns an error:
    
    ```plaintext
    140111600609088:error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:ssl/record/rec_layer_s3.c:1543:SSL alert number 70
    ```
    
3. Optional: Repeat the command for other TLS protocol versions.
    

### Setting the supported ciphers on an Apache HTTP Server

**Procedure**

1. Edit the `/etc/httpd/conf/httpd.conf` file, and add the `SSLCipherSuite` parameter to the `<VirtualHost>` directive for which you want to set the TLS ciphers:
    
    ```plaintext
    SSLCipherSuite "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!SHA1:!SHA256"
    ```
    
    This example enables only the `EECDH+AESGCM`, `EDH+AESGCM`, `AES256+EECDH`, and `AES256+EDH` ciphers and disables all ciphers which use the `SHA1` and `SHA256` message authentication code (MAC).
    
2. Restart the `httpd` service:
    
    ```plaintext
    # systemctl restart httpd
    ```
    

**Verification steps**

1. To display the list of ciphers the Apache HTTP Server supports:
    
    1. Install the `nmap` package:
        
        ```plaintext
        # yum install nmap
        ```
        
    2. Use the `nmap` utility to display the supported ciphers:
        
        ```plaintext
        # nmap --script ssl-enum-ciphers -p 443 example.com
        ...
        PORT    STATE SERVICE
        443/tcp open  https
        | ssl-enum-ciphers:
        |   TLSv1.2:
        |     ciphers:
        |       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
        |       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
        |       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
        ...
        ```
        
    
    **Procedure**
    
    1. Edit the `/etc/httpd/conf/httpd.conf` file, and add the `SSLCipherSuite` parameter to the `<VirtualHost>` directive for which you want to set the TLS ciphers:
        
        ```plaintext
        SSLCipherSuite "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!SHA1:!SHA256"
        ```
        
        This example enables only the `EECDH+AESGCM`, `EDH+AESGCM`, `AES256+EECDH`, and `AES256+EDH` ciphers and disables all ciphers which use the `SHA1` and `SHA256` message authentication code (MAC).
        
    2. Restart the `httpd` service:
        
        ```plaintext
        # systemctl restart httpd
        ```
        
    
    **Verification steps**
    
    1. To display the list of ciphers the Apache HTTP Server supports:
        
        1. Install the `nmap` package:
            
            ```plaintext
            # yum install nmap
            ```
            
        2. Use the `nmap` utility to display the supported ciphers:
            
            ```plaintext
            # nmap --script ssl-enum-ciphers -p 443 example.com
            ...
            PORT    STATE SERVICE
            443/tcp open  https
            | ssl-enum-ciphers:
            |   TLSv1.2:
            |     ciphers:
            |       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
            |       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
            |       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
            ...
            ```
            
    
    **Prerequisites**
    

**Procedure**

1. Edit the `/etc/httpd/conf/httpd.conf` file and add the following settings to the `<VirtualHost>` directive for which you want to configure client authentication:
    
    ```plaintext
    <Directory "/var/www/html/Example/">
      SSLVerifyClient require
    </Directory>
    ```
    
    The `SSLVerifyClient require` setting defines that the server must successfully validate the client certificate before the client can access the content in the `/var/www/html/Example/` directory.
    
2. Restart the `httpd` service:
    
    ```plaintext
    # systemctl restart httpd
    ```
    

**Verification steps**

1. Use the `curl` utility to access the [`https://example.com/Example/`](https://example.com/Example/) URL without client authentication:
    
    ```plaintext
    $ curl https://example.com/Example/
    curl: (56) OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 **alert certificate required**, errno 0
    ```
    
    The error indicates that the web server requires a client certificate authentication.
    
2. Pass the client private key and certificate, as well as the CA certificate to `curl` to access the same URL with client authentication:
    
    ```plaintext
    $ curl --cacert ca.crt --key client.key --cert client.crt https://example.com/Example/
    ```
    
    If the request succeeds, `curl` displays the `index.html` file stored in the `/var/www/html/Example/` directory.
    

## **Securing web applications on a web server using ModSecurity**
