Create Virtual Hosts, Password Protect Directories and SSL Certificates using “Nginx Web Server” in Arch Linux

The previous Arch Linux ‘LEMP’ article just covered basic stuff, from installing network services (Nginx, MySQL database and PhpMyAdmin) and configure minimal security required for MySQL server and PhpMyadmin.

Useful Nginx configurations on Arch Linux
Useful Nginx configurations on Arch Linux

This topic it’s strictly related to former Installation of LEMP on Arch Linux and will guide you through setting more complex configurations for LEMP stack, especially Nginx web server configurations, like creating Virtual Hosts, use Password Protected Directories, create and configure HTTP Secure Sockets Layer, HTTP insecure redirects to HTTPS and will also present you some useful Bash scripts that will ease the job on activating Virtual Hosts and generate SSL Certificate and Keys.

Requirements

Install LEMP with MariaDB Database in Arch Linux

Step 1: Enable Virtual Hosts on Nginx

One of the simplest method to enable Virtual Hosts is using include statements on main Nginx configuration file, which makes the job of further configurations more simpler and efficient because you can create simple files for every new host and keep main configuration file cleaner.

This approach works the same way as on Apache Web Server, the first thing you need to do is to specify the new URI path where Nginx should read file directives.

1. So, open nginx.conf main file located on /etc/nginx/ system path and at the bottom, before last curly bracket “}” add the path where future Virtual Host configuration files will reside.

$ sudo nano /etc/nginx/nginx.conf

At bottom add following statement.

include /etc/nginx/sites-enabled/*.conf;
Enable Virtual Hosts on Nginx
Enable Virtual Hosts on Nginx

This directive tells Nginx it should read all files that are found in /etc/nginx/sites-enabled/ that ends with a .conf extension.

2. The next step is to create sites-enabled directory and another one, called sites-available, where you store all your Virtual Hosts configuration files.

$ sudo mkdir /etc/nginx/sites-available /etc/nginx/sites-enabled

3. Now it’s time to create a new Virtual Host. This example will use system IP address as Virtual Host Name, so create a new file named name-ip.conf.

sudo nano /etc/nginx/sites-available/name-ip.conf

Add the following content.

## File content ##

server {
    listen 80;
    server_name 192.168.1.33;

    access_log /var/log/nginx/192.168.1.33.access.log;
    error_log /var/log/nginx/192.168.1.33.error.log;

    root /srv/http;
    location / {
    index index.html index.htm index.php;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
 }
    location /phpmyadmin {
        rewrite ^/* /phpMyAdmin last;
    }

    location ~ \.php$ {
        #fastcgi_pass 127.0.0.1:9000; (depending on your php-fpm socket configuration)
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}
Create New Virtual Host
Create New Virtual Host

The directive that activates Virtual Host is server_name statement under listening port. Also, another important directive here is root statement that points Nginx Virtual Host to serve file content from /srv/http/ system path.

4. The last step is to create /srv/http/ directory and make name-ip.conf file configuration available for Nginx reading (using symbolic link), then restart daemon to make new configurations visible.

$ sudo mkdir /srv/http/
$ sudo ln -s /etc/nginx/sites-available/name-ip.conf /etc/nginx/sites-enabled/
$ sudo systemctl restart nginx
Start Nginx Web Server
Start Nginx Web Server

5. To verify it, point your browser to Arch system IP address and you should see that the web content is different from http://localhost. Here I’ve added a small php script that also checks FastCGI PHP configurations like in the screenshot below.

$ sudo nano /srv/http/info.php
## File content ##

<?php
phpinfo();
?>
Verify FastCGI PHP Configurations
Verify FastCGI PHP Configurations

6. Another method that I have developed myself to enable or disable Virtual Hosts on Nginx is a more elegant one and it’s inspired from Apache a2eniste script.

To use this method open a file editor and create a new file, called n2ensite, on your $HOME path with the below content, make it executable, run it with root privileges and pass as an option to your new Virtual Host name without .conf ending ( fill free to modify it according to your needs).

$ sudo nano n2ensite
## File content ##

#!/bin/bash
if test -d /etc/nginx/sites-available && test -d /etc/nginx/sites-enabled  ; then
echo "-----------------------------------------------"
else
mkdir /etc/nginx/sites-available
mkdir /etc/nginx/sites-enabled
fi

avail=/etc/nginx/sites-available/$1.conf
enabled=/etc/nginx/sites-enabled/
site=`ls /etc/nginx/sites-available/`

if [ "$#" != "1" ]; then
                echo "Use script: n2ensite virtual_site"
                echo -e "\nAvailable virtual hosts:\n$site"
                exit 0
else

if test -e $avail; then
sudo ln -s $avail $enabled
else
echo -e "$avail virtual host does not exist! Please create one!\n$site"
exit 0
fi
if test -e $enabled/$1.conf; then
echo "Success!! Now restart nginx server: sudo systemctl restart nginx"
else
echo  -e "Virtual host $avail does not exist!\nPlease see available virtual hosts:\n$site"
exit 0
fi
fi
Use a2eniste Script
Use a2eniste Script

Make it executable and run it as show.

$ sudo chmod +x n2ensite
$ sudo ./n2ensite your_virtual_host
Enable Virtual Host
Enable Virtual Host

7. To disable Virtual Hosts create a new n2dissite file with the following content and apply the same settings as above.

$ sudo nano n2dissite
## File content ##

#!/bin/bash
avail=/etc/nginx/sites-enabled/$1.conf
enabled=/etc/nginx/sites-enabled
site=`ls /etc/nginx/sites-enabled/`

if [ "$#" != "1" ]; then
                echo "Use script: n2dissite virtual_site"
                echo -e "\nAvailable virtual hosts: \n$site"
                exit 0
else
if test -e $avail; then
sudo rm  $avail
else
echo -e "$avail virtual host does not exist! Exiting!"
exit 0
fi
if test -e $enabled/$1.conf; then
echo "Error!! Could not remove $avail virtual host!"
else
echo  -e "Success! $avail has been removed!\nPlease restart Nginx: sudo systemctl restart nginx"
exit 0
fi
fi
Disable Virtual Hosts
Disable Virtual Hosts

8. Now you can use this two scripts to enable or disable any Virtual Host but if you want to apply it as system wide commands just copy both scripts to /usr/local/bin/ and then you can use it without specifying path.

$ sudo cp n2ensite n2dissite /usr/local/bin/
Use n2ensite Script to Enable or Disable Hosts
Use n2ensite Script to Enable or Disable Hosts

Step 2: Enable SSL with Virtual Hosts on Nginx

SSL (Secure Sockets Layer) is a protocol designed to encrypt HTTP connections over networks or Internet, which make data flow to be transmitted over a secure channel using symmetric/asymmetric cryptography keys and is provided in Arch Linux by OpenSSL package.

$ sudo pacman -S openssl
Install Openssl on Arch Linux
Install Openssl Package

9. To enable HTTPS connections with Nginx the first think you need to do is to generate Virtual Hosts keys. Also, to simplify things, I have developed a small scripts that automatically generates cryptographic keys on /etc/nginx/ssl directory path, using Virtual Host naming as key names.

Create a file named nginx_gen_ssl and add the following content.

$ sudo nano nginx_gen_ssl
## File content ##

#!/bin/bash
mkdir /etc/nginx/ssl
cd /etc/nginx/ssl

echo -e "Enter your virtual host FQDN: \nThis will generate the default name for Nginx  SSL certificate!"
read cert

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out $cert.key
chmod 600 $cert.key
openssl req -new -key $cert.key -out $cert.csr
openssl x509 -req -days 365 -in $cert.csr -signkey $cert.key -out $cert.crt

echo -e " The certificate $cert has been generated!\nPlease link it to nginx ssl available website!"
ls -all /etc/nginx/ssl
exit 0
Generate Virtual Hosts Keys
Generate Virtual Hosts Keys

10. After the script has been created append execution permissions, run it and provide your Certificate options, the most important one being Common Name field ( add official domain name here) and leave Password and Optional Company fields blank.

$ sudo chmod +x nginx_gen_ssl
$ sudo ./nginx_gen_ssl
Set Execute Permissions
Set Execute Permissions
Generate SSL Keys
Generate SSL Keys

At the end of keys generating task, a listing with all available keys under Nginx ssl directory will be displayed.

List all Available Keys
List all Available Keys

Also if you want this script as to be used as a system command, copy or move it to /usr/local/bin/.

$ sudo mv nginx_gen_ssl  /usr/local/bin

11. After we have generated keys necessary for Nginx SSL Virtual Host it’s time to actually create SSL Virtual Host configuration file. Use the same system IP address for Virtual Host as above on server_name directive but, slightly change the Virtual Host file name by appending ssl before .conf, to remind you that this file stands for name-ip SSL Virtual Host.

$ sudo nano /etc/nginx/sites-availabe/name-ip-ssl.conf

On this file change listen port statement to 443 ssl and provide SSL and certificate key files paths with the ones created earlier to look like in below excerpt.

## File content ##

server {
    listen 443 ssl;
    server_name 192.168.1.33;

       ssl_certificate     /etc/nginx/ssl/192.168.1.33.crt;
       ssl_certificate_key  /etc/nginx/ssl/192.168.1.33.key;

       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;

       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;

    access_log /var/log/nginx/192.168.1.33-ssl.access.log;
    error_log /var/log/nginx/192.168.1.33-ssl.error.log;
    root /srv/http;
    location / {
    index index.html index.htm index.php;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
 }
    location /phpmyadmin {
        rewrite ^/* /phpMyAdmin last;
    }
    location ~ \.php$ {
        #fastcgi_pass 127.0.0.1:9000; (depending on your php-fpm socket configuration)
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
}
Create SSL Virtual Hosts
Create SSL Virtual Hosts

12. After the file has been created use n2ensite script or ln command line to activate it (creates a file symbolic link in sites-enabled directory), then restart Nginx daemon to apply settings.

$ sudo ./n2ensite name-ip-ssl
OR
$ sudo ln -s /etc/nginx/sites-available/name-ip-ssl.conf /etc/nginx/sites-enabled/
$ sudo systemctl restart nginx
Active SSL Virtual Hosts
Active SSL Virtual Hosts

13. Again point your browser to Arch IP URL but this time using HTTPS protocol – https://192.168.1.33 on my system- and a Connection Untrusted security error should appear ( Add and Confirm Security Exception to go further on page).

Verify HTTPS Connection
Verify HTTPS Connection
Verify Virtual Host Content
Verify Virtual Host Content
Verify PHP Configuration
Verify PHP Configuration

As you can now see your Nginx Virtual Host serves the same content as previous name-ip host but this time using a HTTP secure connection.

Step 3: Access PhpMyAdmin through Virtual Host

If Virtual Host is enabled on Nginx, we no longer have access to http://localhost path contents ( localhost usually serves content using loopback IP address or system IP address if is not otherwise configured) because we have used Arch system IP as server_name so our content path has changed.

14. The simplest method to gain access to PhpMyAdmin through web is to create a symbolic link between /usr/share/webapps/phpMyAdmin/ path and our new defined Virtual Host path (/srv/http).

$ sudo ln -s /usr/share/webapps/phpMyAdmin/ /srv/http/

15. After you executed the above command, refresh your page and you will see a new folder phpMyAdmin appear, if autoindex statement enabled on Nginx Virtual Host or point your URL directly to PhpMyAdmin folder https://arch_IP/phpMyAdmin.

16. If you want to sanitize phpMyAdmin string on browser edit your Virtual Hosts files and add the following content under server block.

location /phpmyadmin {
       rewrite ^/* /phpMyAdmin last;
    }
Access PhpMyAdmin via Virtual Host
Access PhpMyAdmin via Virtual Host

Step 4: Enable Password Protected Directory on Nginx

Unlike Apache, Nginx uses HttpAuthBasic module to enable Password Protected Directories but doesn’t provide any tools to create an encrypted .htpasswd file.

17. To achieve directory password protection with Nginx on Arch Linux install Apache web server and use its tools to generate an encrypted .htaccess file.

$ sudo pacman -S apache

18. After you have installed Apache create a new directory under /etc/nginx/ named intuitively passwd where .htpasswd file will be stored and use htpasswd command with –c switch on first added user to generate file, then if you want to add more users use htpasswd without –c switch.

$ sudo mkdir /etc/nginx/passwd

$ sudo htpasswd -c /etc/nginx/passwd/.htpasswd first_user
$ sudo htpasswd /etc/nginx/passwd/.htpasswd second_user
$ sudo htpasswd /etc/nginx/passwd/.htpasswd third_user
Enable Password Protected Directory
Enable Password Protected Directory

19. In order to protect name-ip-ssl Virtual Host root /srv/http/ served path with all its sub folders and files beneath it add the following instructions inside your Virtual Host server block under root directive and point it to absolute .htpasswd file path.

auth_basic "Restricted Website";
auth_basic_user_file /etc/nginx/passwd/.htpasswd;
Restricted Website Configuration
Restricted Website Configuration

20. After you restart Nginx service, refresh page and an Authentication Required popup should appear demanding for your credentials.

Authentication Required
Authentication Required

Now you have successfully enabled Nginx Password Protected Directories but be aware that the same time Apache web server is installed in your system so make sure that it stays disabled and by any means do not start it because can lead to ports conflicting with Nginx.

Step 5: Redirect HTTP to HTTPS on Nginx

21. If you like for browsers to automatically redirect all insecure HTTP requests to HTTPS protocol open and edit you’re non-ssl Virtual Host and add the following instruction under server_name directive.

rewrite        ^ https://$server_name$request_uri? permanent;
Redirect HTTP to HTTPS on Nginx
Redirect HTTP to HTTPS

All of settings presented on this article where made under an Arch Linux system that acts as a server, but most of them, especially those regarding Nginx configurations files, are available on most of Linux systems with slightly differences.

Matei Cezar
I'am a computer addicted guy, a fan of open source and linux based system software, have about 4 years experience with Linux distributions desktop, servers and bash scripting.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

2 thoughts on “Create Virtual Hosts, Password Protect Directories and SSL Certificates using “Nginx Web Server” in Arch Linux”

  1. Install Apache just to encrypt passwords? lolwut? Just use OpenSSL with the command “openssl passwd -apr1”. OpenSSL should be installed on almost all servers.

    Reply

Got something to say? Join the discussion.

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.