January 18, 2018

How I build my personal website (Part 1)

This summer I set a goal to learn to make and deploy websites and after tons of Googling, I built my personal website and this blog to practice my skill.

Here's what I find most fascinating: Even though I just learned some very basic web development skill, this website is not any more or less real compare to the one made by the most skillful web developer, or the most resourceful company.

As a programmer, it's perhaps no surprise that I love building things. Since you are here, I suspect you are too! If that's the case then you came to the right place! In this quick guide, I'll help you build a static personal site.

What you will need

  1. A computer that is connected to the internet.
  2. Preferably a Unix or Unix-like system (e.g. Linux, OSX)
  3. I will also assume you have some basic knowledge of computer science (let say, a semester of CS at university)
  4. I anticipate it will take a few hours to complete this guide so make yourself a coffee and pick a good playlist. =)

Ok, enough of me talking, let just jump straight to it!

Step 0: Get Github Student Developer pack (Optional)

If you are a student I strongly encourage you to check out the
Github developer pack because you will pretty much get free money to help you learn to program! Just follow the link and fill in the required details. The verification should be done in a few minutes.

When you are done, go take a look at the perks you can get as a student! You will want to pay extra attention to Digital Ocean and NameCheap.

Step 1: Rent a cloud server

What is this for?
A cloud server is effectively a remote computer that you rent. We are going to store our files here, and when user visit your site they are going to access content on this server.
Why are we renting? Can we use my own PC?
Technically yes! But your computer and local network is not designed to host website, and so there could be problems in the future. It's easier to rent a cloud server.

We are going to use Digital Ocean for this service (Another popular alternative is Amazon Web Service). Make an account and select Create > Droplet (Droplet is Digital Ocean's name for a server.).

Here you will notice that you have plenty of varieties to choose from. For our purpose we will go with:

  • Ubuntu 16.04 x64
  • 1 GB Memory
  • 1 CPU
  • 25 GB SSD
  • 1000 GB data transfer.
  • Singapore data center - if you are in Australia like me =)

Don't worry about the spec, we can always up/down grade it later.

What about the SSH key option?

Good question! It's actually recommended to add an SSH key. But to make things simpler we'll leave that for now.

To access your server, open your terminal and type this (Replace your_ip_addr with the IP address you can find on the Digital Ocean Dashboard.)
ssh root@your_ip_addr

You should now be prompted to enter your password, which you should receive from through your email.

If you got in then Congratulation! You just visited your remote server in Singapore!

One last thing before we move on to the next step. It's usually not recommended to use your root account on a day-to-day basis. We will instead make a new user and provide it root or "sudo" privilege.

adduser your_username

Once you did that, add your new user to the "sudo" group with this command:

usermod -aG sudo your_username

Helpful tip: Use this command if you need to change your password in the future.

passwd your_username 

Use su (switch user) to login to your newly created user.

su your_username

sudo vs root?
Root is the default admin user for a Unix system. It has two special properties:

  • Root has the highest level of privilege; it can edit any file and execute any program.
  • Root always has user id 0. (Note that this means that any user with uid 0 also enjoys similar privileges.)

Then what about sudo?
Historically, when you need admin privilege, you would use the su command to switch to root. However, it is discouraged to be root unless it is necessary. As a response, sudo was created as a way to gain a one-off privilege for a specific task. In short:

  • sudo is a group that any user can be added to by another user with root privilege.
  • If you are a "sudoer" you can use the sudo command to gain temporary root privilege.

Step 2: Get a domain name

I personally recommend NameCheap, mostly because I'm using it, and they give a free .me domain as part of the Github developer pack. Another very popular website to register a domain name is Go Daddy.

Before we move on, here's a few helpful terminologies:

  1. IP address: This is a set of number that is used to identify your computer. If servers are buildings, then ip address is your street address.
  2. Domain name: Do you know where is "Bennelong Point, Sydney NSW 2000"? Most likely not. What about Sydney Opera House?. The fact is that real address is hard to remember and communicate. Domain name (e.g. google.com) is simply an easy-to-read name that is mapped to one or several ip addresses by the domain name system (DNS) record.
  3. Subdomain: This is a domain that is part of another higher level domain. E.g. both "www.justind.me" and "blog.justind.me" is a subdomain of "justind.me".
  4. Top-level domain: This is the last bit (highest level) of a domain. In my example, ".me" is the TLD.
  5. Port: To reuse my analogy, if servers are buildings, ports are the different floors or room numbers. This is very helpful as you can configure your server to serve "yourpersonalsite.com" at say, port 80, and "blog.yourpersonalsite.com" at port 2368.

All that is left to do is to purchase a domain that is available and you are good to go! (If you are eligible, don't forget to claim your free .me domain from the Github dev pack)

Step 3: Set up your DNS record

This can be done in your domain registry, in our case, Namecheap. Most other registries will have very similar ways to achieve the same result.

Go to your dashboard, select manage then Advanced DNS. Here we will add 2 new records by clicking add new record:

Type Host Value TTL
A record @ your_ip_addr Automatic
CNAME www your.domain (e.g. justind.me) Automatic

Uhhh A record? CNAME...? what are thooooose?

A record means Address record, which does exactly what you would expect: Map domain name to ip address.

CNAME record stands for Canonical name, which is a fancy way of saying "map one domain to another domain". We use this to redirect www.your.domain to your.domain.

Keep in mind that it might take up to 48 hours (usually < 30 mins) for your change to propergate throughout the ISP around the world. But once that is done, you should be able to visit your website with your.domain.

Let's move on to the next step while we wait.

Step 4: Install a web server on to your remote machine

But first:

What is a webserver?
The term 'webserver' can be confusing, mainly because webserver can refer to both the hardware (The server we rent from Digital Ocean) and a software that control how user access contents and files stored in the hardware. In this section, we will be referring to the software when we use the term.

Think of a webserver as a librarian that respond to your request for content. Specifically, users will send HTTP request with a web-browser, and the webserver will respond with an HTTP response. Sometime, the response will be an existing file or article that is presented to you unaltered (Static e.g. Wikipedia pages), in other cases, the webserver will compile a response using several sources (Dynamic e.g. Google search result.). We'll be dealing with static pages in this guide.

We'll use Nginx (pronounce: "Engine X") as our webserver. It's perfectly fine to use other webserver such as Apache, but I'd never work with that so Nginx it is! ;)

First of all, use ssh to access your server. Once that is done installing Nginx is super easy! Just type these on the console:

sudo apt-get update
sudo apt-get install nginx

And we got our web server!

There might be one last thing to do before we get to see if our webserver is working. The server we got comes with a firewall called ufw which might block the webserver from functioning properly.

Use this command to check:

sudo ufw status

If the status is not "inactive", you might need to grant Nginx http access by typing

sudo ufw allow 'Nginx HTTP'
sudo ufw allow 'Nginx HTTPS'

Let's now take a look at whether our webserver is working as expected:

service nginx status

If you visit http://your.domain with your browser you should now see a default Nginx page!

Step 5: Configure Nginx

At this point, you might have a few questions. Where is the default page stored? How do I build my own page?

The default folder from which Nginx serve its pages should be /var/www/html. Try navigate to that folder and you should see a files titled "index.nginx-debian.html" or something similar.

The location of the folder Nginx serve is specified by the file called default located at /etc/nginx/site-available/. This also means we can easily change it to a different folder.

Create a directory called your.domain in /var/www/. This will be where we store our site's file. You actually name it anything you want, but it's good practice to stick to the convention unless you have a good reason to do otherwise.

Understanding Nginx config

Nginx configuration file dictate the way Nginx behave. The main config file is /etc/nginx/nginx.conf which deal with the general and global configuration of the webserver.

Additionally, there are also a site-specific configuration files stored in /etc/nginx/sites-available. These files allow different setting for each sites the host support.

Reading the default config file can be a bit intimidating! But don't worry! We'll go through what each lines mean.

The first thing we will realize, is that once we remove the comments, the content becomes much more intelligible.

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

This tells Nginx to:

  • Retrieve files from the correct folder.
  • Serve index.html as the main page.
  • Use this "server block" when user request "your.domain" or "www.your.domain".
  • Search for a requested files or directory, if not found, return a 404 error.

We will make a copy of the files and name it "your.domain" and edit it such that it looks like this:

server {
    listen 80 default_server;
    listen [::]:80 default;
    root /var/www/your.domain;
    index index.html;
    server_name your.domain www.your.domain;
    location /{
        try_files $uri $uri/ =404;

we then activate (enable) the server block by creating a link to the sites-enable folder

ln -s /etc/nginx/sites-available/your.domain /etc/nginx/sites-enabled/

Step 6: Create index.html

We have finally completed the setup! Just to make sure we can create our own content, we will write a simple page index.html with vim or nano to make sure everything is working.

<!doctype html>

    <title> My first website </title>

    <p> Hello World! =) </p>


Wait for a few second (Or force refresh by restarting Nginx with service nginx restart) and refresh your browser. You should see your new page!

If you got to this point then congratulation! You had just make your first website from scratch!

Optional: Enable HTTPS

Go to any websites that require good security (say Facebook or your bank) and you will see a little padlock that declares the connection is secure, followed by a URL that begins with https://. Turn out, the HTTP protocol that we used so far can be quite insecure. The fact that the connection is unencrypted means that an eavesdropper can read our confidential message such as passwords.

Encrypting our connection, however, is slightly more complicated than expected. Specifically, we'll need to install a TLS or SSL certificate from a certificate authority. Explaining how this system works will an entire blog post, instead, I'll point you to this excellent article that explain how https works in layman term.

Getting a TLS certificate used to be quite complex (And cost some money), luckily the Electronic Frontier Foundation had since developed a wonderful automated tool called Certbot to help you with this! Certbot also uses a free, and trusted, certificate authority call "Let's Encrypt".

To install Certbot, simply type this to your server's console

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx 

Run this command to activate Certbot, where you will be asked for your email and other details.

sudo certbot --authenticator webroot --installer nginx

Note that the free Let's Encrypt certificate will expire after 90 days, so make sure you renew it regularly! (Or you can write a script to help you!)

sudo certbot renew

A few more helpful tools to access server

scp: (Secure copy) allow you to transfer between your local machine and your cloud server:

scp /path/to/your_file your_name@your.domain:/path/to/destination

Filezilla: If you prefer a graphical user interface you can use Filezilla. It's straightforward to use and it's completely free!

Thank you very much for reading through this! Feel free to contact me if you have any suggestion or question.

In the next part I'll go through the fundamental of building static web pages with HTML, CSS and JS.

Til next time! =)

Comments powered by Disqus