People usually use PAM(Pluggable Authentication Module) on Nginx for Basic Authentication using the OS account. While it is very straightforward, it is very not safe practice in terms of security practice if you use the same user & password for the application and the OS.
People can visit your site again and again until they can break the password. And What if they can break the password? They can log in freely to your OS. Of course, you didn’t want this to happen.
There is a better way of using PAM Authentication on Nginx. It is by using MySQL database for managing the user account instead of using OS account.
Let’s see how we can do it.
Check Prerequisite
Before we start, let’s check the prerequisite first to make sure you can follow this tutorial
- Nginx installed, if you don’t have the Nginx yet, you can install it using
apt install nginx
, or you can Install Nginx from Source if you want. - Mysql installed, if you don’t have MySQL yet, you can install it using
apt install mysql-server
- Sudo Privilege, make sure you execute
sudo su
first to make sure we have no permission issue on the installation & configuration.
Install Nginx PAM Dependencies
We need to install some dependencies to make Nginx able to use PAM module.
apt install nginx-extras libpam-mysql
Add Configuration on NGINX
Open your virtual host config file on the Nginx folder
nano /etc/nginx/sites-available/my-site
Add auth_pam
and auth_pam_service_name
configuration on your server block or location block level to using pam authentication on Nginx. For example, if I want to use it at location block level:
. . . location /secure { auth_pam "Restricted Zone"; auth_pam_service_name "secure-nginx"; . . . } location /user { . . . } . . .
This configuration will secure the /secure
location block, but not the other. If a request comes to the /secure
location block, Nginx will read secure-nginx
service on the PAM folder to perform a basic authentication first before serving the request.
Add Configuraion on PAM
Create a file on /etc/pam.d/
that match auth_pam_service_name
directive on the Nginx configuration file. In my case, it is secure-nginx
.
nano /etc/pam.d/secure-nginx
Add this config to the file:
auth required pam_mysql.so user=your_db_user passwd=your_db_pass host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=3 account sufficient pam_mysql.so user=your_db_user passwd=your_db_pass host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=3
Change the highlighted text to suit your MySQL setup:
user
is the MySQL usernamepasswd
is the MySQL passwordhost
is the ip address of the MySQL Serverdb
is the database nametable
is the table name that contains the user and passwordusercolumn
is the column name that contains the userpasswdcolumn
is the column name that contains the user’s passwordcrypt
is the encryption method used on the password. the3
is usingmd5
encryption. It is the most recommended one. I suggest you still use this value.
Restart NGINX
After the configuration is done, you can restart the Nginx.
service nginx restart
That’s it! Now you can create MySQL authentication on Nginx using PAM, a better way to use PAM authentication.