alt text Serve a Website with Lighttpd

Lighttpd is a web server designed and optimized for high performance. It has a small memory footprint compared to most servers, effective management of cpu-load, and an advanced feature set (SSL, URL-Rewrite-Redirect, FastCGI, EVHost (subdomain-ing), Auth, Output-Compression, and many more). Lighttpd is a great do-it-yourself solution for setting up your own light-weight web server.

Web Serving Overview

When you purchase a web domain name from a domain business per year, you will often get inundated with offers to also purchase domain space and other domain hosting services. This is where they make money. If you have little time available it can be simplest to pay the dollars per month and have the domain business do that for you.
Just so you know though, you could just do it yourself.

Building a Server

Keeping in line with the previous article listed on the left, “building a static website with Jekyll”, this Howto provides a method for the “build a website yourself” guy to also be a “host a website yourself” guy.

What’s Needed

  • A PC connected to the internet
          For preference sake it’ll be assumed you have an old/extra laptop kicking around ready to be put to good use. A laptop can be a pretty good choice for hosting your own website. It can sit on the corner of your desk or up on a shelf serving your site, use very little power and even stay running during a power outage because of its battery.
  • An IP Address from your ISP that doesn’t change much
          For the most part the IP address your ISP gives your modem shouldn’t change very often. Usually there will be a reason like they do changes on the network system in your area or you have to reset your modem. (If for some reason you find your IP changing too often you may need to inquire into the cost of a somewhat fixed IP or change ISP’s.)
  • A router
          These days almost all modems used by ISP’s are a modem-router combination providing multiple network jack connections as well as wireless so it’s unlikely you need a separate one. If for some reason you are from the way way back era and have only a modem you need to pick up a router to provide the extra network port for your laptop server as well as the extra firewalling/security a router naturally provides.
  • A domain name
          Using a domain name allows navigation via a name instead of a numeric IP address. When you purchase a domain name from a domain business they will provide a DNS interface where you can asociate your purchased name with your ISP assigned IP address.

    Installation

The instructions below are compatible with Ubuntu Linux distributions. If you don’t have a preference or it’s the first time using a Ubuntu OS give Linux Mint a try. It’s quite a refined stable version of Linux.

  1. Install Linux on the laptop if you haven’t already done so.

  2. Install Lighttpd.
    Open a terminal (command prompt) and paste the following:
    sudo apt-get install lighttpd gamin
    

    Test the Installation

  3. The Lighttpd installation comes with a very basic configuration, enough to present a placeholder page.
    Start the lighttpd service.
    sudo service lighttpd start 
    
  4. On the laptop point the web browser to http://127.0.0.1 to see if lighttpd is running and serving the placeholder page. 127.0.0.1 is the systems local loopback. It is the path to itself. The default configuration should be serving on the HTTP default port 80. Typing http://localhost:80 would achieve the same thing.

  5. It’s always nice to see some progress. Before going further its probably best to stop the service.
    sudo service lighttpd stop 
    

    Folder and File Setup

  6. Linux systems are quite stable by nature and have been serving websites for the internet for many many years. The tradition is for the system to serve web data out of the /var/www folder. A default placeholder page is set in a folder within named html.
    In your terminal you could type:
    sudo ls /var/www
    sudo ls /var/www/html
    cat /var/www/html/index.html 
    

    You should see the html folder, index file and it’s contents in html code.

  7. Create your web documents root folder and change ownership. Create any subdomain folder(s) as well if you want. Best not to use any spaces in the name.
    sudo mkdir /var/www/nameyourwebsitefolder/
    sudo mkdir /var/www/nameyoursubdomainfolder/
    sudo chown www-data:www-data /var/www/nameyour*
    
  8. Place your Jekyll site in the folder you just created (i.e. copy the contents of your Jekyll _site folder, after building, to DocumentRoot)
    Example command: (change the path to your Jekyll project accordingly)
    sudo cp -R /home/owner/Git/myJekyllSite/_site/* /var/www/nameyourwebsitefolder/
    sudo chown www-data:www-data /var/www/nameyour*
    

    Another option, instead, is to simply create a temporary placeholder for testing purposes.

    sudo nano /var/www/nameyourwebsitefolder/index.html
    

    Paste something like the following: (modify YOURSITE.NET accordingly)

     <!doctype html>
     <html lang="en" class="no-js">
     <head>
     <meta charset="utf-8">
     <title>Welcome page</title>
     <style type="text/css" media="screen">
     body { background: #b0b0b0; font-family: Verdana, sans-serif; font-size: 11pt; }
     #page { background: #ffffff; margin: 50px; border: 2px solid #707070; padding: 10px; }
     #header { background: #321e66; border: 2px solid #7590ae; text-align: center; padding: 10px; color: #ffffff; }
     #header h1 { color: #ffffff; }
     #body { padding: 10px; }
     </style>
     </head>
     <body>
     <div id="page">
      <div id="header">
      <h1> YOURSITE.NET </h1>
       What is this site all about? &nbsp;&nbsp;&nbsp;Good question!
      </div>
      <div id="body">
       <h2>Content</h2>
       Yes this is still an empty page.
       <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
       </ul>
       <h2>About</h2>
       <p>
        There is nothing about this page that is fascinating, no.
       </p>
       <p>
        &nbsp;
       </p>
       <p>
        &nbsp;
       </p>
      </div>
     </div>
     </body>
     </html>
    

    Do the same for your subdomain(s), if any. (modify SUB.YOURSITE.NET accordingly)

    sudo nano /var/www/nameyoursubdomainfolder/index.html
    

    Change ownership

    sudo chown www-data:www-data /var/www/nameyour*
    

    Basic Configuration

    NOTE: If at any time you need extra info or further explanation on configuration visit the Lighttpd Wiki.

  9. Modify the Lighttpd configuration file so that it uses your DocumentRoot.
    sudo nano /etc/lighttpd/lighttpd.conf
    

    Change the following variable to point to your folder.

    server.document-root        = "/var/www/nameyourwebsitefolder"
    
  10. Start the lighttpd service again. Your site should be visible at http://127.0.0.1
    sudo service lighttpd start 
    
  11. Add Lighttpd to your boot startup.
    sudo systemctl enable lighttpd
    
  12. Give your laptop server a static IP address on your local network. A static IP address is an address that doesn’t change. You will need to log into your router/modem with whatever the username and password are. You should have documentation for your device either on paper or online. The log-in address is usually something like 129.168.0.1. Somewhere in and around the DHCP settings there should be a screen to associate a constant IP address with your laptop’s network interface card via it’s unique mac number. If it’s not obvious under your DHCP status which mac belongs to the laptop you can issue the following command on your laptop. (look for HWaddr)
    ifconfig
    
  13. Open HTTP port 80. Once the laptop server has a static address find the router’s firewall configuration settings section and open port 80 for the laptop IP address. Something like:
    - - IP ADDRESS- - - -PORT- - - PROTOCOL- - NOTES-
    - - 192.168.0.2 - - - 80 - - - - TCP - - - http -
    
  14. Check if the server is accessible from the internet via your ISP provided modem IP address. From within the routers DHCP status section you should be able to find your external IP address. Type the address in your web browser and see if it can connect. Something like: http://23.45.65.43

  15. Associate your domain name with your IP. Once you know it is accessible via your external IP address log in to your account profile of the domain business where you purchased your domain name from. Under something like “Domain Management” or “Manage My Domain” find the DNS settings section and type in your external IP address. Something like:
    - - - - - - - - DNS IP ADDRESS RECORD - - - - - - - - -
    - - *.yoursiteaddress.net - - POINTS TO - - 23.45.65.43
    
  16. Check if the website is accessible by the domain name. It may take some time for the DNS record to propogate out through the internet. Once it does you should be able to visit the site using HTTP to connect to it. Example: http://yoursiteaddress.net

    Disable Directory Listings

  17. To keep internet users from being able to get a directory listing of the contents of your site folders you can set the dir-listing variable to disable. Add the variable assignment if the line doesn’t already exist.
    server.port                    = 80
    server.dir-listing             = "disable"
    

    Drop the www. with Redirect

  18. Back when the internet was a new project idea it was placed in it’s own space on a campus network somewhere. That space was assigned www as its subdomain location (the World Wide Web). As the internet project grew in size and began to stand on its own outside the early network structure they kept the www. tradition to keep from breaking the hard-coded addresses in much of the early equipment, etc. In this day and age there is very little reason, besides user habit, to keep www. (i.e. Of course its on the world wide web!).

    Make sure the redirect module is listed in the server modules section of the Lighttpd config.

    sudo nano /etc/lighttpd/lighttpd.conf
    

    The default config likely has it enabled already and looks like this with rewrite commented out below it.

    server.modules = (
     	"mod_access",
     	"mod_alias",
     	"mod_compress",
     	"mod_redirect",
    #       "mod_rewrite",
    )
    

    Further down somewhere close to the bottom add a redirect for your domain. This takes the typed in www request and changes it to a request without it. Change the name accordingly.

    # redirect www subdomain requests to the root domain
    $HTTP["host"] =~ "^www\.yoursiteaddress\.net$" {
        url.redirect = ( "^/(.*)" => "http://yoursiteaddress.net/$1" )
    }
    # default listening port for IPv6 falls back to the IPv4 port
    

    Restart Lighttpd and test it out. Now when someone types in http://www.yoursiteaddress.net the location bar will change to http://yoursiteaddress.net.

    sudo service lighttpd restart
    

    Add a Subdomain with EVHost

  19. It can be beneficial to organize parts of your site into a separate subdomain and/or provide a different service, etc. under the umbrella of your domain. Often you’ll see something like docs.whateversite.com.
    Add evhost to the server modules section of the Lighttpd config.
    server.modules = (
     	"mod_access",
     	"mod_alias",
     	"mod_compress",
     	"mod_redirect",
     	"mod_evhost",
    #       "mod_rewrite",
    )
    

    Further down somewhere close to the bottom just below your redirect add an evhost entry for the name of your subdomain pointing to your sub folder. Change the names accordingly.

    $HTTP["host"]                  =~ "docs.yoursiteaddress.net" {
    evhost.path-pattern            = "/var/www/nameyoursubdomainfolder/"
    }
    # default listening port for IPv6 falls back to the IPv4 port
    

    Restart Lighttpd and test it out. Typing the subdomain into your browser should now direct you to the placeholder page or whatever you placed in your sub folder.

    Enable SSL (HTTPS with Lighttpd)

    As technology has evolved, security has become more important. It is now possible to encrypt and decrypt on the fly. If you’re thinking there’s nothing you’re serving that’s super critical to encrypt, another motivating factor to bring your site up to the higher standard is search engines.
    Most search engines these days prefer to display a list of newer, secure (https) sites over original, “unsecure” (http) ones simply due to the possibility there could be input forms in the site pages. When input form data is transmitted over the internet it is much less risky having it encrypted if, by chance, it were to get intercepted and copied along the way. The search engine companies would rather not provide a search result to a site that could put the user at risk.

    The following instructions are largely based on a pretty good tutorial by Vivek, over at nixCraft that uses Neil Pang’s acme.sh script to provide Free SSL Certification from Let’s Encrypt.

  20. Install some dependencies for downloading, installing and utilizing the acme.sh script.
    sudo apt-get install git bc wget curl
    
  21. Clone the acme.sh repo.
    cd /tmp
    git clone https://github.com/Neilpang/acme.sh.git
    sudo -i
    cd /tmp/acme.sh/
    ./acme.sh --install
    
  22. Create the acme-challenge directory in your DocumentRoot site folder. Alter the root folder name accordingly.
    mkdir -vp /var/www/nameyourwebsitefolder/.well-known/acme-challenge/
    chown -R www-data:www-data /var/www/nameyourwebsitefolder/.well-known/acme-challenge/
    chmod 0555 /var/www/nameyourwebsitefolder/.well-known/acme-challenge/
    
  23. Create a site directory to store the SSL certificate. Alter domain name accordingly.
    mkdir -p /etc/lighttpd/ssl/yoursiteaddress.net/
    
  24. Generate your dhparam.pem file.
    cd /etc/lighttpd/ssl/yoursiteaddress.net/
    openssl dhparam -out dhparam.pem -dsaparam 4096
    

    It may take a while and look something like the following.

    Generating DSA parameters, 4096 bit long prime
    .....+..............+......+.+..........+.+++++++++++++++++++++++++++++++++++++++++++++++++++*
    +....................................+............+..........................+.+.....+.+.....+...........+..........+........+...+..+...+..+............+......+.....+....+......+......................................+..+.....+.+............+....+.+.+..+........+...+.............+..+........+++++++++++++++++++++++++++++++++++++++++++++++++++*
    
  25. Issue a certificate for your domain. Include the www. subdomain because even though you redirect it to your root domain (i.e. you drop the www. with redirect - step 18) the header actually still needs to be decrypted before it can read the redirect. Include your subdomain(s) as well. Alter the folder and site names accordingly.
    acme.sh --issue -w /var/www/nameyourwebsitefolder -d yoursiteaddress.net -d www.yoursiteaddress.net -d docs.yoursiteaddress.net -k 4096
    
  26. Edit your Lighttpd config to include support for SSL on port 443 and make it aware of your certificates.
    nano /etc/lighttpd/lighttpd.conf
    

    Add the following just above your redirect entry (added in step 18).
    Alter the site folder name accordingly.

    $SERVER["socket"] == ":443" {
     ssl.engine = "enable"
     ssl.disable-client-renegotiation = "enable"
    
     ssl.pemfile = "/etc/lighttpd/ssl/yoursiteaddress.net/ssl.pem"
     ssl.ca-file = "/etc/lighttpd/ssl/yoursiteaddress.net/ca.cer"
     ssl.dh-file = "/etc/lighttpd/ssl/yoursiteaddress.net/dhparam.pem"
    
    # ECDH/ECDHE ciphers curve strength 
     ssl.ec-curve            = "secp384r1"
    
     ssl.use-compression     = "disable"
    
    # Environment flag for HTTPS enabled
     setenv.add-environment = (
      "HTTPS" => "on"
     )
     ssl.use-sslv2 = "disable"
     ssl.use-sslv3 = "disable"
     ssl.cipher-list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA"
     ssl.honor-cipher-order = "enable"
    # HSTS(15768000 seconds = 6 months)
     setenv.add-response-header  = (
      "Strict-Transport-Security" => "max-age=15768000;"
     )
    }
    # redirect www subdomain requests to the root domain
    
  27. Update the redirect you added in step 18 to use https:// instead of http:// and add a redirect for all http requests.
    Make it look like this. Alter site name accordingly.
    # redirect www subdomain requests to the root domain using https only
    # yet still allow acme.sh update mechanism access to its challenge folder via http
    $HTTP["host"] =~ "^www\.yoursiteaddress\.net$" {
    $HTTP["url"] !~ "^/.well-known/acme-challenge/.*$" {
        url.redirect = ( "^/(.*)" => "https://yoursiteaddress.net/$1" )
    }
    }
    # redirect all http traffic to https
    # yet still allow acme.sh update mechanism access to its challenge folder via http
    $HTTP["scheme"] == "http" {
    $HTTP["host"] =~ ".*" {
        $HTTP["url"] !~ "^/.well-known/acme-challenge/.*$" {
            url.redirect = ( ".*" => "https://%0$0" )
        }
    }
    }
    
  28. Create a hook script that can perform the install of the issued SSL certificate and restart the Lighttpd web server. Alter the folder path accordingly.
    nano /root/.acme.sh/yoursiteaddress.net/hook.sh
    

    Paste the following:

    #!/bin/bash
    dom="yoursiteaddress.net"                       #your domain name 
    dest="/etc/lighttpd/ssl/yoursiteaddress.net"    #lighttpd ssl path root
    croot="/root/.acme.sh/${dom}"                   #acme.sh root path for your domain
         
    ### NO edit below ###
    sslfile="${dest}/ssl.pem"                       #lighttpd .pem file path
    certfile="${croot}/${dom}.cer"                  #lighttpd certficate file path        
    keyfile="${croot}/${dom}.key"                   #lighttpd key file path 
         
    echo "Running lighttpd cmd..."
    /bin/cat "${certfile}" "${keyfile}" > "${sslfile}"
    /bin/systemctl restart lighttpd
    

    Make the script executable

    chmod +x /root/.acme.sh/yoursiteaddress.net/hook.sh
    
  29. Paste the following command to install the certificate and restart the lighttpd web server:
    acme.sh --installcert -d yoursiteaddress.net \
    --capath /etc/lighttpd/ssl/yoursiteaddress.net/ca.cer \
    --reloadcmd '/root/.acme.sh/yoursiteaddress.net/hook.sh'
    
  30. Verify Lighttpd is running and listening on port 443
    netstat -tulpn | grep ':443'
    

    Output should look something like:

    tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 379/lighttpd
    
  31. Make sure the port 443 is open in your ufw firewall. Type the following:
    ufw allow 443/tcp
    
  32. Log in to your router and open port 443 for your server. It should look something like the following.
    - - IP ADDRESS- - - -PORT- - - PROTOCOL- - NOTES-
    - - 192.168.0.2 - - - 80 - - - - TCP - - - http -
    - - 192.168.0.2 - - - 443- - - - TCP - - - https-
    

    If all went well your site should be available via https with your web browser. (i.e. https://yoursiteaddress.net)

NOTE: The SSL certificate is valid for 90 days. The installation of acme.sh created a cron job that will try to do a scheduled renewal of the certificate for you. The cron job looks like this:

33 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null