How to deploy a website WITHOUT LibrePages
+ + + +In this blog post tutorial, I'll show you how to deploy a personal
+website. LibrePages automates everything that is discussed in this
+tutorial and lets you focus on creating content. Automation is good
+but knowing how to do it manually using industry standard
+technologies always helps!
We will be using the following technologies to deploy our website:
+-
+
- GNU/Linux server(Debian) +
- Nginx (webs server) +
- Let's Encrypt (for HTTPS) +
- Gitea (but any Git hosting works) +
Let's get started!
+1. Setup Debian GNU/Linux +
+We are going to start with a fresh GNU/Linux installation, you could get +one from a cloud provider like Digital +Ocean (not affiliated).
+1.1) Give your account sudo
privileges
+
+On GNU/Linux systems, the root
account is the most powerful user account.
+It is good practice to avoid working as root
since a careless mistake
+could wipe the entire system out.
sudo
give the ability to execute commands with root
capabilities
+from a lower-privileged account. Let's make our account sudo capable:
su # become root
+
+# add `realaravinth`, my account` to `sudo` group to be able to use `sudo`
+usermod -aG sudo realaravinth # my account is called `realaravinth`, replace it with yours
+exit
+$ exit
+
+Log out and log back in.
+1.2) Install and setup firewall(ufw
)
+
+Uncomplicated Firewall(ufw
) is a popular firewall that is easy to
+set up and maintain. For most installations, this should be enough.
+System administrators use firewalls to open only the ports that they
+think should receive traffic from external networks. Without it, all
+ports will be open, causing a security nightmare.
We will require standard SSH (22), and the standard web ports (80 and +443). A comprehensive list of services and the list of ports the listen +on is available at `/etc/services.
+install ufw # we are using `ufw` for the firewall
+$ sudo ufw allow ssh # allow SSH traffic on port 22, required to log into the server
+$ sudo ufw enable # deploy firewall
+
+1.3) Secure SSH +
+SSH allows remote access to our servers over secure, encrypted +channels. By default, users can log in with their password +using SSH. But password authentication is susceptible to brute force attacks, so we should disable password logins on our server and only allow public-key authentication only.
+1.3.1) Generate key pair +
+On your local computer, generate an SSH key pair:
+$ ssh-keygen
+Generating public/private rsa key pair.
+Enter file in which to save the key (/home/realaravinth/.ssh/id_rsa):
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /home/realaravinth/.ssh/id_rsa
+Your public key has been saved in /home/realaravinth/.ssh/id_rsa.pub
+The key fingerprint is:
+SHA256:i2DE1b9BQb9DqV0r6O9MfPeVqUwfww1/T8wIXL2Xqdo realaravinth@myserver.com
+The key's random art image is:
++---[RSA 3072]----+
+| .. .o. |
+| . . . .. . . |
+| o o + o .|
+| . o* + .+|
+| o S ooB o+.|
+| . . . o.. +o*=|
+| . . . ooo*X|
+| +=.ooB|
+| o+E .o|
++----[SHA256]-----+
+
+Set a strong password the program prompts for one and save it somewhere
+safe. Your public key will be at ~/.ssh/id_rsa.pub
and your private key at
+~/.ssh/id_rsa
. Never share the private key with anyone.
1.3.2) Setup public-key authentication +
+We have to copy the public key that we generated in the previous setup +onto our server:
+$ ssh-copy-id -i ~/.ssh/id_rsa.pub myserver.com
+/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/realaravinth/.ssh/id_rsa.pub"
+/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
+/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
+realaravinth@myserver.com's password:
+
+Number of key(s) added: 1
+
+Now try logging into the machine, with: "ssh 'myserver.com'"
+and check to make sure that only the key(s) you wanted were added.
+
+1.3.3) Disable SSH password authentication +
+++NOTE: Verify you can log into your account before proceeding
+
Now that we have a private-key authentication setup on both the client and +the server, let's disable password authentication on the server:
+Open /etc/ssh/sshd_config
and add the following lines:
PubkeyAuthentication yes
+PasswordAuthentication no
+
+And restart the SSH server:
+$ sudo systemctl restart sshd
+
+1.3) Install and setup fail2ban
+
+We will be using fail2ban
for intrusion prevention by blackiisting entities (users, bots, etc.) based on failed login attempts.
1.3.1) Install fail2ban
+
+$ sudo apt install fail2ban
+
+1.3.2) Enable fail2ban
for sshd
+
+[sshd]
+enabled = true
+
+1.3.3) Configure fail2ban
to start on boot
+
+$ sudo systemctl enable fail2ban
+$ sudo systemctl start fail2ban
+
+1.4) Install and setup nginx
+
+nginx
is a popular web server that can be used to serve static sites.
+It is fast, stable, and easy to set up.
To install, run the following command:
+1.4.1) Install nginx
:
+
+$ sudo apt install nginx
+
+1.4.2) Allow web traffic: open ports 80
and 443
+
+Ports 80
is the default for HTTP and 443
for HTTPS. To serve
+web traffic, we'll have to Configure ufw
to accept traffic on them:
$ sudo ufw allow 80 # open ports 80 HTTP traffic
+$ sudo ufw allow 443 # open ports 443 for HTTPS traffic
+
+1.4.2) Configure nginx
to start on boot
+
+$ sudo systemtl enable nginx # automatically start nginx on boot
+$ sudo systemtl start nginx # start nginx server
+
+And verify it works:
+$ curl localhost
+<!DOCTYPE html>
+<html>
+<head>
+<title>Welcome to nginx!</title>
+<style>
+ body {
+ width: 35em;
+ margin: 0 auto;
+ font-family: Tahoma, Verdana, Arial, sans-serif;
+ }
+</style>
+</head>
+<body>
+<h1>Welcome to nginx!</h1>
+<p>If you see this page, the nginx web server is successfully installed and
+working. Further configuration is required.</p>
+
+<p>For online documentation and support please refer to
+<a href="http://nginx.org/">nginx.org</a>.<br/>
+Commercial support is available at
+<a href="http://nginx.com/">nginx.com</a>.</p>
+
+<p><em>Thank you for using nginx.</em></p>
+</body>
+</html>
+
+nginx
is working!
2) Deploy website +
+For this demo, we'll deploy a single file(index.html
)
+HTML website.
2.1) Install the webpage on the server +
+Edit /var/www/html/index.html
and add the following HTML to it:
<!DOCTYPE html>
+<html>
+ <head>
+ <title>My cool website!</title>
+ </head>
+ <body>
+ <h1>Welcome to my website! o/</h1>
+ </body>
+</html>
+
+The webpage should now be available on localhost, and we should see it when we run the following command:
+$ curl localhost
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>My cool website!</title>
+ </head>
+ <body>
+ <h1>Welcome to my website! o/</h1>
+ </body>
+</html>
+
+2.2) Serve webpage on a custom domain +
+2.2.1) Buy a domain if you don't own one already +
+2.2.2) Go to the domain's DNS dashboard and add the following record +
+@ A 300 <your server IP address>
+
+2.2.3) Setup nginx
to serve the website at http://<your-domain.
+
+Open /etc/nginx/sites-available/your-domain
and add the following:
server {
+ # serve website on port 80
+ listen [::]:80;
+ listen 80;
+
+ # write error logs to file
+ error_log /var/log/nginx/<your-domain>.error.log;
+ # write access logs to file
+ access_log /var/log/nginx/<your-domain>.access.log;
+
+ # serve only on this domain:
+ server_name <your-domain>; # replace me
+
+
+ # use files from this directory
+ root /var/www/html/;
+
+ # remove .html from URL; it is cleaner this way
+ rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
+
+ # when a request is received, try the index.html in the directory
+ # or $uri.html
+ try_files $uri/index.html $uri.html $uri/ $uri =404;
+}
+
+It is good practice to have all nginx
deployment configurations in
+/etc/nginx/sites-available/
directory and link production websites to
+`/etc/nginx/sites-enabled directory. Doing so allows you to
+work-in-progress configurations or delete deployments without losing
+the configuration files.
Let's enable <your-domain>
$ sudo ln -s /etc/nginx/sites-available/<your-domain> /etc/nginx/sites-available/<your-domain>
+
+Verify configurations before deploying, nginx
has a command
+to do it:
$ sudo nginx -t
+
+If there are no errors, reload nginx
to deploy the website:
$ sudo nginx -s reload
+
+Your webpage should now be accessible at http://<your-domain>
!
2.3) Install certbot
to set up HTTPS
+
+HTTP is insecure. We'll have to set up SSL to serve our website using +HTTPS. To do that, we will be using Let's +Encrypt a popular nonprofit certificate +authority to get our SSL certificates.
+SSL certificates come with set lifetimes, so we renew them before they expire. The process, when done manually, is demanding: you +will have to log in every three months and renew the +certificate. If you fail or forget it, your visitors will see security +warnings on your website.
+Thankfully, Let's Encrypt provides automation through certbot
2.3.1) Install certbot
:
+
+$ sudo apt install certbot python3-certbot-nginx
+
+2.3.2) Get a certificate for <your-domain>
+
+$ sudo certbot --nginx -d <your-domain>
+
+certbot
will prompt you for an email ID, and ask you to accept their
+terms and conditions, privacy policy, etc. Be sure to read them before
+agreeing to them. It will then try to authenticate your domain ownership
+using the ACME
+protocol.
+By configuring the DNS to point to our server and by telling nginx
at
+that domain.
When it has verified ownership, it will automatically issue, deploy the
+certificate on nginx
and setup redirects.
2.3.3) Setup cronjob to automate SSL certificate renewals +
+Become root and edit crontab
+$ su
+crontab -e
+
+Add the following job and exit:
+0 */12 * * * certbot -n --nginx renew
+
+It will attempt to renew SSL certificates every 12 hours. If a the
+certificate is due for renewal, certbot
will go through the ACME
+challenge, get the new certificates and automatically deploy them for
+you.
Now our GNU/Linux server is configured and ready to serve our website at
+http://<your-website>
!
+
+ +