thomastweets - Techhttps://blog.thomasemmerling.de/2019-03-11T00:00:00+01:00Setting up IPv6 with FritzBox 7530 and EdgeRouter Lite2019-03-11T00:00:00+01:002019-03-11T00:00:00+01:00Thomas Emmerlingtag:blog.thomasemmerling.de,2019-03-11:/setting-up-ipv6-with-fritzbox-7530-and-edgerouter-lite.html<p>I have been running a 'double NAT' setup for some years now: in the beginning because I had to due to my ISP regulations (yes, Ziggo.nl and plusnet, I am looking at you), nowadays as a deliberate choice to segment the network into ISP specific devices (mostly the SIP …</p><p>I have been running a 'double NAT' setup for some years now: in the beginning because I had to due to my ISP regulations (yes, Ziggo.nl and plusnet, I am looking at you), nowadays as a deliberate choice to segment the network into ISP specific devices (mostly the SIP client) and my own network. On the WAN-facing side I am using a <a href="https://en.avm.de/products/fritzbox/fritzbox-7530/">FritzBox 7530</a>. Behind the FritzBox I use the almighty <a href="https://www.ui.com/edgemax/edgerouter-lite/">EdgeRouter Lite</a> that gives you a full-fledged <a href="https://en.wikipedia.org/wiki/Vyatta">Vyatta</a>-based router. However, with great power comes great responsibility so you have to do some digging if you want to configure certain features. Finally, I have a <a href="https://www.ui.com/unifi/unifi-ap-ac-pro/">Unifi AP AC Pro</a> as my WiFi access point - very recommendable piece of hardware but not the star of this blog post.</p>
<p>Recently, I wanted to set up IPv6 again after having moved to a new place and a new ISP. This turned out to be a little longer journey and I decided to document it here, potentially for my future self ;)</p>
<hr>
<p>Let's start with the FritzBox (sorry for the German menu item names; my FritzBox version does not let me change the language setting). First of all, backup your current configuration (<code>System</code>-><code>Sicherung</code>)! You obviously want to enable IPv6 at <code>Internet</code> -> <code>Zugangsdaten</code> -> <code>IPv6</code>. Make sure that <code>IPv6-Unterstützung aktiv</code> is checked as well as (if your ISP still offers IPv4) <code>Native IPv4-Anbindung verwenden</code>. <code>DHCPv6 Rapid Commit verwenden</code> should also be active. This should already give you an IPv6 address that you can see in <code>Internet</code> -> <code>Online-Monitor</code>.</p>
<p>Next, you want to configure the announcing of IPv6 into the network and, therefore, towards the EdgeRouter. In <code>Heimnetz</code>-> <code>Netzwerk</code>-><code>Netzwerkeinstellungen</code> scroll down and click on <code>IPv6-Adressen</code>. Select <code>Unique Local Addresses (ULA) zuweisen, solange keine IPv6-Internetverbindung besteht (empfohlen)</code>, deselect <code>Auch IPv6-Präfixe zulassen, die andere IPv6-Router im Heimnetz bekanntgeben</code>, select <code>Diese FRITZ!Box stellt den Standard-Internetzugang zur Verfügung</code>, and select <code>DNSv6-Server auch über Router Advertisement bekanntgeben (RFC 5006)</code>.</p>
<p>Select <code>DHCPv6-Server in der FRITZ!Box für das Heimnetz aktivieren:</code> and <code>DNS-Server, Präfix (IA_PD) und IPv6-Adresse (IA_NA) zuweisen</code> (see also <a href="https://web.nettworks.org/wiki/pages/viewpage.action?pageId=35651587">here</a> as a reference). Finally click <code>OK</code>.</p>
<p>As the last step on the FritzBox, you want to expose the EdgeRouter. Go to <code>Internet</code>-><code>Freigaben</code>-><code>Portfreigaben</code>. Click on <code>Gerät für Freigaben hinzufügen</code>. Select the hostname of the EdgeRouter (e.g. <code>ubnt</code>). Activate all checkmarks on this page (<code>Selbstständige Portfreigaben für dieses Gerät erlauben.</code>, <code>Dieses Gerät komplett für den Internetzugriff über IPv4 freigeben (Exposed Host).</code>, <code>PING6 freigeben.</code>, <code>Firewall für delegierte IPv6-Präfixe dieses Gerätes öffnen.</code>, <code>Dieses Gerät komplett für den Internetzugriff über IPv6 freigeben (Exposed Host).</code>). These settings will ensure that all IPv6 tests can pass making your network devices fully IPv6 compliant (see also <a href="https://www.bjoerns-techblog.de/2017/06/ipv6-icmp-filtered-an-fritzbox-beheben/">here</a>) - and also completely exposed to the internet! So we will need to take care of configuring the firewall on the EdgeRouter.</p>
<hr>
<p>On to the EdgeRouter Lite. A great set of helpful articles by Logan Marchione about setting up the EdgeRouter Lite can be found <a href="https://loganmarchione.com/2016/04/ubiquiti-edgerouter-lite-setup/">here</a>. Again, as a first step you should backup your configuration, either via the GUI or via SSH using <code>show configuration commands</code>. Then, it is a good idea to start fresh an run the <code>Basic Setup</code> Wizard. Please note that this wipes your current configuration!</p>
<p>It is not necessary to set autoconf for IPv6 interfaces when IA_PD and IA_NA are served by the FritzBox (see above). You also do not need to explicitly set Router Advertisement (RA) when SLAAC is active on the WAN interface as the EdgeRouter is creating the RA automatically (see <a href="https://community.ubnt.com/t5/EdgeRouter/IPv6-Setup/m-p/1833655/highlight/true#M150102">here</a> for a more detailed explanation). Finally, you need to set up a firewall rule to allow incoming ICMPv6 packages (see also <a href="https://community.ubnt.com/t5/EdgeRouter/Filtered-ICMP-on-ipv6-test-com/m-p/2093368/highlight/true#M180948">here</a>).</p>
<p>As a reference, I am posting part of my configuration below (created with <code>show configuration commands</code>). Please adapt to your needs before running it on your EdgeRouter.</p>
<div class="highlight"><pre><span></span><span class="nb">set</span> firewall all-ping <span class="nb">enable</span>
<span class="nb">set</span> firewall broadcast-ping disable
<span class="nb">set</span> firewall ipv6-name WANv6_IN default-action drop
<span class="nb">set</span> firewall ipv6-name WANv6_IN description <span class="s1">'WAN inbound traffic forwarded to LAN'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN enable-default-log
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">10</span> action accept
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">10</span> description <span class="s1">'Allow established/related sessions'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">10</span> state established <span class="nb">enable</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">10</span> state related <span class="nb">enable</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">20</span> action drop
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">20</span> description <span class="s1">'Drop invalid state'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">20</span> state invalid <span class="nb">enable</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">30</span> action accept
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">30</span> description <span class="s1">'Allow IPv6 icmp'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_IN rule <span class="m">30</span> protocol ipv6-icmp
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL default-action drop
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL description <span class="s1">'WAN inbound traffic to the router'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL enable-default-log
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">10</span> action accept
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">10</span> description <span class="s1">'Allow established/related sessions'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">10</span> state established <span class="nb">enable</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">10</span> state related <span class="nb">enable</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">20</span> action drop
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">20</span> description <span class="s1">'Drop invalid state'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">20</span> state invalid <span class="nb">enable</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">30</span> action accept
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">30</span> description <span class="s1">'Allow IPv6 icmp'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">30</span> protocol ipv6-icmp
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">40</span> action accept
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">40</span> description <span class="s1">'allow dhcpv6'</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">40</span> destination port <span class="m">546</span>
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">40</span> protocol udp
<span class="nb">set</span> firewall ipv6-name WANv6_LOCAL rule <span class="m">40</span> <span class="nb">source</span> port <span class="m">547</span>
<span class="nb">set</span> firewall ipv6-receive-redirects disable
<span class="nb">set</span> firewall ipv6-src-route disable
<span class="nb">set</span> firewall ip-src-route disable
<span class="nb">set</span> firewall log-martians <span class="nb">enable</span>
<span class="nb">set</span> firewall name WAN_IN default-action drop
<span class="nb">set</span> firewall name WAN_IN description <span class="s1">'WAN to internal'</span>
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">10</span> action accept
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">10</span> description <span class="s1">'Allow established/related'</span>
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">10</span> state established <span class="nb">enable</span>
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">10</span> state related <span class="nb">enable</span>
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">20</span> action drop
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">20</span> description <span class="s1">'Drop invalid state'</span>
<span class="nb">set</span> firewall name WAN_IN rule <span class="m">20</span> state invalid <span class="nb">enable</span>
<span class="nb">set</span> firewall name WAN_LOCAL default-action drop
<span class="nb">set</span> firewall name WAN_LOCAL description <span class="s1">'WAN to router'</span>
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">10</span> action accept
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">10</span> description <span class="s1">'Allow established/related'</span>
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">10</span> state established <span class="nb">enable</span>
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">10</span> state related <span class="nb">enable</span>
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">20</span> action drop
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">20</span> description <span class="s1">'Drop invalid state'</span>
<span class="nb">set</span> firewall name WAN_LOCAL rule <span class="m">20</span> state invalid <span class="nb">enable</span>
<span class="nb">set</span> firewall receive-redirects disable
<span class="nb">set</span> firewall send-redirects <span class="nb">enable</span>
<span class="nb">set</span> firewall source-validation disable
<span class="nb">set</span> firewall syn-cookies <span class="nb">enable</span>
<span class="nb">set</span> interfaces ethernet eth0 address dhcp
<span class="nb">set</span> interfaces ethernet eth0 description Internet
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> interface eth1 host-address <span class="s1">'::1'</span>
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> interface eth1 prefix-id <span class="s1">':1'</span>
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> interface eth1 service slaac
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> interface eth2 host-address <span class="s1">'::1'</span>
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> interface eth2 prefix-id <span class="s1">':2'</span>
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> interface eth2 service slaac
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd pd <span class="m">0</span> prefix-length /60
<span class="nb">set</span> interfaces ethernet eth0 dhcpv6-pd rapid-commit <span class="nb">enable</span>
<span class="nb">set</span> interfaces ethernet eth0 duplex auto
<span class="nb">set</span> interfaces ethernet eth0 firewall in ipv6-name WANv6_IN
<span class="nb">set</span> interfaces ethernet eth0 firewall in name WAN_IN
<span class="nb">set</span> interfaces ethernet eth0 firewall <span class="nb">local</span> ipv6-name WANv6_LOCAL
<span class="nb">set</span> interfaces ethernet eth0 firewall <span class="nb">local</span> name WAN_LOCAL
<span class="nb">set</span> interfaces ethernet eth0 speed auto
<span class="nb">set</span> interfaces ethernet eth1 address <span class="m">192</span>.168.40.1/24
<span class="nb">set</span> interfaces ethernet eth1 description Local
<span class="nb">set</span> interfaces ethernet eth1 duplex auto
<span class="nb">set</span> interfaces ethernet eth1 speed auto
<span class="nb">set</span> interfaces ethernet eth2 address <span class="m">192</span>.168.2.1/24
<span class="nb">set</span> interfaces ethernet eth2 description <span class="s1">'Local 2'</span>
<span class="nb">set</span> interfaces ethernet eth2 duplex auto
<span class="nb">set</span> interfaces ethernet eth2 speed auto
<span class="nb">set</span> interfaces loopback lo
<span class="nb">set</span> port-forward auto-firewall <span class="nb">enable</span>
<span class="nb">set</span> port-forward hairpin-nat <span class="nb">enable</span>
<span class="nb">set</span> port-forward lan-interface eth1
<span class="nb">set</span> port-forward wan-interface eth0
<span class="nb">set</span> service dhcp-server disabled <span class="nb">false</span>
<span class="nb">set</span> service dhcp-server hostfile-update disable
<span class="nb">set</span> service dhcp-server shared-network-name LAN1 authoritative <span class="nb">enable</span>
<span class="nb">set</span> service dhcp-server shared-network-name LAN1 subnet <span class="m">192</span>.168.40.0/24 default-router <span class="m">192</span>.168.40.1
<span class="nb">set</span> service dhcp-server shared-network-name LAN1 subnet <span class="m">192</span>.168.40.0/24 dns-server <span class="m">192</span>.168.40.1
<span class="nb">set</span> service dhcp-server shared-network-name LAN1 subnet <span class="m">192</span>.168.40.0/24 lease <span class="m">86400</span>
<span class="nb">set</span> service dhcp-server shared-network-name LAN1 subnet <span class="m">192</span>.168.40.0/24 start <span class="m">192</span>.168.40.20 stop <span class="m">192</span>.168.40.200
<span class="nb">set</span> service dhcp-server shared-network-name LAN2 authoritative <span class="nb">enable</span>
<span class="nb">set</span> service dhcp-server shared-network-name LAN2 subnet <span class="m">192</span>.168.2.0/24 default-router <span class="m">192</span>.168.2.1
<span class="nb">set</span> service dhcp-server shared-network-name LAN2 subnet <span class="m">192</span>.168.2.0/24 dns-server <span class="m">192</span>.168.2.1
<span class="nb">set</span> service dhcp-server shared-network-name LAN2 subnet <span class="m">192</span>.168.2.0/24 lease <span class="m">86400</span>
<span class="nb">set</span> service dhcp-server shared-network-name LAN2 subnet <span class="m">192</span>.168.2.0/24 start <span class="m">192</span>.168.2.38 stop <span class="m">192</span>.168.2.243
<span class="nb">set</span> service dhcp-server static-arp disable
<span class="nb">set</span> service dhcp-server use-dnsmasq disable
<span class="nb">set</span> service dns forwarding cache-size <span class="m">150</span>
<span class="nb">set</span> service dns forwarding listen-on eth1
<span class="nb">set</span> service dns forwarding listen-on eth2
<span class="nb">set</span> service gui http-port <span class="m">80</span>
<span class="nb">set</span> service gui https-port <span class="m">443</span>
<span class="nb">set</span> service gui older-ciphers <span class="nb">enable</span>
<span class="nb">set</span> service nat rule <span class="m">5010</span> description <span class="s1">'masquerade for WAN'</span>
<span class="nb">set</span> service nat rule <span class="m">5010</span> outbound-interface eth0
<span class="nb">set</span> service nat rule <span class="m">5010</span> <span class="nb">type</span> masquerade
<span class="nb">set</span> service ssh port <span class="m">22</span>
<span class="nb">set</span> service ssh protocol-version v2
<span class="nb">set</span> service unms disable
<span class="nb">set</span> system gateway-address <span class="m">192</span>.168.178.1
<span class="nb">set</span> system host-name ubnt
<span class="nb">set</span> system ntp server <span class="m">0</span>.ubnt.pool.ntp.org
<span class="nb">set</span> system ntp server <span class="m">1</span>.ubnt.pool.ntp.org
<span class="nb">set</span> system ntp server <span class="m">2</span>.ubnt.pool.ntp.org
<span class="nb">set</span> system ntp server <span class="m">3</span>.ubnt.pool.ntp.org
<span class="nb">set</span> system syslog global facility all level notice
<span class="nb">set</span> system syslog global facility protocols level debug
<span class="nb">set</span> system time-zone Europe/Berlin
</pre></div>
<p>I found some helpful commands for debugging in <a href="https://kazoo.ga/dhcpv6-pd-for-native-ipv6/">this article</a> describing the IPv6 setup for the EdgeRouter Lite. Also a tcpdump command for ICMPv6 packets on the EdgeRouter itself can help a lot when debugging:</p>
<div class="highlight"><pre><span></span>sudo tcpdump -n -i eth1 icmp6 and ip6<span class="o">[</span><span class="m">40</span><span class="o">]==</span><span class="m">133</span> or ip6<span class="o">[</span><span class="m">40</span><span class="o">]==</span><span class="m">134</span>
</pre></div>
<p>If you made it this far you are hopefully ready to enjoy a full 20/20 score on <a href="http://ipv6-test.com/">ipv6-test.com</a>. Congratulations!</p>Owncloud on docker behind nginx-proxy: file size error solved2017-03-01T00:00:00+01:002017-03-01T00:00:00+01:00Thomas Emmerlingtag:blog.thomasemmerling.de,2017-03-01:/owncloud-on-docker-behind-nginx-proxy-file-size-error-solved.html<p>Wow, this took me a while: I am running an <a href="https://owncloud.org">Owncloud</a> server on my private VPS as a <a href="https://www.docker.com">Docker</a> container. I orchestrate all the different webapps that run on that server using <a href="https://docs.docker.com/compose/">Docker Compose</a> and make use of the magnificent <a href="https://github.com/jwilder/nginx-proxy">jwilder/nginx-proxy</a> (in combination with the <a href="https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion">docker-letsencrypt-nginx-proxy-companion</a>)to serve different …</p><p>Wow, this took me a while: I am running an <a href="https://owncloud.org">Owncloud</a> server on my private VPS as a <a href="https://www.docker.com">Docker</a> container. I orchestrate all the different webapps that run on that server using <a href="https://docs.docker.com/compose/">Docker Compose</a> and make use of the magnificent <a href="https://github.com/jwilder/nginx-proxy">jwilder/nginx-proxy</a> (in combination with the <a href="https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion">docker-letsencrypt-nginx-proxy-companion</a>)to serve different domains on the same VPS.</p>
<p>While I was using Owncloud I encountered a nasty upload error every now and then. Something like <code>Error downloading [file] - server replied: Request Entity Too Large</code> or <code>Continue blacklisting: Error downloading [file] - server replied: Request Entity Too Large</code> or simply <code>Error downloading [file] - server replied: Request Entity Too Large</code> and your file stays marked with a red cross or yellow exclamation mark. You get the point. There are a lot of <a href="https://doc.owncloud.org/server/9.1/admin_manual/configuration_files/big_file_upload_configuration.html">guides</a> on how to setup your <a href="https://httpd.apache.org">Apache</a> configuration to play nicely with Owncloud when it comes to bigger files. But in my case everything was set up using the <a href="https://hub.docker.com/_/owncloud/">official Owncloud docker image</a> that comes with all configuration files optimised already.</p>
<p>Finally, today I <a href="https://forums.freenas.org/index.php?threads/owncloud-request-entity-too-large.41794/">realized</a> that the Nginx reverse proxy that is running in front of the Apache also demands configuration. Following <a href="https://github.com/jwilder/nginx-proxy#per-virtual_host">this part of the documentation</a> you want to volume mount the <code>/etc/nginx/vhost.d</code> folder and add a configuration file for your Owncloud domain:</p>
<div class="highlight"><pre><span></span>client_max_body_size 4096m<span class="p">;</span>
</pre></div>
<p>Go ahead and reload the nginx container. You might have to move the files that did not sync out of your local Owncloud folder and move them back in for the sync process to trigger again. And you have nice green checkmarks again!</p>
<p>Hoping that I save someone time and headaches...
Cheers!</p>Automatic LaTeX CV publishing on GitHub Pages via TravisCI2016-01-28T00:00:00+01:002016-01-28T00:00:00+01:00Thomas Emmerlingtag:blog.thomasemmerling.de,2016-01-28:/automatic-latex-cv-publishing-on-github-pages-via-travisci.html<p>Recently, I wanted to update my CV and as I had good experiences with <em>LaTeX</em> for writing my <a href="http://dx.doi.org/10.13140/RG.2.1.1129.0644">diploma thesis</a> I thought to give it a try for typesetting my CV, too. I started to remember that keeping the full LaTeX stack up-to-date and, more importantly, all package dependencies for …</p><p>Recently, I wanted to update my CV and as I had good experiences with <em>LaTeX</em> for writing my <a href="http://dx.doi.org/10.13140/RG.2.1.1129.0644">diploma thesis</a> I thought to give it a try for typesetting my CV, too. I started to remember that keeping the full LaTeX stack up-to-date and, more importantly, all package dependencies for compilation was a bit of a hassle (although there are great projects like <a href="http://tug.org/mactex/">MacTeX</a> of course!). It certainly did not appeal to my desire to keep things versionized and automated. And as I had <a href="https://blog.thomasemmerling.de/automatic-pelican-publishing-on-github-pages-via-travisci.html">good experiences</a> with <a href="https://travis-ci.org/">Travis CI</a> and <a href="https://pages.github.com">GitHub Pages</a> I thought to give it a try for my CV, too. So, here we go.</p>
<p>We will use TravisCI to run a docker container that uses an image with an updated <a href="http://tug.org/texlive/">TeX Live distribution</a>. This docker container will then compile the file 'cv.tex' into a nice PDF file on every commit (and push) to the GitHub repository. This PDF file, in turn, is then pushed to the <code>gh-pages</code> branch of the repository accompanied with an index.html that displays this very PDF and (if configured) a CNAME to customize the (sub-)domain under which this beautiful CV is available. Voila!
You can see an example at <a href="http://cv.thomasemmerling.de">cv.thomasemmerling.de</a>.</p>
<p>I that was a little too fast just head over to my GitHub repository <a href="https://github.com/thomastweets/cv-on-ghpages">cv-on-ghpages</a> and let me walk you through setting it up over there. It should be pretty straightforward - if not, please send me a comment, mail, tweet, issue, you name it.
And good luck with this job application!</p>Let's already encrypt!2015-12-02T00:00:00+01:002015-12-02T00:00:00+01:00Thomas Emmerlingtag:blog.thomasemmerling.de,2015-12-02:/lets-already-encrypt.html<p>It seems that the internet finally understood that encryption is a necessity. Recently, the brilliant guys of <a href="https://letsencrypt.org">Let's Encrypt</a> started their beta program and I got myself an invite for it. They <a href="https://letsencrypt.org/2015/11/12/public-beta-timing.html">announced</a> that they will open their beta to the public tomorrow and I thought that this is a …</p><p>It seems that the internet finally understood that encryption is a necessity. Recently, the brilliant guys of <a href="https://letsencrypt.org">Let's Encrypt</a> started their beta program and I got myself an invite for it. They <a href="https://letsencrypt.org/2015/11/12/public-beta-timing.html">announced</a> that they will open their beta to the public tomorrow and I thought that this is a good moment to show off the small script that I used until now before it vanishes into obsolescence.</p>
<p>Before <a href="https://letsencrypt.org">Let's Encrypt</a> came along <a href="https://www.startssl.com">StartSSL</a> was one way to obtain a ssl certificate at no cost. However, the workflow of creating and installing the certificates was not very straight forward which led to <a href="https://konklone.com/post/switch-to-https-now-for-free">some</a> <a href="https://joshemerson.co.uk/blog/secure-your-site">blogposts</a> trying to help the novice user. I wanted to streamline the process so that I could have SSL certificates for some domains including all kinds of subdomains in place. As the free StartSSL certificates are not wildcard certificates this called for some scripting.</p>
<p>You can look at the code at <a href="https://github.com/thomastweets/setupSSL">github.com/thomastweets/setupSSL</a>. There is small ReadMe and some settings in the bash script. Things should be pretty self-explanatory - otherwise just send me a message!
From tomorrow on <a href="https://letsencrypt.org">Let's Encrypt</a> might be the better choice. But no matter which tool you use: encrypt your traffic!</p>If I post, you tweet!2015-07-02T00:00:00+02:002015-07-02T00:00:00+02:00Thomas Emmerlingtag:blog.thomasemmerling.de,2015-07-02:/if-i-post-you-tweet.html<p>When I set up the <a href="https://blog.thomasemmerling.de/automatic-pelican-publishing-on-github-pages-via-travisci.html">automatic pelican publishing</a> I did not want to stop there to automatize things. I am a late adopter when it comes to Twitter and have only recently started to use it on a regular basis. And more tweets seem to be a good thing on …</p><p>When I set up the <a href="https://blog.thomasemmerling.de/automatic-pelican-publishing-on-github-pages-via-travisci.html">automatic pelican publishing</a> I did not want to stop there to automatize things. I am a late adopter when it comes to Twitter and have only recently started to use it on a regular basis. And more tweets seem to be a good thing on this platform. So why not throw in some tweets when I write new content here on my blog? But do it manually? Nah...</p>
<p>Say hello to IF-This-Then-That or, shorter, <a href="https://ifttt.com">IFTTT</a>. This is a service to make short program routines (called <em>recipes</em>) that run automatically and can make your modern digital life much easier when it comes to connectability between alls kinds of apps and services. By now (July 2015) they support an impressive 196 so-called <em>channels</em> that serve as the connections to bespoke apps and services. Users can share their recipes and your problem has been probably solved by someone else already.</p>
<p>I went ahead and created a recipe that would monitor the <a href="http://blog.thomasemmerling.de/feeds/all.atom.xml">atom feed</a> of this blog and post a new tweet to my <a href="https://twitter.com/thomastweets">Twitter account</a> everytime there is a new blog post. You can have a look at the recipe <a href="https://ifttt.com/recipes/304261-tweet-every-new-blog-post">here</a>. Actually, it's straightforward to create your own recipes there, so go ahead and try it out!</p>
<p>By the way, I just tweeted about this blog post...</p>Automatic Pelican publishing on GitHub Pages via TravisCI2015-06-27T00:00:00+02:002015-06-28T00:00:00+02:00Thomas Emmerlingtag:blog.thomasemmerling.de,2015-06-27:/automatic-pelican-publishing-on-github-pages-via-travisci.html<p>As I wrote in the <a href="https://blog.thomasemmerling.de/fresh-starts.html">last blog post</a>, the <em>static site generator</em> that I use to publish this post is <a href="http://getpelican.com/">Pelican</a>. Rather than generating the HTML on my machine and then pushing it to the <code>gh-pages</code> branch of <a href="https://github.com/thomastweets/blog.thomasemmerling.de">github.com/thomastweets/blog.thomasemmerling.de</a> I automatized this process using <a href="https://travis-ci.org/">Travis …</a></p><p>As I wrote in the <a href="https://blog.thomasemmerling.de/fresh-starts.html">last blog post</a>, the <em>static site generator</em> that I use to publish this post is <a href="http://getpelican.com/">Pelican</a>. Rather than generating the HTML on my machine and then pushing it to the <code>gh-pages</code> branch of <a href="https://github.com/thomastweets/blog.thomasemmerling.de">github.com/thomastweets/blog.thomasemmerling.de</a> I automatized this process using <a href="https://travis-ci.org/">Travis CI</a>. Travis CI is a <a href="https://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> that is free to use for open source projects. It can not only run automated tests of your project but also trigger deployment tasks when the build is successful.</p>
<p>Using information from <a href="http://blog.mathieu-leplatre.info/publish-your-pelican-blog-on-github-pages-via-travis-ci.html">two</a> <a href="https://zonca.github.io/2013/09/automatically-build-pelican-and-publish-to-github-pages.html">blogs</a> I was able to let Travis CI react on any push to GitHub and automatically generate HTML from the Pelican sources and push them back to the <code>gh-pages</code> branch. Here is how to do that:</p>
<ul>
<li>If you have not done that yet: Create a repository on GitHub called (<em>e.g.</em>) <code>blog.thomasemmerling.de</code>.</li>
<li>Add it as a remote to your local git repository from command line (if you use ssh-keys for authentication - you should do so! <a href="https://help.github.com/articles/generating-ssh-keys/">how to generate</a> and <a href="https://help.github.com/articles/changing-a-remote-s-url/">use</a> them):</li>
</ul>
<div class="highlight"><pre><span></span><span class="c1"># Go to your local Pelican sources</span>
<span class="nb">cd</span> ~/blog
<span class="c1"># Add the remote GitHub repository</span>
git remote add origin git@github.com:thomastweets/blog.thomasemmerling.de.git
<span class="c1"># set the default upstream and push to it</span>
git push --set-upstream origin master
</pre></div>
<ul>
<li>As Travis CI needs to be able to push to your GitHub repository you need to authenticate it. As you do not want to store any passwords, ssh, or API keys in your repo or the Travis CI configuration the easiest way is to use the <code>travis</code> command line tool that is available as a gem to encrypt an Authentication Token for GitHub so that Travis CI can decrypt it when needed. First we need to install it:</li>
</ul>
<div class="highlight"><pre><span></span><span class="c1"># on OSX using the default Ruby installation</span>
sudo gem install travis
</pre></div>
<ul>
<li>Now we create a personal access token on GitHub to use with Travis CI. Follow <a href="https://help.github.com/articles/creating-an-access-token-for-command-line-use/">these instructions</a> to do so. I named mine <code>TravisCI blog.thomasemmerling.de</code> and kept the standard scope settings. Copy the token when you created it as you will not be able to see it again after you close the page.</li>
<li>Encrypt the token with the <code>travis</code> command line tool:</li>
</ul>
<div class="highlight"><pre><span></span><span class="c1"># where 'your_token' is the token from the last step</span>
travis encrypt <span class="nv">GH_TOKEN</span><span class="o">=</span>your_token
</pre></div>
<ul>
<li>Create a file <code>.travis.yml</code> (mind the dot at the beginning!) in the root of your git repository and paste the following (replace the encrypted part after <code>- secure:</code> with what <code>travis encrypt</code> got back to you):</li>
</ul>
<div class="highlight"><pre><span></span><span class="n">language</span><span class="o">:</span> <span class="n">python</span>
<span class="n">branches</span><span class="o">:</span>
<span class="n">only</span><span class="o">:</span>
<span class="o">-</span> <span class="n">master</span>
<span class="n">install</span><span class="o">:</span>
<span class="o">-</span> <span class="n">pip</span> <span class="n">install</span> <span class="n">pelican</span>
<span class="o">-</span> <span class="n">pip</span> <span class="n">install</span> <span class="n">ghp</span><span class="o">-</span><span class="k">import</span>
<span class="o">-</span> <span class="n">pip</span> <span class="n">install</span> <span class="n">markdown</span>
<span class="n">script</span><span class="o">:</span>
<span class="o">-</span> <span class="n">make</span> <span class="n">publish</span>
<span class="o">-</span> <span class="n">make</span> <span class="n">github</span>
<span class="n">env</span><span class="o">:</span>
<span class="n">global</span><span class="o">:</span>
<span class="o">-</span> <span class="n">secure</span><span class="o">:</span> <span class="s2">"A4MpKClryaExBapCaXO3bgATD1KK/SmrdmPz7vk+6aUcJbOnQ/r2A1xjtCUv09PWW+QlA8SRBV626H7tfIONlXwLIn9tt6ZA419uoUWMs8Z2DsLvpHZtmP4TVi4Vi192TQDGqGwCh48aakhHlzWm0DTQKtn2MIJuUGOVOeT8DVhvT0jLOxYLAiRRuJI4OR6hVzHWH0Wa8U2BLC+iNsWn+RKro/HzzilY9p62nAahWe0toqltazQHq8AFMbc9BFuucMbfU/fpPYq1tesacQZG1gUFhs2TG1v7addJY63E0jaQ6jWSLgNdMibEvwmjrkKIeqF0E7J1/xZfoNg2KQpVFARqDkl4NOaf6T4inCaBAlvyxVQ6JszdkasM2AX3zzrg/Ph4ooRQ9sxdshq6g69tWbuDWkUGJMEfcKGfH9cbATeR87TXZZo0J5WajzNae1+zv86E2tVYmQM7wJwdve48wi6q+QpGWShMrT5VVOyLZ5txSYDPKgjCU7LrKqWmwVqEeZC8b49rSam6vsC1QAKsMQ+oiseZFuVAh+ZMpW9Tes9kSSQ1wX/zSepM3jbv+1dIpsjrJNZgQasR/yLAM7QjLQz8TwYG2LNPtOG/gWwdA/txLqGFAWnEgqFXeykbLgFwuFucdRe9I3yFi5VLTbwXw6FonWrjWOvSzKzNydP+fTw="</span>
</pre></div>
<ul>
<li>In the <code>Makefile</code> in the root directory add (or change) the <code>github</code> subcommand (this makes the <code>make github</code> command in the <code>.travis.yml</code> file work):</li>
</ul>
<div class="highlight"><pre><span></span>github: publish
ghp-import -n <span class="k">$(</span>OUTPUTDIR<span class="k">)</span>
@git push -fq https://<span class="si">${</span><span class="nv">GH_TOKEN</span><span class="si">}</span>@github.com/<span class="k">$(</span>TRAVIS_REPO_SLUG<span class="k">)</span>.git gh-pages > /dev/null
</pre></div>
<ul>
<li>Add the <code>.travis.yml</code> file and the <code>Makefile</code> to your git repository, commit, and push to GitHub.</li>
</ul>
<p>Now, if all went well, after some minutes you should see a successful build in Travis CI and the new version of your homepage/blog at the <code>.github.io</code> address (or in my case the custom domain).</p>