<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="https://uname.pingveno.net/blog/index.php/feed/rss2/xslt" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title># uname -a - Hacks</title>
    <link>https://uname.pingveno.net/blog/index.php/</link>
    <atom:link href="https://uname.pingveno.net/blog/index.php/feed/category/notes/informatique/hacks/rss2" rel="self" type="application/rss+xml" />
    <description>Le blog de uname.pingveno.net</description>
    <language>fr</language>
    <pubDate>Wed, 01 Apr 2026 16:19:15 +0200</pubDate>
    <copyright>Mathieu Pellegrin</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>Dotclear</generator>
          <item>
        <title>Configure a 3CX extension with Big Blue Button conferencing bridge (Freeswitch)</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2020/10/23/Configure-a-3CX-extension-with-Big-Blue-Button-conferencing-bridge-%28Freeswitch%29</link>
        <guid isPermaLink="false">urn:md5:c6d5cd185f79ab65b59e18b2078e003a</guid>
        <pubDate>Fri, 23 Oct 2020 16:43:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>3cx</category>
                  <category>bigbluebutton</category>
                  <category>freepbx</category>
                  <category>freeswitch</category>
                <description>          &lt;p&gt;Just a quick note for reference.&lt;/p&gt;

&lt;p&gt;I managed to successfully configure the phone bridge with FreePBX as a SIP provider for Big Blue Button using this documentation : &lt;a href=&quot;https://docs.bigbluebutton.org/2.2/customize.html#add-a-phone-number-to-the-conference-bridge&quot; hreflang=&quot;en&quot;&gt;https://docs.bigbluebutton.org/2.2/customize.html#add-a-phone-number-to-the-conference-bridge&lt;/a&gt; . My trunk is connectd to the SIP server running FreePBX and Big Blue Button is registering as a phone extension to receive phone calls and route them to the conference room.&lt;/p&gt;

&lt;p&gt;But using a similar architecture with 3CX instead of FreePBX as a provider was failing. Actually, you have to add the AuthID as &quot;auth-username&quot; attribute (see &lt;a href=&quot;https://freeswitch.org/confluence/display/FREESWITCH/Sofia+Gateway+Authentication+Params&quot;&gt;https://freeswitch.org/confluence/display/FREESWITCH/Sofia+Gateway+Authentication+Params&lt;/a&gt; )&lt;/p&gt;

&lt;p&gt;In Big Blue Button, the profile file would looks like :&lt;/p&gt;

&lt;pre&gt;
&amp;lt;include&amp;gt;
  &amp;lt;gateway name=&quot;ANY-NAME-FOR-YOUR-PROVIDER&quot;&amp;gt;
    &amp;lt;param name=&quot;proxy&quot; value=&quot;sip.example.net&quot;/&amp;gt;
    &amp;lt;param name=&quot;username&quot; value=&quot;EXTENSION NUMBER (for instance 100)&quot;/&amp;gt;
    &amp;lt;param name=&quot;auth-username&quot; value=&quot;THE AUTHID&quot;/&amp;gt;
    &amp;lt;param name=&quot;password&quot; value=&quot;PASSWORD&quot;/&amp;gt;
    &amp;lt;param name=&quot;extension&quot; value=&quot;CALLED-NUMBER&quot;/&amp;gt;
    &amp;lt;param name=&quot;register&quot; value=&quot;true&quot;/&amp;gt;
    &amp;lt;param name=&quot;context&quot; value=&quot;public&quot;/&amp;gt;
  &amp;lt;/gateway&amp;gt;
&amp;lt;/include&amp;gt;&lt;/pre&gt;

&lt;p&gt;I hope it will help someone stuck with the official documentation.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Redémarrer une machine lorsqu'un programme l'étouffe inopinément (Debian 10)</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2020/10/15/Red%C3%A9marrer-une-machine-lorsqu-un-programme-l-%C3%A9touffe-inopin%C3%A9ment-%28Debian-10%29</link>
        <guid isPermaLink="false">urn:md5:2df2a5ec71b76a25b469cd103931185c</guid>
        <pubDate>Wed, 14 Oct 2020 12:40:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>debian</category>
                  <category>limits</category>
                  <category>linux</category>
                  <category>memory</category>
                  <category>overflow</category>
                  <category>reboot</category>
                  <category>watchdog</category>
                <description>          &lt;p&gt;Admettons que vous ayez une machine avec un programme bugué. Typiquement, un logiciel métier avec une fuite de mémoire, qui va pour une raison inconnue saturer la mémoire vive et provoquer son propre crash ou le crash des autres services sur la machine.&lt;/p&gt;

&lt;p&gt;Vous pourriez lui mettre une limite de mémoire via &lt;a href=&quot;https://linux.die.net/man/5/limits.conf&quot; hreflang=&quot;en&quot;&gt;/etc/security/limits.conf&lt;/a&gt; mais ça ne fera que planter le programme (segmentation fault) pour protéger les autres, et dans le cas d'un logiciel métier cela veut dire prendre ensuite d'autres actions, manuelles ou automatiques, via un système de monitoring approprié.&lt;/p&gt;

&lt;p&gt;C'est vrai, le monitoring est la bonne solution quand on suit un logiciel aussi critique qu'un logiciel métier, mais dans le cas d'un logiciel qui doit &quot;juste tourner&quot;, d'une équipe de maintenance réduite ou n'ayant pas la possibilité d'astreintes, une solution simple pour s'assurer que la machine tourne même en cas d'incident, c'est de redémarrer la machine lors d'un incident. Pour cela, on peut utiliser le programme &lt;strong&gt;watchdog&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cela doit être fait avec motivations et circonspection, une analyse &quot;post-mortem&quot; doit suivre chaque reboot, dans le cas d'une tentative d'élévation de privilèges par Buffer Overflow, rien ne dit que l'attaque n'a pas réussie même si le système a redémarré.&lt;/p&gt;

&lt;h3&gt;Watchdog : Configuration&lt;/h3&gt;

&lt;p&gt;Watchdog s'installe via les paquets :&lt;/p&gt;

&lt;pre&gt;
apt install watchdog&lt;/pre&gt;

&lt;p&gt;Il y a ensuite deux choses à configurer : les règles pour déclencher le reboot, et le mode de chargement du programme (&quot;no actions&quot; ou actif).&lt;/p&gt;

&lt;p&gt;Dans mon cas, je voulais redémarrer si le serveur avait moins de 20% de RAM disponible, ce serveur tourne en permanence à 50% de consommation de RAM et n'est jamais sensé dépasser, ou alors c'est signe d'un problème, d'où le reboot à déclencher.&lt;/p&gt;

&lt;p&gt;La configuration de watchdog se trouve dans &lt;strong&gt;/etc/watchdog.conf&lt;/strong&gt; et fournit deux valeurs à régler : &lt;strong&gt;min-memory&lt;/strong&gt; et &lt;strong&gt;allocatable-memory&lt;/strong&gt; . Attention, ces valeurs sont à renseigner en &lt;strong&gt;taille de page RAM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pour identifier la taille des pages sur le système, utilisez la commande :&lt;/p&gt;

&lt;pre&gt;
getconf PAGESIZE&lt;/pre&gt;

&lt;p&gt;Ensuite, un simple calcul permet d'identifier la valeur à mettre dans min-memory et allocatable-memory. Par exemple, pour un PAGESIZE de 4096 (4 kB), 2 GB (2048 MB) de RAM et 20% de ce total :&lt;/p&gt;

&lt;pre&gt;
( 20 % * 2048 * 1000 ) / 4096&lt;/pre&gt;

&lt;p&gt;Une fois &lt;strong&gt;min-memory&lt;/strong&gt; et &lt;strong&gt;allocatable-memory&lt;/strong&gt; configurés, il convient de tester le trigger avant de le démarrer;&lt;/p&gt;

&lt;p&gt;Les options de lancement se trouvent dans &lt;strong&gt;/etc/default/watchdog&lt;/strong&gt; . Modifier &lt;strong&gt;watchdog_options&lt;/strong&gt; pour y renseigner :&lt;/p&gt;

&lt;pre&gt;
watchdog_options=&quot;-v --no-action&quot;&lt;/pre&gt;

&lt;p&gt;Désactivez Watchdog du démarrage automatique, puis démarrez-le :&lt;/p&gt;

&lt;pre&gt;
systemctl disable watchdog
service watchdog start&lt;/pre&gt;

&lt;p&gt;Vous en verrez la trace dans les logs via &lt;strong&gt;service watchdog status&lt;/strong&gt; ou &lt;strong&gt;journalctl -f&lt;/strong&gt; .&lt;/p&gt;

&lt;h3&gt;Watchdog : Activation&lt;/h3&gt;

&lt;p&gt;Si les essais sont concluants, retournez dans &lt;strong&gt;/etc/default/watchdog&lt;/strong&gt; pour activer le module noyau. Cela évitera que Watchdog se fasse tuer par un processus quelconque (oom-killer par exemple) :&lt;/p&gt;

&lt;pre&gt;
watchdog_module=&quot;softdog&quot;&lt;/pre&gt;

&lt;p&gt;Si vous ne voulez laisser aucune chance pour éviter le reboot (par exemple si oom-killer a réussi à baisser la consommation de ram sous le seuil acceptable et que le reboot n'est plus nécessaire), rajoutez &lt;strong&gt;nowayout&lt;/strong&gt; :&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;watchdog_module=&quot;softdog nowayout&quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Attention, une fois chargé en &lt;strong&gt;nowayout&lt;/strong&gt;, le module noyau restera actif même si watchdog est stoppé (légitimement ou non), le seul moyen de le retirer est de retirer softdog des modules noyau (via &lt;strong&gt;rmmod&lt;/strong&gt;), ou de rebooter.&lt;/p&gt;

&lt;p&gt;Activez ensuite watchdog :&lt;/p&gt;

&lt;pre&gt;
systemctl enable watchdog
service watchdog start&lt;/pre&gt;

&lt;p&gt;watchdog doit être visible dans les modules noyau chargés :&lt;/p&gt;

&lt;pre&gt;
lsmod | grep softdog&lt;/pre&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.cyberciti.biz/faq/linux-check-the-size-of-pagesize/&quot; hreflang=&quot;en&quot;&gt;Page size check&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.supertechcrew.com/watchdog-keeping-system-always-running/&quot; hreflang=&quot;en&quot;&gt;Watchdog configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Maman, j'ai patché Debian</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2020/03/19/Maman-j-ai-patch%C3%A9-Debian</link>
        <guid isPermaLink="false">urn:md5:71a75a5565e36a22a1a7aac2045ae2d7</guid>
        <pubDate>Thu, 19 Mar 2020 15:33:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>compile</category>
                  <category>debian</category>
                  <category>debuild</category>
                  <category>package</category>
                  <category>patch</category>
                <description>          &lt;p&gt;Un billet en forme de note à moi-même sur ce qu'il faut faire pour correctement :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Récupérer un package depuis upstream&lt;/li&gt;
	&lt;li&gt;Appliquer un ou plusieurs patches&lt;/li&gt;
	&lt;li&gt;Le signer et le re-déployer en production&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Préparer l'environnement&lt;/h3&gt;

&lt;p&gt;Pour compiler et signer un paquet simplement il vous faut :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Un utilisateur (non root)&lt;/li&gt;
	&lt;li&gt;Une clé GPG&lt;/li&gt;
	&lt;li&gt;Les build-essentials et les devscripts (parce qu'on est feignasse)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Créez un utilisateur non-root et loguez-vous avec. N'utilisez pas &quot;su&quot; à partir de root, parce que sinon GPG ne pourra pas vous demander la phrase de passe (des histoires de droits sur les TTY).&lt;/p&gt;

&lt;p&gt;Créez une clé GPG, et paramétrez-la :&lt;/p&gt;

&lt;pre&gt;
gpg --full-generate-key&lt;/pre&gt;

&lt;p&gt;Récupérez l'identifiant de clé à la fin de la procédure, ou avec &lt;strong&gt;gpg&amp;nbsp;--list-keys&lt;/strong&gt; si vous l'avez loupé.&lt;/p&gt;

&lt;p&gt;Modifiez ou créez le fichier &lt;strong&gt;~/.devscripts&lt;/strong&gt; et ajoutez :&lt;/p&gt;

&lt;pre&gt;
DEBUILD_SET_ENVVAR_DEBSIGN_KEYID=xxxxxxxx
&lt;/pre&gt;

&lt;p&gt;Avec le xxxxxx qui correspond à votre identifiant de clé.&lt;/p&gt;

&lt;h3&gt;Récupérer le paquet et les dépendances de compilation&lt;/h3&gt;

&lt;p&gt;Le plus simple c'est quand le paquet existe déjà et qu'il faut simplement patcher. S'il n'existe aucun paquet, il faut créer un nouveau paquet, éventuellement debianizer la configuration, et c'est une autre paire de manches (et c'est pas le sujet ici).&lt;/p&gt;

&lt;p&gt;Pour récupérer le paquet upstream :&lt;/p&gt;

&lt;pre&gt;
apt-get source nomdupaquet&lt;/pre&gt;

&lt;p&gt;Si le paquet est introuvable, ajoutez les dépôts src à votre sources.list :&lt;/p&gt;

&lt;pre&gt;
&lt;strong&gt;deb-src&lt;/strong&gt; http://deb.debian.org/debian/ buster main contrib
&lt;strong&gt;deb-src&lt;/strong&gt; http://security.debian.org/debian-security buster/updates main contrib
&lt;strong&gt;deb-src&lt;/strong&gt; http://deb.debian.org/debian/ buster-updates main contrib&lt;/pre&gt;

&lt;p&gt;Il faut ensuite récupérer les paquets nécessaires à la compilation. Coup de bol, si vous avez pu avoir le paquet source à l'étape précédente, c'est facile :&lt;/p&gt;

&lt;pre&gt;
apt-get build-dep nomdupaquet&lt;/pre&gt;

&lt;h3&gt;Patcher le paquet&lt;/h3&gt;

&lt;p&gt;Le format dpatch est obsolète, en principe votre package utilise quilt comme tout paquet récent. Il suffit de télécharger le patch depuis git et le placer dans le dossier &lt;strong&gt;debian/patches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ensuite, ajoutez le nom du fichier que vous avez ajouté au fichier &lt;strong&gt;debian/patches/series&lt;/strong&gt; . Attention, l'ordre dans series est important.&lt;/p&gt;

&lt;h3&gt;Déclarer les changements&lt;/h3&gt;

&lt;p&gt;Ce n'est pas nécessaire la première fois, mais si vous re-compilez un paquet, il faut ajouter un commentaire dans le Changelog. Le plus simple : utilisez la commande &lt;strong&gt;dch -i&amp;nbsp; &lt;/strong&gt;et modifiez la ligne de changelog, en changeant bien la version du paquet pour qu'elle soit consécutive à la précédente.&lt;/p&gt;

&lt;h3&gt;Compiler le paquet&lt;/h3&gt;

&lt;p&gt;Rendez-vous dans le dossier du paquet, et lancez la commande &lt;strong&gt;debuild&lt;/strong&gt; . C'est tout. Rentrez votre phrase de passe pour la clé à la fin de la procédure.&lt;/p&gt;

&lt;h3&gt;Déployer en production&lt;/h3&gt;

&lt;p&gt;Pour déployer un paquet, deux solutions :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Envoyer le paquet puis l'installer avec &lt;strong&gt;dpkg -i lefichier.deb&lt;/strong&gt; ou un outil d'orchestration&lt;/li&gt;
	&lt;li&gt;Installer un DPA (Debian Private Repository) et l'ajouter au sources.list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'installation du serveur DPA fera l'objet d'un autre billet (un jour).&lt;/p&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://help.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key&quot;&gt;Create GPG KEY&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://wiki.debian.org/debian/patches&quot;&gt;Patch a Debian package&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.debian.org/doc/manuals/maint-guide/build.en.html&quot;&gt;Build a Debian package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Setup Letsencrypt certificates on Gitlab and Mattermost</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2017/10/19/Setup-Letsencrypt-certificates-on-Gitlab-and-Mattermost</link>
        <guid isPermaLink="false">urn:md5:6269a356f381138560626142d150fc6c</guid>
        <pubDate>Thu, 19 Oct 2017 13:01:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                        <description>          &lt;p&gt;The new versions of Gitlab are embedding the Mattermost server. Here is how to setup the certificates for these instances.&lt;/p&gt;

&lt;h3&gt;1. Install certbot&lt;/h3&gt;

&lt;p&gt;Read the docs here (choose Nginx on the appropriate system) : &lt;a href=&quot;https://certbot.eff.org/&quot;&gt;certbot.eff.org&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;2. Make a webroot&lt;/h3&gt;

&lt;pre&gt;
mkdir -p /var/www/letsencrypt/.well-known&lt;/pre&gt;

&lt;h3&gt;3. Configure Gitlab and Mattermost to answer /.well-known to this webroot&lt;/h3&gt;

&lt;p&gt;Edit &lt;strong&gt;/etc/gitlab/gitlab.rb&lt;/strong&gt; and add :&lt;/p&gt;

&lt;pre&gt;
nginx['custom_gitlab_server_config']=&quot;location ^~ /.well-known/ {\n alias /var/www/letsencrypt/.well-known/;\n}\n&quot;
mattermost_nginx['custom_gitlab_mattermost_server_config']=&quot;location /.well-known/ {\n alias /var/www/letsencrypt/.well-known/;\n}\n&quot;&lt;/pre&gt;

&lt;p&gt;And reconfigure Gitlab :&lt;/p&gt;

&lt;pre&gt;
gitlab-ctl reconfigure&lt;/pre&gt;

&lt;h3&gt;4. Create the certificates&lt;/h3&gt;

&lt;p&gt;Run the certbot command :&lt;/p&gt;

&lt;pre&gt;
certbot certonly --staging --webroot --webroot-path=/var/www/letsencrypt/ -d gitlab.your-domain.com
certbot certonly --staging --webroot --webroot-path=/var/www/letsencrypt/ -d mattermost.your-domain.com&lt;/pre&gt;

&lt;h3&gt;5. Tell Gitlab to use the certificates&lt;/h3&gt;

&lt;p&gt;Edit &lt;strong&gt;/etc/gitlab/gitlab.rb&lt;/strong&gt; again, and add :&lt;/p&gt;

&lt;pre&gt;
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate']= &quot;/etc/letsencrypt/live/gitlab.your-domain.com/fullchain.pem&quot;
nginx['ssl_certificate_key'] = &quot;/etc/letsencrypt/live/gitlab.your-domain.com/privkey.pem&quot;

mattermost_nginx['redirect_http_to_https'] = true
mattermost_nginx['ssl_certificate'] = &quot;/etc/letsencrypt/live/mattermost.your-domain.com/fullchain.pem&quot;
mattermost_nginx['ssl_certificate_key'] = &quot;/etc/letsencrypt/live/mattermost.your-domain.com/privkey.pem&quot;
&lt;/pre&gt;

&lt;h3&gt;6. Done&lt;/h3&gt;

&lt;p&gt;Reconfigure Gitlab&amp;nbsp;again :&lt;/p&gt;

&lt;pre&gt;
gitlab-ctl reconfigure&lt;/pre&gt;</description>
        
              </item>
          <item>
        <title>Elasticsearch, Kibana : mapper [hits] cannot be changed from type [long] to [integer]</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2017/10/10/Elastisearch%2C-Kibana-%3A-mapper-%5Bhits%5D-cannot-be-changed-from-type-%5Blong%5D-to-%5Binteger%5D</link>
        <guid isPermaLink="false">urn:md5:c909928e3c21da586381ca95ccee3c3a</guid>
        <pubDate>Tue, 10 Oct 2017 23:34:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                        <description>&lt;p&gt;Every time I upgrade my ELK stack, it breaks. This time, it was the Kibana index with this obscurous errors :&lt;/p&gt;

&lt;pre&gt;
[DEBUG][o.e.a.a.i.m.p.TransportPutMappingAction] [logs] failed to put mappings on indices [[[.kibana]]], type [timelion-sheet]
java.lang.IllegalArgumentException: mapper [hits] cannot be changed from type [long] to [integer][DEBUG][o.e.a.a.i.m.p.TransportPutMappingAction]

[DEBUG][o.e.a.a.i.m.p.TransportPutMappingAction] [logs] failed to put mappings on indices [[[.kibana]]], type [timelion-sheet]
java.lang.IllegalArgumentException: mapper [version] cannot be changed from type [long] to [integer]&lt;/pre&gt;

&lt;p&gt;Here is how to fix it. You will have to re-create an index with the correct mapping, and then reindex it.&lt;/p&gt;          &lt;p&gt;First, export your Kibana index mapping and settings :&lt;/p&gt;

&lt;pre&gt;
curl localhost:9200/.kibana/_settings?pretty
curl localhost:9200/.kibana/_mapping?pretty&lt;/pre&gt;

&lt;p&gt;Then, Create and index template with your settings and mapping (don't forget to change the type of the offending fields) :&lt;/p&gt;

&lt;pre&gt;
curl -XPUT &quot;http://localhost:9200/_template/kibana&quot; -H 'Content-Type: application/json' -d'
{
    &quot;template&quot;:&quot;.kibana-5.6&quot;,
    &quot;settings&quot;:{
        &quot;number_of_shards&quot;:1
    },
    &quot;mappings&quot;:{
        &quot;dashboard&quot;:{
            &quot;properties&quot;:{
                &quot;description&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;hits&quot;:{
                    &quot;type&quot;:&quot;integer&quot;
                },
                &quot;kibanaSavedObjectMeta&quot;:{
                    &quot;properties&quot;:{
                        &quot;searchSourceJSON&quot;:{
                            &quot;type&quot;:&quot;string&quot;
                        }
                    }
                },
                &quot;optionsJSON&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;panelsJSON&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;timeFrom&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;timeRestore&quot;:{
                    &quot;type&quot;:&quot;boolean&quot;
                },
                &quot;timeTo&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;title&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;uiStateJSON&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;version&quot;:{
                    &quot;type&quot;:&quot;integer&quot;
                }
            }
        },
        &quot;_default_&quot;:{
            &quot;dynamic&quot;:&quot;strict&quot;
        },
        &quot;url&quot;:{
            &quot;dynamic&quot;:&quot;strict&quot;,
            &quot;properties&quot;:{
                &quot;accessCount&quot;:{
                    &quot;type&quot;:&quot;long&quot;
                },
                &quot;accessDate&quot;:{
                    &quot;type&quot;:&quot;date&quot;,
                    &quot;format&quot;:&quot;strict_date_optional_time||epoch_millis&quot;
                },
                &quot;createDate&quot;:{
                    &quot;type&quot;:&quot;date&quot;,
                    &quot;format&quot;:&quot;strict_date_optional_time||epoch_millis&quot;
                },
                &quot;url&quot;:{
                    &quot;type&quot;:&quot;string&quot;,
                    &quot;fields&quot;:{
                        &quot;keyword&quot;:{
                            &quot;type&quot;:&quot;string&quot;,
                            &quot;index&quot;:&quot;not_analyzed&quot;,
                            &quot;ignore_above&quot;:2048
                        }
                    },
                    &quot;fielddata&quot;:false
                }
            }
        },
        &quot;search&quot;:{
            &quot;properties&quot;:{
                &quot;columns&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;description&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;hits&quot;:{
                    &quot;type&quot;:&quot;integer&quot;
                },
                &quot;kibanaSavedObjectMeta&quot;:{
                    &quot;properties&quot;:{
                        &quot;searchSourceJSON&quot;:{
                            &quot;type&quot;:&quot;string&quot;
                        }
                    }
                },
                &quot;sort&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;title&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;version&quot;:{
                    &quot;type&quot;:&quot;integer&quot;
                }
            }
        },
        &quot;index-pattern&quot;:{
            &quot;properties&quot;:{
                &quot;fieldFormatMap&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;fields&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;timeFieldName&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;title&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                }
            }
        },
        &quot;server&quot;:{
            &quot;dynamic&quot;:&quot;strict&quot;,
            &quot;properties&quot;:{
                &quot;uuid&quot;:{
                    &quot;type&quot;:&quot;string&quot;,
                    &quot;index&quot;:&quot;not_analyzed&quot;
                }
            }
        },
        &quot;config&quot;:{
            &quot;properties&quot;:{
                &quot;buildNum&quot;:{
                    &quot;type&quot;:&quot;string&quot;,
                    &quot;index&quot;:&quot;not_analyzed&quot;
                },
                &quot;defaultIndex&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;discover:aggs:terms:size&quot;:{
                    &quot;type&quot;:&quot;long&quot;
                }
            }
        },
        &quot;visualization&quot;:{
            &quot;properties&quot;:{
                &quot;description&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;kibanaSavedObjectMeta&quot;:{
                    &quot;properties&quot;:{
                        &quot;searchSourceJSON&quot;:{
                            &quot;type&quot;:&quot;string&quot;
                        }
                    }
                },
                &quot;savedSearchId&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;title&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;uiStateJSON&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                },
                &quot;version&quot;:{
                    &quot;type&quot;:&quot;integer&quot;
                },
                &quot;visState&quot;:{
                    &quot;type&quot;:&quot;string&quot;
                }
            }
        }
    }
}
'&lt;/pre&gt;

&lt;p&gt;Then, reindex (copy) the values of your old kibana index to the new one :&lt;/p&gt;

&lt;pre&gt;
curl -XPOST &quot;http://localhost:9200/_reindex&quot; -H 'Content-Type: application/json' -d'
{
  &quot;source&quot;: {
    &quot;index&quot;: &quot;.kibana&quot;
  },
  &quot;dest&quot;: {
    &quot;index&quot;: &quot;.kibana-5.6&quot;
  }
}'&lt;/pre&gt;

&lt;p&gt;And finally, change your kibana index in &lt;strong&gt;/etc/kibana/kibana.yml&lt;/strong&gt; :&lt;/p&gt;

&lt;pre&gt;
kibana.index: &quot;.kibana-5.6&quot;&lt;/pre&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://github.com/elastic/kibana/issues/9888&quot; hreflang=&quot;en&quot;&gt;#9888 : mapper [hits] cannot be changed from type [long] to [integer]&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://github.com/elastic/kibana/issues/5648&quot; hreflang=&quot;en&quot;&gt;#5648 : mapper [version] cannot be changed from type [long] to [int] #5648&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Mémo rsync pour mes collègues</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2017/07/17/M%C3%A9mo-rsync-pour-mes-coll%C3%A8gues</link>
        <guid isPermaLink="false">urn:md5:7af6c8e95c4068248d8708cb442e4c70</guid>
        <pubDate>Mon, 17 Jul 2017 15:01:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                        <description>&lt;p&gt;Un rappel de l'usage pratique de rsync pour mes collègues qui oublient tout le temps les commandes à taper.&lt;/p&gt;          &lt;h3&gt;Format de base&lt;/h3&gt;

&lt;pre&gt;
rsync arguments source destination&lt;/pre&gt;

&lt;h3&gt;Arguments courants&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;-r&lt;/code&gt; : récursif (copie les dossiers et leur contenu)&lt;br /&gt;
&lt;code&gt;-a&lt;/code&gt; : récursif + conserve permissions et propriétaire (si root)&lt;br /&gt;
&lt;code&gt;-u&lt;/code&gt; : ne pas changer les fichiers plus récents dans la destination&lt;br /&gt;
&lt;code&gt;-v&lt;/code&gt; : verbeux (affiche les fichiers et dossiers affectés)&lt;br /&gt;
&lt;code&gt;-z&lt;/code&gt; : compression du tunnel (pour une connexion fibrée vers des machines lowcost, on peut omettre le paramètre pour soulager le CPU)&lt;br /&gt;
&lt;code&gt;--exclude&lt;/code&gt; : exclus certains chemins d'accès de la synchronisation. Attention, les chemins sont relatifs au chemin la source.&lt;br /&gt;
&lt;code&gt;--dry-run&lt;/code&gt; : montre les opérations sans rien toucher&lt;br /&gt;
&lt;code&gt;--delete&lt;/code&gt; : efface les dossiers supplémentaires de la destination&lt;/p&gt;

&lt;h3&gt;Format de &quot;source&quot; et &quot;destination&quot;&lt;/h3&gt;

&lt;pre&gt;
login@hôte:/chemin/dacces/&lt;/pre&gt;

&lt;p&gt;Attention avec l'utilisation du récursif (activé avec &quot;-r&quot; ou &quot;-a&quot;), &lt;strong&gt;le / à la fin du chemin de la source est important&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;Exemples d'usages corrects&lt;/h3&gt;

&lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot;&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th scope=&quot;col&quot;&gt;Usage&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Source&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Destination&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Résultat&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Remarques&lt;/th&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer un fichier dans un dossier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/source/fichier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;
			&lt;p&gt;/chemin/destination/dossier/&lt;/p&gt;
			&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/dossier/fichier&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer des fichiers dans un dossier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/source/*&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;
			&lt;p&gt;/chemin/destination/dossier/&lt;/p&gt;
			&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/dossier/fichier1&lt;br /&gt;
			/chemin/destination/dossier/fichier2&lt;br /&gt;
			/chemin/destination/dossier/fichier3&lt;br /&gt;
			...&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer un dossier dans un dossier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/source/dossier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;
			&lt;p&gt;/chemin/destination/&lt;/p&gt;
			&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/dossier&lt;/td&gt;
			&lt;td&gt;&lt;strong&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;Ne pas confondre avec la ligne 5 !&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Synchroniser deux fichiers&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/source/fichier1&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/fichier2&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/fichier2&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Synchroniser deux dossiers&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/source/dossier1/&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/dossier2/&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/dossier2&lt;/td&gt;
			&lt;td&gt;&lt;strong&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;Ne pas confondre avec la ligne 3 !&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3&gt;Exemples de mésusages&lt;/h3&gt;

&lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot;&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th scope=&quot;col&quot;&gt;Mésusage&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Source&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Destination&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Résultat&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Remarques&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer un dossier dans un dossier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/source/dossier/&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;/chemin/destination/&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;/chemin/destination/&lt;/span&gt;&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;Va synchroniser les deux dossiers au lieu de placer dossier/ dans destination/&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

			&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;Si des fichiers ont le même nom, ils seront remplacés. Particulièrement dangereux aussi avec --delete&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
&lt;/table&gt;

&lt;h3&gt;Exemples d'utilisations correctes&lt;/h3&gt;

&lt;table border=&quot;1&quot; cellpadding=&quot;1&quot; cellspacing=&quot;1&quot;&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th scope=&quot;col&quot;&gt;Usage&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Commande&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Résultat&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer un fichier dans un dossier distant&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run -azv /source/fichier login@serveur:/destination/dossier/&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/dossier/fichier&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer des fichiers dans un dossier distant&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run -azv /source/* login@serveur:/destination/dossier/&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/dossier/fichier1&lt;br /&gt;
			/destination/dossier/fichier2&lt;br /&gt;
			/destination/dossier/fichier3&lt;br /&gt;
			...&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer des fichiers dans un dossier distant&lt;br /&gt;
			&lt;strong&gt;et efface les autres fichiers contenus dans le dossier de destination&lt;/strong&gt;&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run &lt;strong&gt;--delete&lt;/strong&gt; -azv /source/* login@serveur:/destination/dossier/&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/dossier/fichier1&lt;br /&gt;
			/destination/dossier/fichier2&lt;br /&gt;
			/destination/dossier/fichier3&lt;br /&gt;
			...&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Envoyer un dossier dans un dossier&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run -azv /source/dossier login@serveur:/destination/&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/dossier&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Synchroniser deux fichiers&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run -azv /source/fichier1 login@serveur:/source/fichier2&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/fichier2&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Synchroniser deux dossiers&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run -azv /source/dossier1/ login@serveur:/source/dossier2/&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/dossier2&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Synchroniser deux dossiers&lt;br /&gt;
			&lt;strong&gt;et efface les autres fichiers présents dans le dossier de destination&lt;/strong&gt;&lt;/td&gt;
			&lt;td style=&quot;white-space: nowrap;&quot;&gt;rsync --dry-run &lt;strong&gt;--delete&lt;/strong&gt; -azv /source/dossier1/ login@serveur:/source/dossier2/&lt;/td&gt;
			&lt;td&gt;
			&lt;p&gt;Sur &lt;strong&gt;serveur&lt;/strong&gt; :&lt;/p&gt;

			&lt;p&gt;/destination/dossier2&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
&lt;/table&gt;
&lt;style type=&quot;text/css&quot;&gt;.post-content table, .post-content tr, .post-content th, .post-content td, .post-excerpt table, .post-excerpt tr, .post-excerpt th, .post-excerpt td { border: solid thin #000; }
.post-content td, .post-excerpt td { padding: 0.5em; }
.post-content th, .post-excerpt th { padding: 0.5em; text-align: center; }
&lt;/style&gt;</description>
        
              </item>
          <item>
        <title>Configure Wordpress for Performance and Stability</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/12/08/Configure-Wordpress-for-Performance-and-Stability</link>
        <guid isPermaLink="false">urn:md5:157bb5b206a5971af1189799723bb63b</guid>
        <pubDate>Tue, 11 Jul 2017 10:05:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                        <description>&lt;p&gt;Wordpress is a very common CMS nowadays, and works well out-of-the-box. But when it comes to Performance and Security, its default options are not hardening it enough.&lt;/p&gt;

&lt;p&gt;This topic has been discussed a lot on Internet, but here are my tips, as a web developer and sysadmin.&lt;/p&gt;

&lt;h3&gt;Performance : the main culprits&lt;/h3&gt;

&lt;p&gt;On a public websites, the slowness can com from :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Network : your provider has as slow network, a huge traffic load, or the user simply has a bad connection&lt;/li&gt;
	&lt;li&gt;Database access : the provider's database may be under load, you query's sizes may be too important, or the access time between the script and the datbase is just &quot;usually slow&quot;.&lt;/li&gt;
	&lt;li&gt;Disk access : the disk where is stored your files may be slow, or does not have proper in-ram caching&lt;/li&gt;
	&lt;li&gt;CPU : the CPU of the machine where you site is hosted may be slow, or you are on a low-cost VPS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no &quot;miracle solution&quot; for a badly designed website, but in the vast majority of cases, we could help a bit with simple solutions.&lt;/p&gt;

&lt;h3&gt;Security : the main threats&lt;/h3&gt;

&lt;p&gt;The main threat in a Wordpress installation is the updates execution. You should update your modules, themes, and core as soon as possible.&lt;/p&gt;

&lt;p&gt;Custom and unmaintained modules and themes can also become a threat as they are not updated anymore, and can contain exploitable leaks.&lt;/p&gt;

&lt;p&gt;There are several way to prevent your site from leaking too many informations on its &quot;healthiness&quot;. It can give you some time to update your website before its exploitation by hackers.&lt;/p&gt;          &lt;h3&gt;Security : Disable XMLRPC&lt;/h3&gt;

&lt;p&gt;Unless you are absolutely sure that you are using it (in particular if you are using Jetpack), disable XMLRPC. XMLRPC is a sort of &quot;remote control&quot; for Wordpress and is widely used as an attack vector for Wordpress : bruteforce, denial of service, scans and other nasty things.&lt;/p&gt;

&lt;p&gt;Save yourself from the unexpected, disable XMLRPC either &lt;a href=&quot;https://fr.wordpress.org/plugins/disable-xml-rpc/&quot;&gt;with a module&lt;/a&gt; or &lt;a href=&quot;https://wordpress.stackexchange.com/questions/219643/best-way-to-eliminate-xmlrpc-php&quot;&gt;web server rules&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Security : Enable Brute Force Protection&lt;/h3&gt;

&lt;p&gt;Brute force is a technique that aims at guessing the administrator password by testing common or stolen passwords. Even if they have little chance to succeeed, they are sucking CPU and network acess for your users.&lt;/p&gt;

&lt;p&gt;Many modules are offering basic brute force protection, please check that your WAF (if you have one) does not provides one already.&lt;/p&gt;

&lt;h3&gt;Performance : Install a cache plugin&lt;/h3&gt;

&lt;p&gt;Caching is very important. It can save you hours of CPU and database access time, and is widely standardized. There are various techniques :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Static cache : the web page is stored &quot;as the user sees it&quot;, and is served immediately without executing all the databases queries&lt;/li&gt;
	&lt;li&gt;In-RAM (object) cache : the PHP processor keeps in-memory objects, to load faster. Some assets like images or CSS files can also be cached in-memory by the web server.&lt;/li&gt;
	&lt;li&gt;Browser cache : expiry time can be set for static elements or pages, so that the browser does not query back the file when it is not needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these techniqes are widely known and used in cache plugins. Please use (and configure) one of them.&lt;/p&gt;

&lt;h3&gt;Security : Install a WAF&lt;/h3&gt;

&lt;p&gt;A WAF (Web Application Firewall) is a sort of filter that will prevent your website from being attacked, scanned, or inflitrated by hackers. It is not an absolute protection,&amp;nbsp; but it easily kicks out script kiddies that could scan your website, saving you resources for real users.&lt;/p&gt;

&lt;p&gt;A WAF can be available from your hosting provider, in that case a simple button can enable it. Several modules are also available for Wordpress to do it.&lt;/p&gt;

&lt;p&gt;Beware, these modules are often heavy as they filter every requests, use it combined with a properly configured cache system.&lt;/p&gt;

&lt;h3&gt;Performance : Watch database size and optimize&lt;/h3&gt;

&lt;p&gt;You probably does not need so many content revisions. The revisions are backups of your articles and pages, stored in the database. You can regularly delete older revisions.&lt;/p&gt;

&lt;p&gt;Some modules can do it for you, for instance &lt;a href=&quot;https://fr.wordpress.org/plugins/wp-optimize/&quot;&gt;WP-Optimize&lt;/a&gt;. It is advised to do a backup before executing the purge.&lt;/p&gt;

&lt;p&gt;It should not be a problem, but if your hosting provider does not optimize databases automatically, it can become one.&lt;/p&gt;

&lt;h3&gt;Performance : Use a CDN if possible&lt;/h3&gt;

&lt;p&gt;A CDN is a server designed to give you static content faster that the original site, by using well-located servers, and long retry-times.&lt;/p&gt;

&lt;p&gt;You can have many benefits on using a CDN : caching, faster loading of assets, default compression and optimization, etc.&lt;/p&gt;

&lt;p&gt;If you can afford and configure one, you can really see a performance improvement.&lt;/p&gt;

&lt;h3&gt;Performance : Tweak Apache settings&lt;/h3&gt;

&lt;p&gt;Some actions can be taken if you have access to Apache configuration :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Enable gzip compression : gzip compression can be enabled on top of Apache configuration, to compress assets and pages and improve the network overload.&lt;/li&gt;
	&lt;li&gt;Set high expiration duration : you can tell the user's browser to cache the content by setting &lt;a href=&quot;https://wordpress.org/plugins/far-future-expiry-header/&quot; hreflang=&quot;en&quot;&gt;Expiration headers&lt;/a&gt; in your htaccess.&lt;/li&gt;
	&lt;li&gt;Enable Google's mod_pagespeed : Google provides an &lt;a href=&quot;https://developers.google.com/speed/pagespeed/&quot;&gt;auto-optimization module&lt;/a&gt; that can help if your theme is messy. Warning : you must have a good I/O rate in order to use this plugin, it makes many accesses to disks.&lt;/li&gt;
&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Sample public calendar for ownCloud using ICS parser</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/07/30/Sample-public-calendar-for-ownCloud-using-ICS-parser</link>
        <guid isPermaLink="false">urn:md5:f4a988fe3fc58cd4cb73d840ed3068f5</guid>
        <pubDate>Sat, 30 Jul 2016 08:09:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                        <description>&lt;p&gt;When ownCloud removed the ability to share a calendar publicly, I had no other choice than forcing my acquaintances to register to my ownCloud.&lt;/p&gt;

&lt;p&gt;I didn't want that, so I implemented my own solution.&lt;/p&gt;          &lt;h3&gt;1. Abstract&lt;/h3&gt;

&lt;p&gt;My calendar works like this :&lt;/p&gt;

&lt;p&gt;I write events in a particular calendar.&lt;/p&gt;

&lt;p&gt;I share this calendar with a special ownCloud user, dedicated for this.&lt;/p&gt;

&lt;p&gt;The script will login on the CalDAV API with the credential of the special user, and get the content of the shared calendar.&lt;/p&gt;

&lt;p&gt;The script compile the events and compile a nice table, with the content of the calendar.&lt;/p&gt;

&lt;p&gt;Please note that the events I write are special: I only use the title field to specify a &quot;color&quot; that will be displayed for the day. The colors are corresponding to my « level of availability » (to show my holidays dates, for instance)&lt;/p&gt;

&lt;h3&gt;2. Create the calendar and the user&lt;/h3&gt;

&lt;p&gt;In owncloud, create the second user. I called it &lt;strong&gt;public&lt;/strong&gt;, for instance.&lt;/p&gt;

&lt;p&gt;In ownCloud, create the shared calendar on your own account, and give &lt;strong&gt;public&lt;/strong&gt; access to it. Do not tick write permissions.&lt;/p&gt;

&lt;p&gt;Create a test event, and log out.&lt;/p&gt;

&lt;p&gt;Log in back with the &lt;strong&gt;public&lt;/strong&gt; user, and check that you see the shared calendar and its content.&lt;/p&gt;

&lt;h3&gt;3. Download the library&lt;/h3&gt;

&lt;p&gt;I used &lt;a href=&quot;https://github.com/johngrogg/ics-parser&quot; hreflang=&quot;en&quot;&gt;this ICS parser&lt;/a&gt; to parse the CalDAV respponses. Download it on your web hosting to the direcory &lt;strong&gt;ics-parser/&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;4. Install the script&lt;/h3&gt;

&lt;p&gt;Here is the script I use:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
// Require ICS parser library
require_once('ics-parser/class.iCalReader.php');

// Use it to debug, the previously included parser disables the errors
error_reporting(E_ALL);
ini_set('display_errors', '1');

// Simple caching system, feel free to change the delay
if (file_exists('calendar.cache.html')) {
    $last_update = filemtime('calendar.cache.html');
} else {
        $last_update = 0;
}
if ($last_update + 60*60 &amp;lt; time()) {

// Get events

$headers = array(
        'Content-Type: application/xml; charset=utf-8',
        'Depth: 1',
        'Prefer: return-minimal'
    );

// Setup the calendar URL and the credentials here
$calendar_url = 'https://example.com/remote.php/caldav/calendars/public/public_shared_by_YOU';
$calendar_user = 'public';
$calendar_password = 'public_password';

// Prepare request body
$doc  = new DOMDocument('1.0', 'utf-8');
$doc-&amp;gt;formatOutput = true;

$query = $doc-&amp;gt;createElement('c:calendar-query');
$query-&amp;gt;setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:c', 'urn:ietf:params:xml:ns:caldav');
$query-&amp;gt;setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:d', 'DAV:');

$prop = $doc-&amp;gt;createElement('d:prop');
$prop-&amp;gt;appendChild($doc-&amp;gt;createElement('d:getetag'));
$prop-&amp;gt;appendChild($doc-&amp;gt;createElement('c:calendar-data'));
$query-&amp;gt;appendChild($prop);

$prop = $doc-&amp;gt;createElement('c:filter');
$filter = $doc-&amp;gt;createElement('c:comp-filter');
$filter-&amp;gt;setAttribute('name', 'VCALENDAR');
$prop-&amp;gt;appendChild($filter);
$query-&amp;gt;appendChild($prop);

$doc-&amp;gt;appendChild($query);
$body = $doc-&amp;gt;saveXML();

// Debugging purpose
//echo '&amp;lt;pre&amp;gt;' . htmlspecialchars($body) . '&amp;lt;/pre&amp;gt;';

// Prepare cURL request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $calendar_url);
curl_setopt($ch, CURLOPT_USERPWD, $calendar_user . ':' . $calendar_password);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'REPORT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$response = curl_exec($ch);
if (curl_error($ch)) {
    //echo curl_error($ch);
    exit();
}
curl_close($ch);

// Debugging purpose
//echo '&amp;lt;pre&amp;gt;' . htmlspecialchars($response) . '&amp;lt;/pre&amp;gt;';

// Get the useful part of the response
$xml = simplexml_load_string($response);
$data = $xml-&amp;gt;xpath('//cal:calendar-data');

// Debugging purpose
//echo '&amp;lt;pre&amp;gt;' . htmlspecialchars($data[0]) . '&amp;lt;/pre&amp;gt;';

// Parse events
$calendar_events = array();
foreach ($data as $vcalendars) {
    $ical = new ICal();
    $vcalendars = $vcalendars-&amp;gt;__tostring();

    $lines = explode(&quot;\n&quot;, $vcalendars);
    $ical-&amp;gt;initLines($lines);
    $events = $ical-&amp;gt;events();

    foreach ($events as $event) {
        $start = $ical-&amp;gt;iCalDateToUnixTimestamp($event['DTSTART']);
        $end = $ical-&amp;gt;iCalDateToUnixTimestamp($event['DTEND']);
        $summary = $event['SUMMARY'];
        $calendar_events[] = array(
            'start' =&amp;gt; $start,
            'end' =&amp;gt; $end,
            'summary' =&amp;gt; $summary,
        );
    }
}

// Function to sort the events by start date
function _sort_events($a, $b) {
    return ($a['start'] &amp;gt; $b['start']);
}

// Sort the events by start date
// By doing so, you can have overlapping events, the newest event will superseed the previous
usort($calendar_events, '_sort_events');

// Function to convert my &quot;special titles&quot; into hex colors
function color2hex($color) {
    $color = strtolower($color);

    switch($color) {
        case 'green':
        return '#00ff00';
        break;

        case 'orange':
        return '#ffaa00';
        break;

        case 'red':
        return '#ff0000':
        break;

        case 'black':
        return '#000000';
        break;

        case 'blue':
        return '#0000ff';
        break;
    }
}

// Bufferize output for caching system
ob_start();

// Get current date
$now = mktime(0,0,0);

// Initiate the color array
// Each day in our calendar table will have a color
// Each color is an hex color, corresponding tu the event title (see the switch-case block upper)
$day_color = array();

// Loop through ALL events (old events included)
foreach ($calendar_events as $event) {

    // Discard passed events
    if ($event['end'] &amp;lt; time()) {
        continue;
    }

    // Calculate the timestamp of the &quot;start&quot; date of the event
    $current_day = mktime(0,0,0, date('n', $event['start']), date('j', $event['start']), date('Y', $event['start']));
    $first_loop = true;
    // Loop to fill the color array from the event start date to the event end date
    for ($d = $current_day; ($first_loop || $d &amp;lt; $event['end']); $d+=(60*60*24)) {

        // Debugging purpose
        //var_dump(date('r', $current_day) . ' ' . date('r', $d) . ' ' . date('r', $event['start']) . ' ' . date('r', $event['end']));

        // Handle overlapping events: stack color at the beginning of the sub-array
        if (isset($day_color[$d]) &amp;amp;&amp;amp; is_array($day_color[$d])) {
            array_unshift($day_color[$d], color2hex($event['summary']));
        } else {
            $day_color[$d][0] = color2hex($event['summary']);
        }

        $first_loop = false;
    }
}

// Debugging purpose
//var_dump($day_color);

// Output the final table
/ My week starts on Monday, but you can change it

$week_day = date('N', $now);

echo '&amp;lt;table class=&quot;forecast&quot;&amp;gt;';
echo '&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Mon&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Tue&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Wed&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Thu&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Fri&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Sat&amp;lt;/th&amp;gt;&amp;lt;tH&amp;gt;Sun&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;';

// Loop through the color array
for ($row = 0; $row &amp;lt; 10; $row++) {
    echo '&amp;lt;tr&amp;gt;';

    echo '&amp;lt;td class=&quot;week&quot;&amp;gt;' . (date('W', $now) + $row) . '&amp;lt;/td&amp;gt;';
    for ($col = 0; $col &amp;lt; 7; $col++) {

        // Skip past days from the first week (leave it blank)
        if ($row == 0 &amp;amp;&amp;amp; $col &amp;lt; $week_day-1) {
            echo '&amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;';
            continue;
        }

        $current_day = $now + ($row)*(7*60*60*24) + ($col-($week_day-1))*(60*60*24);
        $current_day = mktime(0,0,0, date('n', $current_day), date('j', $current_day), date('Y', $current_day)); // Working around daylight saving time
        if (isset($day_color[$current_day]) &amp;amp;&amp;amp; isset($day_color[$current_day][0])) {
            // We choose to get the first color of the array,
            //   but if you want to display overlapping events colors,
            //   you can use the other values of the array
            $color = $day_color[$current_day][0];
            echo '&amp;lt;td class=&quot;' . $color . '&quot;&amp;gt;';
        } else {
            echo '&amp;lt;td&amp;gt;';
        }
        // Debugging purpose
        //echo '&amp;lt;pre&amp;gt;' . $current_day . '&amp;lt;/pre&amp;gt;';
        //echo date('r', $current_day);
        // Label the cell with the current day
        echo date('j', $current_day) . ' ' . date('M', $current_day) . ' ' . date('Y', $current_day);
        echo '&amp;lt;/td&amp;gt;';
    }
    echo '&amp;lt;/tr&amp;gt;';
}

echo '&amp;lt;/table&amp;gt;';

$html = ob_get_clean();
ob_end_flush();

file_put_contents('calendar.cache.html', $html);

} else {
    $html = file_get_contents('calendar.cache.html');
}

echo $html;&lt;/pre&gt;

&lt;p&gt;Copy and paste it to an empty PHP file.&lt;/p&gt;

&lt;p&gt;Please note that it has a small caching system (calendar.cache.html) to prevent fetching events every time someone loads the page. You can easily reduce the delay or deactivate this feature.&lt;/p&gt;

&lt;p&gt;Refer to the comments to extend it.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Drupal 8 : create a custom Rule Action</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/07/27/Drupal-8-%3A-create-a-custom-Rule-action</link>
        <guid isPermaLink="false">urn:md5:4028da17989c185a5f86e2d3f8a25968</guid>
        <pubDate>Wed, 27 Jul 2016 10:56:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>action</category>
                  <category>drupal</category>
                  <category>drupal 8</category>
                  <category>module</category>
                  <category>php</category>
                  <category>rules</category>
                <description>          &lt;p&gt;Warning : the Rule plugin for Drupal 8 was not considered stable when I wrote this post.&lt;/p&gt;

&lt;h3&gt;1. Drupal 8: the new modules paradigm&lt;/h3&gt;

&lt;p&gt;Drupal 8 modules structure changed, and many modules are now using the new API.&lt;/p&gt;

&lt;p&gt;No more plain old functions name like hook_something, no more obscurous PHP for menu entries. Instead, Object Oriented programming, YAML configuration files, magic comments, and Symfony routing.&lt;/p&gt;

&lt;p&gt;Let's give it a try, let's make our first simplest module.&lt;/p&gt;

&lt;h3&gt;2. Base module configuration&lt;/h3&gt;

&lt;p&gt;If you already know how to do this, jumb to next section.&lt;/p&gt;

&lt;p&gt;Create a directory for your module, for instance &lt;strong&gt;mymodule&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create an info file in YAML format : &lt;strong&gt;mymodule/mymodule.info.yaml&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;
name: 'My Module'
type: module
core: 8.x
package: Custom&lt;/pre&gt;

&lt;p&gt;You don't need more! You don't need routing as you will plug into Rules.&lt;/p&gt;

&lt;h3&gt;3. File names and Namespaces&lt;/h3&gt;

&lt;p&gt;Create the &lt;strong&gt;RulesAction&lt;/strong&gt; directory and its parents: &lt;strong&gt;mymodule/src/Plugin/RulesAction/&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a PHP file for your class: &lt;strong&gt;MyAction.php&lt;/strong&gt;. The class will be loaded with the autoload system.&lt;/p&gt;

&lt;p&gt;Edit the file you just created, and specify the namespace at the beginning of the file:&lt;/p&gt;

&lt;pre&gt;
/**
 * @file
 * Contains \Drupal\mymodule\Plugin\RulesAction\MyAction.
 */
namespace Drupal\mymodule\Plugin\RulesAction;
use Drupal\rules\Core\RulesActionBase;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;The namespace must correspond to your module name and class name!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;4. Rule Action specifications and parameters&lt;/h3&gt;

&lt;p&gt;Comments are very important as they are also specifications. You will define your Action id, description, and parameters. For instance, here is a copied sample from the predefined action DataSet:&lt;/p&gt;

&lt;pre&gt;
/**
 * Provides a 'My action' action.
 *
 * @RulesAction(
 *   id = &quot;rules_myaction&quot;,
 *   label = @Translation(&quot;Set a data value&quot;),
 *   category = @Translation(&quot;Data&quot;),
 *   context = {
 *     &quot;data&quot; = @ContextDefinition(&quot;any&quot;,
 *       label = @Translation(&quot;Data&quot;),
 *       description = @Translation(&quot;Specifies the data to be modified using a data selector, e.g. 'node:author:name'.&quot;),
 *       allow_null = TRUE,
 *       assignment_restriction = &quot;selector&quot;
 *     ),
 *     &quot;value&quot; = @ContextDefinition(&quot;any&quot;,
 *       label = @Translation(&quot;Value&quot;),
 *       description = @Translation(&quot;The new value to set for the specified data.&quot;),
 *       default_value = NULL,
 *       required = FALSE
 *     )
 *   }
 * )
 */
&lt;/pre&gt;

&lt;p&gt;The Rule id is &lt;strong&gt;rules_myaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The category of the action in the dropdown menu is &lt;strong&gt;Data&lt;/strong&gt; and it will be labeled &lt;strong&gt;Set a data value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The current action will have two parameters : the data that will be changed, and the corresponding value.&lt;/p&gt;

&lt;h3&gt;5. Rule Action callback&lt;/h3&gt;

&lt;p&gt;Again, no more plain callback, the function &lt;strong&gt;doExecute&lt;/strong&gt; will be called to execute your Action:&lt;/p&gt;

&lt;pre&gt;
class MyAction extends RulesActionBase {

  /**
   * Executes the Plugin.
   *
   * @param mixed $data
   *   Original value of an element which is being updated.
   * @param mixed $value
   *   A new value which is being set to an element identified by data selector.
   */
  protected function doExecute($data, $value) {
    $typed_data = $this-&amp;gt;getContext('data')-&amp;gt;getContextData();
    $typed_data-&amp;gt;setValue($value);
  }

  /**
   * {@inheritdoc}
   */
  public function autoSaveContext() {
    // Saving is done at the root of the typed data tree, for example on the
    // entity level.
    $typed_data = $this-&amp;gt;getContext('data')-&amp;gt;getContextData();
    $root = $typed_data-&amp;gt;getRoot();
    $value = $root-&amp;gt;getValue();
    // Only save things that are objects and have a save() method.
    if (is_object($value) &amp;amp;&amp;amp; method_exists($value, 'save')) {
      return ['data'];
    }
    return [];
  }

}&lt;/pre&gt;

&lt;p&gt;The class name has to correspond to your file name.&lt;/p&gt;

&lt;p&gt;In this sample, the parameter &lt;strong&gt;$value&lt;/strong&gt; will be set to &lt;strong&gt;$data&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;6. Troubleshooting&lt;/h3&gt;

&lt;pre&gt;
Uncaught PHP Exception Drupal\\Component\\Plugin\\Exception\\PluginException: &quot;Plugin (rules_myaction) instance class &quot;Drupal\\tbh_system\\Plugin\\RulesAction\\MyAction&quot; does not exist.&quot;&lt;/pre&gt;

&lt;p&gt;Your namespace/classname/filename/directoryname is probably wrong.&lt;/p&gt;

&lt;h3&gt;Source&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://fago.gitbooks.io/rules-docs/content/extending_rules/rules_action_plugins.html&quot; hreflang=&quot;en&quot;&gt;Drupal 8 Rules Action documentation&lt;/a&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Debian 8 : Configure Nginx and Passenger to supercharge your PuppetMaster</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/06/22/Debian-8-%3A-Configure-Nginx-and-Passenger-to-supercharge-your-PuppetMaster</link>
        <guid isPermaLink="false">urn:md5:67dac3b40d4c262e3ea9a071eb94d2e6</guid>
        <pubDate>Wed, 22 Jun 2016 21:16:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>debian</category>
                  <category>jessie</category>
                  <category>mongrel</category>
                  <category>nginx</category>
                  <category>passenger</category>
                  <category>puppet</category>
                  <category>puppetmaster</category>
                  <category>ruby</category>
                <description>&lt;p&gt;The &lt;a href=&quot;http://puppetlabs.com/&quot;&gt;Puppet&lt;/a&gt; master comes by default with a basic WEBrick server. It allow a quick start for those that are not familiar with Puppet, but when the number of Puppet nodes grows, the performances of the default WEBrick server are going down quickly.&lt;/p&gt;

&lt;p&gt;The Puppet documentation show how to configure Apache and Passenger to replace the default WEBrick server, but what if you have a lot of nodes ? What if you want to apply your configuration within minutes, instead of the default half-hour threshold before the agent asks the master if something changed ?&lt;/p&gt;

&lt;p&gt;Or you may just want a fancy Nginx instead of your plain-old-reliable Apache.&lt;/p&gt;

&lt;p&gt;Here is how.&lt;/p&gt;          &lt;h3&gt;Check your hostname&lt;/h3&gt;

&lt;p&gt;Your hostname is the base configuration for your node, you should check that it's correct, otherwise you will run into problems after Puppet installation.&lt;/p&gt;

&lt;pre&gt;
# hostname -f&lt;/pre&gt;

&lt;p&gt;If everything is okay, check your hosts file&lt;/p&gt;

&lt;pre&gt;
# cat /etc/hosts&lt;/pre&gt;

&lt;p&gt;If your hostname is inside your host file, carry on. Otherwise, set it.&lt;/p&gt;

&lt;h3&gt;Install Puppet and Puppetmaster&lt;/h3&gt;

&lt;p&gt;I suppose that you also need the puppet agent installed on the Puppetmaster server.&lt;/p&gt;

&lt;p&gt;Install Puppet and Puppetmaster :&lt;/p&gt;

&lt;pre&gt;
# apt-get install puppet puppetmaster&lt;/pre&gt;

&lt;p&gt;Stop the Puppetmaster :&lt;/p&gt;

&lt;pre&gt;
# service puppetmaster stop&lt;/pre&gt;

&lt;p&gt;Prevent the puppetmaster from starting. Nginx will spawn on the right port instead of the WEBrick server, previously spawn by Puppetmaster service. Edit the file &lt;strong&gt;/etc/defaults/puppetmaster&lt;/strong&gt; :&lt;/p&gt;

&lt;pre&gt;
# Start puppetmaster on boot?
START=no&lt;/pre&gt;

&lt;p&gt;Configure the Puppet agent : edit the file &lt;strong&gt;/etc/puppet/puppet.conf&lt;/strong&gt; to point your agent on the master (for instance puppetmaster.example.com).&lt;/p&gt;

&lt;p&gt;Also, &lt;strong&gt;comment&lt;/strong&gt; the two lines that are &quot;needed for passenger&quot;, our configuration don't need them. Actually, &lt;strong&gt;if you keep it, it will not work&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;
[main]
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$vardir/lib/facter
prerun_command=/etc/puppet/etckeeper-commit-pre
postrun_command=/etc/puppet/etckeeper-commit-post
&lt;strong&gt;server=puppetmaster.example.com&lt;/strong&gt;

[master]
# These are needed when the puppetmaster is run by passenger
# and can safely be removed if webrick is used.
&lt;strong&gt;#ssl_client_header = SSL_CLIENT_S_DN
#ssl_client_verify_header = SSL_CLIENT_VERIFY&lt;/strong&gt;

[agent]
report = true&lt;/pre&gt;

&lt;p&gt;Enable your puppet agent :&lt;/p&gt;

&lt;pre&gt;
# puppet agent --enable&lt;/pre&gt;

&lt;h3&gt;Install Nginx and Passenger&lt;/h3&gt;

&lt;p&gt;We will install the bundle Nginx+Passenger shipped by Phusion repositories.&lt;/p&gt;

&lt;p&gt;Add the key to your keyring :&lt;/p&gt;

&lt;pre&gt;
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7&lt;/pre&gt;

&lt;p&gt;The Phusion repository uses HTTPS, add HTTPS transport to APT :&lt;/p&gt;

&lt;pre&gt;
# apt-get install apt-transport-https ca-certificates&lt;/pre&gt;

&lt;p&gt;Finally, install Nginx and Passenger :&lt;/p&gt;

&lt;pre&gt;
# apt-get update
# apt-get install nginx-extras passenger&lt;/pre&gt;

&lt;h3&gt;Configure Nginx and Puppetmaster application&lt;/h3&gt;

&lt;p&gt;Edit &lt;strong&gt;/etc/nginx/nginx.conf&lt;/strong&gt; and uncomment the reference to passenger config :&lt;/p&gt;

&lt;pre&gt;
    ##
    # Phusion Passenger config
    ##
    # Uncomment it if you installed passenger or passenger-enterprise
    ##

    include /etc/nginx/passenger.conf;&lt;/pre&gt;

&lt;p&gt;Create the file &lt;strong&gt;/etc/nginx/nginx/sites-available/puppet.conf&lt;/strong&gt; with the following content :&lt;/p&gt;

&lt;pre&gt;
server {
    listen                     8140 ssl;
    server_name                puppet puppetmaster puppetmaster.example.com;

    passenger_enabled          on;
    passenger_app_env          production;

    passenger_set_header       X-Client-Verify  $ssl_client_verify;
    passenger_set_header       X-Client-DN $ssl_client_s_dn;
    passenger_set_header       X-SSL-Subject    $ssl_client_s_dn;
    passenger_set_header       X-SSL-Issuer     $ssl_client_i_dn;

    access_log                 /var/log/nginx/puppet_access.log;
    error_log                  /var/log/nginx/puppet_error.log;

    root                       /etc/puppet/rack/public;

    ssl_certificate            /var/lib/puppet/ssl/certs/puppetmaster.example.com.pem;
    ssl_certificate_key        /var/lib/puppet/ssl/private_keys/puppetmaster.example.com.pem;
    ssl_crl                    /var/lib/puppet/ssl/ca/ca_crl.pem;
    ssl_client_certificate     /var/lib/puppet/ssl/certs/ca.pem;
    ssl_ciphers                'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
    ssl_prefer_server_ciphers  on;
    ssl_verify_client          optional;
    ssl_verify_depth           1;
    ssl_session_cache          shared:SSL:128m;
    ssl_session_timeout        5m;
}&lt;/pre&gt;

&lt;p&gt;Remove the default virtual host from Nginx as we don't need it :&lt;/p&gt;

&lt;pre&gt;
# rm /etc/nginx/sites-enabled/default&lt;/pre&gt;

&lt;p&gt;And enable your newly created server :&lt;/p&gt;

&lt;pre&gt;
# ln -s /etc/nginx/sites-available/puppet.conf /etc/nginx/sites-enabled/puppet.conf&lt;/pre&gt;

&lt;p&gt;Before restarting Nginx, we will configure the Ruby application for Puppetmaster.&lt;/p&gt;

&lt;p&gt;Create the directory &lt;strong&gt;/etc/puppet/rack&lt;/strong&gt; and its subdirectories &lt;strong&gt;/etc/puppet/rack/public&lt;/strong&gt; and &lt;strong&gt;/etc/puppet/rack/tmp&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;
# mkdir -p /etc/puppet/rack/public /etc/puppet/rack/tmp&lt;/pre&gt;

&lt;p&gt;Create the file &lt;strong&gt;/etc/puppet/rack/config.ru&lt;/strong&gt; with the following content :&lt;/p&gt;

&lt;pre&gt;
# a config.ru, for use with every rack-compatible webserver.
# SSL needs to be handled outside this, though.

# if puppet is not in your RUBYLIB:
# $LOAD_PATH.unshift('/opt/puppet/lib')

$0 = &quot;master&quot;

# Set the PATH in environment variable
ENV['PATH'] = &quot;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&quot;

# if you want debugging:
# ARGV &amp;lt;&amp;lt; &quot;--debug&quot;

ARGV &amp;lt;&amp;lt; &quot;--rack&quot;

# Rack applications typically don't start as root.  Set --confdir, --vardir,
# --logdir, --rundir to prevent reading configuration from
# ~/ based pathing.
ARGV &amp;lt;&amp;lt; &quot;--confdir&quot; &amp;lt;&amp;lt; &quot;/etc/puppet&quot;
ARGV &amp;lt;&amp;lt; &quot;--vardir&quot;  &amp;lt;&amp;lt; &quot;/var/lib/puppet&quot;
ARGV &amp;lt;&amp;lt; &quot;--logdir&quot;  &amp;lt;&amp;lt; &quot;/var/log/puppet&quot;
ARGV &amp;lt;&amp;lt; &quot;--rundir&quot;  &amp;lt;&amp;lt; &quot;/var/run/puppet&quot;
#ARGV &amp;lt;&amp;lt; &quot;--codedir&quot;  &amp;lt;&amp;lt; &quot;/etc/puppet/code&quot;

# always_cache_features is a performance improvement and safe for a master to
# apply. This is intended to allow agents to recognize new features that may be
# delivered during catalog compilation.
ARGV &amp;lt;&amp;lt; &quot;--always_cache_features&quot;

# NOTE: it's unfortunate that we have to use the &quot;CommandLine&quot; class
#  here to launch the app, but it contains some initialization logic
#  (such as triggering the parsing of the config file) that is very
#  important.  We should do something less nasty here when we've
#  gotten our API and settings initialization logic cleaned up.
#
# Also note that the &quot;$0 = master&quot; line up near the top here is
#  the magic that allows the CommandLine class to know that it's
#  supposed to be running master.
#
# --cprice 2012-05-22

require 'puppet/util/command_line'
# we're usually running inside a Rack::Builder.new {} block,
# therefore we need to call run *here*.
run Puppet::Util::CommandLine.new.execute&lt;/pre&gt;

&lt;p&gt;Chown the file for Puppet user :&lt;/p&gt;

&lt;pre&gt;
# chown puppet:puppet /etc/puppet/rack/config.ru&lt;/pre&gt;

&lt;p&gt;And finally, restart Nginx :&lt;/p&gt;

&lt;pre&gt;
# service nginx restart&lt;/pre&gt;

&lt;p&gt;Then, test you configuration by running the agent :&lt;/p&gt;

&lt;pre&gt;
# puppet agent --test&lt;/pre&gt;

&lt;h3&gt;Troubleshooting and errors&lt;/h3&gt;

&lt;h4&gt;Error 500&lt;/h4&gt;

&lt;pre&gt;
Warning: Error 500 on SERVER: Internal Server Error&lt;/pre&gt;

&lt;p&gt;Read the logs at &lt;strong&gt;/var/log/nginx/error.log&lt;/strong&gt; and &lt;strong&gt;/etc/nginx/puppet_error.log&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;Error 403&lt;/h4&gt;

&lt;pre&gt;
Warning: Error 403 on SERVER: Forbidden request: localhost(127.0.0.1) access to /node/puppetmaster.example.com [find] at :119&lt;/pre&gt;

&lt;p&gt;Check that your hostname resolves, and that your host file is clean. In particular, you should have the host name of your server on the same line than localhost :&lt;/p&gt;

&lt;pre&gt;
127.0.0.1    localhost puppetmaster puppetmaster.example.com&lt;/pre&gt;

&lt;p&gt;Also check that your Puppet configuration is correct, in particular check that the two lines &quot;required for Passenger&quot; are commented.&lt;/p&gt;

&lt;h3&gt;Sources&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://docs.puppet.com/puppet/4.5/reference/passenger.html#install-rackpassenger&quot;&gt;[Puppet Doc] Configuring a Puppet Master Server with Passenger and Apache&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.linode.com/docs/websites/ror/ruby-on-rails-nginx-debian-8&quot;&gt;[Linode] Ruby on Rails with Nginx on Debian 8&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.phusionpassenger.com/library/install/nginx/install/oss/jessie/&quot;&gt;[Phusion Passenger] Installing Passenger + Nginx&lt;/a&gt;
	&lt;ul&gt;
		&lt;li&gt;&lt;a href=&quot;https://www.phusionpassenger.com/library/config/nginx/reference/&quot;&gt;[Phusion Passenger] Configuration reference&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://ask.puppet.com/question/13176/puppet-master-could-not-retrieve-fact-fqdnipaddress/?answer=13351#post-id-13351&quot;&gt;[Ask Puppet] Puppet Master - Could not retrieve fact fqdn/ipaddress&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a class=&quot;question-hyperlink&quot; href=&quot;http://serverfault.com/questions/456680/puppet-master-rest-api-returns-403-when-running-under-passenger-works-when-maste&quot;&gt;Puppet master REST API returns 403 when running under passenger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;</description>
        
              </item>
          <item>
        <title>&quot;SQLSTATE[HY000] [2002] No such file or directory&quot; for compiled PHP</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/04/19/SQLSTATE%5BHY000%5D-%5B2002%5D-No-such-file-or-directory-for-compiled-PHP</link>
        <guid isPermaLink="false">urn:md5:fe7ea9121022705600cf591fb8363708</guid>
        <pubDate>Tue, 19 Apr 2016 22:52:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>compiled</category>
                  <category>debian</category>
                  <category>mysql</category>
                  <category>php</category>
                <description>          &lt;p&gt;Let's say you connect to MySQL using &quot;localhost&quot;&lt;/p&gt;

&lt;p&gt;Let's say you compiled PHP&lt;/p&gt;

&lt;p&gt;Let's say you didn't specify the --with-mysql-sock= parameter in your configure command when you built mysql&lt;/p&gt;

&lt;p&gt;And let's suppose you cannot connect to MySQL using PHP. CLI works fine, but not CGI.&lt;/p&gt;

&lt;p&gt;Solution : fix the default sockets in php.ini (use your own working socket paths) :&lt;/p&gt;

&lt;pre&gt;
pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock
mysqli.default_socket = /var/run/mysqld/mysqld.sock

# You shouldn't use mysql_ extension, but if you did:
mysql.default_socket = /var/run/mysqld/mysqld.sock&lt;/pre&gt;

&lt;p&gt;I suppose that automatically converting &quot;localhost&quot; to an unix socket is done for performance reason on unix systems.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Debian 8 : Limit SSH users to SFTP</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/01/07/Limit-SSH-users-to-SFTP-only</link>
        <guid isPermaLink="false">urn:md5:d5a47c46eec6232c19a682eae095d7a1</guid>
        <pubDate>Thu, 18 Feb 2016 10:38:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>debian</category>
                  <category>jessie</category>
                  <category>server</category>
                  <category>sftp</category>
                  <category>ssh</category>
                <description>&lt;p&gt;Let&amp;#8217;s say you want to configure a secure remote file access for you users, but you can&amp;#8217;t use FTPS for some reasons (problems with passive mode and commercial firewalls&amp;#160;? Yes&amp;#160;!). Your only secure solution is either a VPN, or a SFTP access.&lt;/p&gt;&lt;p&gt;SFTP is great, but it may implies giving full command line access to your end users.&amp;nbsp; In order to prevent that, you could set-up a jailed SSH access with &lt;a href=&quot;http://olivier.sessink.nl/jailkit/&quot;&gt;Jailkit&lt;/a&gt; and some &lt;a href=&quot;http://unix.stackexchange.com/questions/198590/what-is-a-bind-mount&quot;&gt;bind mount&lt;/a&gt;, but it&amp;#8217;s not that trivial to configure and to maintain&amp;#160;; and it may not work with software virtualization (Docker, LXCs&amp;#8230;). There is a simpler solution.&lt;/p&gt;&lt;p&gt;The solution is&amp;#160;: use the native chroot and limitations abilities of OpenSSH. Here is how.&lt;/p&gt;          &lt;h3&gt;Warning!&lt;/h3&gt;&lt;p&gt;You should not configure this on your primary SSH access. By doing so, you will simply lock you out of your server.&lt;/p&gt;&lt;p&gt;In this article, we will set up a completely new instance of OpennSSH server, running next to the original, and handling SFTP only.&lt;/p&gt;&lt;h3&gt;1. Setup the secondary SSH access (SFTP-only)&lt;/h3&gt;&lt;p&gt;Create a new configuration file by copying the primary configuration&amp;#160;:&lt;/p&gt;&lt;pre&gt;cp /etc/ssh/sshd_config /etc/ssh/sftp_config&lt;/pre&gt;&lt;p&gt;Now edit the file &lt;strong&gt;/etc/ssh/sftp_config&lt;/strong&gt; and change the listening port (for instance 10022)&amp;#160;:&lt;/p&gt;&lt;pre&gt;Port 10022&lt;/pre&gt;&lt;p&gt;Change the PID file for this new instance, set something meaningful&amp;#160;:&lt;/p&gt;&lt;pre&gt;PidFile /var/run/sftp.pid&lt;/pre&gt;&lt;p&gt;Then add these lines to&amp;nbsp;&lt;strong&gt;/etc/ssh/sftp_config&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no&lt;/pre&gt;&lt;p&gt;Here is a sample of a full configuration&amp;#160;:&lt;/p&gt;&lt;pre&gt;# Package generated configuration file
# See the sshd_config(5) manpage for details

# What ports, IPs and protocols we listen for
&lt;strong&gt;Port 10022&lt;/strong&gt;
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

&lt;strong&gt;PidFile /var/run/sftp.pid&lt;/strong&gt;

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile    %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

&lt;strong&gt;X11Forwarding no&lt;/strong&gt;
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
#Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

&lt;strong&gt;Subsystem sftp /usr/lib/openssh/sftp-server
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no&lt;/strong&gt;

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of &quot;PermitRootLogin without-password&quot;.
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
&lt;/pre&gt;&lt;p&gt;Now, let&amp;#8217;s configure autostart. Copy &lt;strong&gt;/lib/systemd/system/ssh.service&lt;/strong&gt; to&amp;nbsp;&lt;strong&gt;/lib/systemd/system/sftp.service&lt;/strong&gt; and adjust settings&amp;#160;:&lt;/p&gt;&lt;pre&gt;[Unit]
Description=&lt;strong&gt;OpenBSD Secure Shell server (SFTP only)&lt;/strong&gt;
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS -f &lt;strong&gt;/etc/ssh/sftp.conf&lt;/strong&gt;
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=&lt;strong&gt;sftp.service&lt;/strong&gt;
&lt;/pre&gt;&lt;p&gt;And enable your service&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl enable sftp.service&lt;/pre&gt;&lt;p&gt;Make sure the symlink&amp;nbsp;&lt;strong&gt;/etc/systemd/system/sftp.service&lt;/strong&gt; is created.&lt;/p&gt;&lt;p&gt;And try to start it&amp;#160;:&lt;/p&gt;&lt;pre&gt;service sftp start&lt;/pre&gt;&lt;h3&gt;2. Reconfigure the primary SSH access&lt;/h3&gt;&lt;p&gt;In order to prevent normal users to log into a full shell, we have to change the primary configuration.&lt;/p&gt;&lt;p&gt;The configuration file should be located in &lt;strong&gt;/etc/ssh/sshd_config&lt;/strong&gt; . Add an AllowUsers or AllowGroups directive to this file&amp;#160;:&lt;/p&gt;&lt;pre&gt;# One or the other but not both!
AllowUsers root admin
#AllowGroups sudo
&lt;/pre&gt;&lt;p&gt;Here is a sample of a full configuration&amp;#160;:&lt;/p&gt;&lt;pre&gt;# Package generated configuration file
# See the sshd_config(5) manpage for details

# What ports, IPs and protocols we listen for
&lt;strong&gt;Port 22&lt;/strong&gt;
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin without-password
StrictModes yes
&lt;strong&gt;AllowUsers root admin&lt;/strong&gt;

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile    %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding no
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

UsePAM yes&lt;/pre&gt;&lt;p&gt;Restart your primary SSH access, but &lt;strong&gt;don&amp;#8217;t close your terminal afterwards&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;service ssh restart&lt;/pre&gt;&lt;p&gt;Now open a new terminal and check that your primary SSH is still working. If not, rollback your configuration.&lt;/p&gt;&lt;h3&gt;3. Conclusion&lt;/h3&gt;&lt;p&gt;Now you should have two SSH sockets listening&amp;#160;: one for everyone using exclusively SFTP, and the other with full SSH access for authorized accounts.&lt;/p&gt;&lt;p&gt;Don&amp;#8217;t hesitate to reply in comments if you encounter problems. &lt;img src=&quot;/blog/themes/mathedit_material3/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot;&gt;&lt;/p&gt;&lt;h3&gt;Sources&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/SFTP_chroot&quot;&gt;https://wiki.archlinux.org/index.php/SFTP_chroot&lt;/a&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Add Drush to Jailkit</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/02/16/Add-Drush-to-Jailkit</link>
        <guid isPermaLink="false">urn:md5:956e4551f046b5202f2d1531357cd1d1</guid>
        <pubDate>Tue, 16 Feb 2016 10:16:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>debian</category>
                  <category>drush</category>
                  <category>jailkit</category>
                <description>          &lt;p&gt;Here is the configuration I use to make &lt;a href=&quot;http://www.drush.org&quot;&gt;Drush&lt;/a&gt; working inside a &lt;a href=&quot;http://olivier.sessink.nl/jailkit/&quot;&gt;Jailkit&lt;/a&gt; chrooted shell&amp;#160;:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;/etc/jailkit/jk_init.ini&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;[php]
comment = the PHP interpreter and libraries
executables = /usr/bin/php5, /usr/bin/php
directories = /usr/lib/php5, /usr/share/php, /usr/share/php5, /etc/php5, /usr/share/php-geshi, [B]/usr/share/zoneinfo[/B]
includesections = env

[env]
comment = environment variables
executables = /usr/bin/env

[mysql-client]
comment = mysql client
executables = /usr/bin/mysql
paths = /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18

[drush]
comment = drush (drupal command line)
includesections = php, mysql-client, uidbasics, netbasics
directories = /usr/share/zoneinfo, /etc/ssl/certs, /usr/share/ca-certificates&lt;/pre&gt;&lt;p&gt;Once the jailed shell works, add the Drush dependencies to the jail&amp;#160;:&lt;/p&gt;&lt;pre&gt;jk_init -v -c /etc/jailkit/jk_init.ini -f -k -j /absolute/path/to/jail/ drush&lt;/pre&gt;</description>
        
              </item>
          <item>
        <title>DomPDF : load custom local fonts in you own folder</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/02/12/DomPDF-%3A-load-custom-local-fonts-in-you-own-folder</link>
        <guid isPermaLink="false">urn:md5:64ccb411255b47015d970c64cf67b956</guid>
        <pubDate>Fri, 12 Feb 2016 23:28:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>dompdf</category>
                  <category>font</category>
                  <category>html</category>
                  <category>pdf</category>
                  <category>php</category>
                  <category>ttf</category>
                <description>          &lt;p&gt;I needed custom fonts for &lt;a href=&quot;https://github.com/dompdf/dompdf&quot;&gt;domPDF&lt;/a&gt;, but I didn&amp;#8217;t want to use the &amp;#8220;remote&amp;#8221; capabilities of domPDF, and I didn&amp;#8217;t wanted to spoil my &amp;#8220;contrib&amp;#8221; folder with my own fonts. Dependencies should remain clean.&lt;/p&gt;&lt;p&gt;My domPDF version was &lt;strong&gt;0.6.3&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;To use your own &amp;#8220;fonts&amp;#8221; folder in order to autoload you own fonts, do&amp;#160;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Creates a directory for your fonts and font cache&amp;#160;:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;mkdir myfonts&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Copy your &lt;strong&gt;.ttf&lt;/strong&gt; files in this folder.&lt;/li&gt;&lt;li&gt;Creates a file named &lt;strong&gt;dompdf_font_family_cache.php&lt;/strong&gt; in the &lt;strong&gt;myfonts&lt;/strong&gt; folder, and reference your files. As a sample, you can use the file &lt;strong&gt;dompdf/lib/fonts/dompdf_font_family_cache.dist.php&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;In your configuration (&lt;strong&gt;dompdf_config.custom.inc.php&lt;/strong&gt;), change the &lt;strong&gt;DOMPDF_FONT_DIR&lt;/strong&gt; and &lt;strong&gt;DOMPDF_FONT_CACHE&lt;/strong&gt; to point on your folder &lt;strong&gt;myfonts&lt;/strong&gt; (relative use &lt;strong&gt;realpath&lt;/strong&gt; on relative paths).&lt;/li&gt;&lt;li&gt;Use your fonts like native fonts in font-family declarations.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I hope it will be useful to you.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Set-up SQL quarantine with Amavisd-new and ISPConfig</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/12/05/Set-up-SQL-quarantine-with-Amavisd-new-and-ISPConfig</link>
        <guid isPermaLink="false">urn:md5:c449e2fbaef8eadc5d8276ac89e472d3</guid>
        <pubDate>Sun, 06 Dec 2015 16:56:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>amavis</category>
                  <category>debian</category>
                  <category>ISPConfig</category>
                  <category>jessie</category>
                  <category>mail</category>
                  <category>quarantine</category>
                  <category>server</category>
                  <category>spam</category>
                  <category>sql</category>
                <description>&lt;p&gt;It's documented, but it took me two days to do it correctly, so here is how to reconfigure an ISPConfig installation of Amavis to store quarantined mail in SQL database, in order to install a quarantine viewer like Mailzu.&lt;/p&gt;          &lt;h3&gt;1. Prerequisites&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;A working Postfix+Amavis stack with ISPConfig&lt;/li&gt;
	&lt;li&gt;A working SQL (PostgreSQL, MySQL...) database&lt;/li&gt;
	&lt;li&gt;Optional : a working mail server with PHP (for Mailzu)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jump to &lt;a href=&quot;https://uname.pingveno.net/blog/index.php/post/2015/12/05/Set-up-SQL-quarantine-with-Amavisd-new-and-ISPConfig#installation&quot;&gt;Installation&lt;/a&gt; if you know what you are doing.&lt;/p&gt;

&lt;h3&gt;2. Off-subject generic explanations&lt;/h3&gt;

&lt;h4&gt;2.1 Amavis and ISPConfig policies&lt;/h4&gt;

&lt;figure style=&quot;float: right; margin: 0 0 1em 1em;&quot;&gt;&lt;a class=&quot;media-link&quot; href=&quot;https://uname.pingveno.net/blog/public/captures/ispconfig/ispconfig_mail_spamfilter_policy_tag_levels.png&quot;&gt;&lt;img alt=&quot;ispconfig_mail_spamfilter_policy_tag_levels.png&quot; class=&quot;media&quot; src=&quot;https://uname.pingveno.net/blog/public/captures/ispconfig/.ispconfig_mail_spamfilter_policy_tag_levels_s.png&quot; /&gt;&lt;/a&gt;

&lt;figcaption&gt;ISPConfig policies, Tag-Levels&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In a default ISPConfig installation per-user ISPConfig policies are loaded. The configuration file for Amavis, written by ISPConfig contains :&lt;/p&gt;

&lt;pre&gt;
@lookup_sql_dsn =
   ( ['DBI:mysql:database=dbispconfig;host=127.0.0.1;port=3306', 'ispconfig', 'xxxx'] );
$sql_select_policy =
   'SELECT *,spamfilter_users.id'.
   ' FROM spamfilter_users LEFT JOIN spamfilter_policy ON spamfilter_users.policy_id=spamfilter_policy.id'.
   ' WHERE spamfilter_users.email IN (%k) ORDER BY spamfilter_users.priority DESC';
$sql_select_white_black_list = 'SELECT wb FROM spamfilter_wblist'.
    ' WHERE (spamfilter_wblist.rid=?) AND (spamfilter_wblist.email IN (%k))' .
    ' ORDER BY spamfilter_wblist.priority DESC';&lt;/pre&gt;

&lt;p&gt;It means that whatever you would set as&amp;nbsp;&lt;strong&gt;$sa_spam_subject_tag&lt;/strong&gt;, &lt;strong&gt;$sa_tag_level_deflt&lt;/strong&gt;, &lt;strong&gt;$sa_tag2_level_deflt&lt;/strong&gt;, &lt;strong&gt;$sa_kill_level_deflt&lt;/strong&gt;, &lt;strong&gt;$sa_dsn_cutoff_level&lt;/strong&gt;, it will be overridden by per-user policies.&lt;/p&gt;

&lt;p&gt;The ISPConfig policies can be changed in tab Email =&amp;gt; Spamfilter =&amp;gt; Policy in ISPConfig panel. If you struggle wondering why your message keeps getting smashed at level 4.5, look at the sa_tag_level in policies. We will have to change values in that policies, to make the SQL quarantine working.&lt;/p&gt;

&lt;h4&gt;2.2 Lookup DSN and Storage DSN&lt;/h4&gt;

&lt;p&gt;DSN (Data Source Name) are the connection strings with host, username, and password, used to connect to databases.&lt;/p&gt;

&lt;p&gt;Amavis can set two DSN : one for Policies lookup (used to retrieve ISPConfig policies from Panel), and one for storage of mail meta informations and quarantine. We will use the Storage DSN to set up a secondary database for quarantine storage, to not mess with existing ISPConfig database.&lt;/p&gt;

&lt;h4&gt;2.3 Levels and cutoffs&lt;/h4&gt;

&lt;p&gt;Amavis uses Spamassassin to score the mail, in order to decide what to do with it. The category of test (spam test, antivirus, etc) and the score along with levels determines the actions Amavis will trigger, and the final destiny where the mail belongs.&lt;/p&gt;

&lt;p&gt;Spamassassin levels are :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;tag_level&lt;/strong&gt; : a message above that score will be tagged with &lt;strong&gt;X-Spam-Status&lt;/strong&gt;, &lt;strong&gt;X-Spam-Score&lt;/strong&gt; and &lt;strong&gt;X-Spam-Level&lt;/strong&gt; headers.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;tag2_level&lt;/strong&gt; : a message above that score will be marked &lt;strong&gt;as X-Spam-Status: Yes&lt;/strong&gt; and the subject is changed if &lt;strong&gt;sa_spam_modifies_subj&lt;/strong&gt; is set to true.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;kill_level&lt;/strong&gt; : a message above that score is taken to the &lt;strong&gt;final_spam_destiny&lt;/strong&gt;, and quarantined, it will not be delivered unless &lt;strong&gt;D_PASS&lt;/strong&gt; is set to &lt;strong&gt;final_spam_destiny&lt;/strong&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;dsn_cutoff_level&lt;/strong&gt; : a message above that level will never trigger a bounce or a reject, whatever &lt;strong&gt;spam_destiny&lt;/strong&gt; is.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;quarantine_cutoff_level&lt;/strong&gt; : a message above that level will not be quarantined.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;2.4 Final &lt;span class=&quot;gt-baf-back&quot;&gt;destinations&lt;/span&gt;&lt;/h4&gt;

&lt;p&gt;Once the message is categorized by Amavis tests (through SpamAssassin, ClamAV, etc), Amavis decides if it should be delivered to user mailbox or not, and if a bounce will be issued.&lt;/p&gt;

&lt;p&gt;This is the purpose of &lt;strong&gt;$final_virus_destiny&lt;/strong&gt;, &lt;strong&gt;$final_spam_destiny&lt;/strong&gt;, &lt;strong&gt;$final_banned_destiny&lt;/strong&gt;, &lt;strong&gt;$final_bad_header_destiny&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They can take the following values :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;D_PASS&lt;/strong&gt; : mail will be delivered to inbox.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;D_BOUNCE&lt;/strong&gt; : mail will not be delivered, and a &lt;em&gt;delivery status notification&lt;/em&gt; will be returned by Postifx to sender (except if the score exceeds the &lt;strong&gt;dsn_cutoff&lt;/strong&gt; level)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;D_REJECT&lt;/strong&gt; : Postfix will answer REJECT to the distant mail server, and the distant mail server may produce a &lt;em&gt;delivery status notification&lt;/em&gt; to the user&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;D_DISCARD&lt;/strong&gt; : forgive and forget : the mail will not be delivered and the sender is not informed. The mail may be quarantined if the &lt;strong&gt;quarantine_cutoff&lt;/strong&gt; level is not exceeded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;a name=&quot;installation&quot;&gt;3. Installation&lt;/a&gt;&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;For Amavis : Nothing ! Amavis comes out-of-the-box with SQL storage.&lt;/li&gt;
	&lt;li&gt;For Mailzu : see &lt;a href=&quot;https://uname.pingveno.net/blog/index.php/post/2015/12/05/Set-up-SQL-quarantine-with-Amavisd-new-and-ISPConfig#mailzu&quot;&gt;Mailzu&lt;/a&gt; section.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;4. Configuration&lt;/h3&gt;

&lt;h4&gt;4.1 Database&lt;/h4&gt;

&lt;p&gt;Create an user and a database for quarantine storage :&lt;/p&gt;

&lt;pre&gt;
# mysql -u root -p
mysql&amp;gt; CREATE DATABASE amavis_storage;
mysql&amp;gt; CREATE USER 'amavis_storage'@'localhost' IDENTIFIED BY 'xxxx';
mysql&amp;gt; GRANT ALL PRIVILEGES ON amavis_storage.* TO 'amavis_storage'@'localhost';
mysql&amp;gt; FLUSH PRIVILEGES;&lt;/pre&gt;

&lt;p&gt;Load the initial schema from Amavis docs (usually located in &lt;strong&gt;/usr/share/doc/amavisd-new&lt;/strong&gt;/ ).&lt;/p&gt;

&lt;p&gt;Delete unnecessary tables, as we will be using this database only for mail storage and not for lookups :&lt;/p&gt;

&lt;pre&gt;
# mysql -u amavis_storage -p amavis_storage
mysql&amp;gt; DROP TABLE users;
mysql&amp;gt; DROP TABLE mailaddr;
mysql&amp;gt; DROP TABLE policy;
mysql&amp;gt; DROP TABLE wblist;
&lt;/pre&gt;

&lt;p&gt;Nota Bene : while executing &lt;strong&gt;DROP TABLE users&lt;/strong&gt;, don't be silly, and do not remove mysql users database.&lt;/p&gt;

&lt;h4&gt;4.2 Amavis&lt;/h4&gt;

&lt;p&gt;Update your Amavis configuration &lt;strong&gt;/etc/amavis/conf.d/50_user&lt;/strong&gt; :&lt;/p&gt;

&lt;pre&gt;
@storage_sql_dsn = ( ['DBI:mysql:database=amavis_storage;host=127.0.0.1;port=3306', 'amavis_storage', 'xxxx'] );  # none, same, or separate database

# Quarantine SPAM into SQL server.
$spam_quarantine_to = 'spam-quarantine';
$spam_quarantine_method = 'sql:';

# Quarantine VIRUS into SQL server.
$virus_quarantine_to = 'virus-quarantine';
$virus_quarantine_method = 'sql:';

# Quarantine BANNED message into SQL server.
$banned_quarantine_to = 'banned-quarantine';
$banned_files_quarantine_method = 'sql:';

# Quarantine Bad Header message into SQL server.
$bad_header_quarantine_method = 'sql:';
$bad_header_quarantine_to = 'badheader-quarantine';

# Do not store non-quarantined messages info
# You can set it to 1 (the default) to test if Amavis is filling correctly the tables maddr, msgs, and msgcrpt
$sql_store_info_for_all_msgs = 0;

#
# SQL Select statements
#

$sql_select_policy =
   'SELECT *,spamfilter_users.id'.
   ' FROM spamfilter_users LEFT JOIN spamfilter_policy ON spamfilter_users.policy_id=spamfilter_policy.id'.
   ' WHERE spamfilter_users.email IN (%k) ORDER BY spamfilter_users.priority DESC';

$sql_select_white_black_list = 'SELECT wb FROM spamfilter_wblist'.
    ' WHERE (spamfilter_wblist.rid=?) AND (spamfilter_wblist.email IN (%k))' .
    ' ORDER BY spamfilter_wblist.priority DESC';

#
# Quarantine settings
#

$final_virus_destiny = D_BOUNCE;
$final_spam_destiny = D_DISCARD;
$final_banned_destiny = D_BOUNCE;
$final_bad_header_destiny = D_PASS;

# Default settings, we st this very high to not filter aut emails accidently
$sa_spam_subject_tag = '[SPAM] ';
$sa_tag_level_deflt  = 20.0;  # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 60.0; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 60.0; # triggers spam evasive actions
$sa_dsn_cutoff_level = 100;   # spam level beyond which a DSN is not sent
#$sa_debug = 1;

#
# Disable spam and virus notifications for the admin user.
# Can be overridden by the policies in mysql
#

$virus_admin = undef;
$spam_admin = undef;

#
# Enable Logging
#

$DO_SYSLOG = 1;
$LOGFILE = &quot;/var/log/amavis.log&quot;;  # (defaults to empty, no log)

# Set the log_level to 5 for debugging
$log_level = 0;                # (defaults to 0)&lt;/pre&gt;

&lt;h4&gt;4.3 ISPConfig policies&lt;/h4&gt;

&lt;p&gt;Remember that ISPconfig policies are overriding a lot of our configuration in &lt;strong&gt;50_user&lt;/strong&gt;. In order to majke the quarantine work, you have to reconfigure all the available policies in ISPConfig Panel.&lt;/p&gt;

&lt;p&gt;Look at your policies list, you have to change the quarantine settings for every policies :&lt;/p&gt;

&lt;figure style=&quot;{figureStyle}&quot;&gt;&lt;a class=&quot;media-link&quot; href=&quot;https://uname.pingveno.net/blog/public/captures/ispconfig/ispconfig_mail_spamfilter_policy.png&quot;&gt;&lt;img alt=&quot;ispconfig_mail_spamfilter_policy.png&quot; class=&quot;media&quot; src=&quot;https://uname.pingveno.net/blog/public/captures/ispconfig/ispconfig_mail_spamfilter_policy.png&quot; /&gt;&lt;/a&gt;

&lt;figcaption&gt;ISPConfig Mail Spamfilter Policy&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4&gt;When editing a policy, on the Quarantine tab, set the destinations :&lt;/h4&gt;

&lt;figure style=&quot;{figureStyle}&quot;&gt;&lt;a class=&quot;media-link&quot; href=&quot;https://uname.pingveno.net/blog/public/captures/ispconfig/ispconfig_mail_spamfilter_policy_quarantine.png&quot;&gt;&lt;img alt=&quot;ispconfig_mail_spamfilter_policy_quarantine.png&quot; class=&quot;media&quot; src=&quot;https://uname.pingveno.net/blog/public/captures/ispconfig/ispconfig_mail_spamfilter_policy_quarantine.png&quot; /&gt;&lt;/a&gt;

&lt;figcaption&gt;ISPConfig Mail Spamfilter Policy Quarantine destinations&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;If you do not fill something in these fields, Amavis will not store quarantined mails in SQL database, and will just discard it !&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These fields correspond to the &lt;strong&gt;virus_quarantine_to&lt;/strong&gt;, &lt;strong&gt;spam_quarantine_to&lt;/strong&gt;, &lt;strong&gt;banned_quarantine_to&lt;/strong&gt;, &lt;strong&gt;bad_header_quarantine_to&lt;/strong&gt; variables in Amavis configuration, and an empty value is overriding those we set in Amavis configuration.&lt;/p&gt;

&lt;h4&gt;4.4 Test&lt;/h4&gt;

&lt;p&gt;Send some spam to your server, check if the tables are populated :&lt;/p&gt;

&lt;pre&gt;
mysql&amp;gt; SELECT * FROM maddr;&lt;/pre&gt;

&lt;p&gt;Check if meta informations are populated :&lt;/p&gt;

&lt;pre&gt;
mysql&amp;gt; SELECT * FROM msgs;
mysql&amp;gt; SELECT * FROM msgrcpt;&lt;/pre&gt;

&lt;p&gt;And if quarantine is filling :&lt;/p&gt;

&lt;pre&gt;
mysql&amp;gt; SELECT * FROM quarantine;&lt;/pre&gt;

&lt;h3&gt;5. Cleanup !&lt;/h3&gt;

&lt;p&gt;You should not &quot;setup and forget&quot; your quarantine SQL storage. Messages has to be deleted periodically, otherwise your database will grow forever. Look at the documentaion in &lt;strong&gt;/usr/share/docs/amavisd-new&lt;/strong&gt; to make a cronjob like this :&lt;/p&gt;

&lt;pre&gt;
#!/bin/bash

SQL_HOST=&quot;localhost&quot;;
SQL_LOGIN=&quot;amavis_storage&quot;
SQL_PASSWORD=&quot;xxxx&quot;
SQL_DB=&quot;amavis_storage&quot;

mysql --user=&quot;$SQL_LOGIN&quot; --password=&quot;$SQL_PASSWORD&quot; --host=&quot;$SQL_HOST&quot; $SQL_DB -e &quot; \
  DELETE FROM msgs WHERE time_num &amp;lt; UNIX_TIMESTAMP() - 30*24*3600; \
  DELETE FROM msgrcpt WHERE NOT EXISTS (SELECT 1 FROM msgs WHERE mail_id=msgrcpt.mail_id); \
  DELETE FROM quarantine WHERE NOT EXISTS (SELECT 1 FROM msgs WHERE mail_id=quarantine.mail_id); \
  DELETE FROM maddr WHERE NOT EXISTS (SELECT 1 FROM msgs WHERE sid=id) AND NOT EXISTS (SELECT 1 FROM msgrcpt WHERE rid=id); \
&quot;
&lt;/pre&gt;

&lt;h3&gt;&lt;a name=&quot;mailzu&quot;&gt;6. Mailzu&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I have to admit, Mailzu seems a bit obsolete as I had to patch to make it working with Amavis 3.3 tables. But it still works pretty well for a simple task like reading and releasing quarantine mails.&lt;/p&gt;

&lt;h4&gt;6.1 Installation&lt;/h4&gt;

&lt;p&gt;Download the source files at &lt;a href=&quot;http://sourceforge.net/projects/mailzu/&quot;&gt;http://sourceforge.net/projects/mailzu/&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;62. Patch&lt;/h4&gt;

&lt;p&gt;The existing Mailzu source code is quite old, and the schema of Amavis SQL tables changed. Download and apply &lt;a href=&quot;http://sourceforge.net/p/mailzu/patches/10/&quot;&gt;this patch&lt;/a&gt; in to make Mailzu work.&lt;/p&gt;

&lt;h4&gt;6.3 Configuration&lt;/h4&gt;

&lt;p&gt;I suppose that you know how to spawn PHP with CGI to serve the Mailzu files.&lt;/p&gt;

&lt;p&gt;Configure your database login and password in &lt;strong&gt;config/config.php&lt;/strong&gt; :&lt;/p&gt;

&lt;pre&gt;
$conf['db']['dbType'] = 'mysql';
$conf['db']['dbUser'] = 'amavis_storage';
$conf['db']['dbPass'] = 'xxxx';
$conf['db']['dbName'] = 'amavis_storage';
$conf['db']['hostSpec'] = 'localhost:3306';&lt;/pre&gt;

&lt;p&gt;I am using IMAP login to authenticate in Mailzu. Unfortunately, I had to turn off SSL authentication, as it wasn't working. Here is my configuration :&lt;/p&gt;

&lt;pre&gt;
$conf['auth']['serverType'] = 'imap';
$conf['auth']['imap_hosts'] = array( 'localhost:143' );
$conf['auth']['imap_type'] = 'imaptls';
$conf['auth']['imap_domain_name'] = 'example.com';&lt;/pre&gt;

&lt;p&gt;Don't forget to set yourself &quot;super&quot; :&lt;/p&gt;

&lt;pre&gt;
$conf['auth']['s_admins'] = array ('me@example.com');&lt;/pre&gt;

&lt;p&gt;And to set your web uri :&lt;/p&gt;

&lt;pre&gt;
$conf['app']['weburi'] = 'https://example.com/mailzu';&lt;/pre&gt;

&lt;h4&gt;6.4 Configure in-app release&lt;/h4&gt;

&lt;p&gt;Mailzu can also release quarantined mail. I did not implement this function, but you have to set up the amavisd-release internface on an inet socket on port 9998, instead of the existing unix socket located at &lt;strong&gt;/var/lib/amavis/amavisd.sock&lt;/strong&gt; . &lt;a href=&quot;https://www.ijs.si/software/amavisd/amavisd-new-docs.html#quar-release&quot;&gt;Read more&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;References&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.iredmail.org/docs/amavisd.sql.db.html&quot;&gt;Explanation of Amavisd SQL database&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://blog.bravi.org/?p=683&quot;&gt;AMaViS: deal with SPAM, Viruses, Banned attachments, and Bad headers&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.ijs.si/software/amavisd/amavisd-new-docs.html#quarantine&quot;&gt;amavisd-new documentation bits and pieces&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.raygibson.net/kb/amavis/amavisd.conf&quot;&gt;amavis.conf&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://sourceforge.net/projects/mailzu/&quot;&gt;Mailzu&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://sourceforge.net/p/mailzu/patches/10/&quot;&gt;Mailzu patch for Amavis 2.7.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
        
          <enclosure url="/blog/public/code/sql/amavis_storage_partial_schema.sql" length="4518" type="application/octet-stream" />
        
              </item>
          <item>
        <title>Owncloud : batch set calendar events to &quot;CONFIDENTIAL&quot;</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/11/09/Owncloud-%3A-batch-set-calendar-events-to-CONFIDENTIAL</link>
        <guid isPermaLink="false">urn:md5:69e99ed872eaaef4496117481ef71ec0</guid>
        <pubDate>Mon, 09 Nov 2015 13:11:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>calendar</category>
                  <category>confidential</category>
                  <category>owncloud</category>
                  <category>public</category>
                <description>&lt;p&gt;You are sharing your owncloud calendar with others. Good.&lt;/p&gt;&lt;p&gt;You don&amp;#8217;t want others to see the details of your events, you only want to share the fact that your are &amp;#8220;not available&amp;#8221;, so you set the event to &amp;#8220;CONFIDENTIAL&amp;#8221;.&lt;/p&gt;&lt;p&gt;By default, Owncloud sets the events to &amp;#8220;PUBLIC&amp;#8221; (visible by anyone who have read access).&lt;/p&gt;&lt;p&gt;&lt;strong&gt;How to change all the default public events to &amp;#8220;CONFIDENTIAL&amp;#8221;&amp;#160;?&lt;/strong&gt; Here is how.&lt;/p&gt;          &lt;p&gt;The iCal standard used by Owncloud sets three event types&amp;#160;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;PUBLIC&amp;#160;: the event is fully visible by anyone.&lt;/li&gt;&lt;li&gt;CONFIDENTIAL&amp;#160;: the event is fully visible to owner, but only shows time segment for those who have a read access to the calendar.&lt;/li&gt;&lt;li&gt;PRIVATE&amp;#160;: the event is only visible to owner and fully hidden to others (no time segment).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Owncloud stores the events in its database in iCal format, setting the value &amp;#8220;CLASS&amp;#8221; to the privacy level if needed, and nothing if not specified.&lt;/p&gt;&lt;p&gt;So, let&amp;#8217;s change all the default events to CONFIDENTIAL&amp;#160;:&lt;/p&gt;&lt;pre&gt;UPDATE clndr_objects SET calendardata = REPLACE(calendardata, 'END:VEVENT', 'CLASS:CONFIDENTIAL
END:VEVENT') WHERE objecttype='VEVENT' AND calendardata NOT LIKE '%CLASS:CONFIDENTIAL%' AND calendardata NOT LIKE '%CLASS:PRIVATE%' AND calendardata NOT LIKE '%CLASS:PUBLIC%';&lt;/pre&gt;&lt;p&gt;Note that the new line after &amp;#8220;CONFIDENTIAL&amp;#8221; is &lt;strong&gt;mandatory&lt;/strong&gt; and should not trigger the query until you type the &amp;#8221;&amp;#160;; &amp;#8221; and press enter.&lt;/p&gt;&lt;p&gt;Note that it will change the events &lt;strong&gt;for all users&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Backup your database before executing the query&lt;/strong&gt;.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Configurer dibbler-client pour IPv6 sur une Dedibox (Online.net) avec Debian 8 (Jessie)</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/10/21/Configurer-dibbler-client-pour-IPv6-sur-une-Dedibox-%28Online.net%29-avec-Debian-8-%28Jessie%29</link>
        <guid isPermaLink="false">urn:md5:68ab8bab67fba7928f19774250094c5e</guid>
        <pubDate>Wed, 21 Oct 2015 14:24:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>debian</category>
                  <category>dedibox</category>
                  <category>dibbler</category>
                  <category>jessie</category>
                  <category>online</category>
                  <category>proxmox</category>
                  <category>server</category>
                <description>          &lt;p&gt;La documentation d&amp;#8217;Online pour IPv6 ne traite pas le cas de Debian, Ubuntu, ou toute distribution utilisant systemd (CentOS6, etc). La documention doit être étendue pour ajouter le service sysetmd au démarrage, en lieu et place de l&amp;#8217;init script.&lt;/p&gt;&lt;h3&gt;Vérifiez que l&amp;#8217;IPv6 est activé&lt;/h3&gt;&lt;p&gt;Cela devrait normalement être le cas, puisque le noyau par défaut de Debian 8 inclut nativement IPv6 et ne peut pas être désactivé. Mais au cas où vous ne verriez pas le link-local sur vos interfaces&amp;#160;:&lt;/p&gt;&lt;p&gt;Changer dans &lt;code&gt;/etc/modprobe.d/local.conf :&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;options ipv6 disable=0&lt;/pre&gt;&lt;p&gt;Ajouter dans &lt;code&gt;/etc/modules :&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;ipv6&lt;/pre&gt;&lt;p&gt;Il faudra sans doute redémarrer pour appliquer les changments.&lt;/p&gt;&lt;h3&gt;Récupérez votre préfixe et votre DUID depuis la console d&amp;#8217;Online&lt;/h3&gt;&lt;p&gt;Vous devez &lt;a href=&quot;https://console.online.net/fr/assistance/ticket/list&quot;&gt;demander l&amp;#8217;activation de IPv6 au support&lt;/a&gt; et créer votre /64&amp;#160;&lt;a href=&quot;https://console.online.net/fr/network/&quot;&gt;dans la console d&amp;#8217;Online&lt;/a&gt; pour obtenir votre DUID.&lt;/p&gt;&lt;p&gt;Créez un /64 et n&amp;#8217;utilisez pas le /48 ou le 56 directement, vous pourriez le regretter si vous souhaitez redécouper le réseau. Vous n&amp;#8217;avez qu&amp;#8217;un seul /48 par compte, un /56 pour chaque serveur, et un /64 pour chaque failover souscrit.&lt;/p&gt;&lt;h3&gt;Configurez l&amp;#8217;interface réseau&lt;/h3&gt;&lt;p&gt;Encore une fois, c&amp;#8217;est sans doute facultatif puisque Dibbler reconfigure l&amp;#8217;interface lorsqu&amp;#8217;il se lance, donc explicitons ça dans le fichier &lt;strong&gt;/etc/network/interfaces&lt;/strong&gt;, juste au cas où&amp;#160;:&lt;/p&gt;&lt;pre&gt;iface eth0 inet6 static
    address your_ipv6_address
    netmask 64
&amp;nbsp;&amp;nbsp; &amp;nbsp;accept_ra 2
&lt;/pre&gt;&lt;h3&gt;Notes sur Proxmox et le forwarding&lt;/h3&gt;&lt;p&gt;Sous Proxmox on travaille sur l&amp;#8217;interface bridge, c&amp;#8217;est &lt;strong&gt;vmbr0&lt;/strong&gt; et non pas eth0.&lt;/p&gt;&lt;p&gt;Si le forwarding est activé, vous devez forcer le &lt;strong&gt;accept_ra&lt;/strong&gt; à &lt;strong&gt;2&lt;/strong&gt;, une valeur de 1 fera ignorer les router advertisements lorsque le forwarding est activé. &lt;a href=&quot;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&quot;&gt;Explications&lt;/a&gt;. Ajoutez dans sysctl.conf&amp;#160;:&lt;/p&gt;&lt;pre&gt;net.ipv6.conf.vmbr0.accept_ra = 2&lt;/pre&gt;&lt;p&gt;Notez bien que dans le cas où vous adressez vos machines virtuelles en IPv6 vous ne &lt;strong&gt;devez pas brancher l&amp;#8217;interface IPv6 de vos VM directement sur l&amp;#8217;interface vmbr0&lt;/strong&gt;. &lt;a href=&quot;https://forum.online.net/index.php?/topic/5380-configuring-ipv6-in-proxmox-on-dedibox-from-onlinenet/&quot;&gt;Voilà pourquoi&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Compilez et installez Dibbler&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Téléchargez &lt;a href=&quot;http://klub.com.pl/dhcpv6/dibbler/dibbler-1.0.1.tar.gz&quot;&gt;Dibbler 1.0.1&lt;/a&gt; à partir du &lt;a href=&quot;http://klub.com.pl/dhcpv6/#DOWNLOAD&quot;&gt;site officiel&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Installez build-essential&amp;#160;: &lt;code&gt;apt-get install build-essential&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Décompressez Dibbler&amp;#160;: &lt;code&gt;tar -xzf dibbler-1.0.1.tar.gz &amp;amp;&amp;amp; cd dibbler-1.0.1&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Compilez et installez Dibbler&amp;#160;: &lt;code&gt;./configure &amp;amp;&amp;amp; ./make&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Configurez Dibbler&lt;/h3&gt;&lt;p&gt;Créez les dossiers et fichiers de configuration comme le précise la documentation&amp;#160;:&lt;/p&gt;&lt;p&gt;Configurez le DUID dans &lt;strong&gt;/var/lib/dibbler/client-duid&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;mkdir /var/lib/dibbler/
touch /var/lib/dibbler/client-duid
chmod 640 /var/lib/client-duid
# Set up you duid in client-duid
vim /var/lib/client-duid
&lt;/pre&gt;&lt;p&gt;Configurez &lt;strong&gt;/etc/dibbler/client.conf&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;mkdir /etc/dibbler
vim /etc/dibbler/client.conf&lt;/pre&gt;&lt;p&gt;Voici le contenu de mon &lt;strong&gt;client.conf&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;auth-protocol reconfigure-key
auth-replay monotonic
auth-methods digest-hmac-md5
duid-type duid-ll
inactive-mode
log-level 8
iface eth0 {
    pd
    ia
}
&lt;/pre&gt;&lt;p&gt;Encore une fois, c&amp;#8217;est à adapter en fonction du nom de votre interface.&lt;/p&gt;&lt;p&gt;Démarrez le client pour tester la connectivité&amp;#160;:&lt;/p&gt;&lt;pre&gt;dibbler-client run&lt;/pre&gt;&lt;p&gt;Pour vérifier que Dibbler a configuré l&amp;#8217;interface, pressez CTRL+Z pour suspendre le processus et vérifiez que l&amp;#8217;IP et les routes sont bien configurées. Tapez la commande &amp;#8220;fg&amp;#8221; pour retourner au processus en cours d&amp;#8217;exécution, et tapez CTRL+C pour stopper Dibbler.&lt;/p&gt;&lt;p&gt;Si pendant l&amp;#8217;opération les routes et les IPs sont incorrectes, vérifiez que votre pare feu accepte les connexions entrantes par le port 546 UDP.&lt;/p&gt;&lt;h3&gt;Configurez Dibbler au démarrage&lt;/h3&gt;&lt;p&gt;Cette section est différente de la documentation d&amp;#8217;Online.&lt;/p&gt;&lt;p&gt;Avant systemd, le système d&amp;#8217;init par dépendances se contentait d&amp;#8217;un script dans /etc/init.d/. Avec systemd, il faut créer un fichier &lt;strong&gt;service&lt;/strong&gt; dans &lt;strong&gt;/etc/systemd/system/&lt;/strong&gt; .&lt;/p&gt;&lt;p&gt;Créez le fichier suivant&amp;#160;: &lt;strong&gt;/etc/systemd/system/dibbler.service&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;[Unit]
Description=Dibbler
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/sbin/dibbler-client start
ExecStop=/usr/local/sbin/dibbler-client stop
PrivateTmp=true
NonBlocking=yes

[Install]
WantedBy=multi-user.target&lt;/pre&gt;&lt;p&gt;Lancez la commande suivante pour que systemd lise le fichier&amp;nbsp;&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl daemon-reload&lt;/pre&gt;&lt;p&gt;Et activez le service&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl enable dibbler.service&lt;/pre&gt;&lt;p&gt;Et essayez de le lancer pour la première fois&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl start dibbler.service&lt;/pre&gt;&lt;p&gt;Vérifions que tout est correct&amp;#160;:&lt;/p&gt;&lt;pre&gt;service dibbler status
ifconfig
route -6
ping6 whatever-you-want.com&lt;/pre&gt;&lt;p&gt;Si tout va bien, redémarrez et l&amp;#8217;IPv6 fonctionnera dès le démarrage&amp;#160;! &lt;img src=&quot;/blog/themes/mathedit_material3/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot;&gt;&lt;/p&gt;&lt;p&gt;Addendum&amp;#160;: juste au cas où, n&amp;#8217;utilisez pas resolvconf pour pousser les DNS IPv6 automatiquement, conservez autant que possible vos DNS IPv4. Ça serait tellement dommage que votre connectivité IPv6 saute et que vous vous retrouviez sans DNS (oui ça m&amp;#8217;est arrivé&amp;#8230;).&lt;/p&gt;&lt;h3&gt;Sources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://documentation.online.net/en/serveur-dedie/reseau/ipv6-prefix&quot;&gt;http://documentation.online.net/en/serveur-dedie/reseau/ipv6-prefix&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.lowendtalk.com/discussion/48591/configuring-ipv6-for-proxmox-kvm-on-dedibox-online-net&quot;&gt;http://www.lowendtalk.com/discussion/48591/configuring-ipv6-for-proxmox-kvm-on-dedibox-online-net&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://unix.stackexchange.com/questions/47695/how-to-write-startup-script-for-systemd&quot;&gt;http://unix.stackexchange.com/questions/47695/how-to-write-startup-script-for-systemd&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://sulek.fr/index.php?article60/configuration-ipv6-pour-une-dedibox-sous-centos-7&quot;&gt;https://sulek.fr/index.php?article60/configuration-ipv6-pour-une-dedibox-sous-centos-7&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&quot;&gt;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://forum.online.net/index.php?/topic/5380-configuring-ipv6-in-proxmox-on-dedibox-from-onlinenet/&quot;&gt;https://forum.online.net/index.php?/topic/5380-configuring-ipv6-in-proxmox-on-dedibox-from-onlinenet/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Configure dibbler-client for IPV6 networking on Dedibox (or any Online.net) servers with Debian 8 (Jessie)</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/10/21/Configure-dibbler-for-IPV6-networking-on-Dedibox-%28or-any-Online.net%29-servers-with-Debian-8-%28Jessie%29</link>
        <guid isPermaLink="false">urn:md5:cf27b5e56650bb4963d6a1f71966a199</guid>
        <pubDate>Wed, 21 Oct 2015 12:50:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>debian</category>
                  <category>dedibox</category>
                  <category>dibbler</category>
                  <category>jessie</category>
                  <category>online</category>
                  <category>proxmox</category>
                  <category>server</category>
                <description>          &lt;p&gt;The &lt;a href=&quot;http://documentation.online.net/en/serveur-dedie/reseau/ipv6-prefix&quot;&gt;Online documentation for IPv6&lt;/a&gt; is not dealing with the case of Debian 8, Ubuntu, or any distribution using systemd. Systemd replaces upstart, so the procedure has to be extended to add systemd service for startup, replacing the previoux behavior that was using init scripts.&lt;/p&gt;&lt;h3&gt;Ensure that you are IPv6-proof&lt;/h3&gt;&lt;p&gt;It should be the case as Debian 8 is shipping a kernel with native IPv6, but just to be sure&amp;#160;:&lt;/p&gt;&lt;p&gt;In &lt;code&gt;/etc/modprobe.d/local.conf :&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;options ipv6 disable=0&lt;/pre&gt;&lt;p&gt;In &lt;code&gt;/etc/modules :&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;ipv6&lt;/pre&gt;&lt;p&gt;You may have to reboot in order to apply the changes.&lt;/p&gt;&lt;h3&gt;Set up your IPv6 prefix and get your DUID on Online console&lt;/h3&gt;&lt;p&gt;You have to &lt;a href=&quot;https://console.online.net/fr/assistance/ticket/list&quot;&gt;request IPv6 activation to support&lt;/a&gt; and create your /64&amp;#160;&lt;a href=&quot;https://console.online.net/fr/network/&quot;&gt;on Online console&lt;/a&gt; before getting your DUID working.&lt;/p&gt;&lt;p&gt;Make a /64 and do not use your /48 or your /56 directly, as you may regret it. You can have only one /48 by account, one /56 by server, and one /64 by IP failover (the /48 is divided to make the /56 and so on).&lt;/p&gt;&lt;h3&gt;Configure your network interface&lt;/h3&gt;&lt;p&gt;It may not be mandatory as Dibbler will reconfigure your interface, but you have to ensure that you accept router advertisements. Add to &lt;strong&gt;/etc/network/interfaces&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;iface eth0 inet6 static
    address your_ipv6_address
    netmask 64
&amp;nbsp;&amp;nbsp; &amp;nbsp;accept_ra 2
&lt;/pre&gt;&lt;h3&gt;Notes about Proxmox and forwarding&lt;/h3&gt;&lt;p&gt;On Proxmox, you are working on the bridge interface, it should be &lt;strong&gt;vmbr0&lt;/strong&gt; instead of eth0.&lt;/p&gt;&lt;p&gt;If you enabled forwarding on this interface (to give your VM an access to IPv6 network), you have to force the &lt;strong&gt;accept_ra&lt;/strong&gt; to &lt;strong&gt;2&lt;/strong&gt;, while the default value of 1 wil make your Debian to ignore router advertisements when forwarding is enabled&amp;#160;! &lt;a href=&quot;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&quot;&gt;Read more&lt;/a&gt;. Add to sysctl.conf&amp;#160;:&lt;/p&gt;&lt;pre&gt;net.ipv6.conf.vmbr0.accept_ra = 2&lt;/pre&gt;&lt;p&gt;Also &lt;strong&gt;do not set the IPv6 interface of your VM to vmbr0&lt;/strong&gt;, as you can break your network access. &lt;a href=&quot;https://forum.online.net/index.php?/topic/5380-configuring-ipv6-in-proxmox-on-dedibox-from-onlinenet/&quot;&gt;Read more&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Compile and install Dibbler&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Download &lt;a href=&quot;http://klub.com.pl/dhcpv6/dibbler/dibbler-1.0.1.tar.gz&quot;&gt;Dibbler 1.0.1&lt;/a&gt; from the &lt;a href=&quot;http://klub.com.pl/dhcpv6/#DOWNLOAD&quot;&gt;offical website&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Install build-essential&amp;#160;: &lt;code&gt;apt-get install build-essential&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Extract Dibbler&amp;#160;: &lt;code&gt;tar -xzf dibbler-1.0.1.tar.gz &amp;amp;&amp;amp; cd dibbler-1.0.1&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Compile and install Dibbler&amp;#160;: &lt;code&gt;./configure &amp;amp;&amp;amp; ./make&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Configure Dibbler&lt;/h3&gt;&lt;p&gt;Make the directories and set up according to the documentation&amp;#160;:&lt;/p&gt;&lt;p&gt;Set up duid&amp;#160;:&lt;/p&gt;&lt;pre&gt;mkdir /var/lib/dibbler/
touch /var/lib/dibbler/client-duid
chmod 640 /var/lib/client-duid
# Set up you duid in client-duid
vim /var/lib/client-duid
&lt;/pre&gt;&lt;p&gt;Set up client.conf&amp;#160;:&lt;/p&gt;&lt;pre&gt;mkdir /etc/dibbler
vim /etc/dibbler/client.conf&lt;/pre&gt;&lt;p&gt;The content of my client.conf&amp;#160;:&lt;/p&gt;&lt;pre&gt;auth-protocol reconfigure-key
auth-replay monotonic
auth-methods digest-hmac-md5
duid-type duid-ll
inactive-mode
log-level 8
iface eth0 {
    pd
    ia
}
&lt;/pre&gt;&lt;p&gt;Note that if your interface name is different you have to change it accordingly. For instance, on a Proxmox host server, it should be &lt;strong&gt;vmbr0&lt;/strong&gt; instead of eth0.&lt;/p&gt;&lt;p&gt;Start dibbler to try the connectivity&amp;#160;:&lt;/p&gt;&lt;pre&gt;dibbler-client run&lt;/pre&gt;&lt;p&gt;Hit CTRL+Z to suspend the process and check that the IP and routes are configured. Type the command &amp;#8220;fg&amp;#8221; to get back to the running process and hit CTRL+C to stop it.&lt;/p&gt;&lt;p&gt;If it doesn&amp;#8217;t work, check your firewall, dibbler needs to listen port 546 UDP.&lt;/p&gt;&lt;h3&gt;Set Dibbler at startup&lt;/h3&gt;&lt;p&gt;This section differs from Online documentation.&lt;/p&gt;&lt;p&gt;Before systemd, the dependency-based boot sequence only needed an init script, for instance /etc/init.d/dibbler . With systemd, you have to make a &lt;strong&gt;service&lt;/strong&gt; file in &lt;strong&gt;/etc/systemd/system/&lt;/strong&gt; .&lt;/p&gt;&lt;p&gt;Make the following file&amp;#160;: &lt;strong&gt;/etc/systemd/system/dibbler.service&lt;/strong&gt;&amp;#160;:&lt;/p&gt;&lt;pre&gt;[Unit]
Description=Dibbler
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/sbin/dibbler-client start
ExecStop=/usr/local/sbin/dibbler-client stop
PrivateTmp=true
NonBlocking=yes

[Install]
WantedBy=multi-user.target&lt;/pre&gt;&lt;p&gt;Run the following command to make systemd read file&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl daemon-reload&lt;/pre&gt;&lt;p&gt;Enable the service&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl enable dibbler.service&lt;/pre&gt;&lt;p&gt;And then, try to start it&amp;#160;:&lt;/p&gt;&lt;pre&gt;systemctl start dibbler.service&lt;/pre&gt;&lt;p&gt;Check everything is fine&amp;#160;:&lt;/p&gt;&lt;pre&gt;service dibbler status
ifconfig
route -6
ping6 whatever-you-want.com&lt;/pre&gt;&lt;p&gt;Reboot and the IPv6 networking should work at startup&amp;#160;! &lt;img src=&quot;/blog/themes/mathedit_material3/smilies/smile.png&quot; alt=&quot;:)&quot; class=&quot;smiley&quot;&gt;&lt;/p&gt;&lt;p&gt;Addendum&amp;#160;: just in case, don&amp;#8217;t use resolvconf with IPv6 DNS pushing and if possible keep IPv4 DNS, it would be such a pity if the IPv6 networking crashes while your DNS servers are set to IPv6 addresses (yeah, it happened to to me)&amp;#8230;&lt;/p&gt;&lt;h3&gt;Sources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://documentation.online.net/en/serveur-dedie/reseau/ipv6-prefix&quot;&gt;http://documentation.online.net/en/serveur-dedie/reseau/ipv6-prefix&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.lowendtalk.com/discussion/48591/configuring-ipv6-for-proxmox-kvm-on-dedibox-online-net&quot;&gt;http://www.lowendtalk.com/discussion/48591/configuring-ipv6-for-proxmox-kvm-on-dedibox-online-net&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://unix.stackexchange.com/questions/47695/how-to-write-startup-script-for-systemd&quot;&gt;http://unix.stackexchange.com/questions/47695/how-to-write-startup-script-for-systemd&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://sulek.fr/index.php?article60/configuration-ipv6-pour-une-dedibox-sous-centos-7&quot;&gt;https://sulek.fr/index.php?article60/configuration-ipv6-pour-une-dedibox-sous-centos-7&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&quot;&gt;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://forum.online.net/index.php?/topic/5380-configuring-ipv6-in-proxmox-on-dedibox-from-onlinenet/&quot;&gt;https://forum.online.net/index.php?/topic/5380-configuring-ipv6-in-proxmox-on-dedibox-from-onlinenet/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Un dotclear vous manque et tout est dépeuplé</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/10/17/Un-dotclear-vous-manque-et-tout-est-d%C3%A9peupl%C3%A9</link>
        <guid isPermaLink="false">urn:md5:5665047e7acb8d5e22bba3e42baf2ea8</guid>
        <pubDate>Sat, 17 Oct 2015 19:24:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>blog</category>
                  <category>bug</category>
                  <category>dotclear</category>
                  <category>timeout</category>
                <description>          &lt;p&gt;Aujourd&amp;#8217;hui je n&amp;#8217;arrivais pas à accéder au panel d&amp;#8217;administration de mon Dotclear aujourd&amp;#8217;hui. Après avoir rentré le bon mot de passe, La page tournait en boucle pour terminer sur une erreur 500.&lt;/p&gt;&lt;p&gt;Le blog fonctionnait toujours et toutes les autres pages utilisant PHP n&amp;#8217;afichaient aucun problème.&lt;/p&gt;&lt;p&gt;Dans les logs Apache, j&amp;#8217;avais&amp;#160;:&lt;/p&gt;&lt;pre&gt;mod_fcgid: read data timeout in 40 seconds
End of script output before headers: index.php
mod_fcgid: process 3114 graceful kill fail, sending SIGKILL
&lt;/pre&gt;&lt;p&gt;Aucun processus n&amp;#8217;était à 100% de CPU, la BDD était au repos, le processus PHP semblait se &amp;#8220;figer&amp;#8221; au moment d&amp;#8217;ouvrir la page d&amp;#8217;administration.&lt;/p&gt;&lt;p&gt;Le site de Dotclear était down lui aussi. Coincidence&amp;#160;?&lt;/p&gt;&lt;p&gt;Juste pour voir, j&amp;#8217;ai rajouté dans le fichier host de mon serveur la ligne suivante&amp;#160;:&lt;/p&gt;&lt;pre&gt;127.0.0.1    download.dotclear.org
&lt;/pre&gt;&lt;p&gt;Après avoir relancé Apache, l&amp;#8217;administration s&amp;#8217;est mise à fonctionner&amp;#160;!&lt;/p&gt;&lt;p&gt;Ce n&amp;#8217;était donc pas une coincidence, si Dotclear essaie de recherche ses mises à jour alors que le site &lt;a href=&quot;http://download.dotclear.org&quot;&gt;download.dotclear.org&lt;/a&gt; est en panne (pour des causes naturelles ou non), le panel d&amp;#8217;administration reste en attente d&amp;#8217;une connexion et on ne peut plus s&amp;#8217;y connecter. Évidemment, plus on raffraichit la page, plus on tape sur ce pauvre serveur de Dotclear.&lt;/p&gt;&lt;center&gt;&lt;figure style=&quot;{figureStyle}&quot;&gt;&lt;img class=&quot;media&quot; alt=&quot;heavy-mallet.gif&quot; src=&quot;https://uname.pingveno.net/blog/public/posts_thumb/.heavy-mallet_m.jpg&quot; /&gt;&lt;/figure&gt;&lt;/center&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Pour ceux qui n&amp;#8217;ont pas accès à leur serveur, vous pouvez changer l&amp;#8217;URL de DC_UPDATE_URL dans le fichier &lt;strong&gt;inc/prepend.php&lt;/strong&gt; pour le faire pointer ailleurs, temporairement&amp;#160;:&lt;/p&gt;&lt;pre&gt;define('DC_UPDATE_URL','http://download.dotclear.org/versions.xml');
&lt;/pre&gt;&lt;p&gt;N&amp;#8217;oubliez pas de le remettre comme avant une fois le site &lt;a href=&quot;http://download.dotclear.org&quot;&gt;download.dotclear.org&lt;/a&gt; réparé, sinon vous n&amp;#8217;aurez plus jamais de mises à jour automatiques &lt;img src=&quot;/blog/themes/mathedit_material3/smilies/wink.png&quot; alt=&quot;;)&quot; class=&quot;smiley&quot;&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Mise à jour&lt;/strong&gt;&amp;#160;: à priori, il y a aussi les flux RSS qui s&amp;#8217;affichent sur le côté de l&amp;#8217;admin qui sont aussi à désactiver, j&amp;#8217;ai fais un gros patch dans le fichier &lt;strong&gt;admin/index.php&lt;/strong&gt; pour finir par faire marcher l&amp;#8217;administration&amp;#160;:&lt;/p&gt;&lt;pre&gt;--- admin/index.php    2015-10-17 19:58:19.873121948 +0200
+++ admin/index.php    2015-10-17 19:58:08.713227238 +0200
@@ -80,6 +80,7 @@
 $favs = $core-&amp;gt;favs-&amp;gt;getUserFavorites();
 $core-&amp;gt;favs-&amp;gt;appendDashboardIcons($__dashboard_icons);
 
+/*
 # Check plugins and themes update from repository
 function dc_check_store_update($mod, $url, $img, $icon)
 {
@@ -165,7 +166,7 @@
 }
 
 $core-&amp;gt;callBehavior('adminDashboardItems', $core, $__dashboard_items);
-
+*/
 # Dashboard content
 $dashboardContents = '';
 $__dashboard_contents = new ArrayObject(array(new ArrayObject,new ArrayObject));
&lt;/pre&gt;</description>
        
              </item>
          <item>
        <title>Postfix : configure postmaster, hostmaster, and abuse catchall  for RFC compliance</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/08/29/Postfix-%3A-configure-postmaster%2C-hostmaster%2C-and-abuse-catchall-for-RFC-compliance</link>
        <guid isPermaLink="false">urn:md5:2236b92a9adc8066108e9709c6c32959</guid>
        <pubDate>Sat, 29 Aug 2015 18:02:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>catchall</category>
                  <category>debian</category>
                  <category>mail</category>
                  <category>postfix</category>
                  <category>server</category>
                <description>          &lt;p&gt;This short howto will show you how to set up a catchall for common required email addresses. Some mail servers are testing if mail is accepted on this addresses to detect spammymail servers. Hostmaster address can also be used for domain Trading, to check the ownership of the domain.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. &lt;/strong&gt;Create a file named &lt;strong&gt;/etc/postfix/regexp-catchall.cf&lt;/strong&gt; with the following content:&lt;/p&gt;&lt;pre&gt;# Catchall to comply with RFC standards
/^postmaster@/    youshouldreadit@mydomain.com
/^hostmaster@/    youshouldreadit@mydomain.com
/^abuse@/         youshouldreadit@mydomain.com&lt;/pre&gt;&lt;p&gt;Replace &lt;em&gt;youshouldreadit@mydomain.com&lt;/em&gt; with a mail address you actually read.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Open &lt;strong&gt;/etc/postfix/main.cf&lt;/strong&gt; and locate (or create) the line &lt;strong&gt;virtual_alias_maps&lt;/strong&gt;, and add at the end &lt;strong&gt;regexp:/etc/postfix/regexp-catchall.cf&lt;/strong&gt;, for instance:&lt;/p&gt;&lt;pre&gt;virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, regexp:/etc/postfix/regexp-catchall.cf&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;3. &lt;/strong&gt;Restart Postfix.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Warning&amp;#160;: read &lt;a href=&quot;http://uname.pingveno.net/blog/index.php/post/2015/08/29/Postfix-%3A-configure-postmaster%2C-hostmaster%2C-and-abuse-catchall-for-RFC-compliance#c73895&quot;&gt;comment #4&lt;/a&gt; for issues with this setup&lt;/strong&gt;.&lt;/p&gt;</description>
        
              </item>
      </channel>
</rss>
