Host a website(+ssl) with Nginx and a Digitalocean droplet

Cristian Cedacero
9 min readNov 4, 2020


Photo by Christina Morillo from Pexels

Nowadays there’s an endless number of cloud hosting solutions and they make it super easy to host your own website online. Some hosting providers even throw a free domain to incentivize you to buy multi year hosting. For most people, this is all they will ever need but if you’ve ever wonder about the steps that go into setting up your own server, pointing your domain to it, and installing an ssl certificate, then keep on reading.

Recently I found myself migrating from a Google vm to a Digitalocean droplet and I ran into a couple of issues that took me many hours to debug. While the Digitalocean documentation is superb, I’m writing this article as a way to centralize and summarize the pieces of knowledge I learned during my learning journey. You can find many of the original documentation I read linked at the end. With that said, let’s get get started 🐱‍💻

We’ll be using a digital ocean droplet that runs at $5 per month but the process is pretty similar when using a google cloud virtual machine.I also recently learned that you can deploy up to three static sites for free on digital ocean using their app platform. I will be testing it out and writing about it in the upcoming weeks.

Step1. Sign up for DigitalOcean here if you don’t have an account. Disclaimer, this is my referral link where you get $100 to use within 60 days. Feel free to use or just sign up by googling.

Step2. Once logged in, create a new debian droplet and choose the lowest tier at $5 month. I’ve opted for Debian but you can choose whichever distro flavor you’d like (commands used here may vary). During the setup process, you have to set up authentication. I recommend ssh for additional security and that’s what we’ll be using but you can also create a password.

To easily copy your public ssh key to your clipboard, you can use the terminal command below. You can then paste the keyin the ssh key section and complete the new droplet setup.

$ pbcopy < ~/.ssh/

Step3. We’re going to ssh into your newly created droplet. Open your terminal and use the syntax below. You can find your server ip on your droplet homepage.

$ ssh root@your_server_ip
Default ssh Linux login desclaimer

If you’ve added your ssh key correctly, this should automatically log you in and you should be greeted with a screen similar to the above. The beauty of ssh keys !🐱‍💻

Now, we’re going to create a regular user for our droplet. We don’t want to use our droplet as root.

$ adduser username

Now, it’s time to grant admin privileges. The command below will allow you to type sudo to user admin rights.

$ usermod -aG sudo username

Our droplet currently has no firewall configured. You can do this either though the droplet settings or you can use Uncomplicated Firewall (ufw). We’re going to install ufw, allow ssh connections, enable our firewall, check the firewall status with the commands below. Don’t forget to allow ssh because you’ll get locked out if you don’t . Speaking from experience😅

$ apt install ufw$ ufw allow OpenSSH$ ufw enable$ ufw status

Once you’ve successfully configured ufw, the last thing to do is to share your public ssh key with the user you just created.

The first command below will copy your ssh directory to your new users home directory. The second command will change the owner of the directory to your new user.

$ cp -r ~/.ssh /home/username$ chown -R username:username /home/username/.ssh

You should now be good go to, but don’t close your current root session just in case something goes wrong. Open a new terminal window to login with your new account.

$ ssh username@your_server_ip

If you can login and execute sudo commands successfully, feel free to close your root terminal window. Now, we’ll be working with our newly created user account.

Step4. Install Nginx and configure ufw to allow ‘Nginx full’ 🖥️

$ sudo apt update$ sudo apt install nginx$ sudo ufw allow 'Nginx Full'$ sudo ufw reload$ systemctl status nginx

We’re reloading our firewall above to ensure our new firewall rule is applied. We’re allowing Nginx Full because we’re going to be serving our website on port 80 and 443 for unencrypted and encrypted traffic.

The last command above will output the status of our server. It will look something like below if it’s running successfully.

Nginx status out after running ‘systemctl status nginx’

If all has gone well, we can now visit the server default index page by visiting the droplet’s ip address. You can get the ip address from your droplet configuration or by running the command below.

$ ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'

You can then simply copy and paste the ip on your address bar .You will be greeted with the message below.

Default nginx index file

We’re halfway there! We’ll now set up a server block to serve our website and link it to our sites available to be served. First, we’ll create a directory for our website and assign the ownership to the current user.

$ sudo mkdir -p /var/www/domain_name/html$ sudo chown -R $USER:$USER /var/www/domain_name/html

We’re now going to create a sample index page for our website and add some minimal html for testing. We can do so with the command below.

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

We’ll now add some simple html. You can add anything you’d like, but the html directory is where you’ll eventually add your website files. This test index file will be replaced by your website’s index.

<title>Test domain_name🐶</title>
<h1> It's working! 🐱‍💻</em>. </h1>

After you’ve created a test index file, we’ll configure the server block to serve our website. The first thing we need is to create an additional configuration file.

$ sudo nano /etc/nginx/sites-available/domain_name

We’ll then use the configuration file below adjusted for your own domain_name.

server {
listen 80;
listen [::]:80;
root /var/www/domain_name/html;
index index.html index.htm index.nginx-debian.html;
server_name; location / {
try_files $uri $uri/ =404;

In order to enable our configuration file, we’ll use the command below to create a symbolic link.

$ sudo ln -s /etc/nginx/sites-available/domain_name /etc/nginx/sites-enabled/$ ls -l

A symbolic link simply points to another file and it’s similar to a shortcut. You can see active links in a directory by using the second command above. There will be an arrow that points towards the path it’s referencing.

The final section to complete this setup is to uncomment the line below(pic) in your nginx configuration file. This prevents hash bucket memory problems that can arise from multiple server names.

$ sudo nano /etc/nginx/nginx.conf
Nginx configuration line

After you uncomment out the line above, save it and make sure your config file is error free by running the command below.

sudo nginx -t

If all goes well, the test will resuccessfulccesful message. If it does not, it will tell you where the problem is and you can open the referenced file and fix the error.

The last thing to do in this section is to restart your server.

sudo systemctl restart nginx

Step5. We’re almost there! We must now deal with our domain pointing! We’ve set up our server, now we must point our domain to the right place. This will be slightly different depending on the registrar you’re using but you’’ll usually want to use custom settings and point to digitalocean servers like below. You can read detailed steps on how to point to different domains here but we’ll be using a Google domains example here.

*In Custom Name Servers add 3 entries:
Google Domains custom configuration settings

Now go to your digital ocean homepage and under create select the option ‘Domain/DNS’ and add your domain like below.

Digitalocean create menu
Digitalocean add domain menu

Now, create two A records that point to the droplet project where your website is. This will automatically populate their ips. For the first record, type an @ under the hostname. For the second record, you can type www.

Digitalocean DNS configuration settings
Digitalocean DNS configuration settings

Once this is done, your domain should now be point to your server. If you visit www., you should see the test index file we created.

Step6. The second to final step is to user Certbot to add an SSL certificate and encrypt our traffic. That way, Google will like your website and users will be reassured by the small lock on the address bar.

Use the command below to install certbot dependencies.

$ sudo apt install python3-acme python3-certbot python3-mock python3-openssl python3-pkg-resources python3-pyparsing python3-zope.interface

Install certbot for nginx.

$ sudo apt install python3-certbot-nginx

Since we’ve already enabled our server block, and we’ve also enabled ufw to allow ‘’Nginx Full’ access on ports 80 and 443, Certbot should be able to automatically deploy SSL. We can run the command below

$ sudo certbot --nginx -d  -d

The setup wizard will run and you will first be asked to enter your email, agree to the terms of service, and mailing preferences. After this, certbot will download a certificate from let’s encrypt and configure it on your server block. Certbot will then ask whether you’d like to redirect all traffic from http to https. Because we want this, make sure you select yes by typing 2 on the prompt.

Secured SSL lock on address bar

At last! Certbot will finish running and you’ll receive a congratulatory message informing you that you’ve enabled https traffic. At this point, you can now visit your domain and you should see the lock symbol next to your domain. Yay!!! You’re nearly done!

Step7. The last step to this process is securely copying over your website files to your server block so that Nginx servers it. For this, we can use secure copy with the recursive flag like below. You will provide scp the local path of the folder you’d like to copy followed by a space, credentials, and the path of where you’d like to copy the folder to. You can copy it directly to the server block or to any directory and move it over when organized properly.

scp -r files_directory_path username@droplet_ip:/remote/directory

You’re done! Congrats on making it all the way through! I hope I encoured you to try something new :). Below are the resources I used on my learning journey. 🐱‍💻



Cristian Cedacero

Full Stack Developer — Runner — NYC