Fixing “nginx: [emerg] ‘stream’ directive is not allowed here” Error in UDP Load Balancing Configuration


1 views

When working with NGINX's stream module for UDP load balancing, many administrators encounter this configuration error. The message indicates a fundamental misunderstanding about where the stream directive can be placed in NGINX's configuration hierarchy.

The stream block must be placed in the main configuration context, not inside http, server, or location blocks. Here's the correct structure:

# Main nginx.conf file should include this at root level
stream {
    upstream dns_backend {
        server 172.31.9.51:53;
        server 172.31.20.140:53;
    }

    server {
        listen 53 udp;
        proxy_pass dns_backend;
        proxy_timeout 1s;
        proxy_responses 1;
    }
}

For NGINX versions prior to 1.9.0, you needed to explicitly compile with --with-stream and --with-stream_udp_module. Modern versions (including your 1.12.1) include these by default, but it's worth verifying:

nginx -V 2>&1 | grep -o with-stream

Many users make these mistakes:

  • Placing stream configuration in conf.d/ without proper inclusion
  • Forgetting to specify udp in listen directives
  • Mixing HTTP and stream protocols in the same upstream

Here's a fully functional configuration for UDP load balancing:

# In /etc/nginx/nginx.conf
user www-data;
worker_processes auto;

events {
    worker_connections 1024;
}

stream {
    log_format basic '$remote_addr [$time_local] '
                     '$protocol $status $bytes_sent $bytes_received '
                     '$session_time';

    access_log /var/log/nginx/stream-access.log basic;
    error_log /var/log/nginx/stream-error.log;

    upstream game_servers {
        hash $remote_addr consistent;
        server 10.0.1.1:7777;
        server 10.0.1.2:7777;
    }

    server {
        listen 7777 udp;
        proxy_pass game_servers;
        proxy_timeout 5s;
        proxy_responses 1;
    }
}

If you still encounter issues:

  1. Check that the stream module is loaded with nginx -T | grep stream
  2. Verify no conflicting directives in included files
  3. Test configuration with nginx -t before restarting

The error message indicates that NGINX is rejecting your stream configuration because it's placed in the wrong context. The stream block needs to be at the main configuration level, not nested inside other blocks like http.

For UDP load balancing (like DNS, VoIP, or gaming servers), you need to separate your stream configuration from HTTP configurations:

# In /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;

# This is where stream should be declared - at main config level
stream {
    include /etc/nginx/conf.d/stream/*.conf;
}

http {
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Best practice is to create a dedicated directory for stream configurations:

mkdir -p /etc/nginx/conf.d/stream/
mv /etc/nginx/conf.d/load-balancer.conf /etc/nginx/conf.d/stream/

Here's a properly structured configuration for UDP load balancing (example for OpenVPN servers):

# /etc/nginx/conf.d/stream/vpn-balancer.conf
upstream vpn_backend {
    hash $remote_addr consistent;
    
    server 172.31.9.51:1194 weight=5;
    server 172.31.20.140:1194;
    server backup.vpn.example.com:1194 backup;
}

server {
    listen 1194 udp reuseport;
    proxy_pass vpn_backend;
    proxy_timeout 3s;
    proxy_responses 0; # For UDP, typically you want 0 responses
}

After making changes, always test:

sudo nginx -t
sudo systemctl restart nginx
netstat -tulnp | grep nginx
  • Ensure you have NGINX compiled with stream module (nginx -V | grep stream)
  • Docker users: Need to expose UDP ports explicitly with -p 1194:1194/udp
  • Firewall rules must allow UDP traffic

For high-traffic UDP services:

stream {
    proxy_buffer_size 16k;
    proxy_udp_buffer_size 16k;
    proxy_socket_keepalive on;
    
    server {
        listen 53 udp reuseport;
        # ...
    }
}