How to setup a website from scratch

WIP - v0.9

Acquire a Domain Name

  • Domain names are rented.
  • Web hosting often comes with a domain.
  • Alternative: setup a Tor hidden service.
  • I use for this domain.

Find a Hosting Solution

  • Prefer a Debian-based server with SSH.
  • Choose a service that will setup in minutes.
  • Keep your server’s IP address at hand.
  • I use a basic VPS at for this site.

Setup DNS to Point to Your Host

  • It will take some time (Time to Live) ~ from 30 minutes to 3 hours.
  • It involves point your domain name to the IP of your server, as well as all the host names you want to use, e.g., www. For these, you can use a CNAME entry (if you used an A or AAAA entry for the domain itself pointing to your Web server IP address.)
  • Your domain registrar and/or your Web host provider should have an easy to use Web interface to the DNS that won’t let you make mistakes.

Install Web Service

Replace with your domain:

apt install nginx
mkdir /srv/www/

Setup TLS Certificate

Use LetsEncrypt

LetsEncrypt solves an important issue: to provide both gratis and secure TLS certificates for all. If you want to protect your users, you can easily set up a secure link to your Website with LetsEncrypt within minutes. It’s becoming the industry’s de facto standard to provide SSL certificates outside the professional market, creating a basic layer of privacy between users and Web content providers.

On Debian-based systems: apt install letsencrypt

Enable Perfect Forward Secrecy

This is an advanced topic but since we’re at it, let’s customize the DH parameters used for key exchange with your server, and that are required to enable PFS. A custom 256 bits prime number to use as parameter for DH key exchange will also prevent the logjam attack: openssl dhparam -out /etc/ssl/dhparams.pem 2048

This file wll be used in the SSL configuration…

Reuse SSL configuration

The following commands enable you to reuse SSL configuration using LetsEncrypt for different sites on the same server. Be careful when copy-pasting as some lines might require your attention. Lines starting with the # character are comments and contain useful instructions.

Four files play a role in this setup:

  • /etc/nginx/le.conf and /etc/nginx/le-ssl.conf contain the LetsEncrypt configuration
  • /etc/ssl/dhparams.pem contain Diffie-Hellman parameters for OpenSSL key exchange
  • /etc/nginx/sites-available/ contain the example server configuration file (replace with your domain, also in commands)
mkdir -p /srv/www/.well-known/acme-challenge`

cat <<EOD > /etc/nginx/le.conf
# LE configuration for 80 and 443

location /.well-known/acme-challenge {
        alias /srv/www/.well-known/acme-challenge;

cat <<EOD > /etc/nginx/le-ssl.conf
# SSL Configuration
# In /etc/nginx/sites-available/
# Replace '' with your secure domain
# Add the resulting lines to your server configuration:
# include              le-ssl.conf
# ssl_certificate      /etc/letsencrypt/live/;
# ssl_certificate_key  /etc/letsencrypt/live/;

ssl on;


ssl_prefer_server_ciphers on;

ssl_dhparam /etc/ssl/dhparams-2048.pem;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_session_cache shared:SSL:10m;

ssl_stapling on;
ssl_stapling_verify on;

Finally, you can setup your site’s configuration, e.g., in /etc/nginx/sites-available/


server {
        listen       80;
        listen       [::]:80;

        include le.conf;

# Once you have installed the LetsEncrypt certificate, uncomment the following line and restart nginx:
#        return 301$uri;

server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;

        include      le.conf;
        include      le-ssl.conf;

        ssl_certificate      /etc/letsencrypt/live/;
        ssl_certificate_key  /etc/letsencrypt/live/;

        root         /srv/www/;
        index        index.html;

        location / {
                try_files $uri $uri/ $uri.html =404;

Now you can restart your Web service and ask for the certificate:

cd /etc/nginx/sites-enabled
ln -s ../sites-available/
/etc/init.d/nginx restart
letsencrypt certonly --agree-tos --webroot -w /srv/www -d -d

At this point you should remove the # masking the last line in /etc/nginx/sites-available/
Now restart your Web service and point your browser at your Web service, tadaa!

Cerbot - LetsEncrypt Office Hours, presentation at SHA2017.