How to Setup Nginx FastCGI Cache on Ubuntu 26.04, 24.04 and 22.04

Keep repeat PHP requests from overworking the backend across Ubuntu 26.04, 24.04, and 22.04 LTS. The same stock Nginx workflow supports authenticated bypass, shared or per-site planning, MISS diagnostics, and controlled disk or RAM limits despite version differences.

Last updatedAuthorJoshua JamesRead time12 minGuide typeUbuntu

Repeat anonymous visits should not make PHP-FPM rebuild the same page every time. Nginx FastCGI Cache on Ubuntu stores eligible PHP responses so later requests can become a fast cache HIT instead of another backend PHP request.

The configuration uses Ubuntu’s packaged Nginx and WordPress-oriented exclusions for admin paths, login cookies, HTTP authentication, POST requests, and query strings. Do not apply these exclusions unchanged to Laravel, phpMyAdmin, WooCommerce, or another session-driven application; add and test that application’s private paths and session cookies before enabling cache.

These steps support Ubuntu 26.04 LTS, 24.04 LTS, and 22.04 LTS with Ubuntu’s stock Nginx packages. Standard FastCGI caching works across this scope, but URL-based fastcgi_cache_purge is not available in stock Nginx unless you add a separate cache-purge module or use a commercial Nginx build.

Prerequisites

Start with a working Nginx and PHP-FPM site on Ubuntu. If you still need the base web server, use Install Nginx on Ubuntu. If PHP-FPM is not configured yet, use Install PHP on Ubuntu or the full Install WordPress with Nginx on Ubuntu stack guide.

You also need an existing Nginx server block for the site you want to cache. The examples use example.com.conf and www.example.com as placeholders; replace them with your real server block filename and hostname.

Install curl if your server does not already have it. The cache checks use it to read response headers:

sudo apt update
sudo apt install curl

Create the FastCGI Cache Directory

Create a dedicated cache directory under /var/cache/nginx and give the Nginx worker user permission to write cache files:

sudo install -d -o www-data -g www-data -m 0750 /var/cache/nginx/fastcgi

Confirm the directory ownership before adding it to nginx.conf:

sudo ls -ld /var/cache/nginx/fastcgi
drwxr-x--- 2 www-data www-data 4096 Apr 28 10:00 /var/cache/nginx/fastcgi

FastCGI Cache vs Static File Caching

FastCGI Cache stores dynamic responses generated through PHP-FPM. It does not cache normal static files such as images, CSS, JavaScript, fonts, or downloads because those files should be served directly by Nginx without reaching PHP-FPM.

It is also separate from PHP OPcache, directio, and the Linux page cache. OPcache stores compiled PHP bytecode inside PHP, while directio and the Linux page cache affect file I/O for static or large file reads rather than full PHP-generated HTTP responses.

If your goal is static-file performance, configure browser caching for static assets in Nginx, enable open file cache in Nginx, enable the Nginx sendfile directive, or enable Gzip compression in Nginx. Use FastCGI Cache when repeat PHP pages are the slow part.

Confirm Your PHP-FPM Socket

Before editing the PHP location block, confirm the socket path your PHP-FPM pool exposes. Ubuntu’s default PHP branch differs by LTS release, so the safest path is to inspect the running socket files:

ls -l /run/php/*.sock

Default Ubuntu packages normally use these versioned sockets:

Ubuntu releaseDefault PHP-FPM socket
Ubuntu 26.04 LTS/run/php/php8.5-fpm.sock
Ubuntu 24.04 LTS/run/php/php8.3-fpm.sock
Ubuntu 22.04 LTS/run/php/php8.1-fpm.sock

If /run/php/php-fpm.sock exists as a symlink on your server, you can use it. Otherwise, use the versioned socket shown by ls -l /run/php/*.sock in the Nginx fastcgi_pass line.

Check Ubuntu’s FastCGI Snippet

Ubuntu’s stock Nginx package provides /etc/nginx/snippets/fastcgi-php.conf for PHP-FPM server blocks. The snippet splits PHP path information and includes fastcgi.conf, which supplies the required SCRIPT_FILENAME parameter.

sudo grep -HnE 'fastcgi_split_path_info|include fastcgi.conf' /etc/nginx/snippets/fastcgi-php.conf
sudo grep -Hn 'SCRIPT_FILENAME' /etc/nginx/fastcgi.conf
/etc/nginx/snippets/fastcgi-php.conf:2:fastcgi_split_path_info ^(.+?\.php)(/.*)$;
/etc/nginx/snippets/fastcgi-php.conf:13:include fastcgi.conf;
/etc/nginx/fastcgi.conf:2:fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

Use the Ubuntu snippet in your PHP location block unless your site intentionally owns a custom FastCGI include. If you need to build the PHP-FPM location from scratch first, use Configure Nginx PHP-FPM, then add caching after the PHP handler works.

Configure the Cache Zone in nginx.conf

Open the main Nginx configuration file and add the cache zone inside the top-level http block. The fastcgi_cache_path directive belongs in http, not inside an individual server or location block.

sudo nano /etc/nginx/nginx.conf

Add these lines inside the http block, before the final include lines if possible:

fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fcgicache:10m max_size=1g inactive=60m use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Save and close the file. In nano, press Ctrl+O, press Enter, then press Ctrl+X.

FastCGI Directive Placement Reference

The official Nginx FastCGI module documentation defines where each directive is allowed. These are the placement rules used in this configuration:

DirectiveValid contextDefault or package noteUsed for
fastcgi_cache_pathhttpNo default path.Creates the cache directory settings and shared memory zone.
fastcgi_cache_keyhttp, server, locationNo default key.Defines the unique key for each cached response.
fastcgi_cachehttp, server, locationDefault is off.Enables a named cache zone for matching requests.
fastcgi_cache_methodshttp, server, locationDefault is GET HEAD.Limits which request methods can be cached.
fastcgi_cache_validhttp, server, locationNo default cache time.Sets how long selected response codes stay cached.
fastcgi_cache_lockhttp, server, locationDefault is off.Allows one request to populate a missing cache item while similar requests wait.
fastcgi_cache_bypasshttp, server, locationNo default skip condition.Prevents serving a cached response when a condition matches.
fastcgi_no_cachehttp, server, locationNo default store condition.Prevents saving a response when a condition matches.
fastcgi_cache_purgehttp, server, locationUpstream directive exists, but stock Ubuntu Nginx does not include the purge feature by default.Not used here; clear cache files directly unless you knowingly install a purge-enabled build.

Understanding the Cache Path Parameters

  • /var/cache/nginx/fastcgi: Stores cached FastCGI response files under a dedicated Nginx cache path.
  • levels=1:2: Splits cached files into a two-level directory tree so one directory does not contain too many entries.
  • keys_zone=fcgicache:10m: Creates a shared memory zone named fcgicache for cache keys and metadata. Open-source Nginx stores roughly 8,000 keys per megabyte, so this starter value can track about 80,000 active keys.
  • max_size=1g: Caps the on-disk cache size. Nginx removes least recently used entries as the cache approaches this limit; increase it only after checking available storage and real cache use.
  • inactive=60m: Removes cached entries that have not been requested for 60 minutes, even if their normal cache lifetime has not expired.
  • use_temp_path=off: Writes cache files directly under the cache directory instead of staging them in a separate temporary path first.

The cache key combines the request scheme, method, host, and URI. Including $request_method keeps HEAD verification probes separate from normal GET page views, while fastcgi_cache_methods GET HEAD and the skip rules in your server block keep POST responses out of cache entirely. Do not add fastcgi_cache_convert_head; current Nginx provides proxy_cache_convert_head for proxy cache, not an equivalent FastCGI directive.

Use FastCGI Cache for Multiple Sites

Multiple server blocks can use the same fcgicache zone because the cache key includes $host, so identical paths on different hostnames do not share one cache entry. Shared zones also share memory, disk limits, eviction, and manual clearing; deleting files from /var/cache/nginx/fastcgi clears cached responses for every site using that path.

Use a distinct cache directory and keys_zone name for each site when you need independent size limits or per-site clearing. Each server block must then reference its own zone with fastcgi_cache. Keep $host in every cache key even when zones are separate.

Configure FastCGI Cache in Your Server Block

Open the server block for the site you want to cache:

sudo nano /etc/nginx/sites-available/example.com.conf

If your server uses a different layout, such as an nginx.org package with /etc/nginx/conf.d/, edit the active site file used by that package instead of forcing the Debian-style sites-available path.

Add Cache Exclusion Rules

Add the skip-cache rules inside the server block, before the PHP location block. These rules keep WordPress admin pages, logged-in sessions, POST requests, and query-string URLs out of cache.

# Cache by default
set $skip_cache 0;

# Do not cache WordPress admin, feeds, sitemaps, or PHP utility endpoints
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*\.php|^/feed/|/tag/.*/feed/|index.php|/.*sitemap.*\.(xml|xsl)") {
    set $skip_cache 1;
}

# Do not cache logged-in users, comment authors, or password-protected posts
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
    set $skip_cache 1;
}

# Do not cache requests carrying HTTP authentication credentials
if ($http_authorization != "") {
    set $skip_cache 1;
}

# Do not cache POST requests or query-string URLs
if ($request_method = POST) {
    set $skip_cache 1;
}

if ($query_string != "") {
    set $skip_cache 1;
}

This is a limited and common Nginx if use: each condition only changes the $skip_cache variable. Avoid turning this block into complex rewrite logic.

Enable Caching in the PHP Location Block

Add the cache directives inside your existing location ~ \.php$ block. Keep your current include, fastcgi_param, and fastcgi_pass settings, but connect them to the cache zone and skip-cache variable.

location ~ \.php$ {
    include snippets/fastcgi-php.conf;

    # Use the PHP-FPM socket you confirmed earlier.
    fastcgi_pass unix:/run/php/php-fpm.sock;

    # FastCGI cache settings
    fastcgi_cache fcgicache;
    fastcgi_cache_methods GET HEAD;
    fastcgi_cache_valid 200 60m;
    fastcgi_cache_valid 301 302 10m;
    fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
    fastcgi_cache_min_uses 1;
    fastcgi_cache_lock on;

    # Connect skip-cache rules to read and write behavior
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;

    # Show cache state in response headers
    add_header X-FastCGI-Cache $upstream_cache_status always;
}

If /run/php/php-fpm.sock is not present, replace that line with your versioned socket, such as fastcgi_pass unix:/run/php/php8.3-fpm.sock; on a default Ubuntu 24.04 PHP-FPM install.

Understanding the Cache Directives

  • fastcgi_cache fcgicache: Enables caching with the shared memory zone defined in nginx.conf.
  • fastcgi_cache_methods GET HEAD: Keeps FastCGI caching limited to header and normal page reads. Nginx includes GET and HEAD by default, but the explicit line makes the policy easy to audit.
  • fastcgi_cache_valid 200 60m: Uses 60 minutes for successful PHP responses when higher-priority application response headers do not set or disable caching. For microcaching, use a much shorter value, such as seconds instead of minutes.
  • fastcgi_cache_valid 301 302 10m: Caches PHP-generated redirects briefly so stale redirect behavior is less likely to linger.
  • fastcgi_cache_use_stale: Allows Nginx to serve stale cached content during selected PHP-FPM errors or updates.
  • fastcgi_cache_lock on: Lets one request populate a missing cache entry while matching concurrent requests wait, reducing backend spikes.
  • fastcgi_cache_bypass $skip_cache: Prevents Nginx from reading from cache when the request should stay dynamic.
  • fastcgi_no_cache $skip_cache: Prevents Nginx from saving the response when the request should stay dynamic.
  • X-FastCGI-Cache: Adds a visible response header. Common values are MISS, HIT, BYPASS, EXPIRED, STALE, and UPDATING.

Application response headers can override the configured lifetime. X-Accel-Expires: 0 disables caching, while Cache-Control and Expires can set a different lifetime. Nginx also avoids storing responses with Set-Cookie or Vary: *. Keep request-side authentication and session bypass rules anyway: response headers cannot stop Nginx from serving an existing anonymous cache entry before the request reaches PHP-FPM.

This setup intentionally does not cache POST responses. Caching POST traffic can expose user-specific form, login, checkout, or account state on dynamic sites.

Test and Apply the Configuration

Test the Nginx configuration before applying it:

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

Reload Nginx after the syntax test passes:

sudo systemctl reload nginx

Verify FastCGI Cache is Working

Send a normal GET request to a public page that anonymous visitors can view while printing only the response headers. Use the same hostname and scheme your real site uses; if the site does not already use TLS, keep the test URL on http://:

curl -fsS -D - -o /dev/null http://www.example.com/

The first eligible request usually shows MISS because Nginx has not cached the response yet:

HTTP/1.1 200 OK
Server: nginx
X-FastCGI-Cache: MISS

Repeat the GET probe:

curl -fsS -D - -o /dev/null http://www.example.com/
HTTP/1.1 200 OK
Server: nginx
X-FastCGI-Cache: HIT

A later HIT confirms that Nginx served a normal GET response from FastCGI Cache, which matches the method browsers use for page loads. HEAD requests can still be useful for quick header checks, but the $request_method cache key keeps HEAD and GET entries separate.

A BYPASS value is expected for cacheable GET or HEAD requests that match a skip rule, such as logged-in cookies or query-string URLs. POST requests stay uncached, but they may not show an X-FastCGI-Cache value because this configuration only caches GET and HEAD methods.

Inspect Cached Files

List a few cache files to confirm Nginx is writing response entries under the cache directory:

sudo find /var/cache/nginx/fastcgi -type f | head -5
/var/cache/nginx/fastcgi/9/c2/b7f54b2df7773722d382f4809d65029c2
/var/cache/nginx/fastcgi/a/17/8b3f9e4c2a1d876f5e0c9d4b3a2f17a17

Clear FastCGI Cache on Ubuntu

Stock Ubuntu Nginx does not provide URL-based fastcgi_cache_purge in the default package. If you add that directive without the required module, sudo nginx -t fails with an unknown directive error.

For a stock Ubuntu setup, clear cached FastCGI response files directly from the dedicated cache directory. The command clears only that FastCGI response cache; it does not clear browser cache headers, CDN cache, static-file tuning, or a separate proxy_cache path.

sudo find /var/cache/nginx/fastcgi -type f -delete

Run the delete command only against the dedicated FastCGI cache directory. Do not run broad cleanup commands against /var/cache/nginx, /etc/nginx, or your web root.

Do not substitute proxy_cache_purge for this FastCGI setup. Proxy cache and FastCGI cache use different upstream modules even though their cache concepts look similar; use Configure Nginx proxy cache when your upstream is an HTTP proxy instead of PHP-FPM.

After clearing files, the next eligible request should show MISS, and the following request should return to HIT. CMS plugins can coordinate purge behavior only when your server exposes a supported purge method or lets the application safely remove local cache files.

Optimize with RAM-Based Cache Storage

A tmpfs mount can keep the FastCGI cache in RAM. This is optional and works best when the server has enough free memory for both the application and cached responses.

RAM-based cache files disappear on reboot. That is acceptable for many sites because the cache rebuilds from traffic, but it is not a substitute for persistent application data.

A 512 MiB tmpfs needs a cache limit below 512 MiB so Nginx can remove old entries before the mount is full. Change the earlier fastcgi_cache_path line to use max_size=384m before mounting the RAM-backed cache:

fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fcgicache:10m max_size=384m inactive=60m use_temp_path=off;

Confirm Ubuntu’s www-data account uses numeric user and group ID 33. The fstab entry uses numeric values because mount options are processed before normal application startup:

id -u www-data
id -g www-data
33
33

Open /etc/fstab:

sudo nano /etc/fstab

Add a line for the cache mount. The ownership and mode options preserve the writable www-data cache root after every boot. Adjust size=512M and keep max_size below the selected capacity:

tmpfs   /var/cache/nginx/fastcgi   tmpfs   rw,nosuid,nodev,noexec,size=512M,uid=33,gid=33,mode=0750   0 0

Stop Nginx and clear any existing disk-backed cache files before mounting tmpfs. Otherwise, those files remain hidden beneath the RAM mount and continue using disk space until it is unmounted:

sudo systemctl stop nginx && \
sudo find /var/cache/nginx/fastcgi -type f -delete && \
sudo mount /var/cache/nginx/fastcgi

Test the adjusted configuration while Nginx is stopped:

sudo nginx -t

Start Nginx only after the configuration test passes:

sudo systemctl start nginx

Verify the cache path now uses tmpfs:

df -h /var/cache/nginx/fastcgi
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           512M     0  512M   0% /var/cache/nginx/fastcgi

Verify the mounted cache root retains the intended owner, group, mode, and mount options:

stat -c '%U %G %a' /var/cache/nginx/fastcgi
findmnt -no OPTIONS -T /var/cache/nginx/fastcgi
www-data www-data 750

The findmnt line should include rw, nosuid, nodev, noexec, size=524288k, mode=750, uid=33, and gid=33. The kernel may also report default mount options that were not written explicitly in /etc/fstab.

Troubleshoot FastCGI Cache Issues

Cache Always Shows MISS

If every request returns X-FastCGI-Cache: MISS, first test a public page while logged out. Inspect application response headers before changing permissions or skip rules:

curl -sS -D - -o /dev/null http://www.example.com/ | grep -iE '^(HTTP/|Cache-Control:|Expires:|Set-Cookie:|Vary:|X-FastCGI-Cache:)'

Cache-Control: private, no-cache, or no-store, a Set-Cookie header, or Vary: * can prevent Nginx from storing the response. An application can also send X-Accel-Expires: 0, although Nginx normally processes that internal control header without passing it to the client; check the application or framework cache policy when the visible headers do not explain the MISS. Fix that policy only when the page is genuinely public, and do not use fastcgi_ignore_headers to force private or session responses into cache.

Next, inspect the cache directory owner, group, and mode:

stat -c '%U %G %a' /var/cache/nginx/fastcgi
www-data www-data 750

If the values differ, restore the expected directory state:

sudo install -d -o www-data -g www-data -m 0750 /var/cache/nginx/fastcgi

Retest the same public URL twice after correcting the directory:

curl -fsS -D - -o /dev/null http://www.example.com/
curl -fsS -D - -o /dev/null http://www.example.com/

If the second request remains a MISS with correct permissions and no blocking response header, confirm the URL has no query string and the request carries no WordPress login cookie or authorization header. Then review the $skip_cache conditions for a pattern that matches the public path. Do not loosen a rule until you have proved the affected page contains no private or session-specific response.

fastcgi_cache_path Directive Is Not Allowed Here

If sudo nginx -t reports that fastcgi_cache_path is not allowed, the directive is probably inside a server or location block. Move it to the top-level http block in /etc/nginx/nginx.conf.

nginx: [emerg] "fastcgi_cache_path" directive is not allowed here

After moving the directive, retest the configuration and reload Nginx only when the test passes:

sudo nginx -t && sudo systemctl reload nginx

Unknown Directive fastcgi_cache_purge

If Nginx reports an unknown fastcgi_cache_purge directive, remove that purge block from the stock configuration. The directive appears in the official FastCGI module reference, but the purge functionality is not included in Ubuntu’s default Nginx package.

nginx: [emerg] unknown directive "fastcgi_cache_purge"

Retest the edited configuration, then reload Nginx after the test succeeds:

sudo nginx -t && sudo systemctl reload nginx

Configuration Test Fails with mkdir()

If Nginx cannot create or open the cache path, recreate the directory with the expected ownership, retest the configuration, and reload Nginx after the test succeeds:

nginx: [emerg] mkdir() "/var/cache/nginx/fastcgi" failed (2: No such file or directory)
sudo install -d -o www-data -g www-data -m 0750 /var/cache/nginx/fastcgi
sudo nginx -t && sudo systemctl reload nginx

Cache Shows BYPASS Instead of HIT

A BYPASS status means one of the skip-cache rules matched on a cacheable GET or HEAD request. Common triggers are WordPress login cookies, comment-author cookies, password-protected content, query strings, and admin paths such as /wp-admin/.

Test a public URL twice with a clean request before changing the rules:

curl -fsS -D - -o /dev/null http://www.example.com/
curl -fsS -D - -o /dev/null http://www.example.com/

If the clean request reaches HIT, the browser cookie, query string, authorization header, or protected path caused the bypass as intended. If it still shows BYPASS, review the $skip_cache patterns for the public path. POST requests are excluded by fastcgi_cache_methods GET HEAD, so a blank cache-status header on POST traffic is not the same issue as a GET request that stays on BYPASS.

Remove FastCGI Cache Configuration

To disable FastCGI Cache, remove the fastcgi_cache_path and fastcgi_cache_key lines from the http block in /etc/nginx/nginx.conf. Then remove the $skip_cache rules, fastcgi_cache* directives, fastcgi_no_cache, and X-FastCGI-Cache header line from the site server block.

Test and reload Nginx after removing the directives:

sudo nginx -t
sudo systemctl reload nginx

If you configured the optional tmpfs mount, remove its matching line from /etc/fstab and unmount the cache path before deleting the directory:

sudo umount /var/cache/nginx/fastcgi

Skip umount when the cache uses normal disk storage. Clear remaining files only after the active configuration no longer references the path and any tmpfs mount is gone:

sudo rm -rf -- /var/cache/nginx/fastcgi

Back up the server block first if you may need to re-enable caching later.

Best Practices

  • Cache only proven-public pages: The supplied rules cover common WordPress core sessions, not every plugin or application. Add and test the exact cookies and paths used by carts, checkout pages, accounts, previews, and private APIs.
  • Watch HIT ratios: Use the X-FastCGI-Cache header, access logs, or monitoring tools to confirm repeat public traffic becomes HIT.
  • Size the cache conservatively: Start with a modest max_size and adjust after watching disk or RAM use.
  • Coordinate with CDN caching: FastCGI Cache controls origin PHP responses. Cloudflare, reverse proxies, hosting panels, and application caches may add their own cache layer.
  • Separate cache safety from general hardening: Security headers and rate limiting do not prevent private responses from entering cache. Prove the bypass rules first, then configure security headers in Nginx or rate limit in Nginx as separate controls.

Further Reading

Conclusion

Nginx is serving eligible anonymous PHP responses from FastCGI Cache on Ubuntu with WordPress-oriented exclusions, authenticated-request bypass, visible MISS/HIT checks, and a rollback path. Keep application-specific sessions and e-commerce routes uncached, monitor upstream response headers and disk or tmpfs capacity, and use separate cache zones when sites need independent limits or clearing.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show our tutorials more often in Top Stories and mark them as preferred in AI Mode and AI Overviews when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee

2 thoughts on “How to Setup Nginx FastCGI Cache on Ubuntu 26.04, 24.04 and 22.04”

    • Good question, J. The shared setup is automatic as long as both server blocks use fastcgi_cache fcgicache; and the cache key includes $host, as shown in the updated configuration. Site 1 and site 2 can then use the same zone and directory without sharing entries for identical paths. They will still share the size limit, eviction, and manual clearing.

      Use a separate cache directory and keys_zone name for each site only when you need independent limits or want to clear one site’s cache without clearing the other. I added the Use FastCGI Cache for Multiple Sites section to cover both options.

      Reply
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<a href="https://example.com">link</a> link
<blockquote>quote</blockquote> quote block

Add to the discussion

Questions, fixes, command output, and version notes help keep this guide current.

Verify before posting: