How to Fix “unknown directive ‘stream'” Error in Nginx 1.12.0: Enabling Stream Module for TCP/UDP Proxy


1 views

When trying to configure Nginx as a TCP/UDP load balancer using the stream directive, many administrators encounter the frustrating "unknown directive" error despite having Nginx 1.12.0+ installed. The root cause lies in how the stream module gets compiled.

From your nginx -V output, we can see a critical detail:

--with-stream=dynamic

This means the stream module was compiled as a dynamic module rather than being built directly into the binary. While Nginx 1.12.0 includes stream capabilities, they need explicit loading.

Add this line at the very top of your nginx.conf:

load_module modules/ngx_stream_module.so;

Then verify the module loads:

sudo nginx -t
sudo systemctl restart nginx

Here's a verified UDP load balancing configuration that works after module loading:

load_module modules/ngx_stream_module.so;

events {
    worker_connections 1024;
}

stream {
    upstream dns_servers {
        server 172.16.1.10:9516 weight=2;
        server 172.16.1.11:9516;
    }

    server {
        listen 9516 udp reuseport;
        proxy_pass dns_servers;
        proxy_timeout 1s;
        proxy_responses 1;
        error_log /var/log/nginx/stream_error.log;
    }
}

If dynamic loading fails, consider:

  1. Compiling from source with --with-stream (non-dynamic)
  2. Using the official Nginx repository instead of PPAs:
sudo apt-get remove --purge nginx*
sudo apt-get install curl gnupg2 ca-certificates lsb-release
echo "deb http://nginx.org/packages/mainline/ubuntu lsb_release -cs nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install nginx-plus-module-stream
  • Verify module files exist: ls /usr/lib/nginx/modules/
  • Check for conflicting PPA versions
  • Ensure no syntax errors in other config sections
  • Monitor error logs: tail -f /var/log/nginx/error.log

When examining the nginx -V output, I noticed a crucial detail in the configure arguments:

--with-stream=dynamic

This indicates the stream module was compiled as dynamic rather than built-in. This explains why the directive isn't recognized even though you're using Nginx 1.12.0 which technically includes the stream module.

First, let's verify where your modules are stored:

ls -la /usr/lib/nginx/modules/

You should see ngx_stream_module.so among the files. If not, you'll need to install it separately.

Edit your nginx.conf and add this line at the very top (before any events or http blocks):

load_module modules/ngx_stream_module.so;

Here's a working configuration for UDP stream proxying:

load_module modules/ngx_stream_module.so;

events {
    worker_connections  1024;
}

stream {
    upstream dns_servers {
        server 172.16.1.1:9516;
        server 172.16.1.2:9516;
    }

    server {
        listen 9516 udp reuseport;
        proxy_pass dns_servers;
        proxy_timeout 1s;
        proxy_responses 1;
    }
}

After making changes, always test your configuration:

sudo nginx -t

If successful, reload nginx:

sudo systemctl reload nginx

If the dynamic module isn't available, you might need to compile Nginx with stream support:

./configure --with-stream --with-stream_ssl_module
make
sudo make install
  • Make sure the load_module directive appears before any stream blocks
  • Check file permissions on the module file
  • Verify your Nginx worker has permission to bind to the port
  • For UDP, always include reuseport for better performance