Free SSL with NGINX and LetsEncrypt on Debian 10

Let’s Encrypt is a free https certificate you can install on your cheap VPS for free, browser-validated https.  In this tutorial, we’ll walk through setting up Let’s Encrypt https on an nginx host running on Debian 10.

We’ll be installing nginx from scratch but not will not be getting into php-fpm and other extensions in this tutorial. I’ll be starting from a spanking new VPS on Vultr.

This tutorial assumes that you’ve already got your DNS records setup. In other words, if you’re setting up for, then already has an A record or CNAME that points to your VPS. Note that the certbot installer we’ll be using will query DNS, so this must be working properly.

Installing and Setting Up nginx

Installing nginx in straightforward:

apt-get update && apt-get upgrade
apt-get install nginx

I’ll be setting up and putting its web root in /web/

Let’s configure the web root and log directory:

mkdir -p /web/
mkdir -p /var/log/nginx/
chown www-data:adm /var/log/nginx/

Configure Logs and Rotation

We want separate logs for each domain we host, and we want to rotate those logs. We can Debian’s log rotation system to accomplish this. We do this by placing the appropriate rules file in /etc/logrotate.d. Start with nginx’s basic log rotation rule:

cp /etc/logrotated.d/nginx /etc/logrotate.d/nginx_domain_logs

Now edit /etc/logrotate.d/nginx_domain_logs and modify as follows:

# change this: /var/log/nginx/*.log { 
# to this:
/var/log/nginx/*/*.log {

Setting Up nginx http

Before setting up https, we’ll setup http. I’ll place a place-holder index.html in /web/

<title> test page</title>
<h1> works!</h1>

Now take a look at /etc/nginx. /etc/nginx/sites-available should have a file for every single site we might host. Then we symlink into /etc/nginx/sites-enabled to turn on or off specific sites.

Let’s create a basic nginx config by creating /etc/nginx/sites-available/


  access_log /var/log/nginx/;
  error_log /var/log/nginx/;

  location / 
    root /web/;
    index index.html;

Now make it live by:

ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

Let’s syntax check that file:

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Now restart nginx:

systemctl restart nginx

Then I visited and successfully saw the HTML I created early.

Activating Let’s Encrypt

Let’s start by installing certbot, the package that will setup https for us and keep our certificate fresh:

apt-get install certbot python-certbot-nginx

Now for the magic! Run this command:

certbot --authenticator webroot --installer nginx

And then follow along with the interactive install. My input is bolded:

# certbot --authenticator webroot --installer nginx
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at You must
agree in order to register with the ACME server at
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for
Input the webroot for (Enter 'c' to cancel): /web/
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled

(rest snipped)

Now take a look at /etc/nginx/sites-available/


  access_log /var/log/nginx/;
  error_log /var/log/nginx/;

  location / 
    root /web/;
    index index.html;

  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

  if ($host = 
    return 301 https://$host$request_uri;
   # managed by Certbot

  listen 80;
  return 404; # managed by Certbot

certbot has done the following:

  • provisioned an SSL certification for
  • loaded the SSL configuration in /etc/letsencrypt
  • updated /etc/nginx/sites-available/ and put the proper nginx rules in place to serve HTTPS
  • also added an entry so that if you connect on http, it redirects to https

And going to in my browser confirms everything is working correctly.

Keeping Your Certificate Up to Date

Here’s a cool part of the certbot system: this chore is already taken care of for you.

Take a peek in /etc/systemd/system/certbot.timer and you’ll see a job is setup to run twice a day to check renewal and renew if needed.

The post Free SSL with NGINX and LetsEncrypt on Debian 10 appeared first on Low End Box.

Read more »

How To Set Up Apache Virtual Hosts on Debian 8, 9, and 10

In this tutorial, we will start with an empty VPS with a freshly installed Debian 9 and will end up with three different sites sharing the same IP address, hosted on the same machine.

Apache web server analyzes HTTP request headers and appropriately connects it to the directory structure inside the VPS. The technical term for “sites” inside VPS boxes is “virtual host” – the server is the “host” to many domains at the same time, hence, they are not real, but only “virtual”.

Let’s see how it’s done.

What We Are Going To Cover

  • Creating a Non Root User
  • Installing Apache
  • Installing and setting up UFW
  • Defining File Locations For the Default Apache Page
  • Creating File Structure For Our Demo Virtual Hosts
  • Granting Permissions
  • Creating index.html Pages For Our Demo Sites
  • Creating Virtual Hosts Files
  • Turning On the New Virtual Host Files
  • Testing the Virtual Hosts
  • Securing Your Domains With Let’s Encrypt TLS certificates

Read more to continue…


We use Debian 9 but this article has been tested against Debian 8 and 10 as well. The differences are noted in the text:

  • Starting with a clean VPS with
  • At least 512Mb of RAM and
  • 15Gb of free disk space
  • You will need root user access via SSH
  • Two domain names pointed to your server’s IP address using A records at your DNS service provider.
  • We use nano as our editor of choice, and you can install it with this command:
sudo apt install nano -y
  • On Debian 8 you need to install sudo as well:
apt-get install sudo

Step 1: Creating a Non Root User

Once you are logged in as root, you can create a new user account that you’ll use to carry out the rest of the commands in this tutorial. We’ll call the new user simpleuser. To create it, run:

adduser simpleuser

Debian 9.7 will ask you for a UNIX password, while Debian 10 will ask only for a password, however, the procedure is the same. Enter the password twice and press Enter five times to create a new user.

Then, add simpleuser to the sudo group, so that you can run commands as sudo:

usermod -aG sudo simpleuser

On Debian 9.7, you may get a harmless but annoying message like this:

Turns out that your version of Debian 9.7 may come with a package called unscd preinstalled. It is supposed to speed up requests to name servers like LDAP… unfortunately, it contains a bug that forces the lines such as

sent invalidate(passwd) request, exiting
sent invalidate(group) request, exiting

to appear after usermod command.

Feel free to remove unscd with this command:

apt remove unscd

After that, the usermod command won’t report strange lines.

You don’t get this problem on Debian 10.

Anyways, now you will be able to use the simpleuser as a root using the command sudo.

Step 2: Installing Apache

To install Apache web server on all three versions of Debian, type the following commands:

sudo apt update
sudo apt install apache2 apache2-doc

That will install the Apache manual as well.

The following command will show the status of Apache service in a terminal window:

sudo systemctl status apache2    

The real test of successful installation is whether you can access files from the server through your local browser. Navigate to this address:


You should see a welcome page for Apache on Debian, which means that you now have Apache running.

Step 3: Change Firewall Rules to Enable Nginx

On Debian, the iptables firewall is installed by default, but we prefer ufw, the uncomplicated firewall. First install it:

sudo apt install ufw -y

List all the port profiles ufw already knows about:

sudo ufw app list

It will show quite a list, but we are interested only in those entries that have prefix *WWW in them:

Let’s take a closer look at the WWW Full:

sudo ufw app info "WWW Full"

The result is:

It is exactly what we need, two ports 80 and 443, one for the HTTP traffic and the other for HTTPS traffic. Enable it:

sudo ufw allow 'WWW Full'

Here is a list of ports and feel free to add any other that your host requires for the normal functioning of the system:

sudo ufw allow ssh
sudo ufw allow ftp
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 20/tcp
sudo ufw allow 3000
sudo ufw allow 8080
sudo ufw allow 'WWW Full'
sudo ufw enable

The above commands illustrate various ways of defining ports within ufw. For instance, ports 3000 and 8080 are here used only as an example – they are not needed for installing virtual hosts on Apache, but may well be needed for some other type of application running on your VPS. Learn from your VPS provider which ports might be mandatory for normal functioning of the system and then add them to ufw.


Always enable ssh, http, https and other critical ports in ufw, otherwise you will NOT be able to log back into your VPS server!

To see the changes, run:

sudo ufw status

To test, navigate to your domain in your browser. It should load correctly, and if you again see the welcome to Apache on Debian page, you have set up ufw correctly.

Step 4: File Locations For the Default Apache Page

We’ll now learn how did Apache know to serve that welcome page. In Debian, root document page is in directory /var/www/html and it is called index.html. You can see its contents by running this command:

ls -la /var/www/html

Note that the directories and the index.html files belong to the root user.

Execute this command

sudo nano /var/www/html/index.html

to see the contents of index.html:

It is a very long document, so we can scroll through it, change it and so on.

Under Debian, all Apache files are in folder /etc/apache2:

ls -la /etc/apache2

Directories sites-available and sites-enabled hold information on sites that exist and on sites that are permitted to be served to the Internet, respectively.

File /etc/apache2/sites-enabled/000-default.conf is a symbolic link to the file of the same name in folder sites-available. That link enables Apache to read the contents of file


and serve it to the browser. By adding more config files into /etc/apache2/sites-available and creating the corresponding symbolic links in /etc/apache2/sites-enabled, we can serve different pages to different domains. That is how we can host multiple independent sites off of one and the same IP address.

Each site in Apache parlance is called “virtual host” and will have to reside in its own subdirectory. The plan for adding new virtual hosts boils down to

  • creating file structure for each site,
  • populating HTML and other files in the site,
  • creating a new .conf file in /etc/apache2/sites-available, and
  • creating a new symbolic link in /etc/apache2/sites-enabled.

Apache will then do the rest, automatically.

Step 5: Creating File Structure For Our Demo Virtual Hosts

We will create two virtual hosts called and They will correspond to DNS entries and that we have previously made using A records at our DNS service provider. (Instead of these, you should enter your own site domains.) If we now navigated to in a browser, the default index.html page with basic Apache information would be served, again.

Let’s now create a directory to hold our site. Apache on Ubuntu stores its HTML files under /var/www/html so we could also use it to create our demo sites there. One possibility is to make that folder the top one and to put the demo sites into it. With commands such as

cd /var/www/html
sudo mkdir
sudo mkdir
ls -la

we would have the following directory structure:

Here we decide upon the other possibility, and that is to go one level up the directory tree and create the demo sites in /var/www. Inside folders and we can create whatever directory structure we need, for example:

cd /var/www
sudo mkdir -p /var/www/,private,log,cgi-bin,backup
sudo mkdir -p /var/www/,private,log,cgi-bin,backup
ls /var/www/ -la

Step 6: Granting Permissions

From the image above we see that root user is still owning the public_html folder, from which our public files will be served to the Internet. We will now change the ownership so that our simpleuser can access the public_html files. The commands are:

sudo chown -vR simpleuser:simpleuser /var/www/
sudo chown -vR simpleuser:simpleuser /var/www/

Also make sure that files in /var/www and its subfolders can be read correctly:

sudo chmod -R 755 /var/www

Step 7: Create index.html Pages For Our Demo Sites

Our public files will be in /var/www/ and /var/www/ We’ll now create an _index.html in each of these two folders so that we have something to see while browsing. Using nano, we will create index.html for

sudo nano /var/www/

We need only one line of text, preferably in H1 format for better readability. Insert the following text into nano, then save and close the file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<title> Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
    color: #FF3333;


<h1>This is 

Create index.html for

sudo nano /var/www/

and paste this in:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<title> Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
.style1 color: #3333FF

<h1 class="style1">This is</h1>

Step 8: Create Virtual Hosts Files

Let us now inform Apache that there are two new sites to be served. We will copy the default virtual host file, 000-default.conf twice and then alter these new files to reflect the positions of and sites on disk.

Step 8A: Create the First Virtual Hosts File

Copy the original file and rename it

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/

Use nano to see what is in it:

sudo nano /etc/apache2/sites-available/

For clarity, we’ll remove comments and this is what you should return back into nano:

<VirtualHost *:80>
    DocumentRoot /var/www/
    ErrorLog $APACHE_LOG_DIR/error.log
    CustomLog $APACHE_LOG_DIR/access.log combined

Here is a detailed explanation:

  • 80: This virtual host will listen on port 80. You can change port number through file ports.conf with this command:
sudo nano /etc/apache2/ports.conf

The contents of the ports.conf file are here in case you want to actually change them:

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 80

<IfModule ssl_module>
        Listen 443

<IfModule mod_gnutls.c>
        Listen 443

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
  • ServerAdmin: It is the email address to which Apache will send messages for administrator in case of an error in the system. May be omitted.
  • ServerName: Server name, obviously, it should coincide with the domain name.
  • ServerAlias: Another name for the same server as above. You can have as many of these aliases as you like.
  • DocumentRoot: Points to the absolute address of the site on disk.
  • ErrorLog: The address of the error log.
  • CustomLog: The same for access logs – for example, have there been too many unauthorized accesses from the same IP address?

Step 8B: Create the Second Virtual Hosts File

Do the same for the other site/domain. Here are the commands:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/

Again use nano to see what is in it:

sudo nano /etc/apache2/sites-available/

This is what you should return back into nano:

<VirtualHost *:80>
    DocumentRoot /var/www/
    ErrorLog $APACHE_LOG_DIR/error.log
    CustomLog $APACHE_LOG_DIR/access.log combined

Save and close the file.

Step 9: Turn On the New Virtual Host Files

Command a2ensite will create symbolic links from sites-enabled directory to sites-available and so Apache will routinely start serving the virtual hosts. The commands are:

sudo a2ensite
sudo a2ensite

If you want to disable the default site, the command would be:

sudo a2dissite 000-default.conf

You may want to leave it as it is in case that someone enters the IP address directly into the browser – then the default index.html will be activated and the visitor would see what you have prepared for that case.

Once you use the a2ensite and a2dissite commands, you may see something like this in the terminal window:

If you try to activate a link that is already activated, you will be notified as already enabled. And then you will see two lines that say:

To activate new configuration, you need to run:
  service apache2 reload

That is, however, an incorrect advice to follow. The proper command is:

sudo service apache2 reload

In other words, run it as sudo.

Also, be sure to clear cache in your browser or it may start fooling you with old values instead of the properly refreshed ones.

Step 10: Testing the Virtual Hosts

If you have left the default IP address activated, it will currently show the welcome to Apache screen. If you enter address you will see this:

And entering into the browser changes the image to:

Step 11: Securing Your Domains With Let’s Encrypt SSL

We can use free certificates to turn our HTTP traffic into HTTPS traffic, which will make connecting to your site secure.

Certbot for Debian comes from the Backports repo, so let’s create a sources list for our case:

sudo nano /etc/apt/sources.list.d/apache.list

and enter the following line into that file:

deb stretch-backports main


sudo apt update

and install backports:

sudo apt-get install certbot python-certbot-apache -t stretch-backports

Finally, run Certbot:

sudo certbot --apache

It will ask for your email address in case of emergency, then another two questions that you may answer however you like and then the most important question – which names would you like to activate HTTPS for?

I chose 4 and 5 as these are the only real domains and subdomains that I have DNS set up for:


The last question will be whether do you want HTTPS access or not. You do, of course, so choose 2.

Restart Apache:

sudo service apache2 restart

In your browser, go to address

We have entered the HTTP address and Apache automatically redirects to HTTPS, as it should:

You’ll notice that the actual site address starts with HTTPS and that there is green padlock in the address bar.

What Can You Do Next

We have shown how to share one IP address to one, two, three or dozens or hundreds of independent sites. You can now use this knowledge to host all your sites on one low cost VPS box, running Debian 9 or 10.

Dusko Savic is a technical writer and programmer.

Read more »