English (change)

Easily restrict access to hide sensitive data, admin areas & other web pages using the Nginx web server’s Auth_Basic security module & the htpasswd password creation tool.
What we’re gonna do, essentially, is to create a password file, then adapt a site’s virtual host file. That done, Nginx knows there’s a point of restricted access, and knows where to look for the corresponding password so that, when we surf to the appropriate URI, it can prompt us to log in or hack off.
Dead simple, pay attention, here goes ..
[sniplet guvSellBox]
[sniplet vpsIndexSell]
This is the most common requirement so that, for instance, you can protect an administrative zone, else maybe double up security for a handy web client like phpmyadmin or a webmail application.
First up, download this password-creation tool that we’re pinching from the chaps at Apache. It’s quite a nice program because its quick to use and encrypts your token:-
[text]sudo aptitude install apache2-utils[/text]
.. or if you did all that bashrc shortcut stuff, be lazy like me:-
[text]install apache2-utils[/text]
Now cd to your /home/user folder:-
[text]cd ~[/text]
.. and type:-
[text]htpasswd -c .htpasswd some-name[/text]
.. you’ll be asked to give and confirm a password.
You may not need to do this, but for educational purposes, why ever not. Change directory, into the same as the password file:-
[text]cd /usr/local/nginx[/text]
.. and adapt the password file ..
[text]htpasswd .htpasswd another-name[/text]
.. there’s no -c because we’re not creating a new file, instead adapting an existing one. And
another-name is, well, just that.
You’ll be asked to give and confirm a password.
Let’s take a peek:-
[text]cat .htpasswd[/text]
.. and we see, pretty much ..
[text]some-name:encrypted-password
another-name:another-password[/text]
So. A file has been created in your /home/user directory. It can live there. It can live anywhere you like, but it shouldn’t be amongst the actual web files. I’m inclined to move it, like so:-
[text]sudo mv .htpasswd /usr/local/nginx[/text]
.. so it sits with my Nginx config and virtual host files and directories. For some folks (if you installed Nginx using apt-get or aptitude, rather than wget’ting the source code which you should have done really but never mind), that may instead be at a location like /var/www/I-forget-exactly.
If you’ve not bothered with separate vhost files, instead bunching your site configs all in the nginx.conf, pop it open:-
[text]sudo nano /usr/local/nginx/conf/nginx.conf[/text]
For those less messy types who have a virtual host website configuration file, well done, let’s crack that open instead:-
[text]sudo nano /usr/local/nginx/sites-available/yourDomain.com[/text]
Either way, within the file you’ll see the syntax specific to your website, looking something like this:-
[text]
server {
listen 80;
server_name www.mydomain.com;
rewrite ^/(.*) http://mydomain.com/$1 permanent;
}
server {
listen 80;
server_name mydomain.com;
access_log /home/public_html/mydomain.com/log/access.log;
error_log /home/public_html/mydomain.com/log/error.log;
location /
{
root /home/public_html/mydomain.com/public/;
index index.php index.html;
# Basic version of WordPress parameters, supporting nice permalinks.
# include /usr/local/nginx/conf/wordpress_params.regular;
# Advanced version of WordPress parameters supporting nice permalinks and WP Super Cache plugin
include /usr/local/nginx/conf/wordpress_params.super_cache;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/public_html/mydomain.com/public/$fastcgi_script_name;
}
}
[/text]
What we have here, by way of a quick recap is ..
[text]
server {
listen 80;
server_name www.mydomain.com;
rewrite ^/(.*) http://mydomain.com/$1 permanent;
}
[/text]
.. the first server block, basically a rewrite rule so that when someone types in www.whatnot.com, they’re redirected to whatnot.com.
[text]
server {
listen 80;
server_name mydomain.com;
access_log /home/public_html/mydomain.com/log/access.log;
error_log /home/public_html/mydomain.com/log/error.log;
[/text]
.. the top of the key server block, those www types having been redirected to non-www, which contains the core ruleset. 80 is the port Nginx listens on, and the rest pretty clear.
[text]
location /
{
root /home/public_html/mydomain.com/public/;
index index.php index.html;
# Basic version of WordPress parameters, supporting nice permalinks.
# include /usr/local/nginx/conf/wordpress_params.regular;
# Advanced version of WordPress parameters supporting nice permalinks and WP Super Cache plugin
include /usr/local/nginx/conf/wordpress_params.super_cache;
}
[/text]
.. the location block ..
[text]
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/public_html/mydomain.com/public/$fastcgi_script_name;
}
}
[/text]
.. some fastCGI link-ups, which I’ll be talking about more in a future how-to guide. And we close the server block with the final }.
Now then, no excuse for not putting the protected folder info in the right place. The syntax is:-
[text]
location ^~ /path/to/hiddenFolder {
auth_basic “Restricted Access”;
auth_basic_user_file /usr/local/nginx/.htpasswd;
}
[/text]
Save the file. Restart Nginx:-
[text]sudo /etc/init.d/nginx restart[/text]
.. or n2r if you followed the bashrc thing (if you did, by this time I’ll bet you’re pleased about that!)
Mkdir the path to the folder requiring protection, if you’ve not already done so.
Then head over, logging in with using the username and password you gave, to:-
[text]http://www.mydomain.com/path/to/hiddenFolder/etcetera[/text]
Alternatively, maybe you want to protect just a file, some specific document, a media item, whatever. This second option will do just that, but will protect nothing except a precise path. That can be handy if you want everything visible, bar a special item.
The method is the same as for folders, bar a few characters. Create the password file as before, then adapt the virtual host syntax. We had:-
[text]
location ^~ /path/to/hiddenFolder {
auth_basic “Restricted Access”;
auth_basic_user_file /usr/local/nginx/.htpasswd;
}
[/text]
Change it to:-
[text]
location = /path/to/restrictedItem.pdf {
auth_basic “Restricted Access”;
auth_basic_user_file /usr/local/nginx/.htpasswd;
}
[/text]
.. of course, it works for anything, not just pdf’s.
For most of us, the above methods are what we want, and the equivalent of what we’ve been used to, using something horrible like cPanel.
However, there are more advanced techniques one can employ, such as restricting access to a specific IP or IPs, and I’ll be covering that, and other diversions, in a follow-up to this post.
Fix a feed for updates. You know it makes sense.
Here’s the index, which doubtless will expand ..
[sniplet vpsIndex]
markie December 6th, 2009 at 3:43 pm
When i try to password protect a directory like above, Nginx gives me a 404 error after verifying the password? any ideas?
the_guv December 7th, 2009 at 10:01 am
@markie .. checked you file permissions?