One place for hosting & domains

      Nginx

      How to Use the Nginx FastCGI Page Cache With WordPress


      NGINX typically fetches a new copy of a web page each time a new request is made. However for complex sites such as WordPress, each new request often involves querying a database and executing PHP code. For heavily used sites, this can cause performance issues and increased latency. As a workaround, NGINX offers the FastCGI page cache, allowing it to serve a static copy of the page more quickly. This guide explains how to enable caching for a WordPress site hosted on an NGINX web server. It also demonstrates how to configure non-cachable exceptions and how to test whether caching is working.

      How Does Caching Work on NGINX?

      When NGINX receives a request for a WordPress file, it typically has to perform extra processing. The usual work flow for this type of request follows this process:

      1. NGINX receives a request for a WordPress page. It locates the page and determines if further processing is required.
      2. Most WordPress pages include PHP code, which the web server cannot directly interpret. To execute the PHP code, NGINX sends the page to the PHP-FPM (PHP FastCGI Process Manager) module. PHP-FPM is a popular and efficient implementation of the FastCGI protocol. FastCGI allows a web server to interactively interface with other programs.
      3. PHP-FPM interprets the PHP code. If necessary, it connects to a MySQL or MariaDB database and executes any SQL queries in the code.
      4. PHP-FPM converts the original page into a static HTML page and sends it back to NGINX.
      5. NGINX serves the static page to the original web client.

      Unfortunately, this takes more time than serving a static HTML page. The PHP-FPM module must always parse the PHP code and there is often an additional delay to contact the database. For low-volume WordPress sites, this is typically not a problem. But for popular sites, these delays can result in serious performance bottlenecks and unacceptably high latency.

      Caching is one way of speeding up execution and improving performance. When caching is enabled, NGINX stores the pages it receives from the PHP-FPM as static HTML web pages. The next time the page is requested, NGINX does not contact the PHP-FPM to generate a new version of the page. Instead, it retrieves the static HTML version of the page from cache and transmits it to the client. Because it is much faster to retrieve a static page from the NGINX cache, site performance usually improves.

      As an additional bonus, NGINX can serve a cached version of the page even if the database or the PHP interpreter are not reachable. This optimization improves site reliability and robustness. The cached files typically expire after a certain length of time, so users do not continue to receive stale content. Extra configuration can also be added to allow certain pages to bypass the cache.

      No additional components or applications are required to enable the NGINX cache. All cache directives are added to existing virtual host or NGINX configuration files. However, WordPress plugins can improve cache management, allowing the cache to be purged under certain circumstances, such as when a page is updated.

      Before You Begin

      1. If you have not already done so, create a Linode account and Compute Instance. See our
        Getting Started with Linode and
        Creating a Compute Instance guides.

      2. Follow our
        Setting Up and Securing a Compute Instance guide to update your system. You may also wish to set the timezone, configure your hostname, create a limited user account, and harden SSH access.

      3. Configure a LEMP stack on the server, consisting of the NGINX web server, the MariaDB database, and the PHP programming language. MySQL can be substituted in place of MariaDB. For information on how to install and configure a LEMP stack, see the Linode guide on
        installing a LEMP stack on Ubuntu 22.04.

      4. Ensure WordPress is installed and updated. To install WordPress, review the Linode guide on
        installing WordPress on Ubuntu.

      5. WordPress sites are almost always accessed using a domain name. For more information on domains and how to create a DNS record, see the
        Linode DNS Manager guide.

      Note

      This guide is written for a non-root user. Commands that require elevated privileges are prefixed with sudo. If you are not familiar with the sudo command, see the
      Users and Groups guide.

      How to Configure the LEMP Stack to Support Caching

      WordPress caching can be enabled on NGINX without installing additional components. Ensure all Linux packages are updated before proceeding.

      The FastCGI instructions require a LEMP stack including the NGINX web server rather than the more common LAMP stack. These instructions are geared towards Ubuntu 22.04 LTS, but are generally applicable to any Linux distribution using a LEMP stack.

      How to Configure The WordPress Virtual Host for Caching

      Caching is typically enabled on a site-by-site basis. Caching directives are added directly to the .conf file for the WordPress virtual host. If encryption using HTTPS is enabled, the structure of the file might be different. However, the cache directives should still be added to the server and php code blocks as shown below. To enable the NGINX cache for WordPress, follow these instructions. For more information on these directives, see the
      NGINX documentation for the HTTP FastCGI module.

      1. Edit the virtual host .conf file for the WordPress domain. If WordPress is configured according to the Linode guide, this file is found at /etc/nginx/sites-available/example.com.conf. Substitute the actual name of the WordPress domain for example.com.conf.

        sudo nano /etc/nginx/sites-available/example.com.conf
      2. At the top of the file, before the server block, add the following three directives. Some attributes can be configured to best meet the requirements of the site.

        • The fastcgi_cache_path directive specifies the location of the cache and the cache parameters.
        • The keys_zone attribute defines the wpcache cache and the size of the shared memory zone. 200m is enough space for over a million keys. In many cases, this can be set to a smaller size.
        • The max_size field indicates the maximum size of the actual cache on disk. This guide sets max_size to 10g. Feel free to choose a larger or smaller amount.
        • The inactive attribute tells NGINX when to purge data from the cache. This example uses a two-hour limit, indicated by inactive=2h. Cache contents that have not been accessed during this period are deleted.
        • The fastcgi_cache_key directive defines the key format.
        • fastcgi_ignore_headers disables the processing of certain response header fields that could adversely affect caching.

        Note

        This example only enables caching on the WordPress domain. However, the directives in this section can also be configured on a server-wide basis. To apply these instructions to the entire server, add them to the top of the /etc/nginx/nginx.conf file instead. The remaining configuration must be added to the WordPress virtual host file.

        File: /etc/nginx/sites-available/example.com.conf
        1
        2
        3
        
        fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=wpcache:200m max_size=10g inactive=2h use_temp_path=off;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
      3. Include exceptions for any pages that must not be cached. Some examples of pages to bypass are the WordPress administration panel, cookies, session data, queries, and POST requests. When any of the following conditions are met, the temporary variable skip_cache is set to 1. Later on, this variable is used to inform NGINX not to search the cache or cache the new contents. Add the following lines inside the server block, immediately after the line beginning with index.

        File: /etc/nginx/sites-available/example.com.conf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        
        set $skip_cache 0;
        
        if ($request_method = POST) {
            set $skip_cache 1;
        }
        if ($query_string != "") {
            set $skip_cache 1;
        }
        
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)") {
            set $skip_cache 1;
        }
        
        if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
            set $skip_cache 1;
        }
      4. Optional To avoid caching requests from a specific access or test address, include the following lines. Substitute the actual addresses for testaddr1 and testaddr2.

        Note

        Adding this rule means it is not possible to test caching from these addresses.

        File: /etc/nginx/sites-available/example.com.conf
        1
        2
        3
        
        if ($remote_addr ~* "testaddr1|testaddr2") {
            set $skip_cache 1;
        }
      5. Add the next set of directives to the block beginning with location ~ \.php$ beneath any pre-existing instructions. This configuration includes the following directive:

        • The fastcgi_cache tells NGINX to enable caching. The name of the cache must match the name of the cache defined in the fastcgi_cache_path directive.
        • fastcgi_cache_valid defines the cache expiry time for specific HTTP status codes.
        • A handy NGINX attribute is the ability to deliver cached content when PHP-FPM or the database are unavailable. fastcgi_cache_use_stale error defines the conditions where NGINX should serve stale content. In many cases, this is preferable to returning an error page to clients.
        • fastcgi_cache_min_uses indicates how many times a page must be requested before it is cached. Setting this attribute to a larger value avoids caching rarely-used pages and can help manage the cache size.
        • fastcgi_cache_lock tells NGINX how to handle concurrent requests.
        • The fastcgi_cache_bypass and fastcgi_no_cache are assigned based on the value of skip_cache from the previous section. This tells NGINX not to search the cache and not to store any new content.
        • The add_header instruction is used to add a header field indicating whether the resource is taken from the cache or not. This field is handy for debug purposes, but is not strictly required in production code.
        1
        2
        3
        4
        5
        6
        7
        8
        
        fastcgi_cache wpcache;
        fastcgi_cache_valid 200 301 302 2h;
        fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
        fastcgi_cache_min_uses 1;
        fastcgi_cache_lock on;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        add_header X-FastCGI-Cache $upstream_cache_status;
      6. The entire file should be similar to the following example.

        File: /etc/nginx/sites-available/example.com.conf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        
        fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=wpcache:200m max_size=10g inactive=2h use_temp_path=off;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        
        server {
            listen 80;
            listen [::]:80;
        
            server_name example.com www.example.com;
            root /var/www/html/example.com/public_html;
            index index.html;
            set $skip_cache 0;
        
            if ($request_method = POST) {
                set $skip_cache 1;
            }
            if ($query_string != "") {
                set $skip_cache 1;
            }
        
            if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)") {
                set $skip_cache 1;
            }
        
            if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
                set $skip_cache 1;
            }
        
            location / {
                index index.php index.html index.htm;
                try_files $uri $uri/ =404;
            }
            location ~ \.php$ {
                fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
                include snippets/fastcgi-php.conf;
                fastcgi_cache wpcache;
                fastcgi_cache_valid 200 301 302 2h;
                fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
                fastcgi_cache_min_uses 1;
                fastcgi_cache_lock on;
                fastcgi_cache_bypass $skip_cache;
                fastcgi_no_cache $skip_cache;
                add_header X-FastCGI-Cache $upstream_cache_status;
            }
        
            location ~ /\.ht {
                deny all;
            }
        }
      7. Test the NGINX configuration to ensure it contains no errors.

        nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
        nginx: configuration file /etc/nginx/nginx.conf test is successful
            
      8. Restart NGINX to apply the changes.

        sudo systemctl restart nginx

      How to Test the WordPress Cache

      To test whether the WordPress cache is working correctly, use the command curl -I http://example.com, replacing example.com with the actual name of the WordPress site. Ensure you are not logged in to WordPress from this host and have not excluded the host address as a test domain address.

      1. Run the curl command and review the output. The X-FastCGI-Cache indicates MISS because the item has not been cached yet.

        curl -I http://example.com/
        HTTP/1.1 200 OK
        Server: nginx/1.18.0 (Ubuntu)
        Date: Wed, 23 Nov 2022 15:16:03 GMT
        Content-Type: text/html; charset=UTF-8
        Connection: keep-alive
        Link: <http://example.com/index.php?rest_route=/>; rel="https://api.w.org/"
        X-FastCGI-Cache: MISS
            
      2. Run the curl command again. This time, X-FastCGI-Cache now displays HIT because the item is retrieved from the NGINX cache.

        curl -I http://example.com/
        HTTP/1.1 200 OK
        Server: nginx/1.18.0 (Ubuntu)
        Date: Wed, 23 Nov 2022 15:16:08 GMT
        Content-Type: text/html; charset=UTF-8
        Connection: keep-alive
        Link: <http://example.com/index.php?rest_route=/>; rel="https://api.w.org/"
        X-FastCGI-Cache: HIT
            
      3. Run the command a few more times to confirm the cache is HIT each time.

      4. To ensure the exceptions are in effect, use curl to access the wp-admin page. This time, the X-FastCGI-Cache should indicate BYPASS.

        curl -I http://example.com/wp-admin/post.php
        Cache-Control: no-cache, must-revalidate, max-age=0
        ...
        X-FastCGI-Cache: BYPASS
            

      (Optional) How to Enable WordPress Cache Purging

      NGINX does not provide an easy way to clear the cache. While it is possible to write a purge function using NGINX commands, it is easier to use an existing WordPress plugin. The
      Nginx Helper plugin is fully compatible with WordPress and allows users to configure how and when to purge the cache. This plugin also allows users to manually clear the cache. To install and configure Nginx Helper, follow these steps.

      1. To support cache purging, install the following NGINX module.

        sudo apt install libnginx-mod-http-cache-purge
      2. Using the WordPress administration panel, install the Nginx Helper plugin. Select the Plugins option on the side panel, then select Add New.

        Select the WordPress Plugins Panel

      3. In the search box on the upper right corner of the WordPress administration panel, type NGINX Helper and hit Enter. The Nginx Helper plugin is one of the top results on the first line of the plugins. Click the Install Now button beside it to install.

        Install the Nginx Helper plugin

      4. After WordPress installs the plugin, select the Activate button to enable it.

        Activate the Nginx Helper plugin

      5. The Nginx Helper plugin requires some further configuration. From the side navigation panel, click the Settings label, then select Nginx Helper.

        Choose the Nginx Helper settings

      6. On the Nginx Helper Settings page, select Enable Purge. After this option is enabled, the WordPress administration panel displays more options. Ensure the Caching Method is set to nginx Fastcgi cache. Select the Purging Conditions according to your preferences. In most cases, the default settings are appropriate. Select the Save All Changes button to confirm and save the selections.

        Note

        Debug Options are available near the bottom of the configuration page to enable logging and timestamps for easier troubleshooting.

      7. Inside /etc/nginx/sites-available/example.com.conf, add the following lines to the server context. Add this block immediately after the location ~ \.php$ block.

        File: /etc/nginx/sites-available/example.com.conf
        1
        2
        3
        
        location ~ /purge(/.*) {
              fastcgi_cache_purge wpcache "$scheme$request_method$host$1";
        }
      8. Test the NGINX configuration and restart the web server.

        sudo nginx -t
        sudo systemctl restart nginx
      9. Update the main page for the WordPress site. Access the site from an address that is not logged in to WordPress. Despite the caching configuration, the browser displays the updated page.

      Conclusion

      The NGINX FastCGI caching mechanism improves site performance and reduces latency. The NGINX cache stores WordPress pages as static HTTP pages. This eliminates the demand to execute any PHP code or access the database. To enable caching on a WordPress site, add the configuration directly to the WordPress virtual host file. No additional components are required. The FastCGI cache directives allow users to set the cache size and expiry time and add further refinements. NGINX does not directly provide a method for purging the cache, but WordPress plugins like Nginx Helper provide this functionality.

      More Information

      You may wish to consult the following resources for additional information
      on this topic. While these are provided in the hope that they will be
      useful, please note that we cannot vouch for the accuracy or timeliness of
      externally hosted materials.



      Source link

      How to Use IPv6 With Apache and NGINX


      The
      Internet Protocol version 6 (IPv6) provides some performance advantages over IPv4 as well as additional features. On both the Apache and NGINX web servers, IPv6 is enabled by default. However, many users do not take full advantage of all IPv6 capabilities. This guide explains how to configure and use IPv6 on both the Apache and NGINX web server. It also introduces some useful IPv6 tools.

      What is IPv6?

      IPv6 is the most recent version of the Internet Protocol (IP). It is defined in
      RFC 8200. Like the original IPv4 protocol, IPv6 provides consistent addressing for systems connected to the internet. This standard allows for a shared understanding of how to route data packets from source to destination.

      IPv6 was implemented as a solution to IPv4 address exhaustion, meaning the internet was quickly depleting its pool of available IPv4 addresses. IPv6 is intended as a full replacement for IPv4, but the two systems continue to be used together. Many systems are provisioned with both IPv4 and IPv6 addresses. End users are not typically aware of what protocol they are using to access a given resource.

      Why to Use IPv6

      Many system administrators prefer to use IPv6 due to its improved performance and additional features. Here are some of the advantages of IPv6, compared to IPv4.

      • Much larger address space of about 340 duodecillion, or 3.4 × 10^38, addresses. This allows addresses to be liberally assigned and lets organizations receive large address blocks.
      • Better speed and performance. Web page load times are 5% to 15% faster with IPv6.
      • The header is smaller than the one used in IPv4, so IPv6 uses bandwidth more efficiently.
      • Better route aggregation, which limits the size of routing tables.
      • Improved multicast capabilities.
      • Security enhancements, including the mandatory use of Internet Protocol Security (IPSec) and optional data consistency verification.

      Although IPv4 and IPv6 are not directly compatible, several transitional and upgrade strategies are available.

      Before You Begin

      1. If you have not already done so, create a Linode account and Compute Instance. See our
        Getting Started with Linode and
        Creating a Compute Instance guides.

      2. Follow our
        Setting Up and Securing a Compute Instance guide to update your system. You may also wish to set the timezone, configure your hostname, create a limited user account, and harden SSH access.

      Note

      This guide is written for a non-root user. Commands that require elevated privileges are prefixed with sudo. If you are not familiar with the sudo command, see the
      Users and Groups guide.

      How to Configure IPv6

      How to Configure IPv6 on Apache

      The following sections explain how to configure IPv6 on an Apache web server. IPv6 is enabled on Apache by default. Users do not have to do anything else to start using IPv6. However, it is possible to adjust or refine the default configuration.

      Before proceeding, ensure Apache is already installed and running on the system. Enter the command apache2 -v to see the currently installed version. If the system displays the version number, Apache is already running on the system. If the system displays the error message Command 'apache2' not found, use the command sudo apt install apache2 to install it. These instructions are geared towards Ubuntu users, but are generally valid for all Linux distributions.

      Note

      On some distributions, including CentOS/RHEL, IPv6 must be enabled on a system-wide level. See the
      RHEL documentation for details.

      The standard ports.conf configuration includes the directives Listen 80 and Listen 443. This tells Apache to listen for HTTP and HTTPS connections for all addresses on well-known ports 80 and 443. In practice, many administrators configure Apache to only listen to the system IPv4 and IPv6 addresses. To force Apache to only listen for a specific IPv6 address, add the address to the ports.conf file. Additionally, use this technique to listen for different IPv6 addresses on different ports.

      Follow these steps to configure IPv6 addresses on Apache.

      1. Ensure Apache is operational. The systemctl status command should return a value of active.

        sudo systemctl status apache2
        
        apache2.service - The Apache HTTP Server
            Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
            Active: active (running) since Fri 2022-09-23 21:18:57 UTC; 9min ago
      2. For better security, enable and configure the ufw firewall. Allow the Apache Full profile to permit HTTP and HTTPS connections through the firewall. OpenSSH connections must also be allowed. Enable ufw after making all changes. Use the ufw status command to validate the settings.

        sudo ufw allow OpenSSH
        sudo ufw allow in "Apache Full"
        sudo ufw enable
        sudo ufw status
        
        Status: active
        To                         Action      From
        --                         ------      ----
        OpenSSH                    ALLOW       Anywhere
        Apache Full                ALLOW       Anywhere
        OpenSSH (v6)               ALLOW       Anywhere (v6)
        Apache Full (v6)           ALLOW       Anywhere (v6)
      3. Use the Linux ip command to determine the IPv6 address of the system. The ip command replaces the older and now deprecated ifconfig command. To narrow down the output, grep for the inet6 family in the output. The output typically displays several entries. Use the address that is shown as having scope global. In the following example, the second entry represents the relevant IPv6 system address.

        ip addr show | grep inet6
        
        inet6 ::1/128 scope host
        inet6 2001:db8::f03c:93ff:fe25:6762/64 scope global dynamic mngtmpaddr noprefixroute
        inet6 fe80::f03c:93ff:fe25:6762/64 scope link
      4. Edit the ports.conf file and add Listen directives for the addresses on port 80 for HTTP, and port 443 for HTTPS. Enclose the IPv6 address in brackets [] and follow it with the : symbol and the port number. To listen for both IPv4 and IPv6 traffic, add both addresses. To restrict access to IPv6, do not include the IPv4 entry. The following example demonstrates how to configure Apache to only listen for specific requests for its IPv6 and IPv4 addresses.

        Note

        On older installations of Apache, add this configuration to httpd.conf.

        sudo vi /etc/apache2/ports.conf
        
        File: /etc/apache2/ports.conf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        
        Listen [2001:db8::f03c:93ff:fe25:6762]:80
        Listen 192.0.2.162:80
        
        <IfModule ssl_module>
            Listen [2001:db8::f03c:93ff:fe25:6762]:443
            Listen 192.0.2.162:443
        </IfModule>
        
        <IfModule mod_gnutls.c>
            Listen [2001:db8::f03c:93ff:fe25:6762]:443
            Listen 192.0.2.162:443
        </IfModule>
      5. Before restarting Apache, run the configtest script to ensure the syntax is valid.

        sudo apache2ctl configtest
        
        Syntax OK
      6. Restart the Apache server to apply the changes.

        sudo systemctl restart apache2
        
      7. Verify Apache is still active.

        sudo systemctl status apache2
        
        apache2.service - The Apache HTTP Server
            Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
            Active: active (running) since Sat 2022-09-24 19:05:52 UTC; 7s ago
      8. Use the ss “socket statistics” command to confirm the new sockets are in LISTEN mode.

        sudo ss -ltpn
        
        State     Recv-Q    Send-Q                          Local Address:Port       Peer Address:Port    Process
        ...
        LISTEN    0         511                            192.0.2.162:80              0.0.0.0:*        users:(("apache2",pid=9303,fd=4),("apache2",pid=9302,fd=4),("apache2",pid=9301,fd=4))
        ...
        LISTEN    0         511          [2001:db8::f03c:93ff:fe25:6762]:80                 [::]:*        users:(("apache2",pid=9303,fd=3),("apache2",pid=9302,fd=3),("apache2",pid=9301,fd=3))
      9. As a final test, enter the system IPv6 address in the browser, enclosed between the [] brackets. You should see the default web page for the system. If both IPv4 and IPv6 addresses are configured, the host should also respond to a request for the IPv4 address.

        http://[2001:db8::f03c:93ff:fe25:6762]/
        

        Note

        To host multiple domains on the same system using different ports or IP addresses, additional changes to the virtual host files are necessary. See the
        Apache virtual host examples for more complete information. Virtual host changes are not necessary if all domains are accessed using the same IPv6 address and port.

      How to Configure IPv6 on NGINX

      IPv6 is already enabled on NGINX. No further steps have to be taken to use IPv6. However, it is possible to edit the NGINX configuration to only accept configurations for a specified address. Ensure NGINX is already installed on the system. If not, install it using sudo apt install nginx. To configure IPv6 settings on NGINX, follow these steps.

      1. Ensure NGINX is active using the systemctl status command.

        sudo systemctl status nginx
        
        nginx.service - A high performance web server and a reverse proxy server
             Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset:>
             Active: active (running) since Sun 2022-09-25 17:07:13 UTC; 17s ago
      2. NGINX should be properly secured using the ufw firewall. The Nginx Full profit permits HTTP and HTTPS access. Enter the following commands to grant NGINX firewall access.

        sudo ufw allow OpenSSH
        sudo ufw allow in "Nginx Full"
        sudo ufw enable
        sudo ufw status
        
        Status: active
        
        To                         Action      From
        --                         ------      ----
        OpenSSH                    ALLOW       Anywhere
        Nginx Full                 ALLOW       Anywhere
        OpenSSH (v6)               ALLOW       Anywhere (v6)
        Nginx Full (v6)            ALLOW       Anywhere (v6)
      3. To determine the system’s IPv6 address, use the Linux ip command. To restrict the output to IPv6 addresses, use the grep command and search for inet6 in the output. The relevant address is the one having scope global. This is the second address in the following results.

        ip addr show | grep inet6
        
        inet6 ::1/128 scope host
        inet6 2001:db8::f03c:93ff:fe64:3a0c/64 scope global dynamic mngtmpaddr noprefixroute
        inet6 fe80::f03c:93ff:fe64:3a0c/64 scope link
      4. To force NGINX to listen only to the default IPv6 address, add it to the main server block. Enclose the IPv6 address in square brackets []. The server block containing the address might be included in either the nginx.conf file or in a virtual host file. For instance, if the default virtual host is used, add the configuration to /etc/nginx/sites-enabled/default. If the domain uses its own virtual host, add the configuration there. It is easier to use an existing server block because multiple server blocks and default servers might conflict with each other. Add the following configuration to the server block as follows.

        File: /etc/nginx/sites-enabled/default
        1
        2
        3
        4
        5
        
        server {
            listen 80 default_server;
            listen [2001:db8::f03c:93ff:fe64:3a0c]:80 default_server;
        ...
            }
      5. Optional: To only listen for IPv6 requests, add the flag ipv6only=on to the IPv6 server configuration and delete the listen 80 directive. In this configuration, the server block should resemble the following example.

        File: /etc/nginx/sites-enabled/default
        1
        2
        3
        4
        
        server {
            listen [2001:db8::f03c:93ff:fe64:3a0c]:80 ipv6only=on default_server;
        ...
        }
      6. Before restarting the web server, use the NGINX test script to search for errors.

        sudo nginx -t
        
        nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
        nginx: configuration file /etc/nginx/nginx.conf test is successful
      7. Restart NGINX to incorporate the changes.

        sudo systemctl restart nginx
        
      8. Use the ss command to confirm there is a socket in the LISTEN state for the IPv6 address on the designated port.

        sudo ss -ltpn
        
        State  Recv-Q Send-Q                     Local Address:Port   Peer Address:Port Process
        LISTEN 0      4096                       127.0.0.53%lo:53          0.0.0.0:*     users:(("systemd-resolve",pid=454,fd=14))
        LISTEN 0      128                              0.0.0.0:22          0.0.0.0:*     users:(("sshd",pid=586,fd=3))
        LISTEN 0      511     [2001:db8::f03c:93ff:fe64:3a0c]:80             [::]:*     users:(("nginx",pid=3928,fd=6),("nginx",pid=3927,fd=6))
        LISTEN 0      128                                 [::]:22             [::]:*     users:(("sshd",pid=586,fd=4))
      9. To confirm the server is reachable using its IPv6 address, enter the address in a browser. Enclose the address in square [] brackets. If the ipv6only=on flag is on, requests for the IPv4 address should not resolve.

        [2001:db8::f03c:93ff:fe64:3a0c]
        

      Adding an IPv6 Address to the Domain DNS Records

      To enforce the use of an IPv6 address to access a hosted domain, update the DNS record for the domain. Change the DNS record to use the IPv6 address instead of the IPv4 address. For information on domain names and pointing the domain name to a Linode, see the
      Linode DNS Manager guide. All DNS changes take some time to propagate across the internet. Changing the DNS record does not affect direct access to the node using the raw IPv4 or IPv6 addresses.

      For IPv4 networks, several handy tools are available to debug and monitor networks. For IPv6, equivalent tools are available. These often have similar names to their IPv4 equivalents, sometimes with an extra 6 at the end.

      • To restrict the output of the ip command to only list IPv6 addresses, use the -6 option.

        ip -6 addr show
        
        1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
            inet6 ::1/128 scope host
               valid_lft forever preferred_lft forever
        2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
            inet6 2001:db8::f03c:93ff:fe25:6762/64 scope global dynamic mngtmpaddr noprefixroute
               valid_lft 5133sec preferred_lft 1533sec
            inet6 fe80::f03c:93ff:fe25:6762/64 scope link
               valid_lft forever preferred_lft forever
      • Likewise, the ss command accepts the same flag. The command ss -6 only shows socket statistics for IPv6 addresses.

        ss -6ltpn
        
        State          Recv-Q         Send-Q                                    Local Address:Port                 Peer Address:Port        Process
        LISTEN         0              128                                                [::]:22                           [::]:*
        LISTEN         0              511                    [2001:db8::f03c:93ff:fe25:6762]:80                           [::]:*
      • No special configuration is required for the ufw firewall. The Nginx Full profile permits both IPv4 and IPv6 connections.

      • The nslookup command is used to discover DNS information. The same command returns information about both IPv4 and IPv6 addresses, if any.

        nslookup google.com
        
        Server:     127.0.0.53
        Address:    127.0.0.53#53
        
        Non-authoritative answer:
        Name:   google.com
        Address: 142.250.187.206
        Name:   google.com
        Address: 2a00:1450:4009:816::200e
      • nslookup can be used for reverse lookups of IPv6 addresses. The output displays the address in reverse order due to nslookup display conventions.

        nslookup 2620:0:862:ed1a::1
        
        1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.1.d.e.2.6.8.0.0.0.0.0.0.2.6.2.ip6.arpa name = text-lb.esams.wikimedia.org
      • There are IPv6 variants of the popular ping and traceroute utilities. To ping an IPv6 address, use ping6.

        ping6 -c 3 2620:0:862:ed1a::1
        
        PING 2620:0:862:ed1a::1(2620:0:862:ed1a::1) 56 data bytes
        64 bytes from 2620:0:862:ed1a::1: icmp_seq=1 ttl=56 time=6.44 ms
        64 bytes from 2620:0:862:ed1a::1: icmp_seq=2 ttl=56 time=6.54 ms
        64 bytes from 2620:0:862:ed1a::1: icmp_seq=3 ttl=56 time=6.55 ms
        
        --- 2620:0:862:ed1a::1 ping statistics ---
        3 packets transmitted, 3 received, 0% packet loss, time 2004ms
        rtt min/avg/max/mdev = 6.442/6.510/6.550/0.048 ms
      • The IPv6 equivalent of traceroute is traceroute6. This utility is not pre-installed on Ubuntu. To install it, use sudo apt install traceroute.

        traceroute6 wikpedia.org
        
        traceroute to wikpedia.org (2620:0:862:ed1a::3), 30 hops max, 80 byte packets
        1  2600:3c0f:7::1460 (2600:3c0f:7::1460)  0.667 ms  0.618 ms  0.603 ms
        2  2600:3c0f:7:35::8 (2600:3c0f:7:35::8)  2.537 ms 2600:3c0f:7:35::7 (2600:3c0f:7:35::7)  3.104 ms  3.216 ms
        3  2600:3c0f:7:32::2 (2600:3c0f:7:32::2)  0.633 ms  0.621 ms 2600:3c0f:7:32::1 (2600:3c0f:7:32::1)  0.699 ms
        4  2600:3c0f:7:42::2 (2600:3c0f:7:42::2)  0.767 ms  0.755 ms 2600:3c0f:7:42::1 (2600:3c0f:7:42::1)  0.774 ms
        5  lonap.he.net (2001:7f8:17::1b1b:1)  1.933 ms * *

      Conclusion

      More organizations are beginning to use IPv6 in their networks instead of IPv4 due to its larger address space, enhanced functionality, and better performance. It is easy to use IPv6 on Apache or NGINX because IPV6 is already enabled by default on both platforms. However, both the NGINX and Apache IPv6 configurations can be edited for better security and more flexibility. To properly monitor IPv6 performance and debug issues, several additional tools are available. See the
      Apache and
      NGINX documentation for more information about IPv6.

      More Information

      You may wish to consult the following resources for additional information
      on this topic. While these are provided in the hope that they will be
      useful, please note that we cannot vouch for the accuracy or timeliness of
      externally hosted materials.



      Source link

      How To Set Up Nginx with HTTP/2 Support on Ubuntu 20.04


      A previous version of this tutorial was written by Sergey Zhukaev.

      Introduction

      Nginx is a fast and reliable open-source web server. It gained its popularity due to its low memory footprint, high scalability, ease of configuration, and support for a wide variety of protocols.

      HTTP/2 is a newer version of the Hypertext Transport Protocol, which is used on the Web to deliver pages from server to browser. HTTP/2 is the first major update of HTTP in almost two decades: HTTP1.1 was introduced to the public back in 1999 when webpages were much smaller in size. The Internet has dramatically changed since then, and we are now facing the limitations of HTTP 1.1. The protocol limits potential transfer speeds for most modern websites because it downloads parts of a page in a queue – the previous part must download completely before the download of the next part begins – and an average modern web page downloads dozens of individual CSS, javascript, and image assets.

      HTTP/2 solves this problem because it brings a few fundamental changes:

      • All requests are downloaded in parallel, not in a queue
      • HTTP headers are compressed
      • Pages transfer as a binary, not as a text file, which is more efficient
      • Servers can “push” data even without the user’s request, which improves speed for users with high latency

      Even though HTTP/2 does not require encryption, developers of the two most popular browsers, Google Chrome and Mozilla Firefox, have stated that for security reasons they will support HTTP/2 only for HTTPS connections. Hence, if you decide to set up servers with HTTP/2 support, you must also secure them with HTTPS.

      This tutorial will help you set up a fast and secure Nginx server with HTTP/2 support.

      Prerequisites

      Before getting started, you will need a few things:

      • An Ubuntu 20.04 server set up by following the Ubuntu 20.04 initial server setup guide, including a sudo non-root user and a firewall.
      • Nginx installed on your server, which you can do by following How To Install Nginx on Ubuntu 20.04.
      • A domain name configured to point to your server. You can purchase one on Namecheap or get one for free on Freenom. You can learn how to point domains to DigitalOcean Droplets by following the documentation on How To Manage Your Domain With DigitalOcean.
      • A TLS/SSL certificate configured for your server. You have three options:
      • Nginx configured to redirect traffic from port 80 to port 443, which should be covered by the previous prerequisites.
      • Nginx configured to use a 2048-bit or higher Ephemeral Diffie-Hellman (DHE) key, which should also be covered by the previous prerequisites.

      Step 1 — Enabling HTTP/2 Support

      If you followed the server block set up step in the Nginx installation tutorial, you should have a server block for your domain at /etc/nginx/sites-available/your_domain with the server_name directive already set appropriately. The first change we will make will be to modify your domain’s server block to use HTTP/2.

      Open the configuration file for your domain using nano or your preferred editor:

      • sudo nano /etc/nginx/sites-enabled/your_domain

      In the file, locate the listen variables associated with port 443:

      /etc/nginx/sites-enabled/your_domain

      ...
          listen [::]:443 ssl ipv6only=on; 
          listen 443 ssl; 
      ...
      

      The first one is for IPv6 connections. The second one is for all IPv4 connections. We will enable HTTP/2 for both.

      Modify each listen directive to include http2:

      /etc/nginx/sites-enabled/your_domain

      ...
          listen [::]:443 ssl http2 ipv6only=on; 
          listen 443 ssl http2; 
      ...
      

      This tells Nginx to use HTTP/2 with supported browsers.

      Save the configuration file and exit the text editor. If you are using nano, press Ctrl+X then, when prompted, Y and then Enter.

      Whenever you make changes to Nginx configuration files, you should check the configuration for errors, using the -t flag, which runs Nginx’s built-in syntax check command:

      If the syntax is error-free, you will receive output like the following:

      Output of sudo nginx -t

      nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
      nginx: configuration file /etc/nginx/nginx.conf test is successful
      

      Next, you’ll configure your Nginx server to use a more restrictive list of ciphers to improve your server’s security.

      Step 2 — Removing Old and Insecure Cipher Suites

      HTTP/2 has a blocklist of old and insecure ciphers that should be avoided. Cipher suites are cryptographic algorithms that describe how the transferred data should be encrypted.

      The method you’ll use to define the ciphers depends on how you’ve configured your TLS/SSL certificates for Nginx.

      If you used Certbot to obtain your certificates, it also created the file /etc/letsencrypt/options-ssl-nginx.conf that contains ciphers that aren’t secure enough for HTTP/2. However, modifying this file will prevent Certbot from applying updates in the future, so we’ll just tell Nginx not to use this file and we’ll specify our own list of ciphers.

      Open the server block configuration file for your domain:

      sudo nano /etc/nginx/sites-enabled/your_domain
      

      Locate the line that includes the options-ssl-nginx.conf file and comment it out by adding a # character to the beginning of the line:

      /etc/nginx/sites-enabled/your_domain

      
          # include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot<^>
      

      Below that line, add this line to define the allowed ciphers:

      /etc/nginx/sites-enabled/your_domain

      
      ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
      

      Save the file and exit the editor.

      If you used self-signed certificates or used a certificate from a third party and configured it according to the prerequisites, open the file /etc/nginx/snippets/ssl-params.conf in your text editor:

      • sudo nano /etc/nginx/snippets/ssl-params.conf

      Locate the following line:

      /etc/nginx/snippets/ssl-params.conf

      ...
      ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
      ...
      

      Modify it to use the following list of ciphers:

      /etc/nginx/snippets/ssl-params.conf

      
      ...
      ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
      

      Save the file and exit your editor.

      Once again, check the configuration for syntax errors using the nginx -t command:

      If you encounter any errors, address them and test again.

      Once your configuration passes the syntax check, restart Nginx using the systemctl command:

      • sudo systemctl reload nginx.service

      With the server restarted, let’s verify that it works.

      Step 3 — Verifying that HTTP/2 is Enabled

      Let’s ensure the server is running and working with HTTP/2.

      Use the curl command to make a request to your site and view the headers:

      • curl -I -L --http2 https://your_domain

      You’ll receive output like the following:

      HTTP/2 200
      server: nginx/1.18.0 (Ubuntu)
      date: Wed, 10 Nov 2021 17:53:10 GMT
      content-type: text/html
      content-length: 612
      last-modified: Tue, 09 Nov 2021 23:18:37 GMT
      etag: "618b01cd-264"
      accept-ranges: bytes
      

      You can also verify that HTTP/2 is in use in Google Chrome. Open Chrome and navigate to https://your_domain. Open the Chrome Developer Tools (View -> Developer -> Developer Tools) and reload the page (View -> Reload This Page). Navigate to the Network tab, right-click on the table header row that starts with Name, and select the Protocol option from the popup menu.

      You’ll have a new Protocol column that contains h2 (which stands for HTTP/2), indicating that HTTP/2 is working.

      Chrome Developer Tools HTTP/2 check

      At this point, you’re ready to serve content through the HTTP/2 protocol. Let’s improve security and performance by enabling HSTS.

      Step 4 — Enabling HTTP Strict Transport Security (HSTS)

      Even though your HTTP requests redirect to HTTPS, you can enable HTTP Strict Transport Security (HSTS) to avoid having to do those redirects. If the browser finds an HSTS header, it will not try to connect to the server via regular HTTP again for a given time period. No matter what, it will exchange data using only encrypted HTTPS connection. This header also protects us from protocol downgrade attacks.

      Open the server block configuration file for your domain again:

      sudo nano /etc/nginx/your_domain
      

      Add this line to the same block of the file containing the SSL ciphers in order to enable HSTS:

      /etc/nginx/your_domain

      server {
      ...
          ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
          add_header Strict-Transport-Security "max-age=15768000" always;
      }
      ...
      

      The max-age is set in seconds. The value 15768000 is equivalent to 6 months.

      By default, this header is not added to subdomain requests. If you have subdomains and want HSTS to apply to all of them, you should add the includeSubDomains variable at the end of the line, like this:

      /etc/nginx/your_domain

      add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
      

      Save the file, and exit the editor.

      Once again, check the configuration for syntax errors:

      Finally, restart the Nginx server to apply the changes.

      • sudo systemctl reload nginx.service

      Conclusion

      Your Nginx server is now serving HTTP/2 pages. If you want to test the strength of your SSL connection, please visit Qualys SSL Lab and run a test against your server. If everything is configured properly, you should get an A+ mark for security.

      To learn more about how Nginx parses and implements server block rules, try reading Understanding Nginx Server and Location Block Selection Algorithms.



      Source link