Skip to main content

NGINX

NGINX Set-Misc Module: Encoding and Hashing Guide

by ,


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

The NGINX set-misc module extends the standard rewrite module with powerful utility functions for encoding, hashing, escaping, and manipulating variables. Instead of proxying requests to a backend application just to compute an MD5 hash or encode a string to Base64, you can perform these operations directly in your NGINX configuration.

This module is essential for building signed URLs, generating secure tokens, escaping user input for SQL or JSON, and handling data transformations at the edge. Combined with modules like echo and headers-more, the set-misc module transforms NGINX into a versatile request processing engine.

What Is the NGINX Set-Misc Module?

The NGINX set-misc module (ngx_http_set_misc_module) is developed by the OpenResty project and provides 27 directives for variable manipulation. These directives work seamlessly with the standard set directive and can be mixed with other rewrite module directives like if and rewrite.

The module depends on the NGINX Development Kit (NDK) and covers these categories:

  • Encoding/Decoding: Base64, Base64URL, Base32, Hexadecimal
  • Hashing: MD5, SHA1, HMAC-SHA1, HMAC-SHA256
  • Escaping: URI encoding, SQL quoting, PostgreSQL quoting, JSON quoting
  • Random Generation: Pseudo-random numbers, cryptographically secure tokens
  • Utilities: Conditional assignment, time formatting, round-robin rotation

Every directive operates during the rewrite phase and can use NGINX variables as input. The results are stored in variables that can be used anywhere in your configuration.

Installing the NGINX Set-Misc Module

RHEL, CentOS, AlmaLinux, Rocky Linux

Install the module from the GetPageSpeed extras repository:

sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx-module-set-misc

The package automatically installs the required NGINX Development Kit (NDK) as a dependency.

Add module loading to /etc/nginx/nginx.conf at the very top, before any other blocks:

include /usr/share/nginx/modules/*.conf;

Or manually load the modules:

load_module modules/ndk_http_module.so;
load_module modules/ngx_http_set_misc_module.so;

Important: The NDK module must be loaded before the set-misc module because set-misc depends on NDK.

Debian and Ubuntu

First, set up the GetPageSpeed APT repository, then install:

sudo apt-get update
sudo apt-get install nginx-module-set-misc

On Debian/Ubuntu, the package handles module loading automatically. No load_module directive is needed.

For the full list of available platforms and versions, see the RPM module page or APT module page.

Verify the Installation

After installation, verify that NGINX accepts the configuration:

sudo nginx -t

If you see “syntax is ok” and “test is successful,” the module is loaded and ready to use.

NGINX Set-Misc Module Directives Reference

The module provides 27 directives organized into logical categories. All directives work in location, server, and if blocks during the rewrite phase.

Base64 Encoding and Decoding

set_encode_base64

Encodes a value to standard Base64 format.

Syntax: set_encode_base64 $dst <src> or set_encode_base64 $dst

location /base64 {
    set $raw "hello world";
    set_encode_base64 $encoded $raw;
    return 200 "Encoded: $encoded\n";
}

Output: Encoded: aGVsbG8gd29ybGQ=

The single-argument form modifies the variable in place:

location /base64-inplace {
    set $data "secret message";
    set_encode_base64 $data;
    return 200 "Result: $data\n";
}

set_decode_base64

Decodes a Base64-encoded string back to its original form.

Syntax: set_decode_base64 $dst <src> or set_decode_base64 $dst

location /decode {
    set $encoded "aGVsbG8gd29ybGQ=";
    set_decode_base64 $decoded $encoded;
    return 200 "Decoded: $decoded\n";
}

Output: Decoded: hello world

set_encode_base64url

Encodes to URL-safe Base64 format. This variant replaces + with - and / with _, making it safe for URLs and filenames.

Syntax: set_encode_base64url $dst <src> or set_encode_base64url $dst

location /base64url {
    set $raw "hello+world/test";
    set_encode_base64url $encoded $raw;
    return 200 "URL-safe: $encoded\n";
}

Output: URL-safe: aGVsbG8rd29ybGQvdGVzdA

The URL-safe variant is ideal for query parameters and cookie values where standard Base64 characters could cause parsing issues.

set_decode_base64url

Decodes a URL-safe Base64 string.

Syntax: set_decode_base64url $dst <src> or set_decode_base64url $dst

location /decode-url {
    set $encoded "aGVsbG8rd29ybGQvdGVzdA";
    set_decode_base64url $decoded $encoded;
    return 200 "Original: $decoded\n";
}

Base32 Encoding and Decoding

Base32 uses a smaller alphabet than Base64, making it more suitable for case-insensitive systems like DNS and file systems.

set_encode_base32

Encodes a value to Base32 format. The module uses the “base32hex” alphabet (0-9a-v) by default.

Syntax: set_encode_base32 $dst <src> or set_encode_base32 $dst

location /base32 {
    set $raw "hello";
    set_encode_base32 $encoded $raw;
    return 200 "Base32: $encoded\n";
}

Output: Base32: d1imor3f

set_decode_base32

Decodes a Base32-encoded string.

Syntax: set_decode_base32 $dst <src> or set_decode_base32 $dst

set_base32_padding

Controls whether to add = padding characters to Base32 output.

Syntax: set_base32_padding on|off

Default: on

Context: http, server, location

location /base32-nopad {
    set_base32_padding off;
    set $raw "hello";
    set_encode_base32 $encoded $raw;
    return 200 "No padding: $encoded\n";
}

set_base32_alphabet

Customizes the alphabet used for Base32 encoding and decoding. The default alphabet is 0123456789abcdefghijklmnopqrstuv (base32hex). For RFC 3548 compliant encoding, use the standard alphabet.

Syntax: set_base32_alphabet <alphabet>

Default: 0123456789abcdefghijklmnopqrstuv

Context: http, server, location

location /base32-rfc {
    set_base32_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    set $raw "hello";
    set_encode_base32 $encoded $raw;
    return 200 "RFC 3548: $encoded\n";
}

Hexadecimal Encoding and Decoding

set_encode_hex

Converts a string to its hexadecimal representation.

Syntax: set_encode_hex $dst <src> or set_encode_hex $dst

location /hex {
    set $raw "hello";
    set_encode_hex $hex $raw;
    return 200 "Hex: $hex\n";
}

Output: Hex: 68656c6c6f

Hexadecimal encoding is useful for debugging binary data, generating cache keys, and creating URL-safe representations of arbitrary bytes.

set_decode_hex

Converts a hexadecimal string back to its original binary form.

Syntax: set_decode_hex $dst <src> or set_decode_hex $dst

location /unhex {
    set $hex "68656c6c6f";
    set_decode_hex $raw $hex;
    return 200 "Decoded: $raw\n";
}

Output: Decoded: hello

Cryptographic Hashing

set_md5

Computes the MD5 hash of a value and returns it in hexadecimal format.

Syntax: set_md5 $dst <src> or set_md5 $dst

location /md5 {
    set $data "hello";
    set_md5 $hash $data;
    return 200 "MD5: $hash\n";
}

Output: MD5: 5d41402abc4b2a76b9719d911017c592

MD5 is useful for generating cache keys, content fingerprints, and non-security-critical checksums. For security-sensitive applications, use SHA1 or HMAC functions instead.

set_sha1

Computes the SHA1 hash of a value and returns it in hexadecimal format.

Syntax: set_sha1 $dst <src> or set_sha1 $dst

location /sha1 {
    set $data "hello";
    set_sha1 $hash $data;
    return 200 "SHA1: $hash\n";
}

Output: SHA1: aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

SHA1 provides stronger collision resistance than MD5 and is suitable for content integrity verification.

set_hmac_sha1

Computes an HMAC-SHA1 message authentication code using a secret key. The result is returned in raw binary format, so you typically combine it with set_encode_base64 or set_encode_hex.

Syntax: set_hmac_sha1 $dst <secret_key> <message>

location /hmac-sha1 {
    set $secret "my-secret-key";
    set $message "data to sign";
    set_hmac_sha1 $signature $secret $message;
    set_encode_base64 $sig_b64 $signature;
    return 200 "HMAC-SHA1: $sig_b64\n";
}

HMAC-SHA1 is widely used for API authentication, webhook verification, and signed URL generation.

set_hmac_sha256

Computes an HMAC-SHA256 message authentication code. This provides stronger security than HMAC-SHA1 and is recommended for new applications.

Syntax: set_hmac_sha256 $dst <secret_key> <message>

location /hmac-sha256 {
    set $secret "my-secret-key";
    set $message "data to sign";
    set_hmac_sha256 $signature $secret $message;
    set_encode_base64 $sig_b64 $signature;
    return 200 "HMAC-SHA256: $sig_b64\n";
}

Output: The Base64-encoded HMAC-SHA256 signature.

This directive requires OpenSSL support in your NGINX build, which is standard in GetPageSpeed packages.

URI Encoding and Decoding

set_escape_uri

Encodes a string for safe inclusion in URLs. Special characters are converted to percent-encoded form (e.g., space becomes %20).

Syntax: set_escape_uri $dst <src> or set_escape_uri $dst

location /escape {
    set $data "hello world!";
    set_escape_uri $escaped $data;
    return 200 "Escaped: $escaped\n";
}

Output: Escaped: hello%20world!

set_unescape_uri

Decodes a percent-encoded URI string. This is the inverse of set_escape_uri.

Syntax: set_unescape_uri $dst <src> or set_unescape_uri $dst

location /unescape {
    set_unescape_uri $key $arg_key;
    return 200 "Key: $key\n";
}

The built-in $arg_* variables contain raw (escaped) query parameter values. Use set_unescape_uri to decode them before processing.

String Quoting for Database and JSON

set_quote_sql_str

Escapes a string for safe inclusion in MySQL SQL queries. The result is wrapped in single quotes with special characters properly escaped.

Syntax: set_quote_sql_str $dst <src> or set_quote_sql_str $dst

location /sql {
    set $input "hello'world";
    set_quote_sql_str $safe $input;
    return 200 "SQL: $safe\n";
}

Output: SQL: 'hello\'world'

This directive prevents SQL injection when constructing queries dynamically. However, parameterized queries in your application are still the preferred approach.

set_quote_pgsql_str

Escapes a string for safe inclusion in PostgreSQL SQL queries. PostgreSQL uses a different escaping syntax with the E prefix for strings containing escape sequences.

Syntax: set_quote_pgsql_str $dst <src> or set_quote_pgsql_str $dst

location /pgsql {
    set $input "hello'world\n";
    set_quote_pgsql_str $safe $input;
    return 200 "PostgreSQL: $safe\n";
}

Output: PostgreSQL: E'hello\'world\n'

set_quote_json_str

Escapes a string for safe inclusion in JSON. The result is wrapped in double quotes with special characters properly escaped.

Syntax: set_quote_json_str $dst <src> or set_quote_json_str $dst

location /json {
    set $data "hello world";
    set_quote_json_str $json $data;
    return 200 "{\"message\": $json}\n";
}

Output: {"message": "hello world"}

This is particularly useful when constructing JSON responses directly in NGINX configuration.

Random Number Generation

set_random

Generates a pseudo-random integer within a specified range (inclusive).

Syntax: set_random $dst <from> <to>

location /random {
    set_random $rand 1 100;
    return 200 "Random: $rand\n";
}

The random number generator uses the standard C rand() function, seeded automatically by NGINX. For cryptographic applications, use set_secure_random_alphanum instead.

set_secure_random_alphanum

Generates a cryptographically secure random string using characters from [a-zA-Z0-9].

Syntax: set_secure_random_alphanum $dst <length>

Length: 1 to 64 characters

location /token {
    set_secure_random_alphanum $token 32;
    return 200 "Token: $token\n";
}

Output: Token: zuSh9MKf6kVGk3CVlW649JpQGPsVe5GW (example, varies each request)

This directive reads from /dev/urandom and is suitable for generating session tokens, CSRF tokens, and one-time passwords.

set_secure_random_lcalpha

Generates a cryptographically secure random string using only lowercase letters [a-z].

Syntax: set_secure_random_lcalpha $dst <length>

Length: 1 to 64 characters

location /slug {
    set_secure_random_lcalpha $slug 16;
    return 200 "Slug: $slug\n";
}

Output: Slug: qwertyuiopasdfgh (example, varies each request)

Lowercase-only strings are useful for URL slugs, filenames, and systems that normalize case.

Conditional Assignment

set_if_empty

Assigns a value to a variable only if it is empty (not set or contains an empty string).

Syntax: set_if_empty $dst <value>

location /default {
    set $format $arg_format;
    set_if_empty $format "json";
    return 200 "Format: $format\n";
}

When accessing /default, the response is Format: json. When accessing /default?format=xml, the response is Format: xml.

This directive is essential for providing default values for optional query parameters, headers, or cookies.

Time Formatting

set_local_today

Sets the current date in YYYY-MM-DD format using local time.

Syntax: set_local_today $dst

location /today {
    set_local_today $today;
    return 200 "Today: $today\n";
}

Output: Today: 2026-02-22

set_formatted_gmt_time

Formats the current GMT time using strftime format specifiers.

Syntax: set_formatted_gmt_time $dst <format>

location /gmt {
    set_formatted_gmt_time $timestamp "%Y-%m-%d %H:%M:%S GMT";
    return 200 "GMT: $timestamp\n";
}

Output: GMT: 2026-02-22 14:30:00 GMT

Common format specifiers:
%Y – 4-digit year
%m – Month (01-12)
%d – Day of month (01-31)
%H – Hour (00-23)
%M – Minute (00-59)
%S – Second (00-59)
%Z – Timezone abbreviation

set_formatted_local_time

Formats the current local time using strftime format specifiers.

Syntax: set_formatted_local_time $dst <format>

location /local {
    set_formatted_local_time $timestamp "%Y-%m-%d %H:%M:%S %Z";
    return 200 "Local: $timestamp\n";
}

Output: Local: 2026-02-22 21:30:00 WITA

Round-Robin Rotation

set_rotate

Increments a counter and keeps it within a specified range. When the counter exceeds the maximum, it wraps back to the minimum.

Syntax: set_rotate $dst <from> <to>

location /rotate {
    set_rotate $counter 1 5;
    return 200 "Counter: $counter\n";
}

Successive requests produce: 1, 2, 3, 4, 5, 1, 2, …

The counter state is maintained per-location across requests, making it useful for banner rotation, A/B testing, and simple round-robin load distribution.

Hashed Upstream Selection

set_hashed_upstream

Selects an upstream server from a predefined list by hashing a key value. This provides consistent routing where the same key always maps to the same upstream.

Syntax: set_hashed_upstream $dst <upstream_list> <key>

This directive requires defining an upstream list first:

upstream_list backends backend1 backend2 backend3;

upstream backend1 { server 10.0.0.1:8080; }
upstream backend2 { server 10.0.0.2:8080; }
upstream backend3 { server 10.0.0.3:8080; }

location /api {
    set_hashed_upstream $backend backends $arg_user_id;
    proxy_pass http://$backend;
}

Users with the same user_id are consistently routed to the same backend, which is valuable for maintaining session affinity without cookies.

Practical Use Cases

Generating Signed Download URLs

Create time-limited download URLs with HMAC verification:

location /download {
    # Verify signature
    set $expected_data "$uri$arg_expires";
    set_hmac_sha256 $expected_sig "your-secret-key" $expected_data;
    set_encode_base64url $expected_b64 $expected_sig;

    if ($expected_b64 != $arg_sig) {
        return 403 "Invalid signature";
    }

    # Check expiration
    if ($arg_expires < $time_iso8601) {
        return 410 "Link expired";
    }

    # Serve the file
    alias /var/files;
    try_files $uri =404;
}

Building Cache Keys with Content Hashing

Create deterministic cache keys based on request content:

location /api/query {
    set $cache_input "$request_method|$uri|$args";
    set_md5 $cache_key $cache_input;

    proxy_cache_key $cache_key;
    proxy_pass http://backend;
}

Secure Token Generation for APIs

Generate secure tokens for API authentication:

location /auth/token {
    set_secure_random_alphanum $token 64;
    set_formatted_gmt_time $expires "%Y-%m-%dT%H:%M:%SZ";

    default_type application/json;
    return 200 '{"token": "$token", "expires": "$expires"}';
}

URL-Safe Encoding for Cookies

Encode arbitrary data for storage in cookies:

location /set-cookie {
    set $data "user_id=123&role=admin";
    set_encode_base64url $encoded $data;
    add_header Set-Cookie "session=$encoded; HttpOnly; Secure";
    return 200 "Cookie set\n";
}

Dynamic JSON Response Construction

Build JSON responses with properly escaped values:

location /user {
    set $name "John O'Brien";
    set_quote_json_str $safe_name $name;

    default_type application/json;
    return 200 '{"user": $safe_name, "ip": "$remote_addr"}';
}

Performance Considerations

The NGINX set-misc module is designed for high performance:

CPU efficiency: All encoding and hashing operations use optimized C implementations. MD5 and SHA1 compute in microseconds for typical input sizes.

Memory usage: Operations work on NGINX’s internal string pools with minimal allocations. Large Base64-encoded values do require proportional memory.

Cryptographic operations: HMAC-SHA1 and HMAC-SHA256 use OpenSSL, benefiting from hardware acceleration on modern CPUs (AES-NI, SHA extensions).

Secure random: Reading from /dev/urandom is non-blocking on Linux and typically takes microseconds.

For high-traffic endpoints generating cryptographic hashes or signatures, the overhead is negligible compared to network I/O and upstream processing.

Security Best Practices

Use HMAC-SHA256 for New Applications

While HMAC-SHA1 is still secure for message authentication, HMAC-SHA256 provides a larger security margin and is recommended for new applications.

Protect Secret Keys

Store secret keys in NGINX variables defined in included files with restricted permissions:

include /etc/nginx/secrets.conf;  # Contains: set $hmac_secret "...";

Ensure the secrets file is readable only by the NGINX master process:

chmod 600 /etc/nginx/secrets.conf
chown root:root /etc/nginx/secrets.conf

Use Secure Random for Security-Critical Applications

The set_random directive uses a pseudo-random number generator that is predictable. For session tokens, CSRF tokens, or any security-critical purpose, always use set_secure_random_alphanum or set_secure_random_lcalpha.

Validate Input Length

When processing user input with encoding functions, validate the input length to prevent denial-of-service through excessive memory allocation:

if ($request_body_length > 1048576) {
    return 413 "Request too large";
}

Troubleshooting

“unknown directive set_encode_base64”

This error means either the module is not loaded or the NDK module is missing. Ensure both modules are loaded in the correct order:

load_module modules/ndk_http_module.so;
load_module modules/ngx_http_set_misc_module.so;

HMAC Functions Not Available

If set_hmac_sha1 or set_hmac_sha256 fail, verify that your NGINX build includes OpenSSL support. GetPageSpeed packages include OpenSSL by default.

set_if_empty Not Working with Special Variables

Do not use $arg_*, $cookie_*, or $http_* variables as the destination for set_if_empty. These special NGINX variables are read-only and attempting to modify them will cause a segmentation fault. Always copy to a regular variable first:

# WRONG - will crash
set_if_empty $arg_user "guest";

# CORRECT
set $user $arg_user;
set_if_empty $user "guest";

Empty Output from Hashing Functions

If hash functions return empty values, verify that the input variable contains data:

location /debug {
    set $input $arg_data;
    set_md5 $hash $input;
    return 200 "Input: [$input] Hash: [$hash]\n";
}

Conclusion

The NGINX set-misc module brings essential encoding, hashing, and variable manipulation capabilities directly into your NGINX configuration. With 27 directives covering Base64, hexadecimal, cryptographic hashing, secure random generation, and string escaping, this module eliminates the need for backend processing of common data transformation tasks.

Whether you are building signed URLs, generating secure tokens for JWT authentication, constructing JSON responses, or implementing cache key strategies, the set-misc module provides the tools you need at the edge.

Install the module from the GetPageSpeed repository and start building more powerful NGINX configurations today. For the full source code and additional documentation, visit the set-misc-nginx-module GitHub repository.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.