When you need to authenticate web users against Linux system accounts or enterprise directory services, NGINX PAM authentication provides a native solution. Rather than managing separate password files or building custom authentication backends, you leverage PAM (Pluggable Authentication Modules) — the same framework that handles your SSH logins, sudo access, and system services.
This guide covers installing and configuring NGINX PAM authentication on RHEL-based and Debian/Ubuntu systems. You’ll find practical examples for system user authentication, LDAP integration, and performance optimization.
What is PAM Authentication?
PAM (Pluggable Authentication Modules) is Linux’s universal authentication framework. When you SSH into a server, log into a console, or use sudo, PAM handles the credential verification. The NGINX PAM authentication module brings this same flexibility to HTTP Basic Authentication.
Instead of maintaining separate htpasswd files, you authenticate against:
- System users — the same accounts in
/etc/passwdand/etc/shadow - LDAP directories — Active Directory, OpenLDAP, FreeIPA
- Multi-factor authentication — via PAM modules like
pam_google_authenticator - Custom authentication — using
pam_execwith your own scripts
For simpler use cases, you might prefer NGINX Digest Authentication which offers better security than Basic Auth. However, PAM excels when you need enterprise integration.
Installation
RHEL, CentOS, AlmaLinux, Rocky Linux
Install the GetPageSpeed repository and the PAM module:
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx-module-auth-pam
Enable the module by adding to the top of /etc/nginx/nginx.conf:
load_module modules/ngx_http_auth_pam_module.so;
Debian and Ubuntu
First, set up the GetPageSpeed APT repository, then install:
sudo apt-get update
sudo apt-get install nginx-module-auth-pam
On Debian/Ubuntu, the package handles module loading automatically. No load_module directive is needed.
Configuration Directives
The NGINX PAM authentication module provides these directives:
| Directive | Default | Context | Description |
|---|---|---|---|
auth_pam |
— | http, server, location | Set the HTTP Basic Auth realm. Use off to disable. Supports variables. |
auth_pam_service_name |
nginx |
http, server, location | PAM service name (matches /etc/pam.d/<name>) |
auth_pam_set_pam_env |
off |
http, server, location | Export HOST and REQUEST to PAM environment |
Pro Tier Features
The GetPageSpeed Pro subscription includes these additional capabilities:
| Directive | Description |
|---|---|
auth_pam_cache_zone |
Define shared memory cache for authentication results |
auth_pam_cache |
Enable auth caching with configurable TTL |
auth_pam_thread_pool |
Offload PAM calls to thread pool (non-blocking) |
$pam_user |
Variable containing authenticated username |
Basic Configuration
System User Authentication
This configuration protects a location using Linux system accounts:
server {
listen 80;
server_name example.com;
location /admin {
auth_pam "Admin Area";
auth_pam_service_name "nginx";
root /var/www/admin;
index index.html;
}
location / {
root /var/www/html;
index index.html;
}
}
Create the PAM service file /etc/pam.d/nginx:
auth required pam_unix.so
account required pam_unix.so
Understanding PAM Service Files
The PAM service file controls how authentication works:
- auth — verifies the user’s identity (password check)
- account — checks if the account is valid (not expired, not locked)
- pam_unix.so — authenticates against
/etc/passwdand/etc/shadow
Permissions for System User Authentication
NGINX worker processes run as the nginx user. This user cannot read /etc/shadow by default. You have several options to enable NGINX PAM authentication against system users.
Option 1: ACL (Testing Only)
Grant the NGINX user read access via ACL:
sudo setfacl -m u:nginx:r /etc/shadow
Verify the ACL:
getfacl /etc/shadow
This approach works but exposes shadow passwords to NGINX. Use LDAP or saslauthd for production instead.
Option 2: SSSD Integration
If your system uses SSSD (System Security Services Daemon), NGINX can authenticate via the sssd_pam module:
# /etc/pam.d/nginx
auth required pam_sss.so
account required pam_sss.so
This method doesn’t require direct shadow access.
Option 3: Saslauthd (Production Recommended)
For production environments, use saslauthd as an authentication proxy:
sudo dnf install cyrus-sasl cyrus-sasl-plain
sudo systemctl enable --now saslauthd
PAM configuration for saslauthd:
# /etc/pam.d/nginx
auth required pam_saslauthd.so
account required pam_permit.so
LDAP Authentication
NGINX PAM authentication with LDAP is the most common enterprise use case. First, install the LDAP PAM module:
sudo dnf install nss-pam-ldapd
Configure /etc/nslcd.conf for your LDAP server:
uri ldap://ldap.example.com
base dc=example,dc=com
binddn cn=nginx,ou=services,dc=example,dc=com
bindpw secret
Create the PAM service file /etc/pam.d/nginx_ldap:
auth required pam_ldap.so
account required pam_ldap.so
NGINX configuration:
location /intranet {
auth_pam "Company Intranet";
auth_pam_service_name "nginx_ldap";
proxy_pass http://backend;
}
Active Directory Integration
For Active Directory environments, use SSSD:
sudo dnf install sssd sssd-ad
sudo realm join ad.example.com
PAM service file for AD:
# /etc/pam.d/nginx_ad
auth required pam_sss.so
account required pam_sss.so
After joining the domain, NGINX PAM authentication works seamlessly with AD users.
Authentication Caching (Pro Feature)
For high-traffic sites with slow authentication backends (LDAP, AD), caching prevents repeated backend queries:
http {
auth_pam_cache_zone zone=pam_cache:1m;
server {
location /api {
auth_pam "API Access";
auth_pam_service_name "nginx_ldap";
auth_pam_cache zone=pam_cache time=60s;
proxy_pass http://api_backend;
}
}
}
Cache behavior:
- Only successful authentications are cached
- Failed attempts always hit PAM (prevents cache poisoning)
- Passwords are SHA1-hashed in cache keys, never stored in plaintext
- Service name is included in cache key to prevent cross-service collisions
Thread Pool Authentication (Pro Feature)
When NGINX is built with --with-threads (default for GetPageSpeed packages), PAM authentication can be offloaded to a thread pool. This prevents slow PAM backends from blocking worker processes:
thread_pool pam_pool threads=4 max_queue=256;
http {
server {
location /ldap-protected {
auth_pam "LDAP Zone";
auth_pam_service_name "nginx_ldap";
auth_pam_thread_pool pam_pool;
proxy_pass http://backend;
}
}
}
To disable thread pool authentication for a specific location:
location /sync-auth {
auth_pam "Sync Zone";
auth_pam_service_name "nginx";
auth_pam_thread_pool off;
}
Conditional Authentication
The auth_pam directive supports variables. This enables conditional NGINX PAM authentication based on request properties.
Skip Auth for Certificate-Authenticated Clients
map $ssl_client_verify $pam_realm {
SUCCESS "off";
default "Restricted Area";
}
server {
listen 443 ssl;
ssl_client_certificate /etc/nginx/ca.crt;
ssl_verify_client optional;
location /api {
auth_pam $pam_realm;
auth_pam_service_name "nginx";
proxy_pass http://api_backend;
}
}
Bypass Auth for Internal Networks
For network-based access control, combine PAM with the NGINX geo and allow/deny directives:
geo $pam_realm {
default "Restricted";
10.0.0.0/8 "off";
192.168.0.0/16 "off";
}
location /internal {
auth_pam $pam_realm;
auth_pam_service_name "nginx";
root /var/www/internal;
}
Using the $pam_user Variable (Pro Feature)
After successful authentication, the $pam_user variable contains the authenticated username:
location /api {
auth_pam "API Access";
auth_pam_service_name "nginx";
proxy_set_header X-Authenticated-User $pam_user;
proxy_pass http://backend;
}
log_format auth '$remote_addr - $pam_user [$time_local] "$request" $status';
access_log /var/log/nginx/auth_access.log auth;
PAM Environment Variables
Enable auth_pam_set_pam_env on to export request information to PAM. This allows custom authentication scripts to access:
HOST— Request host header (e.g.,example.com:8080)REQUEST— Full request line (e.g.,GET /path?query HTTP/1.1)
Example with pam_exec:
location /custom-auth {
auth_pam "Custom Zone";
auth_pam_service_name "nginx_exec";
auth_pam_set_pam_env on;
}
PAM service file /etc/pam.d/nginx_exec:
auth required pam_exec.so /usr/local/bin/auth-script.sh
account required pam_permit.so
Your script can read PAM_RHOST (client IP), HOST, and REQUEST from the environment.
SELinux Considerations
On SELinux-enabled systems, NGINX needs permission to use PAM:
# Allow NGINX to use PAM authentication
sudo setsebool -P httpd_mod_auth_pam on
# If connecting to LDAP
sudo setsebool -P httpd_can_connect_ldap on
If using ACLs for shadow access:
sudo setsebool -P httpd_read_user_content on
Security Best Practices
Use HTTPS
PAM authentication uses HTTP Basic Auth. This transmits credentials in base64 (not encrypted). Always use HTTPS:
server {
listen 443 ssl;
http2 on;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location /secure {
auth_pam "Secure Zone";
auth_pam_service_name "nginx";
}
}
server {
listen 80;
return 301 https://$host$request_uri;
}
Avoid Direct Shadow Access in Production
While ACLs work, giving NGINX read access to /etc/shadow is a security risk. For production:
- Use LDAP/AD authentication
- Use saslauthd as an authentication proxy
- Use SSSD for centralized authentication
Rate Limiting
Protect against brute-force attacks with NGINX rate limiting:
limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=5r/s;
location /login {
limit_req zone=auth_limit burst=10 nodelay;
auth_pam "Login";
auth_pam_service_name "nginx";
}
Fail2ban Integration
Monitor NGINX error logs for failed PAM authentication and ban offenders:
# /etc/fail2ban/filter.d/nginx-pam.conf
[Definition]
failregex = PAM: user '.*' from <HOST> - not authenticated
ignoreregex =
# /etc/fail2ban/jail.local
[nginx-pam]
enabled = true
filter = nginx-pam
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600
Troubleshooting
Authentication Always Fails
Check the NGINX error log:
tail -f /var/log/nginx/error.log
Common errors:
- “System error” — NGINX cannot read
/etc/shadow. Use ACL or switch to saslauthd/LDAP. - “Authentication failure” — Wrong password or user doesn’t exist.
- “Account expired” — The Linux account has expired.
Verify PAM Configuration
Test PAM independently using pamtester:
sudo dnf install pamtester
pamtester nginx testuser authenticate
Check PAM Service File Syntax
PAM syntax errors can cause silent failures:
# Verify service file exists
ls -la /etc/pam.d/nginx
# Check for typos (common: pam_uxin.so instead of pam_unix.so)
cat /etc/pam.d/nginx
Debug PAM
Enable PAM debugging by adding debug to the module:
auth required pam_unix.so debug
account required pam_unix.so debug
Debug output goes to /var/log/secure or journald.
Comparison with Other Auth Methods
| Method | Pros | Cons |
|---|---|---|
| PAM | Integrates with system users, LDAP, MFA | Requires PAM configuration, shadow access |
| htpasswd | Simple, no system integration | Separate password file to manage |
| LDAP module | Direct LDAP connection | NGINX Plus only, or requires compilation |
| JWT | Stateless, scalable | Requires token infrastructure |
Choose NGINX PAM authentication when you need to authenticate against existing Linux users or enterprise directory services. It avoids managing separate credential stores.
Conclusion
NGINX PAM authentication bridges web authentication with your existing identity infrastructure. Whether you’re protecting an admin panel with system users or integrating with corporate Active Directory, PAM provides a standardized solution.
For high-traffic sites, the Pro tier’s caching and thread pool features prevent authentication bottlenecks. Combined with conditional authentication, you can build sophisticated access control policies directly in NGINX configuration.
Resources:
– Module source code
– RPM packages
– APT packages

