In this part of tutorial we are going to securely run very simple website
using modern server nginx
. You might know another popular webserver called
apache
. Why have I chose nginx
instead? It's mostly the matter of taste,
but my reasons are mainly these two:
nginx
is more recent (1995 vs 2004). Hence it could be build from the beginning as an asynchronous and non-blocking algorithm compared toapache
.- configuration in JSON like style instead of XML like
then there are some other technicalities (described e.g. on DigitalOcean) which are not going to really matter for what we want to achieve here.
Installing and setting nginx
As always we need to install appropriate package by pacman -S nginx
. As you would probably already expect, a server needs to be running all the time and hence it's daemon.
Start it by systemctl start nginx
(and you might enable it too). If you now try to open localhost
in your browser, you should be able to see nginx Welcome page.
Forwarding ports
Let's first open nginx
to world. For browsing websites on the internet the HTTP(S) protocols are used. These specify the default port, which is 80 for (insecure) HTTP and 443 for secure HTTPS. You need to forward this ports to the same ports on your server in the same way as you did in SSH chapter.
If you were successful, you should be able to open see Welcome page when you enter your public IP address into your browser.
Configuration
The configuration file for nginx
is stored in /etc/nginx/nginx.conf
. Remember that lines starting with #
are ignored, so relevant parts are those:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
for now ignore everything except the server
part. listen
specify which port is going to be used for incoming connections and server_name
is specifying to which domain/ipaddress this server corresponds. location
defines the base directory with index
which is called index.htm(l)
. /usr/share/nginx/html/index.html
is the Welcome page of nginx
.
Now you should be able to understand why when you typed localhost
to your browser you saw Welcome page. Your browser opened localhost
on port 80 (default port - you can specify ports by typing them behind domain like localhost:80
), nginx
received this information and found appropriate server block. In this block you know that you should serve /usr/share/nginx/html/index.html
. That's it!
Creating a user who owns the website files
For sandboxing the content which should be served we will create a specific user. If an attacker gets a permissions for this user, he couldn't destroy the whole server, at least. Let's do it:
$ groupadd webdata
$ useradd -M -G webdata nginx -s /dev/null
No one will ever sign in as a nginx
user, so we don't want to create a home
directory for him (the -M
switch) and he cannot run a shell (-s /dev/null
switch assure this). Open nginx
configuration file and insert user nginx
on the very top of the file. Now all subprocesses will be spawned under this user, which again assures that they cannot access somewhere where nginx user cannot.
We will now configure nginx
to do something useful. Let's say we have this beautiful website which we want to serve using our new server:
<html>
<body>
<h1>My Welcome Page</h1>
</body>
</html>
Save this document in e.g. /var/www/index.html
(you might need to create the www
dir). Change the owner to the just created user by chown nginx:webdata /var/www/index.html
. Let's edit an appropriate server blog so it will server our website now instead of the original welcome page.
All you need to change is the location
directive from root /usr/share/nginx/html;
to /var/www;
.
To check if you wrote it correctly you can use nginx
's spell check using nginx -t
. If everything is OK, run nxinx -s reload
, which reloads the configuration.
Creating HTTPS
The last part of this chapter will be a guide how to secure your connection with your own self-signed certificate. Even though our site doesn't need this, because there is no confidential information send out or in, it's very good to know how to handle this.
First, we need to create the certificate we are going to use. That can be done by two commands:
$ openssl genrsa -out privkey.pem 2048
$ openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
$ mv *.pem /var/www # copy keys to www directory
$ chown nginx:webdata /var/www/*.pem # change their owner to nginx user and webdata group
now we need to do small changes in our server block in nginx.conf
. Add these lines right after the listen 80;
directive:
listen 443 ssl;
ssl_certificate /var/www/cacert.pem;
ssl_certificate_key /var/www/privkey.pem;
and reload nginx by nginx -s reload
. This simple change will make our connection through HTTPS
secure while still leaving http
connection possible.
Several other recommendations
These recommendations are so broad that that could have their own chapters as well, but it would be a bit outside of the scope of this guide. You should be already on the level where you could use other resources without problems, because we covered the basics. So, consider these:
- update
nginx
frequently (this should be done with updating your system) - create all website in one directory (in their own sub directories), as we did in
/var/www
and assure that onlynginx
can access them. - do not allow any other ports and servers in your configuration which are not necessary