title: HOMEBREWSERVER.CLUB
url: https://homebrewserver.club/low-tech-website-howto.html
hash_url: ca9ab64328fb30512451b027b252e721

<p>Earlier this year we’ve been asked to help redesign the website of <a href="http://lowtechmagazine.com">lowtechmagazine.com</a>. The primary goal of the redesign was to radically reduce the energy use associated with accesing their web content. At the same time it is an attempt to find out what a low-tech website could be.</p>
<p>In general the idea behind lowtechmagazine.com is to understand technologies and techniques of the past and combine them with the knowledge of today. Not in order to be able to ‘do more with the same’, but rather ‘to do the same with less’. </p>
<p>In this particular case it means that all the optimizations and increases in efficiency do not go towards making a website which is faster at delivering even more megabytes. Rather it is a website which uses all the advances in technological efficiency, combined with specific hardware and software choices, to radically and drastically cut resource usage. At the same time for us a sustainable web site means ensuring support for older hardware, slower networks and improving the portability and archivability of the blog’s content.</p>
<p>This meant making a website and server which could be hosted from the off-grid solar system used in the lowtechmagazine.com’s home-office in Barcelona. </p>
<p>The article <a href="https://solar.lowtechmagazine.com/2018/09/how-to-build-a-lowtech-website/">‘How To Build A Low-Tech Website?’</a> gives more insights into the motivations on making a self-hosted solar-powered server, while this companion article on will give in-depth technical information. </p>
<p>Both the articles and the readesign should be read as a proposition how things could be done, but also as a question on <a href="#room-for-improvements">what could be improved</a>. So we really appreciate additional insights and feedback.</p>
<h1 id="software">Software</h1>
<h2 id="operating-system">Operating system</h2>
<p>The webserver is running on <a href="https://www.armbian.com/olimex-lime-2/">Armbian Stretch</a>, which is a <a href="https://www.debian.org/">Debian</a> based distribution built around the <a href="http://linux-sunxi.org/Main_Page">SUNXI</a> kernel. This is kernel for low-powered AllWinner-based single board computers. The Armbian project provides good documentation on how write an Armbian image to an SD card an boot the board for the first time in the <a href="https://docs.armbian.com/User-Guide_Getting-Started/">Armbian User Guide</a>.</p>
<h2 id="pelican-static-site-design">Pelican Static Site &amp; Design</h2>
<p>The main change in the webdesign was to move from a dynamic website based on Typepad<sup id="fnref:typepad"><a class="footnote-ref" href="#fn:typepad" rel="footnote">1</a></sup> to a static site generated by <a href="https://blog.getpelican.com/">Pelican</a>. Static sites load faster and require less processing than dynamic websites. This is because the pages are pre-generated and read off the disk, rather than being generated on every visit.<sup id="fnref:static"><a class="footnote-ref" href="#fn:static" rel="footnote">2</a></sup></p>
<p>You can find the source code for ‘solar’, the Pelican theme we developed <a href="https://github.com/lowtechmag/solar">here</a></p>
<h3 id="image-compression">Image compression</h3>
<p>One of the main challenges was to reduce the overall size of the website. Particularly to try and reduce the size of each page to something less than 1MB . Since a large part of both the appeal and the weight of the magazine comes from the fact it is richly illustrated, this presented us with a particular challenge. </p>
<p class="img"><img alt="Image from the blog showing 19th century telephone switchboard operators, 159.5KB" src="/images/international-switchboard.jpg"/></p><p class="caption">Image from the blog showing 20th century telephone switchboard operators(<a href="https://commons.wikimedia.org/wiki/File:Bell_System_switchboard.jpg">original source</a>), 159.5KB</p>
<p>In order to reduce the size of the images, without diminishing their role in the design and the blog itself, we reverted to a technique called dithering:</p>
<p class="img"><img alt="The same image but dithered with a 3 color palette" src="/images/international-switchboard3.png"/></p><p class="caption">The same image but dithered with a 3 color palette, 36.5KB</p>
<p>This is a technique ‘to create the illusion of “color depth” in images with a limited color palette’<sup id="fnref:illusion"><a class="footnote-ref" href="#fn:illusion" rel="footnote">3</a></sup>. It based on the print reproduction technique called <a href="https://en.wikipedia.org/wiki/Halftone">halftoning</a>. Dithering, or digital half-toning<sup id="fnref:digitalhalftone"><a class="footnote-ref" href="#fn:digitalhalftone" rel="footnote">4</a></sup>, was widely used in video games and pixel art at a time when a limited amount of video memory constrained the available colors. In essence dithering relies on optical illusions to simulate more colors. These optical illusions are broken however by the distinct and visible patterns that the dithering algorithms generate. </p>
<p class="img"><img alt="Dithered with a six tone palette" src="/images/international-switchboard6.png"/></p><p class="caption">Dithered with a six tone palette, 76KB</p>
<p>As a consequence most of the effort and literature on dithering is around limiting the ‘banding’ or visual artifacts by employing increasingly complex dithering algorithms<sup id="fnref:dithering"><a class="footnote-ref" href="#fn:dithering" rel="footnote">5</a></sup>. </p>
<p>Our design instead celebrates the visible patterns introduced by the technique, this to stress the fact that it is a ‘different’ website. Coincidentally, the ‘Bayesian Ordered Dithering’ algorithm that we use not only introduces these distinct visible patterns, but it is also quite a simple and fast algorithm.</p>
<p class="img"><img alt="Dithered with an eleven tone color palette" src="/images/international-switchboard11.png"/></p><p class="caption">Dithered with an eleven tone palette, 110KB</p>
<p>We chose dithering not only for the compression but also for the aesthetic and reading experience. Converting the images to grayscale and then dithering them allows us to scale them in a visually attractive way to 100% of the view port, despite their small sizes. This gives each article a visual consistency and provides the reader with pauses in the long articles.  </p>
<p>To automatically dither the images on the blog we wrote <a href="https://github.com/lowtechmag/solar-plugins">a plugin for pelican</a> that converts all source images of the blog. The plugin is based on the <a href="https://pillow.readthedocs.io/en/5.2.x/#">Python Pillow</a> imaging library and <a href="https://github.com/hbldh/hitherdither">hitherdither</a>, a dithering palette library by <a href="https://blog.hbldh.se/">Henrik Blidh</a>. </p>
<p>Using this custom plug-in we reduced the total weight of the 623 images that are on the blog so far by 89%. From 194.2MB to a mere 21.3MB.</p>
<h3 id="archiving-and-portability">Archiving and portability</h3>
<p>Another reason to switch to a static site generator was to be able to ensure an off-line workflow, where the articles can be written and previewed locally in the browser. For this to happen the articles had to be converted to <a href="https://en.wikipedia.org/wiki/Markdown">Markdown</a>, a light weight markup language based on plain text files.</p>
<p>While this is quite a bit of work to do with an archive that spans 10 years of writing, it ensures the portability of the archive for future redesigns or other projects. It also makes it possible for us to archive and version the entire blog using the <a href="https://git-scm.com/doc">git</a> versioning system.</p>
<h3 id="off-line-archive">Off-line archive</h3>
<p>Because we designed the system to have an uptime of only 90% it is expected to go off-line 35 days a year. </p>
<p>Increasing the uptime of the server to 99% on solar energy means increasing the website’s ecological footprint by adding more and more tech in the form of extra solar panels, massively increased battery capacity or extra servers in different geographic locations. </p>
<p>Rather than that we opted for a low-tech approach that accepts being off-line during longer stretches of cloudy weather. However, we wanted to provide the reader with off-line reading options. Our primary method of doing so currently is by providing an <a href="https://solar.lowtechmagazine.com/feeds/all.rss.xml">RSS feed containing all the articles and images on the site</a>. In the future we will explore other means of providing off-line reading of the magazine.</p>
<p class="img"><img alt="An image of the built-in feed reader of Firefox showing solar.lowtechmagazine.com's RSS feed" src="/images/off-line-reading.png"/></p><p class="caption"> Most browsers preview only the article titles and summaries of the RSS feed. In fact the feed contains the full articles. Once you add the feed to your favorite reader, it will download the full articles that you can read at any given time.  </p>
<h2 id="material-server">Material Server</h2>
<blockquote>
<p>”[…] the minimal file-based website is contrary to a cloud mentality, where the material circumstances of the hardware and hosting location are made irrelevant (for the cloud/vps customer) meaning that any ‘service’ can be ‘deployed’, ‘scaled’ ‘migrated’ etc. Our approach instead informs what can be hosted based on the material circumstances of the server.”<sup id="fnref:varia"><a class="footnote-ref" href="#fn:varia" rel="footnote">6</a></sup></p>
</blockquote>
<p>One of the page’s fundamental design elements is to stress the materiality of the webserver. In web design there is a clear distinction between ‘front-end’, the visual and content side of the website and the ‘back-end’, the infrastructure it runs on top. Outside of professional circles, the material conditions of the web or the internet’s infrastructure are rarely discussed. This has become especially the case with cloud computing as the dominant paradigm, as resources are taken for granted or even completely virtualised.</p>
<p>A low-tech website means this distinction between front-end and back-end needs to disappear as choices on the front-end necessarily impact what happens on the back-end and vice-versa. Ignoring this connection usually leads to more energy usage.</p>
<p>An increase in traffic for example will have an impact on the amount of energy the server uses, just as a heavy or badly designed website will. Part of <a href="https://solar.lowtechmagazine.com">solar.lowtechmagazine.com</a>‘s design aims to give the visitor an insight in the amount of power consumed and the potential (un)availability of the page in the coming days, based on current power usage and forecasts of the weather.</p>
<p>The power statistics can actually be queried from the server hardware. More on that <a href="#server">below</a>. To make the statistics available to the web site we wrote <a href="https://github.com/lowtechmag/materialserver">a bash script</a> that exposes them as JSON in the webroot.</p>
<p>To activate this feature there is a <code>cron</code> entry that runs the script every minute and writes it into the web directory:</p>
<div class="codehilite"><pre><span></span><span class="go">*/1 * * * * /bin/bash /home/user/stats.sh &gt; /var/www/html/api/stats.json</span>
</pre></div>
<h2 id="configuring-the-webserver">Configuring the webserver</h2>
<p>As a webserver we use <a href="https://www.nginx.com/">NGINX</a> to serve our static files. However we made a few non-standard choices to further reduce the energy consumption and page loading times on (recurrent) visits. </p>
<p>To test some of the assumed optimizations we’ve done some measurements using a few different articles. We’ve used the following pages:</p>
<p><code>FP</code> = <a href="https://solar.lowtechmagazine.com">Front page</a>, 404.68KB, 9 images</p>
<p><code>WE</code> = <a href="https://solar.lowtechmagazine.com/2017/09/how-to-run-the-economy-on-the-weather/">How To Run The Economy On The Weather</a>, 1.31 MB, 21 images</p>
<p><code>HS</code> = <a href="https://solar.lowtechmagazine.com/2017/03/heat-storage-hypocausts-air-heating-middle-ages/">Heat Storage Hypocausts</a>, 748.98KB, 11 images</p>
<p><code>FW</code> = <a href="https://solar.lowtechmagazine.com/2015/12/fruit-walls-urban-farming/">Fruit Walls: Urban Farming in the 1600s</a>, 1.61MB, 19 images</p>
<p><code>CW</code> = <a href="https://solar.lowtechmagazine.com/2011/12/the-chinese-wheelbarrow/">How To Downsize A Transport Network: Chinese Wheelbarrows</a>, 996.8KB, 23 images</p>
<p>For this test the pages which are hosted in Barcelona have been loaded from a machine in the Netherlands. The indicated times are all the averages of 3 measurements.</p>
<h3 id="compression-of-transmitted-data">Compression of transmitted data</h3>
<p>We run gzip compression on all our text-based content, this lowers the size of transmitted information at the cost of a slight increase in required processing. By now this is common practice in most web servers but we enable it explicitly. Reducing the amount of data transferred will also reduce the total environmental footprint.</p>
<div class="codehilite"><pre><span></span><span class="gp">#</span>Compression
<span class="go">gzip on;</span>
<span class="go">gzip_disable "msie6";</span>
<span class="go">gzip_vary on;</span>
<span class="go">gzip_comp_level 6;</span>
<span class="go">gzip_buffers 16 8k;</span>
<span class="go">gzip_http_version 1.1;</span>
<span class="go">gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;</span>
</pre></div>
<p>A comparison of the amount of data sent with gzip compression enabled or disabled:</p>
<div class="codehilite"><pre><span></span>|GZIP      | MP       | WE       | HS       | FW       | CW       |
|----------|----------|----------|----------|----------|----------|
| disabled | 116.54KB | 146.08KB | 127.09KB | 125.36KB | 138.28KB |
| enabled  | 39.6KB   | 51.24KB  | 45.24KB  | 45.77KB  | 50.04KB  |
| savings  | 64%      | 65%      | 66%      | 66%      | 64%      |
</pre></div>
<h3 id="caching-of-static-resources">Caching of static resources</h3>
<p>Caching is a technique in which some of the site’s resources, such as style sheets and images, are provided with additional headers that tell the visitor’s browser to save a local copy of those files. This ensures that the next time they visit the same page, the files are loaded from the local cache rather than being transmitted over the network again. This not only reduces the time to load the entire page, but also lowers resource usage both on the network and on our server.</p>
<p>The common practice is to cache everything except the HTML, so that when the user loads the web page again the HTML will notify the browser of all the changes. However since lowtechmagezine.com publishes only 12 articles per year, we decided to also cache HTML. The cache is set for one day, meaning it is only after a week that the user’s browser will automatically check for new content. Only for the front and about pages this behaviour is disabled.</p>
<div class="codehilite"><pre><span></span><span class="go">map $sent_http_content_type $expires {</span>
<span class="go">    default                    off;</span>
<span class="go">    text/html                  1d;</span>
<span class="go">    text/css                   max;</span>
<span class="go">    application/javascript     max;</span>
<span class="go">    ~image/                    max;</span>
<span class="go">}</span>
</pre></div>
<p>Concretely this had the following effects:</p>
<p>The first time a page is loaded (FL) it around one second to fully load the page. The second time, however, the file is loaded from the cache and the load time reduced by 40% on average. Since load time are based on the time it takes to load resources over the network and the time it takes for the browser to render all the styling, caching can really decrease load times. </p>
<div class="codehilite"><pre><span></span>| Time(ms) | FP    | WE     | HS    | FW     | CW     |
|----------|-------|--------|-------|--------|--------|
| FL       | 995ms | 1058ms | 956ms | 1566ms | 1131ms |
| SL       | 660ms |  628ms | 625ms |  788ms |  675ms |
| savings  |  34%  |   41%  |  35%  |   50%  |   40%  |
</pre></div>
<p>In terms of data transferred the change is even more radical, essentially meaning that no data is transferred the second time a page is visited.</p>
<div class="codehilite"><pre><span></span>| KBs      | FP       | WE        | HS       | FW        | CW       |
|----------|----------|-----------|----------|-----------|----------|
| FL       | 455.86KB | 1240.00KB | 690.48KB | 1610.00KB | 996.21KB |
| SL       |   0.38KB |    0.37KB |   0.37KB |    0.37KB |   0.38KB |
| savings  |   &gt;99%   |   &gt;99%    |   &gt;99%   |    &gt;99%   |   &gt;99%   |
</pre></div>
<p>In case you want to force the browser to load cached resources over the network again, do a ‘hard refresh’ by pressing <code>ctrl+r</code></p>
<h3 id="http2-a-more-efficient-hyper-text-transfer-protocol">HTTP2, a more efficient hyper text transfer protocol.</h3>
<p>Another optimization is the use of <a href="https://http2.github.io/">HTTP2</a> over HTTP/1.1. This is a relatively recent protocol that increases the transport speed of the data. This increase is the result of HTTP2 compressing the packet data headers and multiplexing multiple requests into a single TCP connection. In other words, it produces less overhead data and needs to opens less connections between the server and the browser. </p>
<p>The effect of this is most notable when the browser needs to do a lot of different requests, since these can all be fit into a single connection. In our case that specifically means that articles with more images will load slightly faster over HTTP2 than over HTTP/1.1.</p>
<div class="codehilite"><pre><span></span>|          | FP    | WE    | HS    | FW    | CW    |
|----------|-------|-------|-------|-------|-------|
| HTTP/1.1 | 1.46s | 1.87s | 1.54s | 1.86s | 1.89s |
| HTTP2    | 1.30s | 1.49s | 1.54s | 1.79s | 1.55s |
| Images   |   9   |   21  |   11  |   19  |   23  |
| savings  |  11%  |  21%  |   0%  |   4%  |  18%  |
</pre></div>
<p>Not all browsers support HTTP2 but the NGINX implementation will automatically serve the files over HTTP/1.1 for those browsers.</p>
<p>It is enabled at the start of the server directive:</p>
<div class="codehilite"><pre><span></span><span class="go">server{</span>
<span class="go">        listen 443 ssl http2;</span>
<span class="go">}</span>
</pre></div>
<h3 id="serve-the-page-over-https">Serve the page over HTTPS</h3>
<p>Even though the website has no dynamic functionality like login forms, we have also implemented SSL to provide Transport Layer Security. We do this mostly to improve page rankings in search engines.</p>
<p>There is something to be said in favour of supporting both HTTP and HTTPS versions of the website but in our case that would mean more redirects or maintaining two versions of the website.</p>
<p>For this reason we redirect all our traffic to HTTPS via the following server directive:</p>
<div class="codehilite"><pre><span></span><span class="go">server {</span>
<span class="go">    listen       80;</span>
<span class="go">    server_name  solar.lowtechmagazine.com;</span>

<span class="go">    location / {</span>
<span class="go">    return 301 https://$server_name$request_uri;</span>
<span class="go">    }</span>
<span class="go">}</span>
</pre></div>
<p>Then we’ve set up SSL with the following tweaks:</p>
<div class="codehilite"><pre><span></span><span class="gp">#</span> Improve HTTPS performance with session resumption
<span class="go">ssl_session_cache shared:SSL:10m;</span>
<span class="go">ssl_session_timeout 180m;</span>
</pre></div>
<p>SSL sessions only expire after three hours meaning that while someone browses the website, they don’t need to renegotiate a new SSL session during this period:</p>
<div class="codehilite"><pre><span></span><span class="gp">#</span> Enable server-side protection against BEAST attacks
<span class="go">ssl_prefer_server_ciphers on;</span>
<span class="go">ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;</span>
</pre></div>
<p>We use a limited set of modern cryptographic ciphers and protocols:</p>
<div class="codehilite"><pre><span></span># Disable SSLv3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
</pre></div>
<p>We tell the visitors browser to always use HTTPS, in order to reduce the amount of 301 redirects, which might slow down loading times:</p>
<div class="codehilite"><pre><span></span><span class="gp">#</span> Enable HSTS <span class="o">(</span>https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security<span class="o">)</span>
<span class="go">add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";</span>
</pre></div>
<p>We enable OCSP stapling which is quick way in which browsers can check whether the certificate is still active without incurring more round trips to the Certificate Issuer. Most tutorials recommend setting Google’s <code>8.8.8.8</code> and <code>8.8.4.4</code> DNS servers but we don’t want to use those. Instead we chose some servers provided through <a href="https://www.opennic.org">https://www.opennic.org</a> that are close to our location:</p>
<div class="codehilite"><pre><span></span><span class="gp">#</span> Enable OCSP stapling <span class="o">(</span>http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox<span class="o">)</span>
<span class="go">ssl_stapling on;</span>
<span class="go">ssl_stapling_verify on;</span>
<span class="go">ssl_trusted_certificate /etc/letsencrypt/live/solar.lowtechmagazine.com/fullchain.pem;</span>
<span class="go">resolver 87.98.175.85 193.183.98.66 valid=300s;</span>
<span class="go">resolver_timeout 5s;</span>
</pre></div>
<p>Last but not least, we set change the size of the SSL buffer to increase to so-called ‘Time To First Byte’<sup id="fnref:TTFB"><a class="footnote-ref" href="#fn:TTFB" rel="footnote">7</a></sup> which  shortens the amount of time between passing between a click and elements changing on the screen:</p>
<div class="codehilite"><pre><span></span><span class="gp">#</span> Lower the buffer size to increase TTFB
<span class="go">ssl_buffer_size 4k;</span>
</pre></div>
<p>The above SSL tweaks are heavily indebted to these two articles by <a href="https://bjornjohansen.no/optimizing-https-nginx">Bjorn Johansen</a> and <a href="https://haydenjames.io/nginx-tuning-tips-tls-ssl-https-ttfb-latency/">Hayden James</a></p>
<h3 id="setting-up-letsencrypt-for-https">Setting up LetsEncrypt for HTTPS</h3>
<p>The above are all the SSL performance tweaks but we still need to get our SSL certificates. We’ll do so using <a href="https://letsencrypt.org/">LetsEncrypt</a>.</p>
<p>First install certbot:</p>
<div class="codehilite"><pre><span></span><span class="go">apt-get install certbot -t stretch-backports</span>
</pre></div>
<p>Then run the command to request a certificate using the webroot authenticator:</p>
<div class="codehilite"><pre><span></span><span class="go">sudo certbot certonly --authenticator webroot --pre-hook "nginx -s stop" --post-hook "nginx"</span>
</pre></div>
<p>Use the <code>certonly</code> directive so it just creates the certificates but doesn’t touch much config.</p>
<p>This will prompt an interactive screen where you set the (sub)domain(s) you’re requesting certificates for. In our case that was <code>solar.lowtechmagazine.com</code>.</p>
<p>Then it will ask for the location of the webroot, which in our case is <code>/var/www/html/</code>. It will then proceed to generate a certificate.</p>
<p>Then the only thing you need to do in your NGINX config is to specify where your certificates are located. This is usually in <code>/etc/letsencrypt/live/domain.name/</code>. In our case it is the following:</p>
<div class="codehilite"><pre><span></span><span class="go">ssl_certificate /etc/letsencrypt/live/solar.lowtechmagazine.com/fullchain.pem;</span>
<span class="go">ssl_certificate_key /etc/letsencrypt/live/solar.lowtechmagazine.com/privkey.pem;</span>
</pre></div>
<h3 id="full-nginx-config">Full NGINX config</h3>
<p>Without further ado:</p>
<div class="codehilite"><pre><span></span><span class="gp">root@solarserver:/var/log/nginx#</span> cat /etc/nginx/sites-enabled/solar.lowtechmagazine.com

<span class="gp">#</span> Expires map
<span class="go">map $sent_http_content_type $expires {</span>
<span class="go">    default                    off;</span>
<span class="go">    text/html                  7d;</span>
<span class="go">    text/css                   max;</span>
<span class="go">    application/javascript     max;</span>
<span class="go">    ~image/                    max;</span>
<span class="go">}</span>

<span class="go">server {</span>
<span class="go">    listen       80;</span>
<span class="go">    server_name  solar.lowtechmagazine.com;</span>

<span class="go">    location / {</span>
<span class="go">    return 301 https://$server_name$request_uri;</span>
<span class="go">    }</span>
<span class="go">}</span>

<span class="go">server{</span>
<span class="go">        listen 443 ssl http2;</span>
<span class="go">        server_name solar.lowtechmagazine.com;</span>

<span class="go">        charset UTF-8; #improve page speed by sending the charset with the first response.</span>

<span class="go">        location / {</span>
<span class="go">        root /var/www/html/;</span>
<span class="go">        index index.html;</span>
<span class="go">        autoindex off;</span>
<span class="go">        }</span>


<span class="gp">        #</span>Caching <span class="o">(</span>save html pages <span class="k">for</span> <span class="m">7</span> days, rest as long as possible, no caching on frontpage<span class="o">)</span>
<span class="go">        expires $expires;</span>

<span class="go">        location @index {</span>
<span class="go">            add_header Last-Modified $date_gmt;</span>
<span class="go">            add_header Cache-Control 'no-cache, no-store';</span>
<span class="go">            etag off;</span>
<span class="go">            expires off;</span>
<span class="go">        }</span>

<span class="gp">        #</span>error_page  <span class="m">404</span>              /404.html<span class="p">;</span>

<span class="gp">        #</span> redirect server error pages to the static page /50x.html
<span class="gp">        #</span>error_page   <span class="m">500</span> <span class="m">502</span> <span class="m">503</span> <span class="m">504</span>  /50x.html<span class="p">;</span>
<span class="gp">        #</span><span class="nv">location</span> <span class="o">=</span> /50x.html <span class="o">{</span>
<span class="gp">        #</span>    root   /var/www/<span class="p">;</span>
<span class="gp">        #</span><span class="o">}</span>

<span class="gp">        #</span>Compression

<span class="go">        gzip on;</span>
<span class="go">        gzip_disable "msie6";</span>
<span class="go">        gzip_vary on;</span>
<span class="go">        gzip_comp_level 6;</span>
<span class="go">        gzip_buffers 16 8k;</span>
<span class="go">        gzip_http_version 1.1;</span>
<span class="go">        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;</span>


<span class="gp">        #</span>Caching <span class="o">(</span>save html page <span class="k">for</span> <span class="m">7</span> days, rest as long as possible<span class="o">)</span>
<span class="go">        expires $expires;</span>

<span class="gp">        #</span> Logs
<span class="go">        access_log   /var/log/nginx/solar.lowtechmagazine.com_ssl.access.log;</span>
<span class="go">        error_log    /var/log/nginx/solar.lowtechmagazine.com_ssl.error.log;</span>

<span class="gp">        #</span> SSL Settings:
<span class="go">        ssl_certificate /etc/letsencrypt/live/solar.lowtechmagazine.com/fullchain.pem;</span>
<span class="go">        ssl_certificate_key /etc/letsencrypt/live/solar.lowtechmagazine.com/privkey.pem;</span>

<span class="gp">        #</span> Improve HTTPS performance with session resumption
<span class="go">        ssl_session_cache shared:SSL:10m;</span>
<span class="go">        ssl_session_timeout 5m;</span>

<span class="gp">        #</span> Enable server-side protection against BEAST attacks
<span class="go">        ssl_prefer_server_ciphers on;</span>
<span class="go">        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;</span>

<span class="gp">        #</span> Disable SSLv3
<span class="go">        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</span>

<span class="gp">        #</span> Lower the buffer size to increase TTFB
<span class="go">        ssl_buffer_size 4k;</span>

<span class="gp">        #</span> Diffie-Hellman parameter <span class="k">for</span> DHE ciphersuites
<span class="gp">        #</span> $ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem <span class="m">4096</span>
<span class="go">        ssl_dhparam /etc/ssl/certs/dhparam.pem;</span>

<span class="gp">        #</span> Enable HSTS <span class="o">(</span>https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security<span class="o">)</span>
<span class="go">        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";</span>

<span class="gp">        #</span> Enable OCSP stapling <span class="o">(</span>http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox<span class="o">)</span>
<span class="go">        ssl_stapling on;</span>
<span class="go">        ssl_stapling_verify on;</span>
<span class="go">        ssl_trusted_certificate /etc/letsencrypt/live/solar.lowtechmagazine.com/fullchain.pem;</span>
<span class="go">        resolver 87.98.175.85 193.183.98.66 valid=300s;</span>
<span class="go">        resolver_timeout 5s;</span>
<span class="go">}</span>
</pre></div>
<h1 id="hardware">Hardware</h1>
<p class="img"><img alt="Image of an A20 Olimex SoC board" src="/images/lime2.png"/></p>
<h3 id="server">Server</h3>
<p>The server itself is an <a href="https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXino-LIME2/">Olimex Olinuxino A20 Lime 2</a> single board computer.</p>
<p>We chose it because of the quality of the (open source) hardware<sup id="fnref:manual"><a class="footnote-ref" href="#fn:manual" rel="footnote">8</a></sup>, the low power consumption and useful extra components such as the charging circuit based on the <a href="http://dl.linux-sunxi.org/AXP/AXP209_Datasheet_v1.0en.pdf">AXP209 power managment chip</a>. </p>
<p>This chip makes it possible to query power statistics such as current voltage and amperage both from the DC-barrel jack connection and the battery. The maintainers of <a href="https://www.armbian.com/olimex-lime-2/">Armbian</a> exposed these statistics via <code>sysfs</code> bindings in their OS.</p>
<p>In addition to the power statistics the power chip can charge and discharge a Lithium Polimer battery and automatically switch between the battery and DC-barrel connector. This means the battery can then act as an uninterruptible power supply, which helps prevent sudden shutdowns. The LiPo battery used has a capacity of 6600mAh which is about 24 Watt hour.</p>
<p>The server operating system all runs on an SD-card. Not only are these low-powered but also much faster than hard drives. We use high speed Class 10 16GB mirco-sd card. A 16GB card is actually a bit of an overkill considering the operating system is around 1GB and the website a mere 30MB, but considering the price it doesn’t make sense to buy any smaller high-performance cards. </p>
<p class="img"><img alt="" src="/images/sps_close.png"/></p>
<h3 id="network">Network</h3>
<p>The server gets it’s internet access through the existing connection of the home office in Barcelona. This connection is a 100mbit consumer fiber connection with a static IP-adress. </p>
<p>The fiber connection itself is not necessary, especially if you keep your data footprint small, but a fixed IP adress is very handy.</p>
<p>The router is a standard consumer router that came with the internet contract. To make the website available, some settings in the router’s firewall had to be changed. </p>
<p>Using a process called ‘port forwarding’, the following ports had to be forwarded between the external network and the server’s local IP address:</p>
<div class="codehilite"><pre><span></span>Port 80 to 80 for HTTP
Port 443 to 443 for HTTPS
Port 22 to 22 for SSH
</pre></div>
<h1 id="room-for-improvements">Room for improvements?</h1>
<h3 id="os-optimization">OS Optimization</h3>
<p>While the Armbian operating system has all kinds of optimizations for running on a SoC, there probably are still many tweaks that can be made to lower the energy usage. </p>
<p>For example energy savings from disabling some of the hardware such as the the USB-hub? Some tips or insights into this are greatly appreciated!</p>
<h3 id="image-dithering">Image dithering</h3>
<p>We’re looking for suggestions how to further compress the images while maintaining this visual quality. We know PNGs are in theory not optimal for representing images on the web, even though they let us limit the color palette to save bandwidth and produce very crisp dithered images. </p>
<p>We’ve found that saving them as JPEG after dithering in fact increases the file size but perhaps other file formats exist that give is similar quality but have a lighter footprint.</p>
<h3 id="sensible-comments-on-static-sites">Sensible comments on static sites</h3>
<p>Dynamic content such as comments are in theory incompatible with a static site. </p>
<p>At the same time they are a big part of the community of knowledge around lowtechmagazine.com. </p>
<p>The comment box under each article on that site is widely used, but e-mail is equally used (often the comments are then added to the article by the author after moderating).</p>
<p>There are some plugins that might address this such as Bernhard Scheirle’s <a href="https://github.com/getpelican/pelican-plugins/tree/master/pelican_comment_system">‘Pelican Comment System’</a> but these we haven’t tested. </p>
<h3 id="ssl-legacy-browsers">SSL &amp; Legacy browsers</h3>
<p>An open question remains: In what a way would it be possible to further extend the support for older machines and browsers without comprimising on security by using deprecated ciphers? Should we maintain both HTTP and HTTPS versions of the site? </p>
<h1 id="donations">Donations</h1>
<p>As is mentioned on the <a href="https://solar.lowtechmagazine.com/donate/">‘donate’</a> page of the site, advertising trackers are incompatible with the new web site design and we really want to keep Low-Tech Magazine tracker free and sustainable so if you enjoy our work or find our public research useful please consider donating. </p>
