<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>chr4</title>
    
    
    
    <link>https://chr4.org/</link>
    <description>Recent content on chr4</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Mon, 21 Jan 2019 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://chr4.org/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Make keepalived play nicely with netplan/ systemd-network</title>
      <link>https://chr4.org/posts/2019-01-21-make-keepalived-play-nicely-with-netplan-slash-systemd-network/</link>
      <pubDate>Mon, 21 Jan 2019 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2019-01-21-make-keepalived-play-nicely-with-netplan-slash-systemd-network/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: &lt;em&gt;Use &lt;code&gt;use_vmac&lt;/code&gt; directive in keepalived when using multicast and your carrier allows multiple MAC addresses per interface. If that&amp;rsquo;s not an option, migrate away from netplan/systemd-networkd, e.g. to ifupdown.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Saturday night, 06:00&lt;/em&gt;:
I was torn from my sleep by the lovely voice of my colleague, uttering the words dreaded among the ops community: &lt;strong&gt;&amp;ldquo;We&amp;rsquo;re down, Chris.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After opening the lid of my notebook, I started digging into the issue.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re running several high availability services with the help of &lt;a href=&#34;http://keepalived.org/&#34;&gt;keepalived&lt;/a&gt;. When a service goes down, keepalived switches over services to a standby instance. This is usually done by assigning a dedicated virtual IP address (VIP) to a service which can then be migrated on the fly between instances. This is achieved by keepalived using the Virtual Router Redundance Protocol (VRRP) as described in &lt;a href=&#34;https://tools.ietf.org/html/rfc5798&#34;&gt;RFC5789&lt;/a&gt;, and has proved itself to be very reliable in the last years.&lt;/p&gt;
&lt;p&gt;Not so today. The primary server somehow lost its VIP, without any notice in the log files. Just like that. I reassigned the VIP manually, verified that we&amp;rsquo;re back up and went back to sleep.&lt;/p&gt;
&lt;p&gt;We then did a post-mortem on Monday. Obviously, we wanted to know what the heck had happened, and how we could prevent it from happening again in the future.&lt;/p&gt;
&lt;h2 id=&#34;dhcp&#34;&gt;
  DHCP
  &lt;a href=&#34;#dhcp&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our OpenStack hoster relies on DHCP to configure the attached network interfaces.
I usually prefer static configured interfaces on servers, and eyed the configuration with some suspicion for a while. We&amp;rsquo;ve had some minor issues with static routes and DHCP in the past, but the environment was pretty stable, so we went with the hoster&amp;rsquo;s original base images and their configuration.&lt;/p&gt;
&lt;h2 id=&#34;ubuntu-upgrade&#34;&gt;
  Ubuntu upgrade
  &lt;a href=&#34;#ubuntu-upgrade&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Keeping this in mind, we&amp;rsquo;ve been implementing one bigger change in our infrastructure: We&amp;rsquo;ve upgraded some instances (including the database node that had the outage) from Ubuntu 16.04 LTS (xenial) to Ubuntu 18.04 LTS (bionic). One of the major changes between the two releases is the change of the default networking stack from ifupdown to netplan. Could this have caused the issue?&lt;/p&gt;
&lt;h2 id=&#34;netplan&#34;&gt;
  netplan
  &lt;a href=&#34;#netplan&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;After digging around a bit more, I found out that calling &lt;code&gt;netplan apply&lt;/code&gt; (to apply a network configuration) resulted in dropped VIPs.&lt;/p&gt;
&lt;p&gt;Apparently, keepalived doesn&amp;rsquo;t monitor the VIP assigned to it, and neither initiates a failover, nor tries to reinstate the dropped VIP after it was removed from the interface. This is a &lt;a href=&#34;https://github.com/acassen/keepalived/issues/836&#34;&gt;known issue&lt;/a&gt;, and was fixed by &lt;a href=&#34;https://github.com/acassen/keepalived/commit/8ecbb591994a567375d78239d075ed032d9f9b07&#34;&gt;this commit&lt;/a&gt; which was released with &lt;code&gt;keepalived-2.0.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, Ubuntu ships with &lt;code&gt;keepalived-1.3.9&lt;/code&gt;, and the keepalived developers do not provide an official repository for more recent versions.
After considering providing packages myself, I came to the conclusion that this actually wouldn&amp;rsquo;t fit the actual problem, as keepalived would just note the removed VIP and failover to another machine. But I wanted to fix the underlying problem itself, instead of just coping with the symptoms.&lt;/p&gt;
&lt;h2 id=&#34;systemd-networkd&#34;&gt;
  systemd-networkd
  &lt;a href=&#34;#systemd-networkd&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The default renderer for netplan on Ubuntu is systemd-networkd, a &lt;a href=&#34;https://freedesktop.org/wiki/Software/systemd/&#34;&gt;systemd&lt;/a&gt; component. On every &lt;code&gt;netplan apply&lt;/code&gt;, the systemd-networkd is restarted, applying the new configuration. This apparently also happens when a DHCP lease is renewed and results in the VIPs being removed, because systemd-networkd is unaware of them, as they are assigned by keepalived and are not configured in &lt;code&gt;/etc/netplan&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This seems to be &lt;a href=&#34;https://github.com/systemd/systemd/issues/780#issuecomment-126067240&#34;&gt;a feature&lt;/a&gt;, and I kind of agree why: If you have a messy interface configuration and you connect to a network, it makes sense to make sure the interface is in a defined state.&lt;/p&gt;
&lt;p&gt;But having a downtime every time a DHCP lease is renewed obviously also is not an option.&lt;/p&gt;
&lt;p&gt;So, how do I fix the problem permanently in a clean way? I was thinking about the following approaches:&lt;/p&gt;
&lt;h2 id=&#34;1-migrating-to-a-static-ip-configuration&#34;&gt;
  1. Migrating to a static IP configuration
  &lt;a href=&#34;#1-migrating-to-a-static-ip-configuration&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;As I was critical of using DHCP anyway, I considered migrating to static IPs. While this would fix the issues with DHCP lease renewals, we&amp;rsquo;d still have the same problem on other occasions of &lt;code&gt;systemctl restart systemd-networkd&lt;/code&gt; (e.g. automatic security updates). I was reluctant to change that much of the networking stack, as I believe this should be done by the underlying hypervisor.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update 2020-02-07: Bear in mind that apparently &lt;code&gt;systemd-networkd&lt;/code&gt; still renews DHCP leases upon (automatic) updates (and purges the VIP from the interface) even when DHCP is configured within another service (e.h. &lt;code&gt;ifupdown&lt;/code&gt;). A possible workaround here is to make sure &lt;code&gt;systemd-networkd&lt;/code&gt; service is stopped and disabled (e.g. via &lt;code&gt;systemctl stop systemd-networkd; systemctl disable systemd-networkd&lt;/code&gt;). When using static configuration via &lt;code&gt;ifupdown&lt;/code&gt;, restarting &lt;code&gt;systemd-networkd&lt;/code&gt; doesn&amp;rsquo;t seem to interfere.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;2-dummy-network-interface-plz-dont&#34;&gt;
  2. Dummy network interface (plz don&amp;rsquo;t!)
  &lt;a href=&#34;#2-dummy-network-interface-plz-dont&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;NOTE: An earlier version of the blog post suggested to use a dummy network interface. The Linux networking stack defaults to &amp;ldquo;Weak ES (End System) Model&amp;rdquo; as specified in &lt;a href=&#34;https://tools.ietf.org/html/rfc1122&#34;&gt;RFC1122&lt;/a&gt;), enabling it to handle incoming packages for IP addresses configured on another interface than the physical interface the package came in. Unfortunately, the gratuitous ARP packages (ipv4) and unsolicited neighbour adverts (ipv6) can&amp;rsquo;t be sent out properly with the dummy network interface, resulting in shaky failovers. Furthermore, this solution didn&amp;rsquo;t work at all using ipv6.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;3-macvlan&#34;&gt;
  3. MACVLAN
  &lt;a href=&#34;#3-macvlan&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;After a very helpful &lt;a href=&#34;https://github.com/acassen/keepalived/issues/1170&#34;&gt;discussion with a keepalived maintainer&lt;/a&gt;, the recommended way of solving this is to use MACVLANs. This is a built-in feature of keepalived and can be simply enabled with the &lt;code&gt;use_vmac&lt;/code&gt; directive in the configuration file. Recent versions of keepalived take care of all required &lt;code&gt;sysctl&lt;/code&gt; settings for this, so it should just work.&lt;/p&gt;
&lt;p&gt;The MACVLAN interface (e.g. &lt;code&gt;vrrp.51@eth0&lt;/code&gt;) will be created by keepalived, and it will also take care of the VIP on that interface. Then, &lt;code&gt;systemd-networkd&lt;/code&gt; can configure the original interface at will, without hurting the dedicated interface for the virtual IP when it&amp;rsquo;s reloaded (or a new DHCP lease comes in).&lt;/p&gt;
&lt;p&gt;Bonus: The interface (incl. the master VIP) are also now displayed in Ubuntu&amp;rsquo;s default message-of-the-day (motd) upon login.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the relevant section from the &lt;a href=&#34;https://keepalived.org/manpage.html&#34;&gt;keepalived documentation&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use VRRP Virtual MAC.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# NOTE: If sysctl net.ipv4.conf.all.rp_filter is set,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# and this vrrp_instance is an IPv4 instance, using&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# this option will cause the individual interfaces to be&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# updated to the greater of their current setting, and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# all.rp_filter, as will default.rp_filter, and all.rp_filter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# will be set to 0.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# The original settings are restored on termination.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;use_vmac &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&amp;lt;VMAC_INTERFACE&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the recommended way of implementing VIPs with systemd, and should work with ipv4 and ipv6 setups!&lt;/p&gt;
&lt;p&gt;Unfortunately, using Virtual MAC is only possible when keepalived is running in multicast mode, as &lt;a href=&#34;https://github.com/acassen/keepalived/issues/1170#issuecomment-479885331&#34;&gt;pointed out by the maintainer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While I was able to get multicast running on OpenStack (a security group allowing protocol 112 is necessary), most providers only allow a single MAC address per interface, which leads to unstable failovers. Apparently, MACVLAN also is not an option on AWS, as it &lt;a href=&#34;https://aws.amazon.com/vpc/faqs/&#34;&gt;doesn&amp;rsquo;t allow multicast at all&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When multicast is not allowed, or multiple MAC addresses are no option, there&amp;rsquo;s another method available: IPVLAN&lt;/p&gt;
&lt;h2 id=&#34;4-ipvlan&#34;&gt;
  4. IPVLAN
  &lt;a href=&#34;#4-ipvlan&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;An IPVLAN interface is similar to MACVLAN, but receives packets from the underlying interface based on IP address filtering instead of MAC address filtering.&lt;/p&gt;
&lt;p&gt;You can create it using the following command (NOTE: This won&amp;rsquo;t persist on reboots)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ip link add link eth0 keepalived0 type ipvlan mode l2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ip link set keepalived0 up
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# If you intent to use the interface with IPv4, a dummy IP address might be required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ip address add 1.2.3.4/32 keepalived0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Modify the following lines in your &lt;code&gt;keepalived.conf&lt;/code&gt; to use the interface:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Set the base interface here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;interface eth0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Attach the VIP to the IPVLAN device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;virtual_ipaddress &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    10.1.0.1/32 dev keepalived0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should work and also send unsolicited neighbour adverts and gratuitous ARP packets correctly.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: While IPVLAN worked fine with IPv6, I wasn&amp;rsquo;t able to get this to work for IPv4 in an OpenStack environment. Incoming IPv4 ICMP/ TCP packets are received by the parent interface, but never replied to. When attaching the interface to a namespace and use keepalived&amp;rsquo;s &lt;code&gt;net_namespace&lt;/code&gt; pinging works, but I cannot access the high availability service which resides in the default namespace. Also, both nodes go into MASTER mode and apparently VRRP doesn&amp;rsquo;t work, as the interface needs to be set to the IPVLAN interface inside the namespace. The respective &lt;a href=&#34;https://www.kernel.org/doc/Documentation/networking/ipvlan.txt&#34;&gt;kernel documentation&lt;/a&gt; is pretty scarce and only provides examples including namespaces.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, I found no way so far to persist the IPVLAN interface with systemd-networkd. I&amp;rsquo;ve tried creating the respective systemd &lt;code&gt;.netdev&lt;/code&gt; and &lt;code&gt;.network&lt;/code&gt; files, with no luck (the interface is just not created). Also, netplan doesn&amp;rsquo;t support MACVLAN/ IPVLAN, but at least &lt;a href=&#34;https://bugs.launchpad.net/netplan/+bug/1664847&#34;&gt;there a ticket&lt;/a&gt; with the feature request. I assume though, that creating the interface with netplan/ systemd would also mean, that the interface then will be purged again. So this also is not a solution.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a &lt;a href=&#34;https://github.com/acassen/keepalived/commit/897690b25df0f444142ec37fdea2ce9a77dac493&#34;&gt;commit&lt;/a&gt; that adds an &lt;code&gt;use_ipvlan&lt;/code&gt; option to keepalived to solve this issue and to make the use of IPVLAN as seamless as MACVLAN in keepalived.&lt;/p&gt;
&lt;p&gt;Until this is ready, there are two options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use &lt;a href=&#34;https://gitlab.com/craftyguy/networkd-dispatcher&#34;&gt;networkd-dispatcher&lt;/a&gt; to create the IPVLAN device after systemd-networkd brings the interface up by placing the IPVLAN creation from the above snipped in &lt;code&gt; etc/networkd-dispatcher/routable.d/50-keepalived&lt;/code&gt;. See netplan &lt;a href=&#34;https://netplan.io/faq#use-pre-up-post-up-etc-hook-scripts&#34;&gt;FAQ&lt;/a&gt; for more information. Because seemingly the hook scripts for networkd-dispatcher are global, and I cannot restrict them to a single interface, I personally went for the second approach for now:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Migrate back to &lt;a href=&#34;https://packages.ubuntu.com/bionic/ifupdown&#34;&gt;ifupdown&lt;/a&gt; for all instances using keepalived. I was reluctant to so, as I didn&amp;rsquo;t want to exchange the network stack on every new instance, but the migration went smoother than expected and I was able to automate it quite well using Saltstack. While ifupdown doesn&amp;rsquo;t support IPVLAN natively, it&amp;rsquo;s easy to implement it using the &lt;code&gt;up&lt;/code&gt; directive and just add the necessary commands to &lt;code&gt;/etc/network/interfaces.d/&amp;lt;yourinterface&amp;gt;.cfg&lt;/code&gt;:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iface eth0 &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  address &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gateway &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Create keepalived IPVLAN interface&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  up ip link add link eth0 keepalived0 type ipvlan mode l2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  up ip link set keepalived0 up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While this is not the perfect solution, it makes me feel comfortable enough to run this in production.&lt;/p&gt;
&lt;p&gt;I hope this ensures I can sleep in on Saturdays.&lt;/p&gt;
&lt;h2 id=&#34;a-new-hope&#34;&gt;
  A new hope
  &lt;a href=&#34;#a-new-hope&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s hope. Besides the mentioned &lt;a href=&#34;https://github.com/acassen/keepalived/commit/897690b25df0f444142ec37fdea2ce9a77dac493&#34;&gt;keepalived commit&lt;/a&gt; that adds an &lt;code&gt;use_ipvlan&lt;/code&gt; option, I&amp;rsquo;ve filed an &lt;a href=&#34;https://github.com/systemd/systemd/issues/12050&#34;&gt;systemd issue&lt;/a&gt; explaining the problem to the systemd maintainers.
Even though they currently have more than 1.000 open issues there&amp;rsquo;s already a &lt;a href=&#34;https://github.com/systemd/systemd/pull/12511&#34;&gt;pull request&lt;/a&gt; adding an option to systemd to prevent automatic purging of addresses.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update Oct 2020&lt;/em&gt;: While Ubuntu 20.04 LTS (&lt;code&gt;focal&lt;/code&gt;) has &lt;code&gt;systemd-243&lt;/code&gt; bundled, the new &lt;code&gt;KeepConnection&lt;/code&gt; attribute is not supported by &lt;code&gt;netplan&lt;/code&gt;. I&amp;rsquo;ve added a &lt;a href=&#34;https://bugs.launchpad.net/netplan/+bug/1896799&#34;&gt;bug report&lt;/a&gt;, but with no reply so far.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>cache_warmer - tool to warm-up HTTP caches</title>
      <link>https://chr4.org/posts/2017-12-18-cache-warmer-tool-to-warm-up-http-caches/</link>
      <pubDate>Mon, 18 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2017-12-18-cache-warmer-tool-to-warm-up-http-caches/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I&amp;rsquo;ve written a small tool to warm-up HTTP caches, e.g. services like &lt;a href=&#34;http://nginx.org/&#34;&gt;nginx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Source code as well as &lt;a href=&#34;https://github.com/chr4/cache_warmer/releases&#34;&gt;compiled releases&lt;/a&gt; are available at &lt;a href=&#34;https://github.com/chr4/cache_warmer&#34;&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;comparison-to-other-tools&#34;&gt;
  Comparison to other tools
  &lt;a href=&#34;#comparison-to-other-tools&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;While most tools in this area are designed to apply a certain load to a web server (often for a specified time), cache_warmer is designed to explicitly &lt;code&gt;GET&lt;/code&gt; a set of URLs from a file to warm-up a cache.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;
  Usage
  &lt;a href=&#34;#usage&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Warm-up URLs from a file using a mobile User-Agent&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cache_warmer --mobile urls.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Spawning &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt; threads to warm cache with &lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt; URIs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt; / &lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[===================================================================]&lt;/span&gt; 100.00 % 133.99/s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Processed &lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt; URLs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X-Cache-Status header statistics:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Miss: &lt;span style=&#34;color:#ae81ff&#34;&gt;8991&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Hit: &lt;span style=&#34;color:#ae81ff&#34;&gt;1009&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP Status Code statistics:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Ok: &lt;span style=&#34;color:#ae81ff&#34;&gt;9850&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        NotFound: &lt;span style=&#34;color:#ae81ff&#34;&gt;150&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Total time taken: 450.002s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;features&#34;&gt;
  Features
  &lt;a href=&#34;#features&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h4 id=&#34;multi-threaded&#34;&gt;
  Multi-Threaded
  &lt;a href=&#34;#multi-threaded&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;cache_warmer is multi-threaded. Threads can be specified using the &lt;code&gt;--threads&lt;/code&gt; option.&lt;/p&gt;
&lt;h4 id=&#34;http-keep-alive&#34;&gt;
  HTTP keep-alive
  &lt;a href=&#34;#http-keep-alive&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;It uses keep-alive by default, which can be disabled with &lt;code&gt;--no-keep-alive&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;captcha-detection&#34;&gt;
  Captcha detection
  &lt;a href=&#34;#captcha-detection&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;It supports a &lt;code&gt;--captcha-string&lt;/code&gt; option, which scans the response body for certain strings to detect (and abort) when running into e.g. captchas.&lt;/p&gt;
&lt;h4 id=&#34;base-uri&#34;&gt;
  Base URI
  &lt;a href=&#34;#base-uri&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;If your URL file only contains the base URL (like &lt;code&gt;/products/spoons&lt;/code&gt;), you can add a &lt;code&gt;--base-uri&lt;/code&gt; to prepend the host and scheme, e.g. &lt;code&gt;--base-uri https://example.com&lt;/code&gt;&lt;/p&gt;
&lt;h4 id=&#34;request-delay&#34;&gt;
  Request delay
  &lt;a href=&#34;#request-delay&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Outgoing requests can be toned down with the &lt;code&gt;--delay&lt;/code&gt; flag.&lt;/p&gt;
&lt;h4 id=&#34;x-cache-status-header-support&#34;&gt;
  X-Cache-Status header support
  &lt;a href=&#34;#x-cache-status-header-support&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;If your backend sets the &lt;code&gt;X-Cache-Status&lt;/code&gt; header, you&amp;rsquo;ll get nice statistics about your cache hit rates at the end of the run.&lt;/p&gt;
&lt;p&gt;When using &lt;a href=&#34;http://nginx.org&#34;&gt;nginx&lt;/a&gt;, such a header can be added with this directive:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;add_header&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;X-Cache-Status&lt;/span&gt; $upstream_cache_status;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;custom-user-agent&#34;&gt;
  Custom User-Agent
  &lt;a href=&#34;#custom-user-agent&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;cache_warmer defaults to a Googlebot-like User-Agent. You can use the corresponding mobile User-Agent when specifying the &lt;code&gt;--mobile&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;In case you need a custom User-Agent, you can set it with &lt;code&gt;--user-agent &#39;Your-User-Agent&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;cookie-support&#34;&gt;
  Cookie support
  &lt;a href=&#34;#cookie-support&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Attach arbitrary cookies with the &lt;code&gt;--cookie key=value&lt;/code&gt; option.&lt;/p&gt;
&lt;h2 id=&#34;compile&#34;&gt;
  Compile
  &lt;a href=&#34;#compile&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Compile locally&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cargo build --release
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Cross compile to Linux using Docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker-compose up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
        </description>
    </item>
    
    <item>
      <title>sslsecure.vim - Highlight insecure SSL/TLS cipher suites and protocols as errors in your editor</title>
      <link>https://chr4.org/posts/2017-04-27-sslsecure-dot-vim/</link>
      <pubDate>Thu, 27 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2017-04-27-sslsecure-dot-vim/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;When configuring or programming SSL/TLS servers, at some point a SSL/TLS cipher suite and a list of supported protocols have to be chosen. &lt;strong&gt;Unfortunately, not all configuration options are safe.&lt;/strong&gt; :(&lt;/p&gt;
&lt;p&gt;Meet &lt;strong&gt;&lt;a href=&#34;https://github.com/chr4/sslsecure.vim&#34;&gt;sslsecure.vim&lt;/a&gt;&lt;/strong&gt;!
A plugin for the &lt;a href=&#34;http://www.vim.org/&#34;&gt;Vim&lt;/a&gt; editor, that marks insecure SSL/TLS cipher suites and protocols as errors. &lt;strong&gt;See all potentially insecure options right in your editor!&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&#34;features&#34;&gt;
  Features
  &lt;a href=&#34;#features&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Mark insecure SSL ciphers as errors&lt;/li&gt;
&lt;li&gt;Mark insecure SSL protocols as errors&lt;/li&gt;
&lt;li&gt;Works with all configuration files (web servers, mail servers, &amp;hellip;)&lt;/li&gt;
&lt;li&gt;Works with all source code (independently on the used programming language)&lt;/li&gt;
&lt;li&gt;Works on top of regular syntax highlighting&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on.&lt;/p&gt;
&lt;p&gt;&amp;ndash; Edward Snowden&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;screenshots&#34;&gt;
  Screenshots
  &lt;a href=&#34;#screenshots&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Enough words, see &lt;a href=&#34;https://github.com/chr4/sslsecure.vim&#34;&gt;sslsecure.vim&lt;/a&gt; in action!&lt;/p&gt;
&lt;h4 id=&#34;web-servers&#34;&gt;
  Web Servers
  &lt;a href=&#34;#web-servers&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Nginx:
&lt;img alt=&#34;nginx&#34; src=&#34;https://chr4.org/img/sslsecure_nginx.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Apache:
&lt;img alt=&#34;Apache2&#34; src=&#34;https://chr4.org/img/sslsecure_apache.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Lighttpd:
&lt;img alt=&#34;Lighttpd&#34; src=&#34;https://chr4.org/img/sslsecure_lighttpd.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;mail-servers&#34;&gt;
  Mail Servers
  &lt;a href=&#34;#mail-servers&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Postix:
&lt;img alt=&#34;Postfix&#34; src=&#34;https://chr4.org/img/sslsecure_postfix.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Exim:
&lt;img alt=&#34;Exim&#34; src=&#34;https://chr4.org/img/sslsecure_exim.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Dovecot:
&lt;img alt=&#34;Dovecot&#34; src=&#34;https://chr4.org/img/sslsecure_dovecot.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;load-balancers&#34;&gt;
  Load Balancers
  &lt;a href=&#34;#load-balancers&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Haproxy:
&lt;img alt=&#34;HAProxy&#34; src=&#34;https://chr4.org/img/sslsecure_haproxy.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;ftp-servers&#34;&gt;
  FTP Servers
  &lt;a href=&#34;#ftp-servers&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;ProFTPd:
&lt;img alt=&#34;ProFTPd&#34; src=&#34;https://chr4.org/img/sslsecure_proftpd.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;databases&#34;&gt;
  Databases
  &lt;a href=&#34;#databases&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;PostgreSQL:
&lt;img alt=&#34;PostgreSQL&#34; src=&#34;https://chr4.org/img/sslsecure_postgresql.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;MariaDB/ MySQL
&lt;img alt=&#34;MySQL&#34; src=&#34;https://chr4.org/img/sslsecure_mysql.png&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;programming-languages&#34;&gt;
  Programming languages
  &lt;a href=&#34;#programming-languages&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;C (OpenSSL):
&lt;img alt=&#34;C&#34; src=&#34;https://chr4.org/img/sslsecure_c.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://golang.org&#34;&gt;Go&lt;/a&gt;:
&lt;img alt=&#34;Go&#34; src=&#34;https://chr4.org/img/sslsecure_go.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.rust-lang.org&#34;&gt;Rust&lt;/a&gt; (&lt;a href=&#34;https://github.com/ctz/rustls/blob/master/src/msgs/enums.rs#L982&#34;&gt;Rustls&lt;/a&gt;)
&lt;img alt=&#34;Rust (with Rustls)&#34; src=&#34;https://chr4.org/img/sslsecure_rust.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Jana:
&lt;img alt=&#34;Java&#34; src=&#34;https://chr4.org/img/sslsecure_java.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;additional-notes-on-runtime-cipher-expanding&#34;&gt;
  Additional notes on runtime cipher expanding
  &lt;a href=&#34;#additional-notes-on-runtime-cipher-expanding&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Cipher suites are expanded upon runtime. This is especially important when using &lt;code&gt;+CHIPER&lt;/code&gt; statements in your suite, as insecure ciphers might be included upon runtime.&lt;/p&gt;
&lt;p&gt;Example: The following (&lt;a href=&#34;https://cipherli.st/&#34;&gt;suggested by Cipherli.st&lt;/a&gt;) cipher suite doesn&amp;rsquo;t seem to contain any insecure ciphers when specifying:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, depending on your OpenSSL/ LibreSSL version, this suite expands upon runtime to the following (note the insecure &lt;code&gt;DSS&lt;/code&gt; and &lt;code&gt;SHA&lt;/code&gt; ciphers!):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ openssl chipers &amp;#39;EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH&amp;#39; | vim
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img alt=&#34;ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA&#34; src=&#34;https://chr4.org/img/sslsecure_expand.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;The plugin currently doesn&amp;rsquo;t save you from this pitfall. It&amp;rsquo;s therefore recommended, not to use the &lt;code&gt;+&lt;/code&gt; statement in your cipher suite.
There&amp;rsquo;s an &lt;a href=&#34;https://github.com/chr4/sslsecure.vim/issues/1&#34;&gt;issue&lt;/a&gt; that discusses whether this plugin should also highlight all &lt;code&gt;+&lt;/code&gt; statements.&lt;/p&gt;
&lt;h2 id=&#34;feedback&#34;&gt;
  Feedback
  &lt;a href=&#34;#feedback&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m neither a mathematician, nor a cryptographer. If you are one and you have feedback to this plugin, find a flaw, please open an &lt;a href=&#34;https://github.com/chr4/sslsecure.vim/issues&#34;&gt;issue&lt;/a&gt; or &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;contact me&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;
  Installation
  &lt;a href=&#34;#installation&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Just plug it into your favorite Vim package manager:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;#34; Plug&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Plug&lt;/span&gt; &amp;#39;&lt;span style=&#34;color:#a6e22e&#34;&gt;chr4&lt;/span&gt;/&lt;span style=&#34;color:#a6e22e&#34;&gt;sslsecure&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;vim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;#34; Dein.vim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;call&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dein&lt;/span&gt;#&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chr4/sslsecure.vim&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;#34; Vundle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Plugin&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chr4/sslsecure.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;using-sslsecurevim-and-nginxvim-together&#34;&gt;
  Using sslsecure.vim and nginx.vim together
  &lt;a href=&#34;#using-sslsecurevim-and-nginxvim-together&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/chr4/sslsecure.vim/&#34;&gt;sslsecure.vim&lt;/a&gt;  was inspired by my other plugin
&lt;a href=&#34;https://chr4.org/posts/2017-04-14-better-syntax-highlighting-and-snippets-for-nginx-in-vim/&#34;&gt;nginx.vim&lt;/a&gt;, which also automatically tries to detect insecure settings, but is nginx specific. Both plugins can be used alongside - &lt;code&gt;nginx.vim&lt;/code&gt; automatically detects when &lt;code&gt;sslsecure.vim&lt;/code&gt; is installed, so errors are not highlighted twice.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: Gracias a &lt;a href=&#34;https://www.redeszone.net/&#34;&gt;Redeszone&lt;/a&gt; por &lt;a href=&#34;https://www.redeszone.net/2017/04/30/conoce-esta-extension-para-vim-que-nos-avisara-si-configuramos-cifrados-ssltls-inseguros/&#34;&gt;un revisión muy bien&lt;/a&gt; sobre esta extensión!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: &lt;a href=&#34;https://github.com/shibumi&#34;&gt;Christian Rebischke&lt;/a&gt; packaged this plugin for &lt;a href=&#34;https://www.archlinux.org/&#34;&gt;Archlinux&lt;/a&gt; users in the &lt;a href=&#34;https://aur.archlinux.org/packages/vim-sslsecure/&#34;&gt;Archlinux User Repository (AUR)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: Auch ein Danke an &lt;a href=&#34;https://www.heise.de/security/meldung/Vim-Plug-In-sslsecure-hilft-bei-der-Konfiguration-von-SSL-TLS-Servern-3730524.html&#34;&gt;Heise&lt;/a&gt; für den Artikel über dieses Plugin!&lt;/em&gt;&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>nginx.vim (with better syntax highlighting)</title>
      <link>https://chr4.org/posts/2017-04-14-better-syntax-highlighting-and-snippets-for-nginx-in-vim/</link>
      <pubDate>Fri, 14 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2017-04-14-better-syntax-highlighting-and-snippets-for-nginx-in-vim/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I&amp;rsquo;m editing &lt;a href=&#34;http://nginx.org&#34;&gt;nginx&lt;/a&gt; configuration files. A lot. Naturally, I&amp;rsquo;ve tried several plugins for my favorite editor &lt;a href=&#34;http://neovim.io/&#34;&gt;vim&lt;/a&gt; - but ran around a lot of problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most of the plugins available are outdated.&lt;/li&gt;
&lt;li&gt;Even syntax highlighting of the current vim plugin distributed with the nginx release has some deficits.&lt;/li&gt;
&lt;li&gt;I&amp;rsquo;ve been tired of copying around secure &lt;code&gt;ssl_cipher&lt;/code&gt; directives, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, I&amp;rsquo;ve created a new, super-cool and mega-advanced &lt;strong&gt;vim plugin for nginx&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Ladies and gentlemen: Please welcome, &lt;a href=&#34;https://github.com/chr4/nginx.vim&#34;&gt;chr4/nginx.vim&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: This plugin was integrated into &lt;a href=&#34;https://github.com/vim/vim/blob/master/runtime/syntax/nginx.vim&#34;&gt;Vim&lt;/a&gt; and &lt;a href=&#34;https://github.com/neovim/neovim/blob/master/runtime/syntax/nginx.vim&#34;&gt;Neovim&lt;/a&gt; upstream!&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;features&#34;&gt;
  Features
  &lt;a href=&#34;#features&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The plugin is based on the recent vim plugin distributed with &lt;code&gt;nginx-1.12.0&lt;/code&gt; and additionally features the following syntax improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Highlight IPv4 and IPv6 addresses&lt;/li&gt;
&lt;li&gt;Mark insecure &lt;code&gt;ssl_protocols&lt;/code&gt; as errors&lt;/li&gt;
&lt;li&gt;Inline template syntax highlight for &lt;strong&gt;ERB&lt;/strong&gt; and &lt;strong&gt;Jinja&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Inline syntax highlight for &lt;strong&gt;LUA&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Improve integer matching&lt;/li&gt;
&lt;li&gt;Syntax highlighting for &lt;code&gt;proxy_next_upstream&lt;/code&gt; options&lt;/li&gt;
&lt;li&gt;Syntax highlighting for &lt;code&gt;sticky&lt;/code&gt; options&lt;/li&gt;
&lt;li&gt;Syntax highlighting for &lt;code&gt;upstream&lt;/code&gt; &lt;code&gt;server&lt;/code&gt; options&lt;/li&gt;
&lt;li&gt;More to come!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove annoying delimiters, resulting in strange word boundaries&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;screenshots&#34;&gt;
  Screenshots
  &lt;a href=&#34;#screenshots&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;server&lt;/code&gt; block with highlighted insecure SSL options:
&lt;img alt=&#34;nginx server block with SSL configuration&#34; src=&#34;https://chr4.org/img/nginx_ssl.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;An &lt;code&gt;upstream&lt;/code&gt; block with highlighted options:
&lt;img alt=&#34;nginx upstream configuration&#34; src=&#34;https://chr4.org/img/nginx_upstream.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Embedded highlighting for ERB and Jinja templates:
&lt;img alt=&#34;Embedded highlighting for ERB and Jinja templates&#34; src=&#34;https://chr4.org/img/nginx_templating.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Embedded LUA syntax highlighting:
&lt;img alt=&#34;Embedded LUA highlighting&#34; src=&#34;https://chr4.org/img/nginx_lua.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;snippets&#34;&gt;
  Snippets
  &lt;a href=&#34;#snippets&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The plugin comes with useful snippets which can be accessed using e.g. &lt;a href=&#34;https://github.com/garbas/vim-snipmate&#34;&gt;vim-snipmate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Select a decent cipher for your requirements (all of them can provide &lt;a href=&#34;https://www.ssllabs.com/ssltest/analyze.html&#34;&gt;SSLLabs A+ ratings&lt;/a&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ciphers-paranoid&amp;lt;tab&amp;gt;&lt;/code&gt;: Even-more-secure ciphers (elliptic curves, no GCM), not compatible with IE &amp;lt; 11, OpenSSL-0.9.8, Safari &amp;lt; 7, Android != 4.4&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ciphers-modern&amp;lt;tab&amp;gt;&lt;/code&gt;: High security ciphers (elliptic curves), not compatible with IE &amp;lt; 11, OpenSSL-0.9.8, Safari &amp;lt; 7, Android &amp;lt; 4.4 (recommended)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ciphers-compat&amp;lt;tab&amp;gt;&lt;/code&gt;: Medium security ciphers with good compatibility (No IE on WinXP) but TLSv1 and SHA required&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ciphers-old&amp;lt;tab&amp;gt;&lt;/code&gt;: Low security ciphers (using weak DES and SHA ciphers, TLSv1), but compatible with everything but IE6 and Java6&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssl-options&amp;lt;tab&amp;gt;&lt;/code&gt;: Bootstrap secure SSL options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# High-security ciphers (elliptic curves), less compatibility
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# No IE &amp;lt; 10, OpenSSL-0.9.8, Safari &amp;lt; 7, Android &amp;lt; 4.4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ssl_protocols&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;TLSv1.1&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;TLSv1.2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ssl_ciphers&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or add a robots.txt file with &lt;code&gt;robots.txt&amp;lt;tab&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Tell bots to not index this site
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/robots.txt&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;default_type&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;text/plain&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;User-agent:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;*\nDisallow:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/\n&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It also has auto-completion for location and server blocks with &lt;code&gt;location&amp;lt;tab&amp;gt;&lt;/code&gt; resp. &lt;code&gt;server&amp;lt;tab&amp;gt;&lt;/code&gt;, and &lt;a href=&#34;https://github.com/chr4/nginx.vim/blob/master/snippets/nginx.snippets&#34;&gt;many more&lt;/a&gt;!&lt;/p&gt;
&lt;h3 id=&#34;installation&#34;&gt;
  Installation
  &lt;a href=&#34;#installation&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Just plug it in using your favorite vim package manager&lt;/p&gt;
&lt;p&gt;For example &lt;a href=&#34;https://github.com/junegunn/vim-plug&#34;&gt;vim-plug&lt;/a&gt; (which I&amp;rsquo;m currently using):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Plug&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chr4/nginx.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;#34; Optionally, if you like Jinja template syntax highlighting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Plug&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;lepture/vim-jinja&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For further information and installation options, please consult the &lt;a href=&#34;https://github.com/chr4/nginx.vim/blob/master/README.md&#34;&gt;README&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Feedback and further improvements welcome! Just file an &lt;a href=&#34;https://github.com/chr4/nginx.vim/issues&#34;&gt;issue&lt;/a&gt; or &lt;a href=&#34;https://github.com/chr4/nginx.vim/pulls&#34;&gt;pull request&lt;/a&gt; on Github, or &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;contact me&lt;/a&gt;&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Cross-compile and link a static binary on macOS for Linux with cargo and rust</title>
      <link>https://chr4.org/posts/2017-03-15-cross-compile-and-link-a-static-binary-on-macos-for-linux-with-cargo-and-rust/</link>
      <pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2017-03-15-cross-compile-and-link-a-static-binary-on-macos-for-linux-with-cargo-and-rust/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;One Go feature which I&amp;rsquo;m using regularly is cross-compiling Go code to other platforms (usually from macOS to linux-amd64).&lt;/p&gt;
&lt;p&gt;In Go, this is a built-in feature that &amp;ldquo;just works&amp;rdquo;. The following command produces a statically linked ELF binary which can simply be copied and run on a Linux machine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ GOARCH&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;amd64 GOOS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;linux go build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ file api
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ELF 64-bit LSB executable, x86-64, version &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SYSV&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;, statically linked, not stripped
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;del&gt;Rust doesn&amp;rsquo;t have built-in support for such a feature.&lt;/del&gt;
&lt;em&gt;Edit: Rust core-commiter Steve Klabnik pointed out, that actually what I&amp;rsquo;m showing off here is the built-in Rust support :)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been looking for a while how to achieve this using Cargo and Rust. And (spoiler-alert!) I&amp;rsquo;ve found one, which is relatively simple to set up.&lt;/p&gt;
&lt;p&gt;Assuming you have &lt;a href=&#34;https://rustup.rs/&#34;&gt;rustup&lt;/a&gt; and &lt;a href=&#34;https://brew.sh&#34;&gt;Homebrew&lt;/a&gt; installed, it&amp;rsquo;s actually quite simple to setup cross-compiling on macOS!&lt;/p&gt;
&lt;p&gt;Start with installing the required target. In our case (Linux x86_64) this is &lt;code&gt;x86_64-unknown-linux-musl&lt;/code&gt;. The lightweight standard library &lt;a href=&#34;https://www.musl-libc.org/&#34;&gt;musl&lt;/a&gt; is able to produce statically linked libraries (contrary to the &lt;code&gt;x86_64-unknown-linux-gnu&lt;/code&gt; target, which uses &lt;a href=&#34;https://www.gnu.org/software/libc/&#34;&gt;GNU libc&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ rustup target add x86_64-unknown-linux-musl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What&amp;rsquo;s still missing is the linker. This was always the part where I go into trouble when trying this earlier. Finally, &lt;a href=&#34;http://grahamenos.com/rust-osx-linux-musl.html&#34;&gt;this blog post&lt;/a&gt; from Graham Enos guided me to a &lt;a href=&#34;https://github.com/FiloSottile/homebrew-musl-cross&#34;&gt;Homebrew tap&lt;/a&gt; by Filippo Valsorda, which provides a complete macOS to Linux cross-compile toolchain.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ brew install filosottile/musl-cross/musl-cross
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That was the heavy-lifting. Now just tell Cargo where to find the linker. You can place the following into your projects &lt;code&gt;.cargo/config&lt;/code&gt; or configure it globally in your &lt;code&gt;~/.cargo/config&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[target.x86_64-unknown-linux-musl]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;linker&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x86_64-linux-musl-gcc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Edit: As of rust-1.32.0, it might be required to add a symlink to make it work, which I came accross &lt;a href=&#34;https://aws.amazon.com/blogs/opensource/rust-runtime-for-aws-lambda/&#34;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ln -s /usr/local/bin/x86_64-linux-musl-gcc /usr/local/bin/musl-gcc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it! You can now cross-compile Linux binaries with Cargo!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo build --release --target x86_64-unknown-linux-musl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can find the resulting statically linked ELF binary in the &lt;code&gt;target/x86_64-unknown-linux-musl/release&lt;/code&gt; directory. This file can be copied and run on any Linux x86_64 machine, just like the cross-compiled Go binary!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ file target/x86_64-unknown-linux-musl/release/api
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ELF 64-bit LSB executable, x86-64, version &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;GNU/Linux&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;, statically linked, not stripped
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
        </description>
    </item>
    
    <item>
      <title>Writing An Interpreter In Rust (Part 2)</title>
      <link>https://chr4.org/posts/2016-12-17-writing-an-interpreter-in-rust-part-2/</link>
      <pubDate>Sat, 17 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-12-17-writing-an-interpreter-in-rust-part-2/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;&lt;em&gt;Note: This is a follow-up post to &lt;a href=&#34;https://chr4.org/posts/2016-12-09-writing-an-interpreter-in-rust/&#34;&gt;Writing An Interpreter In Rust&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Thanks for all your feedback, explainations and pull requests! I&amp;rsquo;m pretty overwhelmed by the feedback and I can confirm that the Rust community is very friendly and extremely helpful.&lt;/p&gt;
&lt;p&gt;In this post, I want to quickly review some of the changes to &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust&#34;&gt;my implementation of the Monkey interpreter&lt;/a&gt; I&amp;rsquo;ve made with your help. I&amp;rsquo;ve implemented a small benchmark (Disclaimer: I&amp;rsquo;ve just put &lt;code&gt;next_token()&lt;/code&gt; into a &lt;code&gt;#[bench]&lt;/code&gt;, I&amp;rsquo;m not sure whether that&amp;rsquo;s the best practise for this kind of tests), and the results are really impressive so far!&lt;/p&gt;
&lt;p&gt;First implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo bench
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test tests::bench_next_token ... bench: 30,614 ns/iter &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;+/- 2,177&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Current implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo bench
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test tests::bench_next_token ... bench: 3,863 ns/iter &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;+/- 627&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The new implementation is almost ten times faster than the first one! Let&amp;rsquo;s have a look at the changes:&lt;/p&gt;
&lt;h3 id=&#34;use-built-in-functions&#34;&gt;
  Use built-in functions
  &lt;a href=&#34;#use-built-in-functions&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The first (small) step was to replace hand-written custom functions with built-in Rust functions when possible. For example, the function &lt;code&gt;is_digit()&lt;/code&gt; can be replaced with Rust&amp;rsquo;s built-in &lt;code&gt;is_numeric()&lt;/code&gt;. Unfortunately, there&amp;rsquo;s no built-in function to check whether a character is either a letter or an underscore, but our custom function &lt;code&gt;is_letter()&lt;/code&gt; could at least make use of the built-in function &lt;code&gt;is_alphabetic()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;is_letter&lt;/span&gt;(ch: &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// This was the old statement:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// &amp;#39;a&amp;#39; &amp;lt;= ch &amp;amp;&amp;amp; ch &amp;lt;= &amp;#39;z&amp;#39; || &amp;#39;A&amp;#39; &amp;lt;= ch &amp;amp;&amp;amp; ch &amp;lt;= &amp;#39;Z&amp;#39; || ch == &amp;#39;_&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ch.is_alphabetic() &lt;span style=&#34;color:#f92672&#34;&gt;||&lt;/span&gt; ch &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;_&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In another &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/commit/d3f3b5d6e211a323d49f86e7039ea14857365513&#34;&gt;commit&lt;/a&gt;, a &lt;code&gt;loop&lt;/code&gt; could be improved using the built-in function &lt;code&gt;is_whitespace()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;improve-the-enum&#34;&gt;
  Improve the enum
  &lt;a href=&#34;#improve-the-enum&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Someone pointed out in one of the many &lt;a href=&#34;https://www.reddit.com/r/rust/comments/5hwx3d/writing_an_interpreter_in_rust/db3sf56/&#34;&gt;Reddit comments&lt;/a&gt; that Rust can store different types in a single enum. With this, it was possible to drop the &lt;code&gt;Token&lt;/code&gt; struct completely and merge &lt;code&gt;TokenType&lt;/code&gt; and &lt;code&gt;Token&lt;/code&gt; into a single enum. We can store &lt;code&gt;Ident&lt;/code&gt; and &lt;code&gt;Integer&lt;/code&gt; as a &lt;code&gt;String&lt;/code&gt;, while keeping the other elements plain and simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Debug, PartialEq)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Token&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Illegal,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    EndOfFile,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Literals are stored as strings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    Ident(String),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Integer(String),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// [...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/commit/1f3ff611e69a313dafa0b92a1a0c9e14dc6381e3&#34;&gt;this commit&lt;/a&gt; to review the whole changeset.&lt;/p&gt;
&lt;h3 id=&#34;custom-iterator&#34;&gt;
  Custom iterator
  &lt;a href=&#34;#custom-iterator&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The biggest change was made using Rust&amp;rsquo;s internal &lt;code&gt;Peekable&amp;lt;Chars&amp;gt;&lt;/code&gt; iterator instead of rolling our own. The following struct was the original &lt;code&gt;Lexer&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Lexer&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    input: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    position: &lt;span style=&#34;color:#66d9ef&#34;&gt;usize&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    read_position: &lt;span style=&#34;color:#66d9ef&#34;&gt;usize&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ch: Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/issues/10&#34;&gt;Two&lt;/a&gt; &lt;a href=&#34;https://www.reddit.com/r/rust/comments/5hwx3d/writing_an_interpreter_in_rust/db3oug1/&#34;&gt;people&lt;/a&gt; pointed out, that running a custom iterator in the way I did actually is not very efficient. With their help, and
&lt;a href=&#34;https://github.com/JayKickliter/monkey&#34;&gt;Jay Klickliter&amp;rsquo;s implementation&lt;/a&gt; as a reference, the struct could be reduced to a single &lt;code&gt;Peekable&amp;lt;Chars&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Lexer&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    input: &lt;span style=&#34;color:#a6e22e&#34;&gt;Peekable&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Chars&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See this &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/commit/11b3c07ec4a94ec146ca091c43894f3ab3cfe997&#34;&gt;commit&lt;/a&gt; for the complete adaption.&lt;/p&gt;
&lt;h3 id=&#34;thanks&#34;&gt;
  Thanks
  &lt;a href=&#34;#thanks&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Thanks again for all the valuable feedback I received via different channels! Your comments and &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/pulls&#34;&gt;pull requests&lt;/a&gt; are still welcome!&lt;/p&gt;
&lt;p&gt;The feedback and pull requests of the following four Rustaceans was especially helpful, so let me give you guys a special shoutout!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Taryn Hill&lt;/li&gt;
&lt;li&gt;Jay Kickliter&lt;/li&gt;
&lt;li&gt;Cameron Derwin&lt;/li&gt;
&lt;li&gt;Tohie&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find the &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust&#34;&gt;Writing An Interpreter In Rust&lt;/a&gt; project on Github and my contact details &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Writing An Interpreter In Rust</title>
      <link>https://chr4.org/posts/2016-12-09-writing-an-interpreter-in-rust/</link>
      <pubDate>Fri, 09 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-12-09-writing-an-interpreter-in-rust/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Last month, &lt;a href=&#34;http://thorstenball.com/&#34;&gt;Thorsten Ball&lt;/a&gt; released his first book: &lt;a href=&#34;https://interpreterbook.com/&#34;&gt;Writing An Interpreter In Go&lt;/a&gt;.
It&amp;rsquo;s an awesome book that teaches its readers how to write their own programming language, step by step. It comes bundled with the complete Go code, including tests.&lt;/p&gt;
&lt;p&gt;While reading it, I was looking for a challenge. I&amp;rsquo;m a huge fan of &lt;a href=&#34;https://www.rust-lang.org/&#34;&gt;Rust&lt;/a&gt;, a safe systems programming language by &lt;a href=&#34;https://mozilla.org/&#34;&gt;Mozilla&lt;/a&gt;, so I thought it might be a good exercise to port the Go implementation of the programming language &amp;ldquo;Monkey&amp;rdquo; to Rust.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of what Monkey code looks like (you can find more examples &lt;a href=&#34;https://interpreterbook.com/&#34;&gt;here&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Bind values to names with let statements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;let version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Monkey programming language&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let myArray &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let coolBooleanLiteral &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Use expressions to produce values
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;let awesomeValue &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;let arrayWithValues &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve finished implementing the first chapter of the book (the lexer), and decided to &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/&#34;&gt;share my work&lt;/a&gt;. The code is not very idiomatic yet, so I&amp;rsquo;d welcome pull requests to improve it.&lt;/p&gt;
&lt;p&gt;To checkout and run my version of the Monkey lexer, here&amp;rsquo;s how to do it (in case you do not have Rust or Cargo installed, you can get it via &lt;a href=&#34;https://rustup.rs/&#34;&gt;rustup&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git clone https://github.com/chr4/writing_an_interpreter_in_rust
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cd writing_an_interpreter_in_rust
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While I followed the original source code quite literally, there are a few things that can&amp;rsquo;t be done in Rust in the same way it&amp;rsquo;s implemented in Go. Furthermore, I tried to write idiomatic Rust code, which resulted in quite a few adaptions.&lt;/p&gt;
&lt;p&gt;Let me walk you through the challenges that I faced, and the resulting changes.&lt;/p&gt;
&lt;h3 id=&#34;porting-tokengo&#34;&gt;
  Porting token.go
  &lt;a href=&#34;#porting-tokengo&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The first step was to to migrate was the token constants. Here&amp;rsquo;s how it was implemented in Go:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ILLEGAL&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ILLEGAL&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;EOF&lt;/span&gt;     = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EOF&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Identifiers + literals
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;IDENT&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;IDENT&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// add, foobar, x, y, ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;INT&lt;/span&gt;   = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;INT&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;// 1343456
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// [...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This can be easily ported to Rust by using constants as well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ILLEGAL&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;TokenType&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ILLEGAL&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;EOF&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;TokenType&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EOF&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Identifiers + literals
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;IDENT&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;TokenType&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;IDENT&amp;#34;&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// add, foobar, x, y, ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INT&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;TokenType&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;INT&amp;#34;&lt;/span&gt;;     &lt;span style=&#34;color:#75715e&#34;&gt;// 1343456
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// [...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, there&amp;rsquo;s a more idiomatic way of handling this in Rust. Rust supports &lt;a href=&#34;https://doc.rust-lang.org/book/enums.html&#34;&gt;Enums&lt;/a&gt;. So let&amp;rsquo;s use &lt;code&gt;enum&lt;/code&gt; instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Debug, PartialEq)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;TokenType&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Illegal,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    EndOfFile,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Identifiers + literals
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    Ident,   &lt;span style=&#34;color:#75715e&#34;&gt;// add, foobar, x, y, ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    Integer, &lt;span style=&#34;color:#75715e&#34;&gt;// 1343456
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// [...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Note: For our implementation, the &lt;code&gt;Debug&lt;/code&gt; and &lt;code&gt;PartialEq&lt;/code&gt; traits are derived.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This looks way cleaner. Have a look at &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/commit/d0a23401ff81fd5bcd0a030f62338128a6324925&#34;&gt;this commit&lt;/a&gt; to see the full changeset necessary to migrate from constants to an Enum.&lt;/p&gt;
&lt;h3 id=&#34;porting-lexergo&#34;&gt;
  Porting lexer.go
  &lt;a href=&#34;#porting-lexergo&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The first problem I came across when porting the lexer was, that the Go version uses the integer &lt;code&gt;0&lt;/code&gt; (as a &lt;code&gt;byte&lt;/code&gt;) to indicate when the end of file is reached. Let&amp;rsquo;s have a look at the Go &lt;code&gt;readChar()&lt;/code&gt; function presented in the book:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Lexer&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;readChar&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;readPosition&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; len(&lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;readPosition&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;position&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;readPosition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;readPosition&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The caller then checks whether &lt;code&gt;l.ch&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;. If that&amp;rsquo;s the case, it generates an EOF token:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;l&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;=&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// [...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tok&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Literal&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tok&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Type&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;token&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// [...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;del&gt;In Rust, a &lt;code&gt;char&lt;/code&gt; can&amp;rsquo;t take an integer value.&lt;/del&gt; It&amp;rsquo;s more idiomatic to use an &lt;code&gt;Option&amp;lt;char&amp;gt;&lt;/code&gt; and return &lt;code&gt;None&lt;/code&gt; in case the end of the file is reached. It might be even more idiomatic to return a &lt;code&gt;Result&lt;/code&gt; with an EOF error, but choosing &lt;code&gt;Option&amp;lt;char&amp;gt;&lt;/code&gt; seemed to be the quicker solution for now.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: &lt;a href=&#34;https://www.reddit.com/r/rust/comments/5hwx3d/writing_an_interpreter_in_rust/db6qhwf/&#34;&gt;A Reddit user pointed out&lt;/a&gt; that this statement is not true. You can assign an integer to a &lt;code&gt;char&lt;/code&gt; casting it using the following syntax: &lt;code&gt;let character = 97 as char;&lt;/code&gt;. Thanks!&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt; self.ch {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Some(ch &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;=&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;.]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Handle EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    None &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tok.literal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; String::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tok.token_type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; token::TokenType::EndOfFile;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The full changeset is implemented &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/commit/f0fa65575b650fd22fa39365f5c7c9f6f119fe16&#34;&gt;this commit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Furthermore, I&amp;rsquo;ve &lt;a href=&#34;https://github.com/chr4/writing_an_interpreter_in_rust/commit/2c407a9f2e84e09cb502490e86fc1b7dfae434d8&#34;&gt;changed&lt;/a&gt; the &lt;code&gt;peekChar()&lt;/code&gt; function to &lt;code&gt;peek_char_eq(ch: char) -&amp;gt; bool&lt;/code&gt;, which seemed like a quick solution for not having to return another &lt;code&gt;Option&amp;lt;char&amp;gt;&lt;/code&gt; type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;peek_char_eq&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self, ch: &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Return false on EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; self.read_position &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; self.input.len() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; peek_ch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self.input
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .chars()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .nth(self.read_position)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    peek_ch &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; ch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;porting-the-repl&#34;&gt;
  Porting the REPL
  &lt;a href=&#34;#porting-the-repl&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Porting the REPL was pretty straightforward. Read a line from STDIN and then run the lexer on it.
The only pitfall here is that STDOUT needs to be flushed manually so the PROMPT &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; is actually displayed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; std::io::{self, BufRead, Write};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mod&lt;/span&gt; lexer;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mod&lt;/span&gt; token;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; stdin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; io::stdin();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;loop&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Stdout needs to be flushed, due to missing newline
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        print!(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;gt;&amp;gt; &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        io::stdout().flush().expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error flushing stdout&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; line &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; String::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stdin.lock().read_line(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; line).expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error reading from stdin&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; lexer &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; lexer::Lexer::new(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; line);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;loop&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; tok &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; lexer.next_token();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            println!(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{:?}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, tok);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; tok.token_type &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; token::TokenType::EndOfFile {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;running-the-tests-and-repl&#34;&gt;
  Running the tests and REPL
  &lt;a href=&#34;#running-the-tests-and-repl&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;This is the exiting part. Let&amp;rsquo;s see whether the implementation (still) works!&lt;/p&gt;
&lt;p&gt;Run the tests:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Finished debug &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;unoptimized + debuginfo&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; target&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; in 0.1 secs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Running target/debug/deps/writing_an_interpreter_in_rust-e35a8839d5e6ef77
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;running &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test lexer::new_token_test ... ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test token::lookup_ident_test ... ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test lexer::next_token_test ... ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test result: ok. &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; passed; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; failed; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; ignored; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; measured
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Running target/debug/deps/writing_an_interpreter_in_rust-0dfac4ec669be969
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;running &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test token::lookup_ident_test ... ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test lexer::new_token_test ... ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test lexer::next_token_test ... ok
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test result: ok. &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; passed; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; failed; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; ignored; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; measured
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Doc-tests writing_an_interpreter_in_rust
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;running &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test result: ok. &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; passed; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; failed; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; ignored; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; measured
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;BAM! That worked. Now let&amp;rsquo;s try the REPL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Finished debug &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;unoptimized + debuginfo&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; target&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; in 0.0 secs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Running &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;target/debug/writing_an_interpreter_in_rust&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt; let add &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; fn&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;x, y&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; x + y; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Let, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;let&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Ident, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;add&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Assign, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;=&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Function, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fn&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: LeftParenthesis, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Ident, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Comma, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Ident, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: RightParenthesis, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: LeftBrace, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Ident, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Plus, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Ident, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Semicolon, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: RightBrace, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: Semicolon, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Token &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; token_type: EndOfFile, literal: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it! This is my current implementation of chapter 1 of &lt;a href=&#34;https://interpreterbook.com/&#34;&gt;Writing An Interpreter In Go&lt;/a&gt;!
As mentioned, I&amp;rsquo;m still fairly new to Rust, and I&amp;rsquo;d welcome pull requests or hints on howto make our Monkey interpreter in Rust more idiomatic. Feedback welcome!&lt;/p&gt;
&lt;p&gt;You can find my contact details &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: There&amp;rsquo;s a &lt;a href=&#34;https://chr4.org/posts/2016-12-17-writing-an-interpreter-in-rust-part-2/&#34;&gt;follow up post&lt;/a&gt; reviewing changes I&amp;rsquo;ve made with the help of the Rust community. They improved the overall performance by the factor 10!&lt;/em&gt;&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Use and automate letsencrypt certificates (ACME) in an high availability environment</title>
      <link>https://chr4.org/posts/2016-11-14-use-letsencrypt-acme-in-an-high-availability-environment/</link>
      <pubDate>Mon, 14 Nov 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-11-14-use-letsencrypt-acme-in-an-high-availability-environment/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Mozilla launched a &amp;ldquo;free, automated and open&amp;rdquo; certificate authority called &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Let&amp;rsquo;s encrypt&lt;/a&gt;. As the name suggests, it provides free certificates trusted by all (major) browsers and operating systems. I&amp;rsquo;m using it heavily (on this blog, for example).&lt;/p&gt;
&lt;p&gt;This blog post shows how &lt;a href=&#34;https://syncthing.net&#34;&gt;Syncthing&lt;/a&gt; can be used to deploy letsencrypt certificates in an environment with multiple servers (e.g. in a round-robin scenario) without adding a single-point-of-failure.&lt;/p&gt;
&lt;h2 id=&#34;acme&#34;&gt;
  ACME
  &lt;a href=&#34;#acme&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s encrypt automated the process of requesting and authenticating a certificate using a protocol called ACME. The client requesting a new certificate uses a &lt;code&gt;.well-known&lt;/code&gt; path on its webserver where it places a challenge, and Let&amp;rsquo;s encrypt retrieves this challenge for authentification.&lt;/p&gt;
&lt;p&gt;The actual process is a little more complicated, though. If you want to know how it works in detail, I recommend Let&amp;rsquo;s encrypt&amp;rsquo;s excellent &lt;a href=&#34;https://letsencrypt.org/how-it-works/&#34;&gt;ACME documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-problem-in-high-availability-setups&#34;&gt;
  The problem in high availability setups
  &lt;a href=&#34;#the-problem-in-high-availability-setups&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When using multiple servers for SSL termination (e.g. in the load-balancing scenario described in the picture below, where SSL termination is handled by the nginx instances) each one requires a certificate for the domain(s) they are serving.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;ACME high availablilty setup with HAproxy and nginx&#34; src=&#34;https://chr4.org/img/acme_ha_setup.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;In a setup that e.g. uses a round-robin, we can&amp;rsquo;t guarantee that the incoming request for the ACME challenge ends up on the server actually requesting the certificate. Furthermore, each server needs to request (and renew) its own certificates.&lt;/p&gt;
&lt;p&gt;The cleanest solution I found for this problem is to share the &lt;code&gt;.well-known&lt;/code&gt; challenge directory (and maybe even the certificate) between multiple servers.&lt;/p&gt;
&lt;h2 id=&#34;syncthing-to-the-rescue&#34;&gt;
  Syncthing to the rescue!
  &lt;a href=&#34;#syncthing-to-the-rescue&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The tool I found best to syncronize those directories was &lt;a href=&#34;https://syncthing.net/&#34;&gt;Syncthing&lt;/a&gt;.
It is one of the most exiting tools for file-sharing, as it is completely decentralized and works without any central server (but can be configured to use one, if required), is fully peer-to-peer, open-soure, written in &lt;a href=&#34;https://golang.org/&#34;&gt;Go&lt;/a&gt; and cross-platform.&lt;/p&gt;
&lt;p&gt;Syncthing fulfills all items on my wishlist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Traffic between the instances is encrypted&lt;/li&gt;
&lt;li&gt;The setup is automatically deployable&lt;/li&gt;
&lt;li&gt;Instances can be easily added or removed&lt;/li&gt;
&lt;li&gt;No single-point-of-failure (all nodes connect to each other, syncronizing the same directory between all machines)&lt;/li&gt;
&lt;li&gt;No additional services required&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I chose it to syncronize the &lt;code&gt;/etc/nginx/certs&lt;/code&gt; directory. It shares the dhparams, SSL certificates and the ACME challenges between all nginx instances. Here&amp;rsquo;s what the shared directory looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ tree -a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── .stfolder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── acme
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── .well-known
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       └── acme-challenge
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│           ├── 8xdoeH5OLPUij4xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│           ├── cWaLNpzt_8v--xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│           └── _wsvWIOyvP-45vt-xxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── dhparam.pem
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── www.example.com.crt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── www.example.com.key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; directories, &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;implementation&#34;&gt;
  Implementation
  &lt;a href=&#34;#implementation&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re using &lt;a href=&#34;https://www.chef.io/&#34;&gt;Chef&lt;/a&gt; to automate our infrastructure at &lt;a href=&#34;https://flinc.org&#34;&gt;flinc&lt;/a&gt;, but the process should be easily adaptable to a automation tool of your choice.&lt;/p&gt;
&lt;p&gt;Syncthing is easily deployed, as there&amp;rsquo;s an &lt;a href=&#34;http://apt.syncthing.net&#34;&gt;official repository&lt;/a&gt; available:&lt;/p&gt;
&lt;h3 id=&#34;install-syncthing&#34;&gt;
  Install Syncthing
  &lt;a href=&#34;#install-syncthing&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use the official Syncthing apt repositories&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt_repository &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syncthing-release&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  uri &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;http://apt.syncthing.net&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  distribution &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syncthing&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  components &lt;span style=&#34;color:#e6db74&#34;&gt;%w(release)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  key &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://syncthing.net/release-key.txt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syncthing&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;set-up-systemd-service&#34;&gt;
  Set up systemd service
  &lt;a href=&#34;#set-up-systemd-service&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;systemd.service&lt;/code&gt; is quickly crafted from the &lt;a href=&#34;https://github.com/syncthing/syncthing/blob/master/etc/linux-systemd/system/syncthing%40.service&#34;&gt;provided example&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Description&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Syncthing - Open Source Continuous File Synchronization for %I&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Documentation&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;man:syncthing(1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;After&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;network.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;User&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;ExecStart&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/usr/bin/syncthing -no-browser -no-restart -logflags=0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Restart&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;on-failure&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;SuccessExitStatus&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;3 4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;RestartForceExitStatus&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;3 4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;WantedBy&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;generate-syncthing-configuration-and-keys&#34;&gt;
  Generate Syncthing configuration and keys
  &lt;a href=&#34;#generate-syncthing-configuration-and-keys&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We want to centrally manage our instances, so Syncthing certificates are stored centrally in Chef&amp;rsquo;s encrypted data bags, alongside their device IDs and API keys. Here&amp;rsquo;s how to generate and extract everything that&amp;rsquo;s required:&lt;/p&gt;
&lt;p&gt;First, generate a new key-pair and save the device ID and API key for each node:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NODE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1.nginx.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;syncthing --generate&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$NODE |grep ID |awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{ print $5 }&amp;#39;&lt;/span&gt; &amp;gt; $NODE/device_id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;grep apikey $NODE/config.xml |cut -d&lt;span style=&#34;color:#ae81ff&#34;&gt;\&amp;gt;&lt;/span&gt; -f2 |cut -d&lt;span style=&#34;color:#ae81ff&#34;&gt;\&amp;lt;&lt;/span&gt; -f1 &amp;gt; $NODE/apikey
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm $NODE/config.xml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The resulting &lt;code&gt;key.pem&lt;/code&gt; and &lt;code&gt;cert.pem&lt;/code&gt; will then be deployed into the &lt;code&gt;.config/syncthing&lt;/code&gt; directory on the target machine.&lt;/p&gt;
&lt;p&gt;After using Syncthing&amp;rsquo;s web-interface to configure the share, the resulting &lt;code&gt;config.xml&lt;/code&gt; was then used to craft the following ERB template:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;configuration&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;version=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;16&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- This is our shared folder. Scan it every 5s, so updates are syncronized quickly --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;folder&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vm623-hxlsp&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;label=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;letsencrypt&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/etc/nginx/certs/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;readwrite&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;rescanIntervalS=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;5&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ignorePerms=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;autoNormalize=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Share the folder between all nodes --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;% @nodes.each do |name, config| %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;device&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;%= config[&amp;#39;id&amp;#39;] %&amp;gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;lt;/device&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;% end %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Share settings. Default settings, with simple versioning --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;minDiskFreePct&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/minDiskFreePct&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;versioning&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;simple&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;key=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;keep&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;val=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/versioning&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;copiers&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/copiers&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;pullers&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/pullers&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;hashers&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/hashers&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;order&amp;gt;&lt;/span&gt;random&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/order&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;ignoreDelete&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/ignoreDelete&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;scanProgressIntervalS&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/scanProgressIntervalS&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;pullerSleepS&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/pullerSleepS&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;pullerPauseS&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/pullerPauseS&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;maxConflicts&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/maxConflicts&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;disableSparseFiles&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/disableSparseFiles&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;disableTempIndexes&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/disableTempIndexes&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/folder&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Make sure all nodes are connected to one another --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;% @nodes.each do |name, config| %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;device&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;id=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;%= config[&amp;#39;id&amp;#39;] %&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;%= name %&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;compression=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;introducer=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;address&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;%= config[&amp;#39;address&amp;#39;] %&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/address&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/device&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;% end %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;gui&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;enabled=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tls=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;debugging=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;address&amp;gt;&lt;/span&gt;127.0.0.1:8384&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/address&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;apikey&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;%= @apikey %&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/apikey&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;theme&amp;gt;&lt;/span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/theme&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/gui&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;options&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;listenAddress&amp;gt;&lt;/span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/listenAddress&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Disable announcement, as we&amp;#39;re automatically adding all servers above --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;globalAnnounceServer&amp;gt;&lt;/span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/globalAnnounceServer&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;globalAnnounceEnabled&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/globalAnnounceEnabled&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;localAnnounceEnabled&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/localAnnounceEnabled&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;localAnnouncePort&amp;gt;&lt;/span&gt;21027&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/localAnnouncePort&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;localAnnounceMCAddr&amp;gt;&lt;/span&gt;[ff12::8384]:21027&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/localAnnounceMCAddr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;maxSendKbps&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/maxSendKbps&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;maxRecvKbps&amp;gt;&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/maxRecvKbps&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;reconnectionIntervalS&amp;gt;&lt;/span&gt;60&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/reconnectionIntervalS&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;relaysEnabled&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/relaysEnabled&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;relayReconnectIntervalM&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/relayReconnectIntervalM&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;startBrowser&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/startBrowser&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;natEnabled&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/natEnabled&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;natLeaseMinutes&amp;gt;&lt;/span&gt;60&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/natLeaseMinutes&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;natRenewalMinutes&amp;gt;&lt;/span&gt;30&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/natRenewalMinutes&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;natTimeoutSeconds&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/natTimeoutSeconds&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;urAccepted&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/urAccepted&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;urUniqueID&amp;gt;&amp;lt;/urUniqueID&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;urURL&amp;gt;&lt;/span&gt;https://data.syncthing.net/newdata&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/urURL&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;urPostInsecurely&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/urPostInsecurely&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;urInitialDelayS&amp;gt;&lt;/span&gt;1800&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/urInitialDelayS&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;restartOnWakeup&amp;gt;&lt;/span&gt;true&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/restartOnWakeup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;autoUpgradeIntervalH&amp;gt;&lt;/span&gt;12&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/autoUpgradeIntervalH&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;keepTemporariesH&amp;gt;&lt;/span&gt;24&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/keepTemporariesH&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;cacheIgnoredFiles&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/cacheIgnoredFiles&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;progressUpdateIntervalS&amp;gt;&lt;/span&gt;5&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/progressUpdateIntervalS&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;symlinksEnabled&amp;gt;&lt;/span&gt;true&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/symlinksEnabled&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;limitBandwidthInLan&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/limitBandwidthInLan&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;minHomeDiskFreePct&amp;gt;&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/minHomeDiskFreePct&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;releasesURL&amp;gt;&lt;/span&gt;https://upgrades.syncthing.net/meta.json&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/releasesURL&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;overwriteRemoteDeviceNamesOnConnect&amp;gt;&lt;/span&gt;false&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/overwriteRemoteDeviceNamesOnConnect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;tempIndexMinBlocks&amp;gt;&lt;/span&gt;10&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/tempIndexMinBlocks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/options&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;deploy-syncthing-configuration&#34;&gt;
  Deploy Syncthing configuration
  &lt;a href=&#34;#deploy-syncthing-configuration&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s how we deploy Syncthing keys and configuration from encrypted data bags to the nginx nodes (Note: It probably makes sense to use run Syncthing as the same user as nginx, as Syncthing needs to deploy a key that should only be readable by nginx and noone else):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Set this to the home directory of your user (probably the same user running nginx)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;nginx&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Populate node information from data bag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node_config &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node_list&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;each &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;node_name&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  config &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Chef&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;EncryptedDataBagItem&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;load(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syncthing&amp;#39;&lt;/span&gt;, node_name, data_bag_secret)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  node_config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;node_name&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  node_config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;node_name&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;device_id&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Set address to &amp;#34;dynamic&amp;#34; if it&amp;#39;s ourselves&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  node_config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;node_name&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;address&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; node&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;name &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; node_name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;dynamic&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tcp://&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node_name&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;domain&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;:22000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Deploy Syncthing certificate (from data bag)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;local_config &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Chef&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;EncryptedDataBagItem&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;load(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syncthing&amp;#39;&lt;/span&gt;, node&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;name, data_bag_secret)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%w(key cert)&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;each &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;k&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Show an error message if key couldn&amp;#39;t be retrieved&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;Chef&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fatal(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;k&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.pem is empty!&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;unless&lt;/span&gt; local_config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;k&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  file &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/home/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;user&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.config/syncthing/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;k&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.pem&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mode &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;o600
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    owner  user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    group  user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    content local_config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;k&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Deploy Syncthing configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;template &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/home/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;user&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/data/.config/syncthing/config.xml&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mode   &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;o600
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  owner  user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  group  user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  source &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syncthing.config.xml.erb&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  variables &lt;span style=&#34;color:#e6db74&#34;&gt;nodes&lt;/span&gt;: node_config, &lt;span style=&#34;color:#e6db74&#34;&gt;apikey&lt;/span&gt;: local_config&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;apikey&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Restart Syncthing upon configuration/ key changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;syncthing@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;user&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  subscribes &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;template[/home/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;user&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.config/syncthing/config.xml]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  subscribes &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;template[/home/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;user&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.config/syncthing/key.pem]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  subscribes &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;template[/home/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;user&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.config/syncthing/cert.pem]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;:enable&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:start&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;restrict-syncthing-to-private-backnet&#34;&gt;
  Restrict Syncthing to private backnet
  &lt;a href=&#34;#restrict-syncthing-to-private-backnet&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We have a dedicated backnet for all environments. Syncthing should only be allowed on this specific backnet (in our case &lt;code&gt;eth1&lt;/code&gt;).
I&amp;rsquo;m using the &lt;a href=&#34;https://supermarket.chef.io/cookbooks/iptables-ng&#34;&gt;iptables-ng cookbook&lt;/a&gt; to manage iptables.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Allow Syncthing in backnet only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iptables_ng_rule &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;50-syncthing&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  rule &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-i eth1 --protocol tcp --dport 22000 --match state --state NEW --jump ACCEPT&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-i eth1 --protocol udp --dport 21025 --match state --state NEW --jump ACCEPT&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;get-the-certificates-and-automate-renewal&#34;&gt;
  Get the certificates and automate renewal
  &lt;a href=&#34;#get-the-certificates-and-automate-renewal&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;To actually request the certificate, the &lt;a href=&#34;https://github.com/schubergphilis/chef-acme&#34;&gt;acme cookbook&lt;/a&gt; got you covered, which uses the ruby ACME library &lt;a href=&#34;https://github.com/unixcharles/acme-client&#34;&gt;acme-client&lt;/a&gt; under the hood.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Get some bonus points for generating your own Diffie-Hellmann parameters:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;execute &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;openssl dhparam -out /etc/nginx/certs/dhparam.pem 2048&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  creates &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/certs/dhparam.pem&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;service[nginx]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Make sure acme-client gem is installed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_recipe &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;letsencrypt::default&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Create a webroot for acme challenges&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;directory &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/certs/acme&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  owner user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  group user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Deploy nginx site to answer ACME challenges&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;template &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/conf.d/letsencrypt.example.com.conf&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mode      &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;o644
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  source   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;letsencrypt.nginx.erb&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;service[nginx]&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:immediately&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  not_if   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;test -f /etc/nginx/certs/www.example.com.crt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;letsencrypt_certificate &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;www.example.com&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  alt_names &lt;span style=&#34;color:#e6db74&#34;&gt;%w(example.com)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  owner     user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  group     user
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fullchain &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/certs/www.example.com.crt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  key       &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/certs/www.example.com.key&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  method    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;http&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  wwwroot   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/certs/acme&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies  &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;service[nginx]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Remove temporary letsencrypt site&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/nginx/conf.d/letsencrypt.example.com.conf&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;service[nginx]&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:immediately&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#e6db74&#34;&gt;:delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The temporary &lt;code&gt;letsencrypt.nginx.erb&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# This is for HAproxy with proxy_protocol, adapt if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;::&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;:80 ipv6only&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;off proxy_protocol;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Serve well-known path for letsencrypt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location /.well-known/acme-challenge &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        root /etc/nginx/certs/acme;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        default_type text/plain;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also make sure to include something like this to your actual nginx site configuration, so challenges of automatic renewals can be answered:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# This is for HAproxy with proxy_protocol, adapt if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;::&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;:80 ipv6only&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;off proxy_protocol;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Use remote_addr from proxy_protocol&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    real_ip_header proxy_protocol;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set_real_ip_from 10.13.37.0/24;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Serve well-known path for letsencrypt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location /.well-known/acme-challenge &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        root /etc/nginx/certs/acme;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        default_type text/plain;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    location / &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;301&lt;/span&gt; https://&amp;lt;%&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; @domain %&amp;gt;$request_uri;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;server &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# This is for HAproxy with proxy_protocol, adapt if necessary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    listen &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;::&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;:443 ssl http2 ipv6only&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;off proxy_protocol;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;wrap-up&#34;&gt;
  Wrap up
  &lt;a href=&#34;#wrap-up&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s it! We can now automatically request and renew free Let&amp;rsquo;s encrypt SSL certificates in our high availability setup! Syncthing will happily keep the certificates and challenges in sync, even if some nodes go down. More nodes can be added by simply adding the credentials to the &lt;code&gt;syncthing&lt;/code&gt; data bag, and the configuration of all nodes will adapt automatically.&lt;/p&gt;
&lt;p&gt;If you have some feedback, feel free to &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;contact me&lt;/a&gt;. I&amp;rsquo;m also available for hire as a freelancer.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>pg-cert-check: A tool to monitor postgresql database SSL certificates</title>
      <link>https://chr4.org/posts/2016-10-24-pg-cert-check-a-tool-to-monitor-postgresql-database-ssl-certificates/</link>
      <pubDate>Mon, 24 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-10-24-pg-cert-check-a-tool-to-monitor-postgresql-database-ssl-certificates/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I recently wrote &lt;a href=&#34;https://github.com/chr4/pg-check-cert&#34;&gt;pg-check-cert&lt;/a&gt;, a small tool to check whether a postgresql server&amp;rsquo;s SSL certificate is about to expire. It was featured in &lt;a href=&#34;http://postgresweekly.com/issues/164&#34;&gt;PostgreSQL Weekly Issue 164&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This script connects to a postgresql instance, checks the certificate and displays the amount of days left before it expires.
It&amp;rsquo;s intended to be used for monitoring your postgresql certificates, using a monitoring tool like &lt;a href=&#34;http://www.zabbix.com/&#34;&gt;Zabbix&lt;/a&gt; or &lt;a href=&#34;https://www.nagios.org/&#34;&gt;Nagios&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;why-openssl-is-not-enough&#34;&gt;
  Why openssl is not enough
  &lt;a href=&#34;#why-openssl-is-not-enough&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I used to monitor my postgresql certificates using &lt;code&gt;openssl&lt;/code&gt;. Unfortunately, the &lt;code&gt;openssl s_client&lt;/code&gt; option does not support the postgresql handshake, and can therefore only look at the &lt;code&gt;.crt&lt;/code&gt; file to monitor the expiration date.
As postgresql needs to be restarted after the &lt;code&gt;.crt&lt;/code&gt; file was replaced, the actual file might be updated, but postgresql is still using the old certificate in-memory, until the server is restarted (as of postgresql-9.5, &lt;code&gt;reload&lt;/code&gt; is not sufficient to read in the new certificate).&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;
  Installation
  &lt;a href=&#34;#installation&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Precompiled versions (linux-amd64, osx-amd64) are available on the &lt;a href=&#34;https://github.com/chr4/pg-check-cert/releases&#34;&gt;release page&lt;/a&gt;.
Download the file, extract it and move it to e.g. &lt;code&gt;/usr/local/bin&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;build&#34;&gt;
  Build
  &lt;a href=&#34;#build&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go build -o pg-check-cert *.go
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;usage&#34;&gt;
  Usage
  &lt;a href=&#34;#usage&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pg-check-cert localhost:5432
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;thanks&#34;&gt;
  Thanks
  &lt;a href=&#34;#thanks&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/thusoy/postgres-mitm/blob/master/postgres_get_server_cert.py&#34;&gt;thusoy/postgres-migm&lt;/a&gt; for the inspiration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;buf.go&lt;/code&gt; and &lt;code&gt;conn.go&lt;/code&gt; are taken from &lt;a href=&#34;https://github.com/lib/pq/&#34;&gt;lib/pq&lt;/a&gt;, see copyright notice in the respective files.&lt;/li&gt;
&lt;/ul&gt;
        
        </description>
    </item>
    
    <item>
      <title>entren - I just stumbled upon a traffic analyser I wrote in C when I was like 17</title>
      <link>https://chr4.org/posts/2016-08-03-entren-i-just-stumbled-upon-a-traffic-analyser-i-wrote-in-c-when-i-was-like-17/</link>
      <pubDate>Wed, 03 Aug 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-08-03-entren-i-just-stumbled-upon-a-traffic-analyser-i-wrote-in-c-when-i-was-like-17/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Around the year 2000-2002 (back in the days when &lt;a href=&#34;https://www.snort.org/&#34;&gt;Snort&lt;/a&gt; was still super young (and I haven&amp;rsquo;t heard of it yet), I decided to write a small network traffic analyser, which could serve as a &amp;ldquo;poor man&amp;rsquo;s intrusion detection system&amp;rdquo;. It was basically a C daemon configured with a &lt;a href=&#34;https://en.wikipedia.org/wiki/INI_file&#34;&gt;ini&lt;/a&gt;-like configuration file, watching for network events.&lt;/p&gt;
&lt;p&gt;If I remember correctly, I wanted a way to detect the (then pretty new and fancy) &lt;a href=&#34;https://nmap.org/&#34;&gt;nmap&lt;/a&gt; stealth scan mechanisms (like half open, xmas, etc), and counter them with alerts and on demand firewall rules.&lt;/p&gt;
&lt;p&gt;I just stumbled upon the old C source on my &lt;del&gt;harddrive&lt;/del&gt; ssd on my macOS machine and tried &lt;code&gt;make&lt;/code&gt; just to see what would happen. Back then I operated some FreeBSD/ OpenBSD and Linux servers, and I didn&amp;rsquo;t really expect much to happen besides tons of errors.&lt;/p&gt;
&lt;p&gt;As it apparently still compiles and runs today (even on macOS), I&amp;rsquo;ve decided to upload the &lt;a href=&#34;https://github.com/chr4/entren&#34;&gt;code to Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Checkout the &lt;a href=&#34;https://github.com/chr4/entren/blob/master/entren.conf.sample&#34;&gt;configuration examples&lt;/a&gt;. Detecting the various nmap portscan types still works (see configuration below)!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# rule to detect tcp connect/half open portscans&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[tcp]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# tcp connect / half open&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tcp_flags&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;syn !ack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# after 20 packages in 60 seconds a scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;20
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    time  = 60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# we need the portscan mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;portscan_mode&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# possible actions against the attacker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# (create a new firewall rule to block his ip for 30 seconds)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command1     = ipfw add deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    delay        = 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command2     = ipfw del deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# the string for syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;logstr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;portscan from: %sip [tcp connect/half open]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# rule to detect &amp;#34;null&amp;#34; scans&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[tcp]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# null scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tcp_flags&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;!syn !ack !psh !rst !urg !fin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# after 10 packages in 60 seconds a scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    time  = 60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# we need the portscan mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;portscan_mode&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# possible actions against the attacker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# (create a new firewall rule to block his ip for 30 seconds)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command1     = ipfw add deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    delay        = 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command2     = ipfw del deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# the string for syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;logstr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;portscan from: %sip [null scan]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# rule to detect &amp;#34;xmas&amp;#34; portscans&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[tcp]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# nmap xmas scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tcp_flags&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;fin urg psh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# after 10 packages in 60 seconds a scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    time  = 60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# we need the portscan mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;portscan_mode&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# possible actions against the attacker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# (create a new firewall rule to block his ip for 30 seconds)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command1     = ipfw add deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    delay        = 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command2     = ipfw del deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# the string for syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;logstr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;portscan from: %sip [xmas scan]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# rule to detect fin portscans&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[tcp]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# fin scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tcp_flags&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;!syn !ack !rst !urg !psh fin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# after 50 packages in 30 seconds a scan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;50
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    time  = 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# we need the portscan mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;portscan_mode&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# possible actions against the attacker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# (create a new firewall rule to block his ip for 30 seconds)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command1     = ipfw add deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    delay        = 30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#    command2     = ipfw del deny ip from %sip to any&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#############################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# string for syslog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;logstr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;portscan from: %sip [fin]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
        </description>
    </item>
    
    <item>
      <title>Running rabbitmq on hosts with numeric hostnames</title>
      <link>https://chr4.org/posts/2016-06-08-running-rabbitmq-on-hosts-with-numeric-hostnames/</link>
      <pubDate>Wed, 08 Jun 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-06-08-running-rabbitmq-on-hosts-with-numeric-hostnames/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I encountered the following issue when running RabbitMQ on a host with the hostname &lt;code&gt;1.rabbitmq.staging&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sudo apt-get install rabbitmq-server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Job &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; rabbitmq-server.service failed because the control process exited with error code. See &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;systemctl status rabbitmq-server.service&amp;#34;&lt;/span&gt; and &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;journalctl -xe&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; details.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;invoke-rc.d: initscript rabbitmq-server, action &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt; failed.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dpkg: error processing package rabbitmq-server &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;--configure&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; subprocess installed post-installation script returned error exit status &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;dmesg shows a segfault happened:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ dmesg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; 7891.350558&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; async_4&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;29072&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;: segfault at &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; ip 000000000055ff71 sp 00007f413997de40 error &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt; in beam.smp&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;400000+234000&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When manually starting &lt;code&gt;rabbitmq-server&lt;/code&gt;, I get the following message:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ rabbitmq-server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ERROR: epmd error &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; host &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;: badarg &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;unknown POSIX error&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-bug&#34;&gt;
  The Bug
  &lt;a href=&#34;#the-bug&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I found a &lt;a href=&#34;https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/1529033&#34;&gt;bug report&lt;/a&gt; for the Ubuntu package &lt;code&gt;rabbitmq-server&lt;/code&gt;, but as of today has no replies.
Apparently, it&amp;rsquo;s not possible to run rabbitmq-server on a host that has a numeric hostname. I assume this is a bug in either Erlang or RabbitMQ and will eventually be fixed, hopefully.&lt;/p&gt;
&lt;p&gt;RabbitMQ interprets everything after the first &lt;code&gt;.&lt;/code&gt; in the hostname as domain, and therefore comes to the conclusion &lt;code&gt;1&lt;/code&gt; is the full hostname.&lt;/p&gt;
&lt;h2 id=&#34;the-workaround&#34;&gt;
  The Workaround
  &lt;a href=&#34;#the-workaround&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The following workaround fixed it for me.&lt;/p&gt;
&lt;p&gt;On Ubuntu, I added the following to &lt;code&gt;/etc/rabbitmq/rabbitmq-env.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# RabbitMQ cannot cope with hostnames containing only numbers.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# &amp;#34;1.rabbitmq.env&amp;#34; will be interpreted as hostname &amp;#34;1&amp;#34;, and then fail.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# The workaround for this is manually adapting the HOSTNAME variable in rabbitmq-env.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# and making sure that it&amp;#39;s resolvable in /etc/hosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HOSTNAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;rabbitmq
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Make sure to also add an entry for &lt;code&gt;rabbitmq&lt;/code&gt; to your &lt;code&gt;/etc/hosts&lt;/code&gt; file, otherwise &lt;code&gt;rabbitmq-server&lt;/code&gt; will complain that it&amp;rsquo;s not resolvable:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Resolve rabbitmq to 127.0.2.2, so we&amp;#39;re not interferring with other localhost hostnames
127.0.2.2 rabbitmq
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After that, starting &lt;code&gt;rabbitmq-server&lt;/code&gt; works like a charm.&lt;/p&gt;
&lt;p&gt;Note: Modifying &lt;code&gt;HOSTNAME&lt;/code&gt; like this might cause other issues. I didn&amp;rsquo;t test it on clustered setups yet. &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;Let me know&lt;/a&gt; if you know more!&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Homebrew betrayed us all to Google</title>
      <link>https://chr4.org/posts/2016-04-26-homebrew-betrayed-us-all-to-google/</link>
      <pubDate>Tue, 26 Apr 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-04-26-homebrew-betrayed-us-all-to-google/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;&lt;a href=&#34;http://brew.sh&#34;&gt;Homebrew&lt;/a&gt; is arguably the best package manager for OSX around. It&amp;rsquo;s a great project, I&amp;rsquo;ve been using it for years, and it&amp;rsquo;s doing what it&amp;rsquo;s supposed to in a very clean manner.
Unfortunately, the &lt;a href=&#34;https://github.com/Homebrew/brew/blob/master/docs/Analytics.md&#34;&gt;team decided to track&lt;/a&gt; the behaviour of its users via Google Analytics.&lt;/p&gt;
&lt;p&gt;This is bad.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open Source is about trust. Trust is underminded by things like tracking.&lt;/li&gt;
&lt;li&gt;Do not track your users. In the rare case you &lt;em&gt;really&lt;/em&gt; need anonymous data, ask your users first.&lt;/li&gt;
&lt;li&gt;Never use Google products (or any other &amp;ldquo;big data&amp;rdquo; company that relies on making money out of the data you provide) to track your users.&lt;/li&gt;
&lt;li&gt;Using Google&amp;rsquo;s tracking and then calling it &amp;ldquo;anonymous&amp;rdquo; is a lie. Google collects tons of information of its users and even non-users. There&amp;rsquo;s no way to know what data Google will relate internally. Even if you don&amp;rsquo;t get to see all of the collected information, Google still has them.&lt;/li&gt;
&lt;li&gt;Opt-out is never an excuse. It always excludes most users (which either don&amp;rsquo;t care, or have more severe things to care about than protecting their privacy in every random app they&amp;rsquo;re using).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Read on to lean howto fix the issue for at least yourself.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: I&amp;rsquo;ve been contacted by a Homebrew maintainer and have been asked to remove the link to the Github issue. His arguments about keeping the issue to the topic convinced me, and I was sad to hear that he apparently received tons of personally insulting emails. When I asked for a more appropriate way to provide feedback, he didn&amp;rsquo;t give any and stated that they won&amp;rsquo;t make the tracking procedure opt-in. They also have removed all comments regarding complaints about their tracking from the issue. I wrote a final comment in the comment section, which was deleted immediately. For completeness, I&amp;rsquo;m quoting it here:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While I can understand you want to keep this Issue productive, I find it disturbing how Homebrew deals with massive complaints from an open-source-loving community (see HN, Reddit, etc. discussions).
Don&amp;rsquo;t just delete this away and hope everybody just forgets about this.&lt;/p&gt;
&lt;p&gt;I know this will probably be deleted in a minute and you guys will probably ban me, but I&amp;rsquo;m still writing this so people get notified via email/ etc.&lt;/p&gt;
&lt;p&gt;There are people out there for whom this is a serious issue. I beg you do not take this lightly.
I want to tell people &amp;ldquo;Homebrew is good, use it&amp;rdquo; and not &amp;ldquo;Homebrew is kinda good, but before you use it make sure to paste this-and-this in your terminal and also block this and that, otherwise you&amp;rsquo;ll be tracked&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;fixing-the-issue&#34;&gt;
  Fixing the issue
  &lt;a href=&#34;#fixing-the-issue&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Homebrew ships with an option to opt-out of the tracking.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set the environment variable &lt;code&gt;HOMEBREW_NO_ANALYTICS=1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Or run &lt;code&gt;git config --file=&amp;quot;$(brew --repository)/.git/config&amp;quot; --replace-all homebrew.analyticsdisabled true&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A more general approach (as there are other programs out there, which are less nice than Homebrew) is to block known tracking hosts.
This can be either done using something like &lt;a href=&#34;http://www.obdev.at/products/littlesnitch/index.html&#34;&gt;Little Snitch&lt;/a&gt;, or by setting up an adblocking &lt;code&gt;/etc/hosts&lt;/code&gt; file. The latter option is free and pretty straightforward. You can use the following script to collect well-known tracking services and tell your computer to not resolve them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# This code is GPLv3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HOSTSFILE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;hosts
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TMPFILE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/tmp/aosp-hosts-file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Updating adblocking hosts file...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://hosts-file.net/download/hosts.txt&amp;#34;&lt;/span&gt; &amp;gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://winhelp2002.mvps.org/hosts.txt&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://pgl.yoyo.org/adservers/serverlist.php?mimetype=plaintext&amp;amp;hostformat=hosts&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://someonewhocares.org/hosts/hosts&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;# This is a generated hostfile for adblocking.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;# Sources:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;# - http://hosts-file.net/download/hosts.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;# - http://www.mvps.org/winhelp2002/hosts.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;# - http://pgl.yoyo.org/adservers/serverlist.php?mimetype=plaintext&amp;amp;hostformat=hosts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;# - http://someonewhocares.org/hosts/hosts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;# Localhost entries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;127.0.0.1 localhost
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;::1 ip6-localhost ip6-loopback
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;fe00::0 ip6-localnet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;ff00::0 ip6-mcastprefix
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;ff02::1 ip6-allnodes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;ff02::2 ip6-allrouters
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;ff02::3 ip6-allhosts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt; $HOSTSFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Streamline all entries to use 0.0.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/127\.0\.0\.1/0\.0\.0\.0/&amp;#39;&lt;/span&gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Remove other localhost entries&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/localhost/d&amp;#39;&lt;/span&gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Remove comments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/#.*$//g&amp;#39;&lt;/span&gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Replace tabs with spaces&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/\t/ /g&amp;#39;&lt;/span&gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Also block ipv6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsed -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/\(0\.0\.0\.0\)\(.*\)/\1\2\n::0\2/&amp;#39;&lt;/span&gt; $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Sort and remove duplicates and empty lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sort -u $TMPFILE |grep -v &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;^\s*$&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; $HOSTSFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dos2unix $HOSTSFILE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm $TMPFILE
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This script will download known tracking services or other malicious domains from three different sources, removes duplicates and makes sure both ipv4 and ipv6 addresses are blocked.
Save it as &lt;code&gt;get-hosts.sh&lt;/code&gt; and you can use it like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Install dependencies, but make sure tracking is disabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export HOMEBREW_NO_ANALYTICS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install dos2unix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install gnu-sed
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Generate hosts file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chmod +x get-hosts.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./get-hosts.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Inspect the hosts file if your paranoid, then deploy it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mv hosts /etc/hosts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;what-homebrew-should-do&#34;&gt;
  What Homebrew should do
  &lt;a href=&#34;#what-homebrew-should-do&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Homebrew should (really!) make the tracking opt-in. A &amp;ldquo;really ask your user whether it&amp;rsquo;s ok&amp;rdquo; opt-in.&lt;/li&gt;
&lt;li&gt;It should really consider other methods for the goals it wants to achieve (like finding out &amp;ldquo;most-used&amp;rdquo; packages), and make sure they are really necessary.&lt;/li&gt;
&lt;/ol&gt;
        
        </description>
    </item>
    
    <item>
      <title>Dualstack multiple IP addresses with systemd-networkd</title>
      <link>https://chr4.org/posts/2016-02-24-dualstack-multiple-ip-addresses-with-systemd-networkd/</link>
      <pubDate>Wed, 24 Feb 2016 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2016-02-24-dualstack-multiple-ip-addresses-with-systemd-networkd/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I&amp;rsquo;m using systemd-networkd on Archlinux on one of my servers to configure the static IP addresses.
While this seems pretty straight-forward, there&amp;rsquo;s a big issue that you can bump into when trying to configure multiple IP addresses. As this took me some time to figure out and it&amp;rsquo;s not well documented, I decided to leave a blog post for future me (and possibly others).&lt;/p&gt;
&lt;p&gt;Apparently, the configuration described in the &lt;a href=&#34;https://wiki.archlinux.org/index.php/Systemd-networkd&#34;&gt;Archlinux wiki&lt;/a&gt; is not feasible when trying to configure multipe addresses. You need to use the alternative method using one &lt;code&gt;[Network]&lt;/code&gt; block. Using multiple &lt;code&gt;Address=&lt;/code&gt; lines in the &lt;code&gt;[Address]&lt;/code&gt; block is apparently not valid.
Unfortunately, &lt;code&gt;systemctl restart systemd-networkd&lt;/code&gt; doesn&amp;rsquo;t complain about an invalid configuration, but instead leaves you without any network config at all - Which then requires a rescue system to boot when you&amp;rsquo;re on a server without physical access.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s the working configuration I ended up with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# cat /etc/systemd/network/eno0.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Name&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;eno1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DNS&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;2.x.x.x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;DNS&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;2.x.x.x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;1.x.x.x/26&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;2001:xxxx:xxxx::1/64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;2001:xxxx:xxxx::2/64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Gateway&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;1.x.x.x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Update: According to &lt;a href=&#34;http://superuser.com/questions/775884/add-multiple-static-ip-addresses-to-a-server-with-systemd-networkd&#34;&gt;this post&lt;/a&gt; I wasn&amp;rsquo;t reading through &lt;code&gt;man systemd.network&lt;/code&gt; carefully enough. It&amp;rsquo;s also possible to just use multiple &lt;code&gt;[Address]&lt;/code&gt; sections with one IP each.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Increase password entropy on developermail.io</title>
      <link>https://chr4.org/posts/2015-07-29-devmail-password-entropy/</link>
      <pubDate>Wed, 29 Jul 2015 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2015-07-29-devmail-password-entropy/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I recently co-founded an email SaaS for developers called
&lt;a href=&#34;http://developermail.io&#34;&gt;developermail.io&lt;/a&gt; where tech-savy people can configure their email
mailboxes using git. We just released a new feature, which enables you to use high-entropy passwords
with our services.&lt;/p&gt;
&lt;p&gt;In this blogpost I&amp;rsquo;ll quickly show you howto generate more secure passwords for your
developermail.io account and mailboxes.&lt;/p&gt;
&lt;h2 id=&#34;increase-mailbox-password-entropy&#34;&gt;
  Increase mailbox password entropy
  &lt;a href=&#34;#increase-mailbox-password-entropy&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;On &lt;a href=&#34;http://developermail.io&#34;&gt;developermail.io&lt;/a&gt;, we generate strong passwords for our users. You can
now set the length of those passwords in the YAML configuration files.&lt;/p&gt;
&lt;p&gt;To increase the length of the generated password for your mailbox, add the &lt;code&gt;password_length&lt;/code&gt;
attribute to your &lt;code&gt;config.yaml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;developermail.io&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;you&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# This will set the password length for the mailbox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# you@developermail.io to 30 characters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;password_length&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Simply git push your configuration, and the changes are live!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git add config.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit am &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Increase password length for mailbox&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once your configuration was pushed and updated successfully, you can trigger a password change to
retrieve a new password. This can be done using a curl request. See the &lt;a href=&#34;https://developermail.io/docs#change-your-mailbox-password&#34;&gt;official
documentation&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;Change your password using the credentials for the mailbox&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST -u &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;you@developermail.io&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://developermail.io/api/mailboxes/change-password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alternatively, you can also trigger a password change using your account login (the one you also use
for git access)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST -u you &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://developermail.io/api/mailboxes/change-password&amp;#34;&lt;/span&gt; --data &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;user&amp;#34;: &amp;#34;chr4&amp;#34;, &amp;#34;domain&amp;#34;: &amp;#34;developermail.io&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;ll retrieve a JSON response including your new high-entropy password:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Password successfully changed.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chr4@developermail.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;increase-account-password-entropy&#34;&gt;
  Increase account password entropy
  &lt;a href=&#34;#increase-account-password-entropy&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;As your account has access to the mailbox configurations, do not forget to also adapt your account
password length. The process is analog to the mailboxes covered above.&lt;/p&gt;
&lt;p&gt;First, set the &lt;code&gt;account_password_length&lt;/code&gt; attribute to the desired length in your &lt;code&gt;settings.yaml&lt;/code&gt;.
In case you do not have a &lt;code&gt;settings.yaml&lt;/code&gt; file in your repository, simply create it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# This sets the password length for your account to 50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;account_password_length&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git add settings.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git commit -m &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Increase password length for account&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the new settings are pushend (and therefore live), you can request a new password using a curl
request. See the &lt;a href=&#34;https://developermail.io/docs#change-your-account-password&#34;&gt;official
documentation&lt;/a&gt; for details.
Use your account credentials for this request (the same you&amp;rsquo;re using for git)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST -u &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;examplecom&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://developermail.io/api/accounts/change-password&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you entered the correct password, you&amp;rsquo;ll receive a JSON response including your brand new, high
entropy password:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: false,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Password successfully changed.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;examplecom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
        </description>
    </item>
    
    <item>
      <title>Howto secure openssh-6.x</title>
      <link>https://chr4.org/posts/2014-09-13-howto-secure-openssh-newer-versions/</link>
      <pubDate>Sat, 13 Sep 2014 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2014-09-13-howto-secure-openssh-newer-versions/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Since &lt;a href=&#34;http://openssh.com&#34;&gt;OpenSSH&lt;/a&gt; 6.x came out, a lot of new ciphers where introduced. I was wondering, which ones where
the best and what I should use, and I read a few articles on the internet to find out.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m certainly not a cryptographer, so if you have any suggestions howto further improve the
configuration below, feel free to &lt;a href=&#34;https://chr4.org/whoami/&#34;&gt;contact&lt;/a&gt; me.&lt;/p&gt;
&lt;p&gt;As a general statement, one should avoid ECDSA and use Ed25519 instead, and due to the fixed
key length of DSA that &lt;code&gt;ssh-keygen&lt;/code&gt; uses, DSA should also be avoided. RSA keys should be at least
2048 bits long, perhaps 4096 bits is the better choice.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Most of the settings covered in this post are incompatible with openssh-5.x. Consider
upgrading!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;availablility-of-openssh-6x&#34;&gt;
  Availablility of openssh-6.x
  &lt;a href=&#34;#availablility-of-openssh-6x&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ubuntu 14.04 ships with openssh-6.6&lt;/li&gt;
&lt;li&gt;Archlinux ships with newest openssh, due to its rolling release package management&lt;/li&gt;
&lt;li&gt;MacOS Mavericks ships with openssh-6.2, you can install openssh-6.6 using
&lt;a href=&#34;http://brew.sh&#34;&gt;Homebrew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Debian Wheezy ships openssh-6.0 (&lt;em&gt;Note: Some covered settings are not compatible with OpenSSH &amp;lt; 6.4&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;RHEL 5.x ships openssh-5.4 :(&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can configure your ssh to prefer good ciphers on both, the client and the server side.&lt;/p&gt;
&lt;h2 id=&#34;securing-the-ssh-client-configuration&#34;&gt;
  Securing the ssh client configuration
  &lt;a href=&#34;#securing-the-ssh-client-configuration&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s two files you can configure your ssh client with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/etc/ssh/ssh_config&lt;/code&gt; (Global configuration, for all users)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.ssh/config&lt;/code&gt; (Your users configuration)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Place the configuration for all hosts at the bottom of the file, and override this default settings
with entries for individual hosts/networks with entries placed above (This is the way how the
configuration file is read).&lt;/p&gt;
&lt;p&gt;So we should start with settings for individual hosts. Here&amp;rsquo;s the settings I use for
&lt;a href=&#34;https://github.com&#34;&gt;Github&lt;/a&gt;, as Github doesn&amp;rsquo;t support recent ciphers unfortunately :(&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Host&lt;/span&gt; github&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Github doesn&amp;#39;t support decent ciphers, using the best available&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;Ciphers&lt;/span&gt;       aes256&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;ctr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;MACs&lt;/span&gt;          hmac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha2&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;512&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;KexAlgorithms&lt;/span&gt; diffie&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;hellman&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;group14&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;IdentityFile&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.ssh/i&lt;/span&gt;d_rsa
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the same way, you can add cipher (as well as other) specifications for other hosts, e.g.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# This is a host with OpenSSH &amp;lt; 6.4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Host&lt;/span&gt; myoldhost&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;User&lt;/span&gt;              katie
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;HostKeyAlgorithms&lt;/span&gt; ssh&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;Ciphers&lt;/span&gt;           aes256&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;ctr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;MACs&lt;/span&gt;              hmac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha2&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;512&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, here&amp;rsquo;s the global defaults, using only secure ciphers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Host&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Use only secure ciphers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Never use ECDSA/DSA, prefer Ed25519, use RSA as fallback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# In case you need to support openssh-server versions &amp;lt; 6.4,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# you need to add ssh-rsa, aes256-ctr and hmac-sha2-512 :(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Update 2015-08-14: Remove ssh-rsa-cert-v00@openssh.com, was deprecated by openssh-7.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;HostKeyAlgorithms&lt;/span&gt; ssh&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;ed25519&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;cert&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;v01@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,ssh&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;ed25519,ssh&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;rsa&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;cert&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;v01@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;Ciphers&lt;/span&gt;           chacha20&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;poly1305@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,aes256&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;gcm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;MACs&lt;/span&gt;              hmac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha2&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;512&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;etm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,hmac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha2&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;256&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;etm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,umac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;etm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;KexAlgorithms&lt;/span&gt;     curve25519&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha256@libssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;org,diffie&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;hellman&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;group&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;exchange&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha256
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Prefer Ed25519 over RSA, never use DSA/ECDSA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;IdentityFile&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.ssh/i&lt;/span&gt;d_ed25519
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;IdentityFile&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.ssh/i&lt;/span&gt;d_rsa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Display randomart images of hostkeys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;VisualHostKey&lt;/span&gt; yes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;securing-openssh-server&#34;&gt;
  Securing openssh-server
  &lt;a href=&#34;#securing-openssh-server&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Server side config resides in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;. I&amp;rsquo;m mostly covering the security/cipher related
configuration settings here. Basically, the configuration resembles the client configuration for
most of the settings.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Using a non-standard ssh port is just security by obscurity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Port 22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# In general, please use pub/priv authentication instead of passwords&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;PasswordAuthentication&lt;/span&gt; no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Speedup login process on machines that have no proper DNS settings, protect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# privacy, no real security drawback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UseDNS&lt;/span&gt; no
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use only secure ciphers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Never use ECDSA/DSA, prefer Ed25519, use RSA as fallback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;HostKey&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/etc/ss&lt;/span&gt;h&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;ssh_host_ed25519_key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;HostKey&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/etc/ss&lt;/span&gt;h&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;ssh_host_rsa_key
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Add aes256-ctr for compatibility with older clients&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Ciphers&lt;/span&gt; chacha20&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;poly1305@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,aes256&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;gcm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Add hmac-sha2-512 for compatibility with older clients&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;MACs&lt;/span&gt; hmac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha2&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;512&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;etm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,hmac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha2&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;256&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;etm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com,umac&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;etm@openssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;KexAlgorithms&lt;/span&gt; curve25519&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha256@libssh&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;org,diffie&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;hellman&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;group&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;exchange&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;sha256
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;issues&#34;&gt;
  Issues
  &lt;a href=&#34;#issues&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;ruby-netssh-library&#34;&gt;
  Ruby net/ssh library
  &lt;a href=&#34;#ruby-netssh-library&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The Ruby &lt;a href=&#34;https://github.com/net-ssh/net-ssh&#34;&gt;net/ssh&lt;/a&gt; library cannot deal with the new ciphers yet.
I tried to fix the library, but couldn&amp;rsquo;t quite fix all the issues. Please see this
&lt;a href=&#34;https://github.com/net-ssh/net-ssh/pull/162&#34;&gt;pull request&lt;/a&gt;, and feel free to contribute!&lt;/p&gt;
&lt;p&gt;Popular programs using this library are among others &lt;a href=&#34;http://vagrantup.com&#34;&gt;Vagrant&lt;/a&gt; and
&lt;a href=&#34;https://docs.getchef.com/knife_ssh.html&#34;&gt;knife ssh&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There best workaround I found was overriding the &lt;code&gt;SSH_AUTH_SOCK&lt;/code&gt; variable when using those programs,
resulting in ignoring the unknown keys in ssh-agent:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SSH_AUTH_SOCK&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; vagrant up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;openssh-versions--6x&#34;&gt;
  OpenSSH versions &amp;lt; 6.x
  &lt;a href=&#34;#openssh-versions--6x&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;When dealing with OpenSSH clients/servers &amp;lt; 6.x, you might add more exceptions into your
&lt;code&gt;ssh_config&lt;/code&gt; resp. &lt;code&gt;sshd_config&lt;/code&gt;. The settings I use for Github above might be a good starting
point. &lt;code&gt;ssh -v&lt;/code&gt; usually gives good hints which ciphers you need to enable.&lt;/p&gt;
&lt;h2 id=&#34;chef-sshd-cookbook&#34;&gt;
  Chef sshd cookbook
  &lt;a href=&#34;#chef-sshd-cookbook&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;If you want to deploy ssh configurations for multiple hosts, you might want to have a look on my
&lt;a href=&#34;https://github.com/chr4-cookbooks/sshd&#34;&gt;sshd cookbook&lt;/a&gt; for Chef.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>conf.d like directories for zsh/bash dotfiles</title>
      <link>https://chr4.org/posts/2014-09-10-conf-dot-d-like-directories-for-zsh-slash-bash-dotfiles/</link>
      <pubDate>Wed, 10 Sep 2014 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2014-09-10-conf-dot-d-like-directories-for-zsh-slash-bash-dotfiles/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I don&amp;rsquo;t like messy dotfiles.&lt;/p&gt;
&lt;p&gt;The thought of having tons of random configuration entries in files like my &lt;code&gt;.zshrc&lt;/code&gt; really bothers
me, so I implemented something that works like a &lt;code&gt;conf.d&lt;/code&gt; like directory structure for my shell
dotfiles.&lt;/p&gt;
&lt;p&gt;I also still use the bash shell in certain situations, and I want a more or less consistent
environment, no matter which shell I use (bash, zsh).&lt;/p&gt;
&lt;p&gt;With the following setup, it&amp;rsquo;s possible to have the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A directory called &lt;code&gt;zshrc.d&lt;/code&gt;, which includes multiple, zsh related configuration files.&lt;/li&gt;
&lt;li&gt;A directory called &lt;code&gt;bashrc.d&lt;/code&gt;, including multiple configuration files concerning bash.&lt;/li&gt;
&lt;li&gt;A directory called &lt;code&gt;rc.d&lt;/code&gt;, including configuration items needed by both shells.&lt;/li&gt;
&lt;li&gt;A directory called &lt;code&gt;login.d&lt;/code&gt;, including elements included by &lt;code&gt;.bash_profile&lt;/code&gt; resp. &lt;code&gt;.zlogin&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This keeps your dotfiles nice and clean, and also allows you do have additional files on systems
where you need them, without them being included on all your systems (e.g. your &lt;code&gt;$GOPATH&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Here are the dotfiles, that do nothing but include all files in the described directories:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# .bashrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[[&lt;/span&gt; $- !&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; *i* &lt;span style=&#34;color:#f92672&#34;&gt;]]&lt;/span&gt; ; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# shell is non-interactive. be done now!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Load all files from .shell/bashrc.d directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d $HOME/.shellrc/bashrc.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in $HOME/.shellrc/bashrc.d/*.bash; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source $file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Load all files from .shell/rc.d directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d $HOME/.shellrc/rc.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in $HOME/.shellrc/rc.d/*.sh; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source $file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# .bash_profile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -f $HOME/.bashrc &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  source $HOME/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Load all files from .shell/login.d directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d $HOME/.shellrc/login.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in $HOME/.shellrc/login.d/*.sh; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source $file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# .zshrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Load all files from .shell/zshrc.d directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d $HOME/.shellrc/zshrc.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in $HOME/.shellrc/zshrc.d/*.zsh; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source $file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Load all files from .shell/rc.d directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d $HOME/.shellrc/rc.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in $HOME/.shellrc/rc.d/*.sh; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source $file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# .zlogin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Load all files from .shell/login.d directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; -d $HOME/.shellrc/login.d &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file in $HOME/.shellrc/login.d/*.sh; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source $file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No you can include all sorts of useful functions, settings and aliases by putting individual files
in your &lt;code&gt;.shellrc/*&lt;/code&gt; folders!&lt;/p&gt;
&lt;p&gt;You can find my full &lt;code&gt;.shellrc&lt;/code&gt; directory on &lt;a href=&#34;https://github.com/chr4/shellrc/&#34;&gt;Github&lt;/a&gt;.
Have a look at the &lt;a href=&#34;https://github.com/chr4/shellrc/blob/master/README.md&#34;&gt;README.md&lt;/a&gt; for more
information!&lt;/p&gt;
&lt;p&gt;Happy housecleaning!&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>gittree: bash/zsh function to run git commands recursively</title>
      <link>https://chr4.org/posts/2014-09-10-gittree-bash-slash-zsh-function-to-run-git-commands-recursively/</link>
      <pubDate>Wed, 10 Sep 2014 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2014-09-10-gittree-bash-slash-zsh-function-to-run-git-commands-recursively/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;I&amp;rsquo;m using Androids &lt;a href=&#34;https://code.google.com/p/git-repo/&#34;&gt;repo&lt;/a&gt; tool from time to time when dealing
with large groups of git repositories. In most situations, it is too bloated though.
Some git &amp;ldquo;batch&amp;rdquo; commands I found very useful, like &lt;code&gt;repo status&lt;/code&gt;, checking the status of all git
repositories recursively.&lt;/p&gt;
&lt;p&gt;To mimic this (and other) behaviour in a simple way, I created the following bash/zsh function (put
this in your &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt;, or another file where you define functions in your dotfiles)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Recursively traverse directory tree for git repositories, run git command&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# e.g.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#   gittree status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#   gittree diff&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gittree&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; $# -lt &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Usage: gittree &amp;lt;command&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; gitdir in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;find . -type d -name .git&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Display repository name in blue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    repo&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;dirname $gitdir&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\033[34m&lt;/span&gt;$repo&lt;span style=&#34;color:#e6db74&#34;&gt;\033[0m&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Run git command in the repositories directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cd $repo &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; git $@
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ret&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Return to calling directory (ignore output)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cd - &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Abort if cd or git command fails&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; $ret -ne &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows me to quickly get an overview of multiple git repositories, and check e.g. whether they
are all clean, or push them all at once:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dockerfiles % gittree status
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./base-go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;On branch master
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your branch is up-to-date with &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;origin/master&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nothing to commit, working directory clean
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./dovecot
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;On branch master
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your branch is up-to-date with &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;origin/master&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nothing to commit, working directory clean
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./nginx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;On branch master
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your branch is up-to-date with &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;origin/master&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Untracked files:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;use &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to include in what will be committed&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  feeling-dirty
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nothing added to commit but untracked files present &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;use &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./dnsmasq
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;On branch master
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your branch is up-to-date with &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;origin/master&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nothing to commit, working directory clean
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;gittree&lt;/code&gt; works with all git commands, try out e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gittree status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gittree diff&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gittree push&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gittree --no-pager log --graph --pretty=format:&#39;%h -%d %s (%cr) &amp;lt;%an&amp;gt;&#39;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s a pretty simple script and for sure not perfect, but it get&amp;rsquo;s the job done!&lt;/p&gt;
&lt;p&gt;If you have any suggestions how to improve it, please file a pull request
&lt;a href=&#34;https://github.com/chr4/shellrc/blob/master/rc.d/functions.sh#L31-L60&#34;&gt;on this file&lt;/a&gt; on Github.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Online resizing LVM guest-partitions on OpenNebula/libvirt guests</title>
      <link>https://chr4.org/posts/2014-08-28-online-resizing-lvm-guest-partitions-on-opennebula-slash-libvirt-guests/</link>
      <pubDate>Thu, 28 Aug 2014 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2014-08-28-online-resizing-lvm-guest-partitions-on-opennebula-slash-libvirt-guests/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Today I found out howto resize guest partitions on &lt;a href=&#34;http://opennebula.org&#34;&gt;OpenNebula&lt;/a&gt; (or in
general with &lt;a href=&#34;http://libvirt.org&#34;&gt;libvirt&lt;/a&gt;, which OpenNebula uses underneath for
&lt;a href=&#34;http://www.linux-kvm.org&#34;&gt;KVM&lt;/a&gt; virtualization).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using a LVM storage for virtual machines. So resizing them is pretty easy.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Replace the &lt;code&gt;XX&lt;/code&gt; below with your virtual machines ID, as you can find out with e.g.
&lt;code&gt;onevm list&lt;/code&gt; or &lt;code&gt;virsh list&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;host ~ $ sudo lvresize -L 50G /dev/volgrp/lv-one-XX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Extending logical volume lv-one-XX to 50.00 GiB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Logical volume lv-one-XX successfully resized
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, you need to tell libvirt about the new size. This can be done with the following command:
&lt;em&gt;Note: The &amp;ndash;path argument is the device name of the partition used by the guest. You can find it
out by using &lt;code&gt;virsh domblklist one-XX&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;host ~ $ sudo virsh blockresize one-XX --path vdX --size 50G
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Block device &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;vdX&amp;#39;&lt;/span&gt; is resized
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now simply login your guest machine and adapt the filesystem (no reboot required)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;guest ~ $ sudo resize2fs /dev/vdX   &lt;span style=&#34;color:#75715e&#34;&gt;# For ext filesystems&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;guest ~ $ sudo xfs_growfs /dev/vdX  &lt;span style=&#34;color:#75715e&#34;&gt;# For xfs filesystems&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, the new size will not display in the &lt;code&gt;SIZE&lt;/code&gt; attribute of the image in OpenNebula (as
seen with &lt;code&gt;oneimage show XX&lt;/code&gt;).
Apparently this is only set when creating the image.&lt;/p&gt;
&lt;p&gt;As far as I know, this only works when using the &lt;code&gt;virtio&lt;/code&gt; or &lt;code&gt;scsi&lt;/code&gt; block drivers. In OpenNebula you
can e.g. set &lt;code&gt;DEV_PREFIX=&amp;quot;vd&amp;quot;&lt;/code&gt; in your image configuration to use &lt;code&gt;virtio&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href=&#34;http://humblec.com/is-it-possible-to-do-online-resizing-of-guest-block-devices-or-without-shutdown&#34;&gt;Humble Chirammal&lt;/a&gt;
for pointing out &lt;code&gt;virsh blockresize&lt;/code&gt;.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Nested if workaround for Nginx to allow a specific ip address access to a disabled site</title>
      <link>https://chr4.org/posts/2013-10-29-nested-if-workaround-for-nginx-to-allow-a-specific-ip-address-access-to-a-disabled-site/</link>
      <pubDate>Tue, 29 Oct 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-10-29-nested-if-workaround-for-nginx-to-allow-a-specific-ip-address-access-to-a-disabled-site/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;When doing maintenance on a web application, you probably have a custom &lt;code&gt;503&lt;/code&gt; site, showing your customers that the servers are currently lying on the operating table.&lt;/p&gt;
&lt;p&gt;At the dynamic ridesharing service &lt;a href=&#34;https://flinc.org&#34;&gt;flinc&lt;/a&gt;, we touch a certain file on our reverse proxies (e.g. using &lt;a href=&#34;https://github.com/capistrano/capistrano/&#34;&gt;capistrano&lt;/a&gt; &lt;code&gt;deploy:web:disable&lt;/code&gt;) when maintenance begins. &lt;a href=&#34;nginx.org&#34;&gt;Nginx&lt;/a&gt; then serves a static &amp;ldquo;we&amp;rsquo;ve disabled the site for maintenance&amp;rdquo; site, instead of the actual content.&lt;/p&gt;
&lt;p&gt;But wouldn&amp;rsquo;t it be nice to test your web application before going live for your customers? It sure would. Unfortunately, this is not as simple as a task as you might think, because you cannot nest &lt;code&gt;if&lt;/code&gt; directives in an Nginx &lt;a href=&#34;http://wiki.nginx.org/HttpCoreModule#location&#34;&gt;location&lt;/a&gt; and &lt;a href=&#34;http://wiki.nginx.org/IfIsEvil&#34;&gt;if is evil&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because of hose limitations, we need another creative approach.
As &lt;code&gt;try_files&lt;/code&gt; is also forbidden in &lt;code&gt;if&lt;/code&gt; directives and only &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;rewrite&lt;/code&gt; are &lt;a href=&#34;http://wiki.nginx.org/IfIsEvil&#34;&gt;safe commands to use&lt;/a&gt; let&amp;rsquo;s abuse the &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error&#34;&gt;unused HTTP status code&lt;/a&gt; &lt;code&gt;418&lt;/code&gt; to work around this.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location / &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunked_transfer_encoding off;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_page 418 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; @try_files;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_page 503 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; @maintenance;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# allow out office ip even when in maintenance mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;$remote_addr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 10.11.12.13&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; 418;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# we are in maintenance mode when this file is present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;-f $document_root/maintenance.html&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; 503;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; 418;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Basically, as long as the &lt;code&gt;maintenance.html&lt;/code&gt; is not present or we are sitting in our office, we return the &lt;code&gt;418&lt;/code&gt; status code. For customers, we&amp;rsquo;re serving &lt;code&gt;503&lt;/code&gt; in case the site is disabled.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s define the locations for normal operation (try serving the static files directly, and redirect all other requests to our upstream)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location @try_files &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    try_files $uri @proxy;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location @proxy &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    proxy_pass https://flinc;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, our maintenance site. We&amp;rsquo;re serving &lt;code&gt;maintenance.html&lt;/code&gt; instead of the requested site.
As &lt;code&gt;POST&lt;/code&gt; requests to static websites are not allowed and therefore all our disabled forms will return a &lt;code&gt;405&lt;/code&gt; instead of the wanted &lt;code&gt;503&lt;/code&gt;, let&amp;rsquo;s correct those as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location @maintenance &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# return 503 for non-GET requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# (returns 405 by default, because POST/etc to a static website is not allowed)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;$request_method !&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; GET&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; 503;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    try_files $uri /maintenance.html;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The last &lt;code&gt;location&lt;/code&gt; directive makes sure that the static assets required for the maintenance page (images, stylesheets, etc) stored in &lt;code&gt;/maintenance&lt;/code&gt; are served normally.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# don&amp;#39;t hand out 503 headers when accessing maintenance assets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location /maintenance &lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
        </description>
    </item>
    
    <item>
      <title>iptables-ng cookbook for chef</title>
      <link>https://chr4.org/posts/2013-09-13-iptables-ng-cookbook-for-chef/</link>
      <pubDate>Fri, 13 Sep 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-09-13-iptables-ng-cookbook-for-chef/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Today, I released &lt;a href=&#34;https://github.com/chr4-cookbooks/iptables-ng&#34;&gt;iptables-ng&lt;/a&gt;,
a cookbook to maintain iptables rules on different machines using chef.&lt;/p&gt;
&lt;p&gt;But why another cookbook? There are two fairly often used around&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/opscode-cookbooks/iptables&#34;&gt;iptables from Opscode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dcrosta/cookbook-simple-iptables&#34;&gt;simple_iptables from Dan Crosta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well, I wanted a tool which can do all the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure iptables rules in a consistent and nice way for all distributions&lt;/li&gt;
&lt;li&gt;Be configured by using LWRPs only&lt;/li&gt;
&lt;li&gt;Be configured by using node attributes only&lt;/li&gt;
&lt;li&gt;Respect the way the currently used distribution stores their rules&lt;/li&gt;
&lt;li&gt;Provide a good-to-read and good-to-maintain way of deploying complex iptables rulesets&lt;/li&gt;
&lt;li&gt;Provide a way of specifying the order of the iptables rules, in case needed&lt;/li&gt;
&lt;li&gt;Only run iptables-restore once during a chef run, and only if something was actually changed&lt;/li&gt;
&lt;li&gt;Support both, ipv6 as well as ipv4&lt;/li&gt;
&lt;li&gt;Be able to assemble iptables rules from different recipes (and even cookbooks), so you can set your iptables rule where you actually configure the service&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;respect-the-way-the-distribution-handles-iptables&#34;&gt;
  Respect the way the distribution handles iptables
  &lt;a href=&#34;#respect-the-way-the-distribution-handles-iptables&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Every distribution has its own way of maintaining iptables rules.
While iptables-restore provides a generic format/tool available to save and restore iptables rules, every distribution uses it differently.&lt;/p&gt;
&lt;h4 id=&#34;debian-and-ubuntu&#34;&gt;
  Debian and Ubuntu
  &lt;a href=&#34;#debian-and-ubuntu&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Debian based systems provide a package called &lt;code&gt;iptables-persistent&lt;/code&gt;, which provides a system service to save and load iptables rules.
Debian Squeeze (and earlier) use an outdated version of iptables-persistent, which doesn&amp;rsquo;t support ipv6.&lt;/p&gt;
&lt;p&gt;iptables-persistent stores the rules in these files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Debian&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/i&lt;/span&gt;ptables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;rules&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;v4 &lt;span style=&#34;color:#75715e&#34;&gt;# ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# ipv6 [not supported]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Ubuntu&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/i&lt;/span&gt;ptables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;rules&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;v4 &lt;span style=&#34;color:#75715e&#34;&gt;# ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/i&lt;/span&gt;ptables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;rules&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;v6 &lt;span style=&#34;color:#75715e&#34;&gt;# ipv6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;-rhel&#34;&gt;
  # RHEL
  &lt;a href=&#34;#-rhel&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Redhat (and clones like CentOS) provide a system service by default which loads iptables rules from the following files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# RHEL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/s&lt;/span&gt;ysconfig&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;iptables  &lt;span style=&#34;color:#75715e&#34;&gt;# ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/s&lt;/span&gt;ysconfig&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;ip6tables &lt;span style=&#34;color:#75715e&#34;&gt;# ipv6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;-gentoo&#34;&gt;
  # Gentoo
  &lt;a href=&#34;#-gentoo&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Gentoo also provides system services by default, but stores the rules here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Gentoo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/var/&lt;/span&gt;lib&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;iptables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;rules&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;save  &lt;span style=&#34;color:#75715e&#34;&gt;# ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/var/&lt;/span&gt;lib&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;ip6tables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;rules&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;save &lt;span style=&#34;color:#75715e&#34;&gt;# ipv6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;-archlinux&#34;&gt;
  # Archlinux
  &lt;a href=&#34;#-archlinux&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Archlinux uses iptables-restore too, and stores its files here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Archlinux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/i&lt;/span&gt;ptables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;iptables&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;rules  &lt;span style=&#34;color:#75715e&#34;&gt;# ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/etc/i&lt;/span&gt;ptables&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;ip6tables&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;rules &lt;span style=&#34;color:#75715e&#34;&gt;# ipv6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-new-iptables-ng-cookbook&#34;&gt;
  The new iptables-ng cookbook
  &lt;a href=&#34;#the-new-iptables-ng-cookbook&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/chr4-cookbooks/iptables-ng&#34;&gt;iptables-ng&lt;/a&gt; cookbook supports all of those platforms transparently for the user, as well as trying to be as compatible as possible to the way of the currently used distribution.&lt;/p&gt;
&lt;p&gt;It automatically saves the assembled rules to the locations specified above, and if the system doesn&amp;rsquo;t support its own service provider, it will fall back to apply to rules manually using iptables-restore.
(This enables e.g. ipv6 support in Debian, yeee!)&lt;/p&gt;
&lt;p&gt;It furthermore provides LWRPs for all its functions, while it also can be configured using only node attributes.&lt;/p&gt;
&lt;h3 id=&#34;examples&#34;&gt;
  Examples
  &lt;a href=&#34;#examples&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Let me show you some examples&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Set default policy to DROP (whitelist mode)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Unless it is already specified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;%w{input output forward}&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;each &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;chain&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  iptables_ng_policy chain&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;upcase &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    policy &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;DROP [0:0]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    action &lt;span style=&#34;color:#e6db74&#34;&gt;:create_if_missing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Drop invalid packages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iptables_ng_rule &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10-input-drop-invalid&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  rule &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;--match state --state INVALID --jump DROP&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Drop ICMP timestamp packages (ipv4 only)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iptables_ng_rule &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;14-drop-icmp-timestamp&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  rule &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;--protocol icmp --icmp-type timestamp-request --jump DROP&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;--protocol icmp --icmp-type timestamp-reply --jump DROP&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ip_version &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Masquerade (nat table automatically is only applied to ipv4)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iptables_ng_rule &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;99-masquerade&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  chain &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POSTROUTING&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  table &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;nat&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  rule  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-o eth0 -j MASQUERADE&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Delete a rule&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iptables_ng_rule &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;10-unwanted-rule&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#e6db74&#34;&gt;:delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All rules will be written to &lt;code&gt;/etc/iptables.d&lt;/code&gt; directory, resulting in the following directory structure:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;├── filter
│   ├── FORWARD
│   │   └── default
│   ├── INPUT
│   │   ├── 10-input-drop-invalid.rule_v4
│   │   ├── 10-input-drop-invalid.rule_v6
│   │   ├── 14-drop-icmp-timestamp.rule_v4
│   │   └── default
│   └── OUTPUT
│       └── default
├── mangle
│   ├── FORWARD
│   │   └── default
│   ├── INPUT
│   │   └── default
│   ├── OUTPUT
│   │   └── default
│   ├── POSTROUTING
│   │   └── default
│   └── PREROUTING
│       └── default
├── nat
│   ├── OUTPUT
│   │   └── default
│   ├── POSTROUTING
│   │   ├── 99-masquerade.rule_v4
│   │   └── default
│   └── PREROUTING
│       └── default
└── raw
    ├── OUTPUT
    │   └── default
    └── PREROUTING
        └── default
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the end of the chef run, they will be assembled into a sinble iptables restore script.
Finally, if the ruleset was changed, iptables-ng takes care of reloading the rules, using the systems provider (e.g. &lt;code&gt;/etc/init.d/iptables&lt;/code&gt;). If the system doesn&amp;rsquo;t provide it&amp;rsquo;s own way of loading the rules, iptables-ng will fall back to &lt;code&gt;iptables-restore&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Fore more examples, have a look at the &lt;a href=&#34;https://github.com/chr4-cookbooks/iptables-ng/blob/master/README.md&#34;&gt;README&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;get-it&#34;&gt;
  Get it!
  &lt;a href=&#34;#get-it&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can grab your copy from these locations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/chr4-cookbooks/iptables-ng&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://community.opscode.com/cookbooks/iptables-ng&#34;&gt;Opscode community site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
        
        </description>
    </item>
    
    <item>
      <title>ipswitch - migrate IP addresses without downtime</title>
      <link>https://chr4.org/posts/2013-08-13-ipswitch/</link>
      <pubDate>Tue, 13 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-08-13-ipswitch/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;When doing quick maintenance tasks on a server, you can use the following approach to keep your site available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Failover the backnet IP address of the host to another host&lt;/li&gt;
&lt;li&gt;Use arping to tell the network that this IP was switched&lt;/li&gt;
&lt;li&gt;Remove the IP from the host that needs maintenance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In case you do not have a full high availability setup available, you can use &lt;a href=&#34;https://github.com/chr4/ipswitch&#34;&gt;ipswitch&lt;/a&gt;, a small tool I wrote to assist with this kind of simple failover tasks.&lt;/p&gt;
&lt;p&gt;You can install it using&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gem install ipswitch
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ipswitch connects to the remote hosts using SSH, and uses the &amp;ldquo;ip&amp;rdquo; command to maintain IP addreses.&lt;/p&gt;
&lt;h3 id=&#34;migrate-an-ip-without-downtime&#34;&gt;
  Migrate an IP without downtime
  &lt;a href=&#34;#migrate-an-ip-without-downtime&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s say you have an application server called rails-1.example.com, and you need to do some maintenance task on it (e.g. install a kernel update and reboot the machine).
While you could modify all of your reverse proxys to exclude this server from their configuration, it is much simpler to just assign the (backnet) IP address of rails-1.example.com to one of your other application servers.&lt;/p&gt;
&lt;p&gt;With ipswitch, this can be done using one command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ipswitch migrate rails-1.example.com rails-2.example.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-perl&#34; data-lang=&#34;perl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Getting IP &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; interface eth0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Found IP &lt;span style=&#34;color:#ae81ff&#34;&gt;192.168.1.2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Adding IP address &lt;span style=&#34;color:#ae81ff&#34;&gt;192.168.1.2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt; to interface eth0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Running arpping
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; packets transmitted, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; packets received, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;% unanswered (&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; extra)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Removing IP address &lt;span style=&#34;color:#ae81ff&#34;&gt;192.168.1.2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt; from interface eth0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ipswitch automatically detects and uses the (primary) IP of the specified interface (default: eth0)&lt;/p&gt;
&lt;p&gt;When your maintenance tasks are done, migrate the IP address back to the original host&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ipswitch migrate rails-2.example.com rails-1.example.com --ip 192.168.1.2/24
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-perl&#34; data-lang=&#34;perl&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Adding IP address &lt;span style=&#34;color:#ae81ff&#34;&gt;192.168.1.2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt; to interface eth0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Running arpping
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; packets transmitted, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; packets received, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;% unanswered (&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; extra)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rails&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;example&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;com: Removing IP address &lt;span style=&#34;color:#ae81ff&#34;&gt;192.168.1.2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;24&lt;/span&gt; from interface eth0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As eth0 now has two IP addresses, you need to specify which once to migrate.
If the original node reclaimed the IP automatically (e.g. due to a reboot), ipswitch still works.&lt;/p&gt;
&lt;h3 id=&#34;simple-tasks&#34;&gt;
  Simple tasks
  &lt;a href=&#34;#simple-tasks&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;You can also use ipswitch to just add/remove IP addresses from your nodes&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ipswitch add --ip 192.168.1.1/24 example.com
$ ipswitch del --ip 192.168.1.1/24 example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assign an IP to an interface other than eth0 and do not use arping to broadcast IP&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ipswitch add --interface eth1 --ip 192.168.1.1/24 --no-broadcast example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Managing IPv6 addresses is also possible&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ipswitch add --family inet6 --ip fe80::abcd:66ff:fede:9999 example.com
$ ipswitch del --family inet6 --ip fe80::abcd:66ff:fede:9999 example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;caveats&#34;&gt;
  Caveats
  &lt;a href=&#34;#caveats&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Currently only works when using SSH keys for authenticating at your hosts.
The following features are planned, and pull requests are apprechiated :)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Password support&lt;/li&gt;
&lt;li&gt;SOCKS proxy support)&lt;/li&gt;
&lt;li&gt;Ability to specify SSH keyfile&lt;/li&gt;
&lt;li&gt;Support for sudo&lt;/li&gt;
&lt;/ul&gt;
        
        </description>
    </item>
    
    <item>
      <title>apt-get cleanup commands</title>
      <link>https://chr4.org/posts/2013-08-04-apt-get-cleanup-commands/</link>
      <pubDate>Sun, 04 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-08-04-apt-get-cleanup-commands/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;Just a short post about some useful cleanup commands for Debian and Ubuntu systems.
There are (to my knowledge) no build in task solving the following things&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove old kernels (while keeping the currently running and the latest)&lt;/li&gt;
&lt;li&gt;Purge removed packages (especially after autoremoving unneeded dependencies)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;remove-old-kernels&#34;&gt;
  Remove old kernels
  &lt;a href=&#34;#remove-old-kernels&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Debian and Ubuntu don&amp;rsquo;t remove old kernels when upgrading. Although this of course makes sense to keep the system bootable in case of a broken kernel, it can fill up /boot pretty quickly.
Usually it should be sufficient to keep the currently running kernel, as well as the latest one. The rest can be safely deleted.
This can be done with the following command:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit: Also purge other kernel packages, like modules and source&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get purge &lt;span style=&#34;color:#ae81ff&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    dpkg --list | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    egrep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;linux-(image|image-unsigned|headers|modules|modules-extra|source|doc)-[0-9]&amp;#39;&lt;/span&gt; | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print \$3,\$2}&amp;#39;&lt;/span&gt; | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    sort -nr | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    tail -n +2 | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    grep -v &lt;span style=&#34;color:#ae81ff&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;uname -r&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print \$2}&amp;#39;&lt;/span&gt; | &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    tr &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[:space:]&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A short explanation&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get purge             remove packages &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;and purge configuration&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; selected by the following lines
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dpkg --list               list installed packages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;egrep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;linux-(...)-[0-9]&amp;#39;&lt;/span&gt; grep installed kernels, modules, source, headers, ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $3,$2}&amp;#39;&lt;/span&gt;       we need the version, as well as the package name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sort -nr                  sort by version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tail -n +2                filter out latest kernel
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;grep -v &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;uname -r&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;       filter out currently running kernel &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;failsafe&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;          cut everything but the package name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tr &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[:space:]&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;        make sure all whitespace characters are real spaces
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;purge-removed-packages&#34;&gt;
  Purge removed packages
  &lt;a href=&#34;#purge-removed-packages&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;If you remove a package using&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get remove &amp;lt;packagename&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The packages configuration will be retained. Also, when autoremoving unneeded dependencies, apt-get by default removes packages instead of purging them.&lt;/p&gt;
&lt;p&gt;To cleanup your system and purge all packages that are removed from the system and their dependencies, use this command&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get autoremove -y; apt-get purge -y &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;dpkg --list |grep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;^rc&amp;#39;&lt;/span&gt; |awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Explanation&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get autoremove -y  remove all dependencies no longer required
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get purge -y       purge packages selected with the following lines
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dpkg --list            list installed packages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;grep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;^rc&amp;#39;&lt;/span&gt;             grep packages removed, but not purged &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;rc&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt;       cut everything but the package name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tr &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[:space:]&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;     make sure all whitespace characters are real spaces
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;chef-cookbook&#34;&gt;
  Chef cookbook
  &lt;a href=&#34;#chef-cookbook&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Furthermore, I created the &lt;a href=&#34;https://github.com/chr4-cookbooks/apt_cleanup&#34;&gt;apt_cleanup&lt;/a&gt; Chef cookbook,
which provides recipes to do all those tasks automatically.&lt;/p&gt;
&lt;p&gt;For a convenient auto-cleanup, the following recipes can be used&lt;/p&gt;
&lt;h4 id=&#34;apt_cleanupdefault&#34;&gt;
  apt_cleanup::default
  &lt;a href=&#34;#apt_cleanupdefault&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Includes all other cleanup recipes&lt;/p&gt;
&lt;h4 id=&#34;apt_cleanupremove_old_kernels&#34;&gt;
  apt_cleanup::remove_old_kernels
  &lt;a href=&#34;#apt_cleanupremove_old_kernels&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Removes all old kernels, but the most recent as well as the currenlty used one.&lt;/p&gt;
&lt;h4 id=&#34;apt_cleanupremove_unneeded_packages&#34;&gt;
  apt_cleanup::remove_unneeded_packages
  &lt;a href=&#34;#apt_cleanupremove_unneeded_packages&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Runs &lt;code&gt;apt-get autoremove&lt;/code&gt; to remove packages not required anymore.&lt;/p&gt;
&lt;h4 id=&#34;apt_cleanuppurge_removed_packages&#34;&gt;
  apt_cleanup::purge_removed_packages
  &lt;a href=&#34;#apt_cleanuppurge_removed_packages&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Purges already removed packages, to get rid of e.g. old config files.&lt;/p&gt;
&lt;h4 id=&#34;apt_cleanupclean_apt_cache&#34;&gt;
  apt_cleanup::clean_apt_cache
  &lt;a href=&#34;#apt_cleanupclean_apt_cache&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Runs &lt;code&gt;apt-get clean&lt;/code&gt; to remove &lt;code&gt;.dpkg&lt;/code&gt; files from &lt;code&gt;/var/cache/apt/archives&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;saltstack-formula&#34;&gt;
  Saltstack formula
  &lt;a href=&#34;#saltstack-formula&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;UPDATE 15th Oct. 2018&lt;/em&gt;: I&amp;rsquo;ve also created a &lt;a href=&#34;https://github.com/chr4/salt-apt&#34;&gt;salt formula&lt;/a&gt; to take care of cleaning up.&lt;/p&gt;
&lt;p&gt;Either run it to clean up packages immediately:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Clean up packages on this system&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo salt-call state.apply apt.cleanup.now
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Clean up packages on all nodes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo salt &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt; state.apply apt.cleanup.now
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Setup systemd timer to automatically clean packages once a day&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo salt-call state.apply apt.cleanup
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Respectively, to install it on all nodes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo salt &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt; state.apply apt.cleanup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unlike Chef, Saltstack doesn&amp;rsquo;t run periodically. To run the cleanup scripts regularily (e.g. daily), the &lt;code&gt;apt.cleanup&lt;/code&gt; state installs a systemd service and timer to cleanup your system automatically on a daily basis. Feel free to use the provided &lt;a href=&#34;https://github.com/chr4/salt-apt/blob/master/cleanup/apt-cleanup.service&#34;&gt;apt-cleanup.service&lt;/a&gt; and &lt;a href=&#34;https://github.com/chr4/salt-apt/blob/master/cleanup/apt-cleanup.timer&#34;&gt;apt-cleanup.timer&lt;/a&gt; files independently of Saltstack!&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Howto use chef with ssl</title>
      <link>https://chr4.org/posts/2013-08-01-howto-use-chef-with-ssl/</link>
      <pubDate>Thu, 01 Aug 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-08-01-howto-use-chef-with-ssl/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;By default, the connections between the chef-client and the chef-server are not secured.
This is a short post on howto encrypt and verify your connections.&lt;/p&gt;
&lt;p&gt;As of chef-11 (unlike chef-10), SSL is enabled by default. But (naturally, as Opscode cannot create trusted certificates for your domain) the certificates are not verified. This essentially means that the connection is not secure at all.&lt;/p&gt;
&lt;p&gt;Unless you only use chef in a trusted network, you should invest some time in securing your clients connections.&lt;/p&gt;
&lt;h3 id=&#34;installing-a-certificate-on-your-server&#34;&gt;
  Installing a certificate on your server
  &lt;a href=&#34;#installing-a-certificate-on-your-server&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;First, grab yourself a certificate for your chef server. This post will use a certificate from &lt;a href=&#34;http://cacert.org&#34;&gt;cacerg.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Installing the certificate to the chef-servers nginx is a little annoying. chef-11 (at least when installed using the official packages from opscode) uses a bundled nginx, instead of a system-wide one. Therefore, you need to change the configuration in &lt;code&gt;/var/opt/chef-server/nginx/etc&lt;/code&gt; which feels a little unsafe, as it might get overwritten automatically by upgrades.&lt;/p&gt;
&lt;p&gt;Fortunately, as &lt;a href=&#34;http://kickflop.net&#34;&gt;Jeff Blaine&lt;/a&gt; pointed out in an email to me, that there&amp;rsquo;s a &lt;a href=&#34;http://docs.opscode.com/config_rb_chef_server.html&#34;&gt;chef-server.rb&lt;/a&gt; config file which takes care of these problems.&lt;/p&gt;
&lt;p&gt;First, set up a resource to reconfigure chef-server when something is changed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;execute &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chef-server-ctl reconfigure&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#e6db74&#34;&gt;:nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Deploy your certificate using the &lt;a href=&#34;https://github.com/atomic-penguin/cookbook-certificate&#34;&gt;certificate cookbook&lt;/a&gt;. After that, notify the reconfigure resource, so it reconfigures in case we renew the certificate later.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# deploy certificate to chef-appliance directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;certificate_manage node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;hostname&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cert_file         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;fqdn&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.crt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cert_path         &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var/opt/chef-server/nginx/ca&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  data_bag          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;certificates&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  data_bag_secret   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/chef/certificate_data_bag_secret&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  create_subfolders &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies          &lt;span style=&#34;color:#e6db74&#34;&gt;:run&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;execute[chef-server-ctl reconfigure]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Configure the &lt;code&gt;/etc/chef-server/chef-server.rb&lt;/code&gt; using a template. Feel free to add additional settings, I chose to disable the webgui.
Again, we notify the reconfigure resource to automatically reconfigure chef in case the configuration is changed.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-erb&#34; data-lang=&#34;erb&#34;&gt;#
# Generated by Chef for &amp;lt;%= node[&amp;#39;fqdn&amp;#39;] %&amp;gt;.
# Local modifications will be overwritten.
#
chef_server_webui[&amp;#39;enable&amp;#39;]  = &amp;lt;%= @webgui.to_s %&amp;gt;
nginx[&amp;#39;ssl_certificate&amp;#39;]     = &amp;#39;&amp;lt;%= @ssl_certificate %&amp;gt;&amp;#39;
nginx[&amp;#39;ssl_certificate_key&amp;#39;] = &amp;#39;&amp;lt;%= @ssl_certificate_key %&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;template &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/chef-server/chef-server.rb&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mode      &lt;span style=&#34;color:#ae81ff&#34;&gt;00644&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  source    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chef-server.rb.erb&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  variables &lt;span style=&#34;color:#e6db74&#34;&gt;ssl_certificate&lt;/span&gt;:     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var/opt/chef-server/nginx/ca/chef.yourcompany.com.crt&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;ssl_certificate_key&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var/opt/chef-server/nginx/ca/chef.yourcompany.com.key&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;webgui&lt;/span&gt;:              &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies  &lt;span style=&#34;color:#e6db74&#34;&gt;:run&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;execute[chef-server-ctl reconfigure]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;tell-your-chef-clients-to-verify-peers&#34;&gt;
  Tell your chef-clients to verify peers
  &lt;a href=&#34;#tell-your-chef-clients-to-verify-peers&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;If you use the &lt;a href=&#34;https://github.com/opscode-cookbooks/chef-client&#34;&gt;chef-client&lt;/a&gt; cookbook you can tell your clients to verify the certificate by overriding the following attributes in your wrapper cookbook (support for verify_mode was added in chef-client-0.3.0).
Note, that you need to specify ssl_ca_path manually, as it is not set by default.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;override&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chef_client&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;config&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chef_server_url&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://chef.yourcompany.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;override&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chef_client&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;config&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ssl_verify_mode&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;verify_peer&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;override&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chef_client&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;config&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ssl_ca_path&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/ssl/certs&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or do it manually in your client.rb&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chef_server_url &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://chef.yourcompany.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_verify_mode &lt;span style=&#34;color:#e6db74&#34;&gt;:verify_peer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssl_ca_path     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/etc/ssl/certs&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you are using cacert, you may need to fix the cacert root certificate (see &lt;a href=&#34;https://gist.github.com/chr4/5805334&#34;&gt;this gist&lt;/a&gt;.
You can use the &lt;a href=&#34;https://github.com/flinc-chef/cacert&#34;&gt;cacert cookbook&lt;/a&gt; to do so automatically.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_recipe &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cacert:cacert.org&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;be-careful-with-the-remote_file-resource&#34;&gt;
  Be careful with the remote_file resource!
  &lt;a href=&#34;#be-careful-with-the-remote_file-resource&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;What I also stumbled across is, that the &lt;a href=&#34;http://docs.opscode.com/resource_remote_file.html&#34;&gt;remote_file resource&lt;/a&gt; doesn&amp;rsquo;t check certificates for https addresses either. So you might be very cautious if you use it for sensitive data, or to download scripts from the internet that will be executed later. I&amp;rsquo;m sure you do not want a script run by root modified on the way.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Chef deploy_revision and Capistrano git_style</title>
      <link>https://chr4.org/posts/2013-07-31-chef-deploy-revision-and-capistrano-git-style/</link>
      <pubDate>Wed, 31 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-07-31-chef-deploy-revision-and-capistrano-git-style/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;One thing that was annoying me for a long time, was that, using Capistrano deployment, you cannot spawn a new vanilla virtual machine, and bring it to a fully up-and-running state with just one Chef command.&lt;/p&gt;
&lt;p&gt;make deploy_revision compatible with Capistrano, so deployments can happen with Capistrano, until we&amp;rsquo;ve decided to fully migrate to Chef, or to stick with the push deployment&lt;/p&gt;
&lt;h3 id=&#34;attributes&#34;&gt;
  Attributes
  &lt;a href=&#34;#attributes&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s manage some things with attributes, so we can adjust them centrally later, in case needed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/var/www/example.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;owner&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;deploy&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;group&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;deploy&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# The shared directories that we&amp;#39;re going to need later&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;shared_directories&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;%w{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  shared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  shared/config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  shared/pids
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  shared/sockets
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;workaround-to-maintain-the-git-repository-with-a-unprivileged-user&#34;&gt;
  Workaround to maintain the git repository with a unprivileged user
  &lt;a href=&#34;#workaround-to-maintain-the-git-repository-with-a-unprivileged-user&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Due to a bug in git, we cannot use the &amp;ldquo;user&amp;rdquo; and &amp;ldquo;group&amp;rdquo; attributes in the deploy resource.
This would result in the following error&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;STDERR: fatal: unable to access &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/root/.config/git/config&amp;#39;&lt;/span&gt;: Permission denied
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Therefore, we&amp;rsquo;re chowning the app directory manually after the deploy. See &lt;a href=&#34;http://tickets.opscode.com/browse/CHEF-3940&#34;&gt;CHEF-3940&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;execute &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chown app root&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  command &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chown -R &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;owner&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;group&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#e6db74&#34;&gt;:nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;bundle-install&#34;&gt;
  bundle install
  &lt;a href=&#34;#bundle-install&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We cannot start up the application without an installed bundle. The following example mimicks the Capistrano way of &amp;ldquo;bundle install&amp;rdquo;, using &lt;a href=&#34;https://chr4.org/posts/2013-07-10-migration-from-rvm-to-chruby-on-production/&#34;&gt;chruby&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;execute &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;bundle install&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  user node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;owner&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cwd &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/current&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# bundler needs LC_ALL set, to prevent &amp;#34;invalid byte sequence in US-ASCII&amp;#34; error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# HOME also needs to be set to allow a user install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  environment &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;LC_ALL&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;en_US.UTF-8&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;HOME&amp;#39;&lt;/span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;File&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;dirname(node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  command &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/local/bin/chruby-exec &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ruby-string&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; --&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bundle install --gemfile &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/current/Gemfile&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;--path &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/shared/bundle&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;--deployment --quiet --without development test&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;].&lt;/span&gt;join(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#e6db74&#34;&gt;:nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;the-deploy-resource&#34;&gt;
  The deploy resource
  &lt;a href=&#34;#the-deploy-resource&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Now to the deploy resource. This was a little tricky, as we&amp;rsquo;re using &lt;a href=&#34;https://github.com/fnichol/capistrano-fanfare&#34;&gt;capistrano_fanfare&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://github.com/fnichol/capistrano-fanfare/blob/master/lib/capistrano/recipes/deploy/strategy/git_style.rb&#34;&gt;git_style&lt;/a&gt; deployment strategy in our deploy.rb&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;set &lt;span style=&#34;color:#e6db74&#34;&gt;:deploy_via&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:git_style&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This has several advantages to timestamped deploys, and actually Chef&amp;rsquo;s &lt;a href=&#34;http://docs.opscode.com/resource_deploy.html#deploy-revision&#34;&gt;deploy_revision&lt;/a&gt; is using a similar approach.
Unfortunately, there are some differences:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The directory where the repository is checked out. Capistrano (with :git_style) uses &lt;code&gt;current&lt;/code&gt;, whereas Chef uses &lt;code&gt;shared/cached-copy&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Release management. Capistrano creates empty folders in &lt;code&gt;releases&lt;/code&gt; using timestamp-SHA directory names, Chef creates SHA directories, with the complete repository content (but without .git)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Chef symlinks &lt;code&gt;current&lt;/code&gt;to &lt;code&gt;releases/current-SHA&lt;/code&gt;, and actually works with the &lt;code&gt;releases/current-SHA&lt;/code&gt; directory during deployment, so we need to setup a temporary link to &lt;code&gt;current&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Chef places an empty file with SHA of the current commit as the filename in the repository_cache directory. This gives Capistrano hickups when checkout out a certain commit (ambigious statement)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I was addressing those issues in the following way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;deploy_revision node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  repository &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;git@github.com:chr4/rails-app.git&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# checkout the repository to current, as capistrano :git_style would do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  repository_cache &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;../current&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  before_symlink &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# create shared directories&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;shared_directories&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;].&lt;/span&gt;each &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;dir&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      directory &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;dir&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        owner node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;owner&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        group node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;group&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        mode  &lt;span style=&#34;color:#ae81ff&#34;&gt;00755&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# remove the release directory (not a real git repo)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    directory release_path &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      recursive &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      action &lt;span style=&#34;color:#e6db74&#34;&gt;:delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# create a workaround symlink&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    link release_path &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      to &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;File&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;dirname(release_path)&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/../current&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# create symlinks to shared directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  purge_before_symlink &lt;span style=&#34;color:#e6db74&#34;&gt;%w{log tmp/sockets tmp/pids}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  create_dirs_before_symlink &lt;span style=&#34;color:#e6db74&#34;&gt;%w{tmp}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  symlinks( { &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;sockets&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tmp/sockets&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;pids&amp;#39;&lt;/span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;tmp/pids&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;log&amp;#39;&lt;/span&gt;     &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;log&amp;#39;&lt;/span&gt;} )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# remove the workaround symlink after restarting services&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  after_restart &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    link release_path &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      action &lt;span style=&#34;color:#e6db74&#34;&gt;:delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# remove strange SHA file, which is hindering capistrano&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    link &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;File&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;dirname(release_path)&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/../current/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;File&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;basename(release_path)&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      action &lt;span style=&#34;color:#e6db74&#34;&gt;:delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# owner workaround (see comment above, CHEF-3940)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies &lt;span style=&#34;color:#e6db74&#34;&gt;:run&lt;/span&gt;,     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;execute[chown app root]&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:immediately&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# install dependencies and start up application&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies &lt;span style=&#34;color:#e6db74&#34;&gt;:run&lt;/span&gt;,     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;execute[bundle install]&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;:immediately&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  notifies &lt;span style=&#34;color:#e6db74&#34;&gt;:restart&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;service[unicorn]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# only run deployment once&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# succeeding deploys will be done using capistrano (for now)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  not_if &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test -e &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-root&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/current&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;not_if&lt;/code&gt; statement allows us to continue using Capistrano to deploy like before, until we might decide to fully migrate to a continous deployment using Chef.&lt;/p&gt;
        
        </description>
    </item>
    
    <item>
      <title>Migration from rvm to chruby on production</title>
      <link>https://chr4.org/posts/2013-07-10-migration-from-rvm-to-chruby-on-production/</link>
      <pubDate>Wed, 10 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/posts/2013-07-10-migration-from-rvm-to-chruby-on-production/</guid>
      <description>
        
          
          
          
        
        
        &lt;p&gt;On our rails and worker servers at &lt;a href=&#34;https://flinc.org&#34;&gt;flinc&lt;/a&gt;, we recently migrated the ruby version management from &lt;a href=&#34;http://rvm.io&#34;&gt;rvm&lt;/a&gt; to &lt;a href=&#34;https://github.com/postmodern/chruby&#34;&gt;chruby&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besides the usual arguments against rvm, like preferring unpatched cd commands, there was another reason:&lt;/p&gt;
&lt;p&gt;The fnichol&amp;rsquo;s &lt;a href=&#34;https://github.com/fnichol/chef-rvm&#34;&gt;chef rvm cookbook&lt;/a&gt; has some issues.&lt;/p&gt;
&lt;h2 id=&#34;issues-i-experienced-using-the-rvm-cookbook&#34;&gt;
  Issues I experienced using the rvm cookbook
  &lt;a href=&#34;#issues-i-experienced-using-the-rvm-cookbook&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;rvmuser_install&#34;&gt;
  rvm::user_install
  &lt;a href=&#34;#rvmuser_install&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The rvm::user_install recipe fails, because it&amp;rsquo;s trying to find rvm in a wrong path (the global one).
This can be fixed by setting a symlink before installing rvm&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;link &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/bin/rvm&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  to &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/home/vagrant/.rvm/bin/rvm&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_recipe &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rvm::user_install&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rvm_ruby &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1.9.3&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  user &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;vagrant&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;file &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/bin/rvm&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  action &lt;span style=&#34;color:#e6db74&#34;&gt;:delete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;rvm_gem&#34;&gt;
  rvm_gem
  &lt;a href=&#34;#rvm_gem&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The rvm_gem LWRP doesn&amp;rsquo;t chown the target directly correctly (needs to belong to the user), when using user_install). It needs to be fixed with a manual chown&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rvm_gem &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;bundler&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  user &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;vagrant&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ruby_string &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;1.9.3@mygemset&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;directory &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/home/vagrant/.rvm&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  owner vagrant
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  group vagrant
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  recursive &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;bash-defunct-processes-zombies&#34;&gt;
  bash defunct processes (zombies)
  &lt;a href=&#34;#bash-defunct-processes-zombies&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Some LWRP/recipe in fnichols cookbook leave zombies behind, shown when having a look at the ps tree.
Those zombies where occurring on every server where the fnichol rvm cookbook was used.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ps axfu
root      8887  0.1  1.1 153668 60756 ?        Sl   Jul07   8:33 chef-client
root     30498  0.5  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     30545  0.7  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     30634  0.7  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     30757  0.6  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     30897  0.8  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     31149  0.7  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     31236  0.8  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     31359  0.7  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     31499  1.0  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     31622  0.9  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
root     31745  0.8  0.0      0     0 ?        Z    16:05   0:00  \_ [bash] &amp;lt;defunct&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As great as a tool as rvm is on your workstation machine, on a (production) server, you usually do not need multiple ruby versions and gemsets, but a clean and stable environment.&lt;/p&gt;
&lt;h2 id=&#34;migrating-to-chruby&#34;&gt;
  Migrating to chruby
  &lt;a href=&#34;#migrating-to-chruby&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The new setup is using fnichol&amp;rsquo;s &lt;a href=&#34;https://github.com/fnichol/chef-ruby_build&#34;&gt;ruby-build cookook&lt;/a&gt;, as well as the &lt;a href=&#34;https://github.com/Atalanta/chef-chruby/&#34;&gt;chruby cookbook&lt;/a&gt; from Atlanta.&lt;/p&gt;
&lt;p&gt;For system processes (like chef-client), I think it&amp;rsquo;s a good idea to stick to the systems ruby (therefore setting it as a default), while the application uses chruby to select its ruby version.
This is how the chruby chef recipe in my wrapper looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# install ruby_build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_recipe &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ruby_build&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# build and install ruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ruby_build_ruby node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ruby-string&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  prefix_path &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/opt/rubies/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ruby-string&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# install chruby&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;default&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chruby&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;system&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_recipe &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;chruby&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# install bundler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gem_package &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;bundler&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gem_binary &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/opt/rubies/&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#{&lt;/span&gt;node&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-rails&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;][&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ruby-string&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/bin/gem&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;migrating-rvm-wrapper-to-chruby-exec&#34;&gt;
  migrating rvm wrapper to chruby-exec
  &lt;a href=&#34;#migrating-rvm-wrapper-to-chruby-exec&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;For starting up services or tasks like &amp;ldquo;bundle install&amp;rdquo;, you can use chruby-exec, which works just as smooth as an rvm wrapper.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chruby-exec 1.9.3-p448 -- bundle install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
        </description>
    </item>
    
    <item>
      <title>whoami</title>
      <link>https://chr4.org/whoami/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://chr4.org/whoami/</guid>
      <description>
        
          
          
          
        
        
        &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ whoami
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chr4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ finger chr4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Login: chr4                             Name: Chris Aumann
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Directory: /home/chr4                   Shell: /bin/zsh
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;On since Thu Jan &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; 05:13 &lt;span style=&#34;color:#ae81ff&#34;&gt;1998&lt;/span&gt; on pts/0 from 2001:1af8:4100:a016:2::3818
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;No mail.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;No Plan.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hi, I&amp;rsquo;m Chris.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m a freelance Devops Architect, Infrastructure Developer, SRE and Security Engineer.&lt;/p&gt;
&lt;p&gt;Companies I work/ worked for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Email SaaS you can configure with git &lt;a href=&#34;https://developermail.netlify.app/&#34;&gt;developermail.io&lt;/a&gt; (Co-Founder, decommissioned)&lt;/li&gt;
&lt;li&gt;On demand responsive transport and autonomous driving service &lt;a href=&#34;http://ioki.com&#34;&gt;ioki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Dynamic ridesharing service flinc (before they where aquired by &lt;a href=&#34;https://daimler.com&#34;&gt;Daimler&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Job search engine &lt;a href=&#34;http://kimeta.de&#34;&gt;kimeta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fintech startup &lt;a href=&#34;http://vaamo.de&#34;&gt;vaamo&lt;/a&gt; (before they where aquired by &lt;a href=&#34;https://moneyfarm.com&#34;&gt;Moneyfarmi&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.ibm.com/&#34;&gt;IBM Financial Services Germany&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lsexperts.de/&#34;&gt;LSE Leading Security Experts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find me/ contact me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on &lt;a href=&#34;https://keybase.io/chr4&#34;&gt;Keybase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;as @_chr4 on &lt;a href=&#34;https://twitter.com/_chr4&#34;&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;on the social coding platform &lt;a href=&#34;https://github.com/chr4&#34;&gt;Github&lt;/a&gt; where you can also find my &lt;a href=&#34;https://github.com/chr4-cookbooks&#34;&gt;Chef cookbooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;on the professional network &lt;a href=&#34;https://www.xing.com/profiles/Chris_Aumann&#34;&gt;Xing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;on the &lt;a href=&#34;http://community.opscode.com/users/chr4?user_tab_string=cookbooks&#34;&gt;Opscode Chef Community&lt;/a&gt; where I share my chef cookbooks&lt;/li&gt;
&lt;li&gt;via email: &lt;span id=&#34;email&#34;&gt;(sorry, no email without JavaScript, because hoping spambots are still stupid)&lt;/span&gt; &lt;span id=&#34;gpg&#34;&gt;[&lt;a href=&#34;https://chr4.org/941AD728.asc&#34;&gt;gpg&lt;/a&gt;]&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;supportsupport&#34;&gt;
  &lt;a href=&#34;https://chr4.org/whoami/#support&#34;&gt;Support&lt;/a&gt;
  &lt;a href=&#34;#supportsupport&#34; class=&#34;h-anchor&#34; aria-hidden=&#34;true&#34;&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m always glad getting little &amp;ldquo;thank-you&amp;rdquo; emails or feedback about an article!&lt;/p&gt;
&lt;script src=&#34;https://chr4.org/obfuscate.js&#34; type=&#34;text/javascript&#34; language=&#34;javascript&#34;&gt;

        
        </description>
    </item>
    
  </channel>
</rss>