<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gradew</title>
    <description>Notes, feedback and rants of some random system and network admin
</description>
    <link>http://gradew.net/</link>
    <atom:link href="http://gradew.net/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 08 Jun 2025 17:11:30 +0200</pubDate>
    <lastBuildDate>Sun, 08 Jun 2025 17:11:30 +0200</lastBuildDate>
    <generator>Jekyll v4.3.1</generator>
    
      <item>
        <title>Hosting your own OpenStreetMap tile server with imposm3</title>
        <description>&lt;p&gt;I’ve grown quite fond of the OpenStreetMap project, especially the self-hosting solution that comes with it.
Of course, I would need an entire server farm to come even close the what Google Maps is capable of,
but with the use of the imposm3 tool, well, one can get very interesting results!&lt;/p&gt;

&lt;p&gt;I will be using imposm3 for the imports and updates, mapnik for the rendering engine and mod_tile to generate and serve files over the almighty intrawebz.&lt;/p&gt;

&lt;h1 id=&quot;why-not-osm2pgsql-&quot;&gt;Why not osm2pgsql ?&lt;/h1&gt;

&lt;p&gt;If you’ve ever tried importing an entire country with osm2pgsql, you’ll know how much of a pain that is.
It took me about 18 hours to import France, and don’t even get me started on diff imports or later country imports.&lt;/p&gt;

&lt;p&gt;If I want to have a somewhat sexy self-hosted mapping solution, at least let me have daily diffs and decent performance from the ground up!&lt;/p&gt;

&lt;p&gt;That’s where imposm rocked my world! It reduced importing time to a mere 2.5 hours, and I found the tables to be most convenient:
some tables are “generalized” to account for various zoom levels, meaning it won’t have to process as much data when only low detail is required.
Also, it’s way easier to figure out where all the objects are: roads/paths/tracks/highways are in osm_roads, buildings are in osm_buildings, areas are in osm_areas, etc.&lt;/p&gt;

&lt;h1 id=&quot;why-cant-i-just-use-that-with-mapnik-then-&quot;&gt;Why can’t I just use that with mapnik then ?&lt;/h1&gt;

&lt;p&gt;Well, you can, but the generated osm.xml file only works with osm2pgsql imports.
That’s when I figured out I needed to understand how this file works, and build my own for imposm3.&lt;/p&gt;

&lt;h1 id=&quot;installink-mapnik-with-libxml2&quot;&gt;Installink mapnik (with libxml2)&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;make cmake g++ libboost-dev libboost-system-dev   libboost-filesystem-dev libexpat1-dev zlib1g-dev   libbz2-dev libpq-dev libproj-dev lua5.2 liblua5.2-dev
apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;clang libxml2 libxml2-dev libxml2-utils liblwgeom-dev libpq-dev libproj-dev zlib1g-dev libharfbuzz-dev libfreetype6-dev libboost-all-dev python-setuptools unifont postgis

git clone https://github.com/mapnik/mapnik
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mapnik
git submodule update &lt;span class=&quot;nt&quot;&gt;--init&lt;/span&gt;
python scons/scons.py &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XMLPARSER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;libxml2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;installing-mod_tile&quot;&gt;Installing mod_tile&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libagg-dev

git clone https://github.com/openstreetmap/mod&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;tile.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mod&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;tile
./autogen.sh
./configure
make &lt;span class=&quot;nt&quot;&gt;-j2&lt;/span&gt;
make &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;make install-mod&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;tile&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next, you’ll need to create /etc/renderd.conf:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;renderd]
&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;socketname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/run/renderd/renderd.sock
num&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;threads&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4
tile&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/lib/mod&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;tile
stats&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/run/renderd/renderd.stats

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;mapnik]
plugins&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/lib/mapnik/input
font&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/lib/mapnik/fonts
font&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;recurse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;default]
&lt;span class=&quot;nv&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tiles/
&lt;span class=&quot;nv&quot;&gt;TILEDIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/lib/mod&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;tile
&lt;span class=&quot;nv&quot;&gt;XML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/osm/imposm.xml
&lt;span class=&quot;nv&quot;&gt;HOST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;localhost
&lt;span class=&quot;nv&quot;&gt;TILESIZE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;256&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, put this in your Apache vhost:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;	ServerAdmin webmaster@localhost
	ServerName map-tiles.gradew.net
	DocumentRoot /var/www/tiles

	&amp;lt;IfModule mod_tile.c&amp;gt;
		LoadTileConfigFile /etc/renderd.conf
		&lt;span class=&quot;c&quot;&gt;#ModTileRenderdSocketName /tmp/osm-renderd&lt;/span&gt;
		ModTileRenderdSocketName /var/run/renderd/renderd.sock
		ModTileRequestTimeout 3
		ModTileMissingRequestTimeout 30
		ModTileMaxLoadOld 2

		&lt;span class=&quot;c&quot;&gt;# In bulk mode, mod_tile does not request any dirty tiles to be rerendered.&lt;/span&gt;
		ModTileBulkMode On

		&lt;span class=&quot;c&quot;&gt;# That&apos;s a week&lt;/span&gt;
		&lt;span class=&quot;c&quot;&gt;# ModTileCacheDurationMax 604800&lt;/span&gt;
		&lt;span class=&quot;c&quot;&gt;# That&apos;s a year&lt;/span&gt;
		ModTileCacheDurationMax 31536000
	&amp;lt;/IfModule&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sun, 06 Jan 2019 21:19:00 +0100</pubDate>
        <link>http://gradew.net/2019/01/06/hosting-osm-tiles/</link>
        <guid isPermaLink="true">http://gradew.net/2019/01/06/hosting-osm-tiles/</guid>
        
        
        <category>system</category>
        
        <category>openstreetmap</category>
        
        <category>tile</category>
        
        <category>imposm</category>
        
      </item>
    
      <item>
        <title>Free SSL/TLS certificates with Let&apos;s Encrypt</title>
        <description>&lt;p&gt;We’ve all been there: buying self-signed certificates is a bit annoying, especially when it comes to wildcards.
A new project has been around for a couple of months now, it’s called Let’s Encrypt.&lt;/p&gt;

&lt;p&gt;It’s basically a bunch of scripts that will help you sign certificates for your Apache/Nginx vhosts… and for free, no less!
The good news is that these certificates will be recognized by pretty much any browser. Farewell, security alerts!
The bad news is: no wildcard support for now. Well… that’s not exactly bad news, since you can create as many certificates
as you want, and SNI is rather widespread now.&lt;/p&gt;

&lt;h1 id=&quot;installing-lets-encrypt&quot;&gt;Installing Let’s Encrypt&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;git clone https://github.com/letsencrypt/letsencrypt
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;letsencrypt
./letsencrypt-auto &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;creatingsigning-a-new-certificate&quot;&gt;Creating/signing a new certificate&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;letsencrypt
./letsencrypt-auto certonly &lt;span class=&quot;nt&quot;&gt;--webroot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /var/www/vhost_path/ &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; FQDN&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;configuring-apache&quot;&gt;Configuring Apache&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;SSLCertificateFile /etc/letsencrypt/live/FQDN/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/FQDN/privkey.pem&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;checking-your-certificates&quot;&gt;Checking your certificates&lt;/h1&gt;

&lt;p&gt;Certificates signed with Let’s Encrypt will be valid for 3 months. All the more reason to crontab a script I whipped up for the occasion:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;rootpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/etc/letsencrypt/live&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;604800 &lt;span class=&quot;c&quot;&gt;# 1 week&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;RETVAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
&lt;span class=&quot;nv&quot;&gt;ISCRON&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--cron&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISCRON&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
    &lt;span class=&quot;k&quot;&gt;fi
fi

for &lt;/span&gt;d &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rootpath&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;certpath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rootpath&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/fullchain.pem
    &lt;span class=&quot;nv&quot;&gt;expirydate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;openssl x509 &lt;span class=&quot;nt&quot;&gt;-enddate&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;certpath&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/notAfter=//&apos;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;openssl x509 &lt;span class=&quot;nt&quot;&gt;-checkend&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;certpath&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ISCRON&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; OK&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fi
    else
        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; WILL EXPIRE ON &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expirydate&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;RETVAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
    &lt;span class=&quot;k&quot;&gt;fi
done

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$RETVAL&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The crontab entry will need to look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;MAILTO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;admin@yourdomain.com
0 0 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /path/check_certs.sh &lt;span class=&quot;nt&quot;&gt;--cron&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Wed, 17 Feb 2016 11:13:00 +0100</pubDate>
        <link>http://gradew.net/2016/02/17/letsencrypt-101/</link>
        <guid isPermaLink="true">http://gradew.net/2016/02/17/letsencrypt-101/</guid>
        
        
        <category>system</category>
        
        <category>certificates</category>
        
        <category>ca</category>
        
        <category>letsencrypt</category>
        
      </item>
    
      <item>
        <title>PostgreSQL replication (part 1/2)</title>
        <description>&lt;p&gt;Here’s a quick manual on how to compile, install and set up PostgreSQL 9.5.
I will also explain how to set up asynchronous replication between two nodes.&lt;/p&gt;

&lt;p&gt;This has been tested on a 64-bit Debian Jessie.&lt;/p&gt;

&lt;p&gt;Note: the binaries will be installed to /opt/postgres, and the scripts and data will be installed to /home/postgres.
Feel free the change the paths from the script according to your needs.&lt;/p&gt;

&lt;h1 id=&quot;compiling-and-installing-postgresql&quot;&gt;Compiling and installing PostgreSQL&lt;/h1&gt;
&lt;p&gt;Install all needed dependencies:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;wget bzip2 g++ flex bison libreadline-dev zlib1g-dev make&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Get the source archive from the official website, un-tar it, compile and install the beast:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xjvf postgresql-9.5.0.tar.bz2
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;postgresql-9.5.0
./configure &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/postgres &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;contrib &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, create a user and its environment:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;groupadd postgres &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; useradd &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; postgres &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/bash &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /home/postgres postgres &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /home/postgres &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /etc/skel/.&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /home/postgres &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; postgres:postgres /home/postgres&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Change to the postgres user:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;su - postgres&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Add the following lines to .bashrc (make sure all paths are correct):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PG_HOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/postgres&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PG_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/home/postgres/data&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PG_HOME&lt;/span&gt;/bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PG_HOME&lt;/span&gt;/lib:&lt;span class=&quot;nv&quot;&gt;$LD_LIBRARY_PATH&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Create a file called ~/vars with the following (make sure all paths are correct):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PG_DATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/home/postgres/data&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PG_WALPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/home/postgres/walarchives&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PG_THISNODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pg01&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PG_OTHERNODE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pg02&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;configuring-postgresql&quot;&gt;Configuring PostgreSQL&lt;/h1&gt;
&lt;p&gt;Make sure you’re still logged in as postgres, and initialize the database:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;initdb &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PG_DATA&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will create an empty database, as well as default configuration files.
Here’s where you start tweaking things on your own, but here’s something to get you started; add the following lines to $PG_DATA/postgresql.conf:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;&lt;span class=&quot;n&quot;&gt;listen_addresses&lt;/span&gt; = &lt;span class=&quot;s1&quot;&gt;&apos;*&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log_destination&lt;/span&gt; = &lt;span class=&quot;s1&quot;&gt;&apos;stderr&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logging_collector&lt;/span&gt; = &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log_directory&lt;/span&gt; = &lt;span class=&quot;s1&quot;&gt;&apos;pg_log&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log_filename&lt;/span&gt; = &lt;span class=&quot;s1&quot;&gt;&apos;postgresql-%Y-%m-%d.log&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;log_rotation_age&lt;/span&gt; = &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;starting-and-stopping-postgresql&quot;&gt;Starting and stopping PostgreSQL&lt;/h1&gt;
&lt;p&gt;You are now ready to use your PostgreSQL instance. Here’s how it goes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pg_ctl &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PG_DATA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;start|stop|reload]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;setting-up-asynchronous-replication&quot;&gt;Setting up asynchronous replication&lt;/h1&gt;
&lt;p&gt;This set-up will assume you have two different servers with no shared filesystem between them.
If you do happen to have a shared filesystem, you might want to change the ugly “scp” from archive_command.sh below to a simple “cp” (still ugly, but should be faster).&lt;/p&gt;

&lt;h2 id=&quot;how-replication-works-in-postgresql&quot;&gt;How replication works in PostgreSQL&lt;/h2&gt;
&lt;p&gt;Many find PG replication a dirty business to set-up. Granted, things look kind of messy when you start calling shell scripts from your database configuration files.
But once you get the hang of it, it actually becomes simple, and even robust.&lt;/p&gt;

&lt;p&gt;Bear in mind that a PG cluster is far more suitable in a dedicated infrastructure (like two servers on the same LAN in a datacenter with a SAN attached to them).
It can still work in other infrastructure types, but you definitely won’t get the same performance out of it.&lt;/p&gt;

&lt;p&gt;Basically, in a nominal state, a cluster will have a master node, which you can use to do SELECTs and INSERTs/UPDATEs/DELETEs, and the like…
The slave node(s) will maintain a connection with the master node to replicate all operations made by the master. If you do anything on the master databases,
it will be replicated to the slave databases.&lt;/p&gt;

&lt;p&gt;This is the purpose of having “recovery.conf” in your $PG_DATA directory. When you boot up PostgreSQL, and it finds recovery.conf, it will start as a slave,
and immediately connect to the master node to be kept updated of all changes that are made.
Being a slave PG node also means the database will have to be created from a backup of the master node. This can be done on-the-fly by using the init_as_slave.sh script
given below.
You’ll notice that this step can be achieved with a simple command run from the slave node: pg_basebackup.&lt;/p&gt;

&lt;p&gt;In case communication fails between the master and the slave, redo logs are created by the master node, and sent over to the slave node. These are called WAL
archives. This is done by the “archive_command.sh” script below. You’ll notice that it uses the “scp” command to copy the WAL archive over to the slave.
Make sure that the “postgres” user from the master node can SSH to the “postgres” user of the slave node. And the other way around.&lt;/p&gt;

&lt;p&gt;Once the WAL archives have been assimilated by the slave node, it runs the pg_archivecleanup command, as declared in recovery.conf.
WAL archives are then deleted from the slave. Make sure you monitor disk space, though: if the slave node fails, the WAL archives will keep
accumulating and will eventually (and rather quickly) gobble up all your storage space.&lt;/p&gt;

&lt;p&gt;And that’s pretty much all there is to understand about replication in PostgreSQL :)&lt;/p&gt;

&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;We’ll assume you’re setting up two replicated servers, one of which will be the master, the other one will be the slave.
Start by setting up the slave server the same way you did with the master.
Then, add the following to $PG_DATA/postgresql.conf on both servers (yes, both - also, make sure the paths are correct):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;&lt;span class=&quot;n&quot;&gt;hot_standby&lt;/span&gt; = &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wal_level&lt;/span&gt; = &lt;span class=&quot;n&quot;&gt;hot_standby&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;archive_mode&lt;/span&gt; = &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;archive_command&lt;/span&gt; = &lt;span class=&quot;s1&quot;&gt;&apos;/home/postgres/archive_command.sh &quot;%p&quot; &quot;%f&quot;&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;archive_timeout&lt;/span&gt; = &lt;span class=&quot;m&quot;&gt;60&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;max_wal_senders&lt;/span&gt; = &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Execute the following script to create ~/archive_command.sh on both servers:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/archive_command.sh&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
#!/bin/sh
. ~/vars

if [ -z &quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_OTHERNODE&quot; ]; then
  echo &quot;PG_OTHERNODE undefined!&quot;
  exit 1
fi
fullpath=&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;1&quot;
walfile=&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;2&quot;
scp &quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;fullpath&quot; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_OTHERNODE:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_WALPATH/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;walfile &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
exit 0
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x ~/archive_command.sh&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, create ~/recovery.conf on both servers (make sure all paths are correct, and don’t forget to replace ‘other_node’ and ‘this_node_name’ with the appropriate values):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/recovery.conf&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
standby_mode = &apos;on&apos;
primary_conninfo = &apos;host=other_node application_name=this_node_name&apos;
trigger_file = &apos;/tmp/pgtrigger&apos;
restore_command = &apos;cp /home/postgres/walarchives/%f %p&apos;
archive_cleanup_command = &apos;/opt/postgres/bin/pg_archivecleanup /home/postgres/walarchives %r&apos;
EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Add the following line to $PG_DATA/pg_hba.conf (again, on both servers):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;&lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;replication&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;     &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;/&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;               &lt;span class=&quot;n&quot;&gt;trust&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Create the final utility script on both servers:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/init_as_slave.sh&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
#!/bin/sh

. ~/vars

if [ -z &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_DATA ]; then
  echo &quot;PG_DATA undeclared!&quot;
  exit 1
fi
if [ -z &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_OTHERNODE ]; then
  echo &quot;PG_OTHERNODE undeclared!&quot;
  exit 1
fi
if [ ! -f &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_DATA/postgresql.conf ]; then
  echo &quot;Wrong directory, mate!&quot;
  exit 1
fi
pg_ctl -D &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_DATA stop &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
rm -rf &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_DATA/*
rm -rf &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;HOME/walarchives/*
pg_basebackup -D &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_DATA --host=&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_OTHERNODE --port=5432
if [ &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;? -eq 0 ]; then
  cp ~/*.conf &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;PG_DATA/
else
  echo &quot;Could not back up database!&quot;
  exit 1
fi
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x ~/init_as_slave.sh&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;ok-so-what-are-all-these-scripts-for-&quot;&gt;Ok, so what are all these scripts for ?&lt;/h2&gt;
&lt;p&gt;You’ve probably guessed by now… For the moment, PostgreSQL bases all of its replication work on scripts and actions on the filesystem:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;copying the redo logs from the master node to the slave node(s) is done by a script, archive_command.sh&lt;/li&gt;
  &lt;li&gt;automatic purging of the redo logs on the slave nodes is also done by a script: the archive_cleanup_command and  restore_command settings defined in recovery.conf&lt;/li&gt;
  &lt;li&gt;promoting a node from slave to master is also done by creating “/tmp/pgtrigger” on the slave node; this is defined in recovery.conf as well&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;

&lt;p&gt;You can start the instance on the master node:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pg_ctl &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PG_DATA&lt;/span&gt; start&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And replication from the slave side can be initiated as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;~/init_as_slave.sh
pg_ctl &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PG_DATA&lt;/span&gt; start&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;this-concludes-part-12&quot;&gt;This concludes part 1/2&lt;/h1&gt;
&lt;p&gt;If everything went according to plan, you should have a working simple PostgreSQL cluster, where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;One node is a master, and can be used to read from and write to&lt;/li&gt;
  &lt;li&gt;The second node is a slave, and can only be used to read from it&lt;/li&gt;
  &lt;li&gt;Replication is asynchronous; the performance impact will be kept to a minimum. Also, if the slave node fails, the master won’t mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we’ve paved the way for all the replication work, here. But keep in mind that all of this doesn’t make for a full-blown, usable cluster; your application will need to use some kind of PostgreSQL proxy in order to always be sure to connect to a master node.
This can be done with PGPool, and will be covered in part 2 :)&lt;/p&gt;

</description>
        <pubDate>Fri, 08 Jan 2016 15:07:00 +0100</pubDate>
        <link>http://gradew.net/2016/01/08/pgsql-replication/</link>
        <guid isPermaLink="true">http://gradew.net/2016/01/08/pgsql-replication/</guid>
        
        
        <category>system</category>
        
        <category>postgresql</category>
        
      </item>
    
      <item>
        <title>NAXSI, a firewall for NGINX</title>
        <description>&lt;p&gt;NAXSI is an open-source WAF for NGINX that uses whitelists to determine whether traffic should be authorized.
Don’t think of it as some simple, ready-to-use IDS, though. You will need to generate the whitelists yourself, based on &lt;strong&gt;your&lt;/strong&gt; own set-up.&lt;/p&gt;

&lt;p&gt;Here is an excerpt of the description:&lt;/p&gt;

&lt;p&gt;_NAXSI means Nginx Anti XSS &amp;amp; SQL Injection.&lt;/p&gt;

&lt;p&gt;Technically, it is a third party nginx module, available as a package for many UNIX-like platforms. This module, by default, reads a small subset of simple (and readable) rules containing 99% of known patterns involved in websites vulnerabilities. For example, &amp;lt;, | or drop are not supposed to be part of a URI.&lt;/p&gt;

&lt;p&gt;Being very simple, those patterns may match legitimate queries, it is Naxsi’s administrator duty to add specific rules that will whitelist those legitimate behaviours. The administrator can either add whitelists manually by analyzing nginx’s error log, or (recommended) start the project by an intensive auto-learning phase that will automatically generate whitelisting rules regarding website’s behaviour.&lt;/p&gt;

&lt;p&gt;In short, Naxsi behaves like a DROP-by-default firewall, the only job needed is to add required ACCEPT rules for the target website to work properly._&lt;/p&gt;

&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Install it and set it to Learning Mode (which is the default)&lt;/li&gt;
  &lt;li&gt;Logs will be appended to /var/log/nginx/error.log, with the “NAXSI_FMT” prefix. Let it run for a while (hours, days, weeks…)&lt;/li&gt;
  &lt;li&gt;While you do that, set up an Elasticsearch instance and create an index called “nxapi”&lt;/li&gt;
  &lt;li&gt;Alter nxapi.json to make it point to your Elasticsearch instance&lt;/li&gt;
  &lt;li&gt;Feed all the generated logs into Elasticsearch:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;nxtool.py &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; nxapi.json &lt;span class=&quot;nt&quot;&gt;--file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/log/nginx/error.log&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Generate whitelists and manually review them:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;nxtool.py &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; nxapi.json &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--slack&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Apply your reviewed whitelists and disable Learning Mode; you’re all set!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, I know… Using Elasticsearch simply to store the logs might seem a bit much, but using Postgres/MySQL apparently wasn’t so easy.
Setting up an ES instance isn’t so hard anyway, I’ll write up an article about that.&lt;/p&gt;

&lt;p&gt;The source for NAXSI can be found here: &lt;a href=&quot;https://github.com/nbs-system/naxsi&quot; target=&quot;_blank&quot;&gt;https://github.com/nbs-system/naxsi&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 04 Jan 2016 15:45:10 +0100</pubDate>
        <link>http://gradew.net/2016/01/04/naxsi/</link>
        <guid isPermaLink="true">http://gradew.net/2016/01/04/naxsi/</guid>
        
        
        <category>system</category>
        
        <category>waf</category>
        
        <category>security</category>
        
      </item>
    
      <item>
        <title>In Memoriam - Ian Murdock (1973 - 2015)</title>
        <description>&lt;p&gt;Thanks for everything, man.&lt;/p&gt;

</description>
        <pubDate>Thu, 31 Dec 2015 12:00:00 +0100</pubDate>
        <link>http://gradew.net/2015/12/31/ripian/</link>
        <guid isPermaLink="true">http://gradew.net/2015/12/31/ripian/</guid>
        
        
        <category>debian</category>
        
        <category>ian</category>
        
        <category>murdock</category>
        
      </item>
    
      <item>
        <title>Google Authenticator and FreeRADIUS</title>
        <description>&lt;p&gt;Two-factor authentication is all around us now, and Google has provided one of those soft authenticators, the likes of which Battle.net use for their gaming platform.
The only difference is, you can integrate Google’s implementation anywhere you like (at least on *nix platforms).
You’ll find plenty of documentation on how to achieve this to implement 2-factor auth on SSH or such services, but I wanted to centralize this and use FreeRADIUS so that more services can use it, namely web services.&lt;/p&gt;

&lt;p&gt;The hardest part was actually the PAM syntax; here’s how I achieved it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;aptitude install g++ make autoconf libtool libpam0g-dev&lt;/li&gt;
  &lt;li&gt;git clone https://github.com/google/google-authenticator &amp;amp;&amp;amp; cd google-authenticator &amp;amp;&amp;amp; ./bootstrap.sh &amp;amp;&amp;amp; ./configure &amp;amp;&amp;amp; make install&lt;/li&gt;
  &lt;li&gt;Set up Freeradius for PAM auth; this is fairly easy, and Google is your friend 😉&lt;/li&gt;
  &lt;li&gt;/etc/pam.d/radiusd:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Google Auth + LDAP&lt;/span&gt;
auth required /usr/local/lib/security/pam_google_authenticator.so &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 &lt;span class=&quot;nv&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/radius/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/google_auth forward_pass
auth required pam_ldap.so use_first_pass&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And that’s it; FreeRADIUS is now tied in to PAM, which in turns uses Google Auth + your LDAP server :-)&lt;/p&gt;
</description>
        <pubDate>Mon, 05 Jan 2015 12:00:00 +0100</pubDate>
        <link>http://gradew.net/2015/01/05/googleauthfreeradius/</link>
        <guid isPermaLink="true">http://gradew.net/2015/01/05/googleauthfreeradius/</guid>
        
        
        <category>system</category>
        
      </item>
    
      <item>
        <title>Microsoft and e-mail deliverability</title>
        <description>&lt;p&gt;Well, it’s been a while since my last rant at Microsoft, but this time just takes the cake.
Here’s what’s happening now: both my mail exchangers have been blacklisted. It might be worth noting that the very same IPs are all in the green on the DNSBLs.
Also, these MXs have a throughput of roughly 200 emails / month. YES, I did check EVERY email in and out of my MXs, and none of them were spam (20 of them were personal emails sent to ONE hotmail.com addy). So I’m no spammer. Nevertheless, I got blacklisted. I asked to be delisted, but I got blacklisted again 2 days afterwards.
Here’s what the guys at support have to say about this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Email filtering is based on many factors, but primarily it’s due to mail content and recipient interaction with that mail.  Because of the proprietary nature of SmartScreen® and because SmartScreen® Filter technology is always adapting and learning more about what is and isn’t unwanted mail, it is not possible for us to offer specific advice about improving your mail content. However, in general SmartScreen® Filter evaluates specific words or characteristics from each e-mail message and weights them, based on their likelihood to indicate that a message is unwanted or legitimate mail.
Unfortunately, after reviewing the information you provided and in compliance with our mail policies, we are unable to offer immediate mitigation for your deliverability issue. However, we have some specific recommendations for you to consider that can help you to improve deliverability over time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In other words, “We don’t know what the hell we’re doing, so go fuck yourself”.
I currently have SPF and DKIM in place. I took some time to check their “guidelines”, and these guys happen to have written a “white paper” on e-mail deliverability; I think someone tricked them into thinking they were some kind of authority on e-mail deliverability. Here’s a funny excerpt from it:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you believe your e-mail has been blocked in error by Microsoft, please review our best practices and technical guidelines to ensure compliance.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Again, in other words “If we’re mistaken, go fuck yourself too.”&lt;/p&gt;

&lt;p&gt;I only have one piece of advice for all Hotmail users out there: switch to another provider! I mean it.
If you haven’t, see my previous post on how Microsoft got hold of one of my aliases to sell it to spammers. If that doesn’t frighten you, I don’t know what will.&lt;/p&gt;

</description>
        <pubDate>Mon, 07 Jul 2014 13:00:00 +0200</pubDate>
        <link>http://gradew.net/2014/07/07/microsoftemail/</link>
        <guid isPermaLink="true">http://gradew.net/2014/07/07/microsoftemail/</guid>
        
        
        <category>system</category>
        
        <category>network</category>
        
      </item>
    
      <item>
        <title>Xen and IPv6</title>
        <description>&lt;p&gt;I whipped up a (seemingly) working IPv6 set-up for both my hypervisors, meaning my services will soon be IPv6-compliant; yay!
I did struggle with it, though. There are a couple of gotchas one needs to be aware of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it is best to use RA, in case your provider changes the default gateway for your server&lt;/li&gt;
  &lt;li&gt;if your hypervisor is going to be a firewall (which I  guess it is), you will need to use RADVD to advertise your dom0 to your domUs&lt;/li&gt;
  &lt;li&gt;RA and IPv6 forwarding do actually work together, but you need to enable both in sysctl.conf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get on with it, then. First, let’s set up IPv6 on the dom0:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/bin:/sbin:/usr/bin:/usr/sbin

sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; net.ipv6.conf.all.forwarding&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; net.ipv6.conf.xenbr0.accept_ra&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2
sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; net.ipv6.conf.xenbr0.autoconf&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1

dhclient &lt;span class=&quot;nt&quot;&gt;-cf&lt;/span&gt; /etc/dhcp/dhclient6.conf &lt;span class=&quot;nt&quot;&gt;-pf&lt;/span&gt; /run/dhclient6.xenbr0.pid &lt;span class=&quot;nt&quot;&gt;-6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; xenbr0
ip &lt;span class=&quot;nt&quot;&gt;-6&lt;/span&gt; a add 2001:c0de:babe:580::1/56 dev xenbr0
ip &lt;span class=&quot;nt&quot;&gt;-6&lt;/span&gt; ro add 2001:c0de:babe:581::/64 dev xapi0

/etc/init.d/radvd start&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is what dhclient6.conf looks like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;interface &lt;span class=&quot;s2&quot;&gt;&quot;xenbr0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
          send dhcp6.client-id &amp;lt;your DUID here&amp;gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          request&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, configure RADVD; it will have to advertise on the internal domU network (xapi0):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;interface xapi0
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        AdvSendAdvert on&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        prefix  2001:c0de:babe:581::/64
        &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                AdvOnLink on&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                AdvAutonomous on&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, you may want to firewall this all up a bit:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; INPUT DROP
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; OUTPUT ACCEPT
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; FORWARD DROP
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Z&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; state &lt;span class=&quot;nt&quot;&gt;--state&lt;/span&gt; ESTABLISHED,RELATED &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT &lt;span class=&quot;c&quot;&gt;# Multicast traffic - needed for IPv6 routing&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ipv6-icmp &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; ff00::/8 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT &lt;span class=&quot;c&quot;&gt;# Link-local traffic as well, I guess it couldn&apos;t hurt...&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ipv6-icmp &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; fe80::/10 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; INPUT &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; udp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 546 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT &lt;span class=&quot;c&quot;&gt;# DHCPv6&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; state &lt;span class=&quot;nt&quot;&gt;--state&lt;/span&gt; ESTABLISHED,RELATED &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; xapi+ &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; xenbr0 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nv&quot;&gt;$IPT6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; xenbr0 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; xapi+ &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; multiport &lt;span class=&quot;nt&quot;&gt;--dports&lt;/span&gt; 80,443 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$vm01_ipv6&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And there you go! You will need to make sure IPv6 multicast traffic can go from the dom0 to the domUs through xapi+: RADVD needs this to advertise.&lt;/p&gt;

</description>
        <pubDate>Mon, 21 Apr 2014 13:00:00 +0200</pubDate>
        <link>http://gradew.net/2014/04/21/xenipv6/</link>
        <guid isPermaLink="true">http://gradew.net/2014/04/21/xenipv6/</guid>
        
        
        <category>system</category>
        
        <category>network</category>
        
      </item>
    
      <item>
        <title>IPSec w/ Racoon and TCP MSS Clamping</title>
        <description>&lt;p&gt;After a couple of weeks running IPSec in transport mode between two dedicated servers (i.e. on their respective public IP addresses), things started running amok, with the following messages in the syslogs:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Mar 16 16:37:29 host1 kernel: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;5985158.107191] pmtu discovery on SA ESP/4f014d9c/ddaec880
Mar 16 16:37:42 host1 kernel: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;5985171.146710] pmtu discovery on SA ESP/4f014d9c/ddaec880
Mar 16 16:37:43 host1 kernel: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;5985172.458608] pmtu discovery on SA ESP/4f014d9c/ddaec880
Mar 16 16:38:10 host1 kernel: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;5985199.337572] pmtu discovery on SA ESP/4f014d9c/ddaec880
Mar 16 16:38:12 host1 kernel: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;5985201.193461] pmtu discovery on SA ESP/4f014d9c/ddaec880&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This appears to happen when big enough packets are trying to get through, and things go wrong because of the overhead induced by ESP packets.
Also, it would appear my iptables rules are breaking PMTU by refusing certain ICMP packets, which are used in PMTU discovery. I will need to dig deeper into that.&lt;/p&gt;

&lt;p&gt;In the meantime, here’s a quick (and dirty?) hack to clamp the Maximum Segment Size for TCP sessions and avoid overloading the packet size:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--tcp-flags&lt;/span&gt; SYN,RST SYN &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; TCPMSS &lt;span class=&quot;nt&quot;&gt;--clamp-mss-to-pmtu&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you’re using PF, it may look something like this (though I haven’t tested it myself, but that’s the general idea):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;match on em0 scrub &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;max-mss 1440&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Tue, 25 Mar 2014 12:00:00 +0100</pubDate>
        <link>http://gradew.net/2014/03/25/ipsecracoonmssclamping/</link>
        <guid isPermaLink="true">http://gradew.net/2014/03/25/ipsecracoonmssclamping/</guid>
        
        
        <category>network</category>
        
      </item>
    
      <item>
        <title>Yubico validation server</title>
        <description>&lt;p&gt;In an era where getting your credentials stolen has become child’s play with spyware and keyloggers, it might be best to start using two-factor authentication.
For a lot of companies out there, this means adding a second factor on top of an AD/LDAP infrastructure.&lt;/p&gt;

&lt;p&gt;It’s actually easier than you think, and it won’t cost you an arm and leg. I will soon write a tutorial on how I achieved this.&lt;/p&gt;

&lt;p&gt;The core service you will need is a validation server for YubiKeys. Whether you’re using LDAP or a Samba 4 instance to authenticate your users,
it will all still come down to validating the OTP strings your users will be sending.
If you search for the Yubico validation server, you’ll find yourself using old/deprecated/broken versions of the tool, depending on your distro (but even on recent ones).&lt;/p&gt;

&lt;p&gt;I stumbled upon Raphaël Barrois’ version, hosted on Github, which was almost exactly what I needed (thanks, honestly!). Then again, I had to add some bells and whistles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Support for PostgreSQL&lt;/li&gt;
  &lt;li&gt;Auditing capabilities on OTP tokens&lt;/li&gt;
  &lt;li&gt;A working example of an init.d script for this baby&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And bam, there it is: &lt;a href=&quot;https://github.com/gradew/yubiserve&quot; target=&quot;_blank&quot;&gt;https://github.com/gradew/yubiserve&lt;/a&gt;. Feel free to use it! :)&lt;/p&gt;

</description>
        <pubDate>Sun, 09 Mar 2014 12:00:00 +0100</pubDate>
        <link>http://gradew.net/2014/03/09/yubicovalidationserver/</link>
        <guid isPermaLink="true">http://gradew.net/2014/03/09/yubicovalidationserver/</guid>
        
        
        <category>system</category>
        
      </item>
    
  </channel>
</rss>
