<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Zakame.Net</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/" />
    <link rel="self" type="application/atom+xml" href="https://zakame.net/atom.xml" />
    <id>tag:zakame.net,2013-12-12://1</id>
    <updated>2017-12-23T08:31:55Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.2.13</generator>

<entry>
    <title>Composing a  Docker Hub Mirror and Private Registry   - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2017/12/composing-a-docker-hub-mirror-and-private-registry.html" />
    <id>tag:zakame.net,2017:/blog//2.15</id>

    <published>2017-12-23T06:37:38Z</published>
    <updated>2017-12-23T08:31:55Z</updated>

    <summary>Building on mirroring the Docker Hub, I next wanted a way to share private Docker images between my main Docker host and with Docker Machines on VMs. Of course, I could have gone the route of subscribing to a service...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="containers" label="containers" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="devops" label="devops" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="docker" label="docker" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="images" label="images" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="virtualization" label="virtualization" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>Building on <a href="https://zakame.net/blog/2017/07/mirroring-the-docker-hub.html">mirroring the Docker Hub</a>, I next wanted a way to share private Docker images between my main Docker host and with Docker Machines on VMs.  Of course, I could have gone the route of subscribing to a service like <a href="https://quay.io">Quay</a> or even <a href="https://hub.docker.com/account/billing-plans/">Docker Hub's own private plans</a>, but again I'm limited on my bandwidth supply and, this would also mean re-downloading images across VMs, which is very wasteful.</p>

<p>It turns out that I can also run local private registries on the same host as my mirror as its own container, and what's more, I can put these all together in a simple Docker Compose system.</p>
]]>
        <![CDATA[<h3>A simple Registry Mirror container</h3>

<p>Using a Docker Compose v3 configuration, I can set up a service like this:</p>

<pre><code>
  registry_mirror:
    container_name: registry-mirror
    restart: always
    image: registry:2
    environment:
      REGISTRY_STORAGE_DELETE_ENABLED: "true"
      REGISTRY_PROXY_REMOTEURL: "https://registry-1.docker.io"
    ports:
      - "50000:5000"
    volumes:
      - mirror:/var/lib/registry
</code></pre>

<p>Note that I give a proper name to the container instead of letting Docker Compose name it for me, so I can easily check on its status or logs via e.g <code>docker logs -f registry-mirror</code>.</p>

<p>I have a pretty simple configuration here, but if I need a more sophisticated one, I can just update the environment hash with new settings.</p>

<h3>A private Docker Registry container for local</h3>

<p>For building and sharing private images, I have this other service:</p>

<pre><code>
  registry_private:
    container_name: registry-private
    restart: always
    image: registry:2
    ports:
      - "50001:5000"
    volumes:
      - private:/var/lib/registry
</code></pre>

<p>Nearly zero customization on the registry config, other than a different exposed port.</p>

<h3>Docker volumes for image storage</h3>

<p>For the meantime, I keep the image storage of both registry services in simple Docker Compose named volumes:</p>

<pre><code>
volumes:
  mirror:
  private:
</code></pre>

<h3>Putting it all together</h3>

<p>I have this all down in a <a href="https://github.com/zakame/docker-registry-compose">GitHub repo</a>, such that starting the Compose system is as easy as a <code>docker-compose up -d</code>.</p>

<p>The only other thing to do next is to make your Docker host (or Docker Machine VMs) use these registries.  For the registry mirror, we need to run <code>dockerd</code> with <code>--registry-mirror</code>, while for the private registry, we use <code>--insecure-registry</code>.  On systems with a <code>/etc/docker/daemon.json</code>, the configuration would look like this:</p>

<pre></code>
  {
      "insecure-registries": ["127.0.0.1:50001"],
      "registry-mirrors": ["http://127.0.0.1:50000"]
  }
</code></pre>

<h3>Extra: Using the same Registries on all Docker Machines</h3>

<p>Perhaps the best use case for setting this all up is when you want to have several Docker Machines using these registries.  In my case, all I have to do is to deploy these like this:</p>

<pre><code>
docker-machine create --driver=kvm --engine-registry-mirror=http://192.168.122.1:50000 --engine-insecure-registry http://192.168.122.1:50001 my-machine
</code></pre>

<p>In my reference libvirt/KVM setup, my Docker host running this Registry Compose system is listening on 192.168.122.1 as well a localhost.  This means that on <code>my-machine</code>, I can pull private images like e.g. <code>docker pull 192.168.122.1:50001/my-private-image:4.2</code> while still being able to fetch Docker Hub hosted images like normal.</p>
]]>
    </content>
</entry>

<entry>
    <title>TIL in this Month&apos;s Perl 6 Bug SQUASHathon - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2017/09/til-in-this-months-perl-6-bug-squashathon.html" />
    <id>tag:zakame.net,2017:/blog//2.14</id>

    <published>2017-09-08T06:07:56Z</published>
    <updated>2017-09-08T07:12:05Z</updated>

    <summary>A bit overdue post, but I attended this months&apos;s Perl 6 Community Bug Squashathon last weekend and it was fun! I had a great time learning some more Perl 6 while making contributions at the same time. Definitely looking forward...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="perl6" label="perl6" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>A bit overdue post, but I attended this months's <a href="http://blogs.perl.org/users/zoffix_znet/2017/08/youre-invited-community-bug-squashathon.html" title="Perl 6 Squashathon">Perl 6 Community Bug Squashathon</a> last weekend and it was fun!  I had a great time learning some more Perl 6 while making contributions at the same time.  Definitely looking forward to next month's!</p>

<p>Here are a few little bits of Things I've Learned...</p>
]]>
        <![CDATA[<ul>
<li>Through type constraints on the <em>invocant</em> in method signatures, Perl 6 classes can have <a href="https://github.com/perl6/doc/pull/1495">class and instance methods</a>.</li>
<li>The same type constraints above are nicknamed <em>type smileys</em>, and check for the <a href="https://github.com/perl6/doc/pull/1502">invocant's <code>.DEFENITE</code>ness</a> (whether if it is a <em>type object</em>, or an <em>object instance</em>)</li>
<li><code>Int</code>/<code>Real</code> <code>.rand</code> method do emit a result between <a href="https://github.com/perl6/doc/pull/1498">0 inclusive and <code>n</code> exclusive</a>.</li>
<li><code>make</code>/<code>made</code> in grammar <code>Match</code> objects <a href="https://github.com/perl6/doc/issues/897">access stores for data</a> in grammar action classes</li>
<li>Perl 6 IRC has <a href="https://github.com/perl6/doc/issues/711">a lot of bots</a> doing all sorts of work, from reporting PRs and reviews, to passing away messages, and even providing a Perl 6 evaluator for tiny programs!</li>
<li>There's virtual pizza in the Squashathon, yum!</li>
</ul>

<p>Even after the month's squashathon ended, there's still a few things I think I can do in the meantime:</p>

<ul>
<li>further help out on the <a href="https://github.com/perl6/doc/issues">perl6/doc issues</a> such as language bits that need more documentation</li>
<li>try to get an <a href="https://github.com/melpa/melpa/pull/4984">updated Emacs perl6-mode to MELPA</a></li>
<li>help out on <a href="https://github.com/perl6/docker/issues">Rakudo Star on Docker</a></li>
</ul>

<p>Thanks to Zoffix, moritz, AlexDaniel, and others for guiding me, so looking forward to helping out further soon!</p>

<p>How about you, dear readers?  Maybe you can help out too?</p>
]]>
    </content>
</entry>

<entry>
    <title>Mirroring the Docker Hub - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2017/07/mirroring-the-docker-hub.html" />
    <id>tag:zakame.net,2017:/blog//2.13</id>

    <published>2017-07-29T10:10:02Z</published>
    <updated>2017-07-30T04:18:04Z</updated>

    <summary>Some recent work in maintaining the official Perl image for Docker lead me into pulling in different copies and tags of buildpack-deps more than once, in different machines; as a result, I used a lot of network bandwidth for image...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="containers" label="containers" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="devops" label="devops" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="docker" label="docker" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="images" label="images" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="virtualization" label="virtualization" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p><a href="https://github.com/Perl/docker-perl/compare/8b57a74...r20170728.0">Some recent work</a> in maintaining the official <a href="https://hub.docker.com/_/perl">Perl</a> image for Docker lead me into pulling in different copies and tags of <a href="https://hub.docker.com/_/buildpack-deps"><code>buildpack-deps</code></a> more than once, in different machines; as a result, I used a lot of network bandwidth for image pulling.  Aside from this, I also run several VMs via libvirt/KVM, via Docker Machine to start up VMs for Docker Swarm and Minikube.</p>

<p>I wanted to save my bandwidth usage, and it turns out there is a way to do this by building on some Docker features...</p>
]]>
        <![CDATA[<h3>Using "remote" Docker daemon environment for the Docker client</h3>

<p>One approach is to not use your local (bare-metal) Docker context at all, and use a Docker Machine's <a href="https://docs.docker.com/machine/reference/env/">environment</a> instead:</p>

<pre><code>
$ docker-machine create my-remote-machine
$ eval $(docker-machine env my-remote-machine)
$ docker info 
</code></pre>

<p>Minikube (which builds on docker-machine) also <a href="https://kubernetes.io/docs/getting-started-guides/minikube/#reusing-the-docker-daemon">encourages</a> this approach:</p>

<pre><code>
$ minikube start
$ eval $(minikube docker-env)
</code></pre>

<p>Either setup will change your shell's environment to use a "remote" Docker server, which means <code>docker pull</code>s will put the images in the remote's own storage.  This is good in cases where you retain a single machine or minikube instance, but should you delete the instance, you'd have to re-pull again.</p>

<h3>Pipe images from local to remote via SSH</h3>

<p>Another approach, especially for Minikube, is to use an SSH pipe to send images from local to remote, like this:</p>

<pre><code>
$ docker pull myimage:4.2
$ docker save myimage:4.2 | minikube ssh docker load
</code></pre>

<p>Again, this borrows from docker-machine:</p>

<pre><code>
$ docker save myimage:4.2 | docker-machine ssh my-remote-machine docker load
</code></pre>

<p>It is good enough for testing local private images in a swarm, but can get tedious real fast.</p>

<h3>Running a pull-through Docker Registry</h3>

<p>Fortunately, Docker's basic architecture already provides a way to reduce the tedium by means of the Docker Registry.  One of the Registry's features is that it can run as a proxy (<a href="https://docs.docker.com/registry/recipes/mirror/">pull-through cache</a>) of the Docker Index.  One can thus start a persistent container like this:</p>

<pre><code>
$ docker run -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io -e REGISTRY_STORAGE_DELETE_ENABLED=true -d -p 50000:5000 --restart=always --name registry registry:2
</code></pre>

<p>This lets me run a Registry proxy on <code>localhost:50000</code>, which I can then point Docker daemons to via the <code>registry-mirrors</code> configuration, e.g. in <code>/etc/docker/daemon.json</code>:</p>

<pre><code>
{
  "registry-mirrors: ["http://127.0.0.1:50000"]
}
</code></pre>

<p>There are a few caveats with it though:</p>

<ul>
<li>The proxy Registry will always fetch images with unqualified tags such as <code>docker pull myimage</code>, translating them into requests for <code>docker pull myimage:latest</code>; thus, it is preferable to use named tags on images so that the proxy Registry will only update its local image copy when there are updates from the remote Docker Index.  The SSH pipe trick would be preferable in this case.</li>
<li>The proxy Registry only works with the Docker Index/Central Hub and not with private registries.</li>
<li>You can't push local images into the proxy Registry; instead you can push to Docker Hub or to another/private registry, or just run another local Registry that accept pushes, but for now I'm fine with this.</li>
</ul>

<h3>Putting it all together</h3>

<p>Making this work on docker-machine and minikube is a matter of passing in certain flags.  In my case, the registry container also listens on my libvirt/KVM default network bridge (192.168.122.1) thus I have to do</p>

<pre><code>
$ minikube start --registry-mirror=http://192.168.122.1:50000
</code></pre>

<p>for minikube.  For docker-machine, it looks like this:</p>

<pre></code>
$ docker-machine create --engine-registry-mirror=http://192.168.122.1:5000 my-docker-machine
</code></pre>
]]>
    </content>
</entry>

<entry>
    <title>nginx and nested locations - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2017/07/nginx-and-nested-locations.html" />
    <id>tag:zakame.net,2017:/blog//2.12</id>

    <published>2017-07-21T09:50:54Z</published>
    <updated>2017-07-21T10:28:54Z</updated>

    <summary>Another quick one for the blog. I was moving around some apps from subdomains to my main domain to take advantage of the new SSL-enabled web, and I needed some schooling about nginx once more to get things right. Here&apos;s...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="devops" label="devops" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="https" label="https" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="nginx" label="nginx" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ssl" label="ssl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>Another quick one for the blog.  I was moving around some apps from subdomains to my main domain to take advantage of the new <a href="https://zakame.net/blog/2017/07/lets-encrypt-with-cryptle.html">SSL-enabled web</a>, and I needed some schooling about <a href="https://nginx.org">nginx</a> once more to get things right.  Here's one bit about locations and nesting.</p>
]]>
        <![CDATA[<h3>From http://foo.mydomain.net to https://mydomain.net/foo</h3>

<p>I have a few things going on under subdomains that I wanted to move off to my main domain as subpaths instead.  As such I have a <code>/etc/nginx/sites-enabled/foo</code> configuration like this:</p>

<pre><code>
server {
        root /srv/somewhere/over/the/rainbow/www;

        index index.php index.html index.htm;

        server_name foo.mydomain.net;

        access_log /srv/somewhere/over/the/rainbow/log/access.log;
        error_log /srv/somewhere/over/the/rainbow/log/error.log info;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
        } 
}       
</code></pre>

<p>I wanted to move things off to <code>/etc/nginx/sites-enabled/main</code>, which has configurations for <code>location / {...}</code> and whatnot.  Naturally, I thought I could get away with doing this:</p>

<pre><code>
        location /foo/ {
                alias /srv/somewhere/over/the/rainbow/www/;
                index index.php;

                location ~ *\.php$ {
                        include snippets/fastcgi-php.conf;
                        fastcgi_pass unix:/var/run/php5-fpm.sock;
                }
        }
</code></pre>

<p>But alas, requests for <code>http://mydomain.net/foo/blah.php</code> returned 404 instead of my expected app.</p>

<h3>Nesting prefix and regex based locations</h3>

<p>Reading about <a href="https://nginx.org/r/location">nginx location</a> again, I noticed this:</p>

<blockquote>
To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used. 
</blockquote>

<p>I was under the impression that the prefix-based locations will also nest their last match with other location blocks within them, but apparently they do not.  Hence the configuration becomes</p>

<pre><code>
        location /foo/ {
                alias /srv/somewhere/over/the/rainbow/www/;
                index index.php;

                location ~ /foo/*\.php$ {
                        include snippets/fastcgi-php.conf;
                        fastcgi_pass unix:/var/run/php5-fpm.sock;
                }
        }
</code></pre>

<p>Taking out the <code>location ~ /foo/*\.php$ { ... }</code> block from the nest will not work, which is consistent with the statement above.</p>

<p>This is further validated in <a href="https://www.ruby-forum.com/topic/4422812#1137038">this post</a> with</p>

<pre><code>
   location /app1/ {
       # something special for app1 here, e.g.
       # access control
       auth_basic ...
       access ...

       location = /app1/login {
           # something special for /app1/login,
           # eveything from /app1/ is inherited

           proxy_pass ...
       }

       location ~ \.jpg$ {
           expires 1m;
       }
   }
</code></pre>

<h3>Handling transitions from old to new location</h3>

<p>After getting schooled and confirming it all works, now I just have to change my old subdomain configs to just use a <code>return</code>:</p>

<pre><code>
        return 301 https://mydomain.net/foo$request_uri;
</code></pre>

<p>And I'm all set.</p>
]]>
    </content>
</entry>

<entry>
    <title>Some Slackware tips - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2017/07/some-slackware-tips.html" />
    <id>tag:zakame.net,2017:/blog//2.11</id>

    <published>2017-07-18T04:37:23Z</published>
    <updated>2017-07-18T07:36:49Z</updated>

    <summary>Intro I&apos;ve been using Slackware Linux since around 2010-2011, moving from Debian mainly because I got tired of the package churn and following the internal politics of DDs. Initially I tried it as a way of getting a close to...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="devops" label="devops" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="slackware" label="slackware" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<h3>Intro</h3>

<p>I've been using Slackware Linux since around 2010-2011, moving from Debian mainly because I got tired of the package churn and following the internal politics of DDs.  Initially I tried it as a way of getting a close to BSD experience on Linux, since I was already using OpenBSD at the time (more on that on a later post.)  Turns out that having a prior BSD experience helps a lot, especially as Slackware is as "upstream" as upstream gets (very minimal, if any, distro-specific changes, as a matter of policy.)</p>

<p>Since it was Slackware's <a href="http://www.slackware.com/announce/1.0.php">birthday</a> just sometime ago, let me share some tips and tricks I've learned over the years.</p>
]]>
        <![CDATA[<h3>Use <code>slacktrack</code> as a next choice after SlackBuilds</h3>

<p>Both <a href="https://www.slackbuilds.org">SlackBuilds.org</a> and <a href="http://www.slackware.com/~alien/slackbuilds/">alienBOB's repo</a> have a large cache of additional software packages to get from, but there are few cases where sometimes you'd need to install software without a SlackBuild.  In those cases, one might just go straight to doing <code>./configure &amp;&amp; make &amp;&amp; make install</code> for those software that claim to be well-behaved and install only into <code>/usr/local</code> and nowhere else.  For more complex software, something like <a href="https://www.gnu.org/software/stow/">GNU stow</a> may be required to track the file changes and try to make sense out of the install.</p>

<p>On Slackware though, there's already a GNU stow alike in the form of <a href="http://packages.slackware.com/?r=slackware-current&amp;p=slacktrack-2.18-i586-1.txz">slacktrack</a>, which not only provides a way to track file changes, but can optionally make a full Slackware package that can be installed using <code>pkgtools</code>.  This is a nice alternative when you don't want to write out a full SlackBuild setup for that package (yet); instead, you write a <code>.build</code> file that is a very thin wrapper for your software's build/install system.</p>

<p>As an example, I use the <a href="https://github.com/teleshoes/acpi_call">acpi_call</a> Linux kernel module and <a href="https://github.com/teleshoes/tpacpi-bat">tpacpi-bat</a> software on my ThinkPad X220, which are not on those two repos above, but on GitHub.  For my case, all I need to do is to <a href="https://github.com/zakame/acpi_call">fork</a> <a href="https://github.com/zakame/tpacpi-bat">those</a> GitHub repos, add a <code>.build</code> and <code>slack-desc</code> file for each (and a <code>doinst.sh</code> for the kernel module so I can run <code>depmod</code> upon install/upgrade,) then invoke slacktrack, like so for <code>tpacpi-bat</code>:</p>

<pre><code># cd tpacpi-bat
# slacktrack -Qp tpacpi-bat_3.0-x86_64-1zakame.tgz '/bin/sh -x tpacpi-bat.build'
</code></pre>

<p>This produces a Slackware package in <code>/tmp</code>, so while tpacpi-bat is already installed and tracked by a dummy record in <code>/var/log/packages</code>, I can still do something like</p>

<pre><code># installpkg /tmp/tpacpi-bat_3.0-x86_64-1zakame.tgz
</code></pre>

<p>To install the package with a proper <code>slack-desc</code> (and in the case of <code>acpi_call</code>, an actual package post-install script.)    </p>

<h3>Generate initrds after <code>slackpkg upgrade-all</code></h3>

<p>This one is something I picked up quite <a href="https://www.linuxquestions.org/questions/slackware-14/requests-for-current-20151216-a-4175561577/page173.html#post5734362">recently</a>.  What I used to do is that after a <code>slackpkg upgrade-all</code> with a kernel update, I'd fire up a separate root shell to run <code>/usr/share/mkinitrd/mkinitrd_command_generator.sh --run /boot/vmlinuz-generic | sh</code> so I can have a new <code>/boot/initrd.gz</code> once slackpkg prompts me to run LILO.</p>

<p>It turns out that slackpkg has a simple mechanism of customizing package post-installation work, since slackpkg is after all a wrapper around the standard <code>pkgtools</code>.  In this case, what I needed to customize is the <code>lookkernel()</code> function in <code>/usr/libexec/slackpkg/functions.d/post-functions.sh</code>.  Copy that function over to a new file (say, <code>/usr/libexec/slackpkg/functions.d/z-lookkernel.sh</code>) and edit so it becomes something like this:</p>

<pre><code>
lookkernel() {
    NEWKERNELMD5=$(md5sum /boot/vmlinuz 2>/dev/null)
    if [ "$KERNELMD5" != "$NEWKERNELMD5" ]; then
        if [ -x /usr/share/mkinitrd/mkinitrd_command_generator.sh ]; then
            echo -e "\n
Your kernel image was updated.
Do you want slackpkg to run mkinitrd now? (Y/n)"
            answer
            if [ "$ANSWER" != "n" ] && [ "$ANSWER" != "N" ]; then
                ( /usr/share/mkinitrd/mkinitrd_command_generator.sh --run /boot/vmlinuz-generic | sh )
            fi
        fi
        if [ -x /sbin/lilo ]; then
            echo -e "\n
Your kernel image was updated.  We highly recommend you run: lilo
Do you want slackpkg to run lilo now? (Y/n)"
            answer
            if [ "$ANSWER" != "n" ] && [ "$ANSWER" != "N" ]; then
                /sbin/lilo
            fi
        else
            echo -e "\n
Your kernel image was updated and lilo is not found on your system.
You may need to adjust your boot manager(like GRUB) to boot appropriate
kernel."
        fi
    fi
}
</code></pre>

<p>This customization will now let <code>slackpkg upgrade-all</code> prompt me about updating my initrd upon a kernel upgrade, along with a subsequent prompt to update LILO.</p>

<h3>Prefer <code>startx</code> over display managers</h3>

<p>For some, this might very obvious, but this one is something I learned early on, even when on Debian or OpenBSD.  I can't count how many times I've read questions from people asking about what to do next after upgrading their display driver and/or kernel, rebooting, and getting a blank screen instead, with some of them not even able to switch virtual consoles back to <code>tty1</code>.  Or, it boots up fine to presenting the display manager, only to break upon logging in because of somesuch.</p>

<p>On a default install, Slackware would drop you to runlevel 3, which will not run a display manager.  This is a good default, since this means you have <code>startx</code> as an option to run X11, and even more, you have some option to check if your configuration is ok, by looking at your <code>/var/log/dmesg</code> or <code>/var/log/Xorg.0.log</code>.  Moreover, logging in to console shell lets you have a chance to set up your environment the way you want it, especially if you need some X11 tweaks.  Which leads to next item...</p>

<h3>Know your login shell's init (and maybe your X11 init too)</h3>

<p>I know most people have a simple login shell configuration, e.g. on bash, just having a <code>.bashrc</code> and maybe even a <code>.profile</code>.  But there's more to that than just those two files.  For example, if you're on a Slackware64 with multilib enabled, you can <code>source /etc/profile.d/32dev.sh</code> to get additional environment tweaks for compiling software under 32-bit mode.</p>

<p>For bash, I recommend reading up the <code>INVOCATION</code> section of the manpage.  For zsh, there's a corresponding <code>STARTUP/SHUTDOWN FILES</code> section in its manpage as well.  Other shells definitely have their own style of setup, so be sure to check out their docs.</p>

<p>If you're going to use X11 via <code>startx</code>, it is often helpful to look around <code>/etc/X11/xinit</code> and peek at the various <code>xinitrc*</code> files.  Reading <code>startx</code>'s manpage should also give a clearer idea about configuring it so you can run your preferred apps and window manager/desktop environment.</p>

<h3>Outro</h3>

<p>These last couple of tips are pretty much something that can be applied to just about any Linux/BSD system, not just Slackware.  However, these are often overlooked so I think it best to tell here, and moreover, I think this shows how well and generic Slackware is.</p>

<p>Kudos once more to Patrick Volkerding and and the Slackware team!</p>
]]>
    </content>
</entry>

<entry>
    <title>Let&apos;s Encrypt with Crypt::LE - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2017/07/lets-encrypt-with-cryptle.html" />
    <id>tag:zakame.net,2017:/blog//2.10</id>

    <published>2017-07-17T03:16:54Z</published>
    <updated>2017-07-17T06:11:45Z</updated>

    <summary>It has been a while since I last posted, let alone update my infra a bit, so here&apos;s one quick entry to document it. For the longest time I haven&apos;t enabled SSL on my blog or other HTTP sites; I...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="devops" label="devops" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="https" label="https" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ssl" label="ssl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>It has been a while since I last posted, let alone update my infra a bit, so here's one quick entry to document it.</p>

<p>For the longest time I haven't enabled SSL on my blog or other HTTP sites; I used to use Comodo, then StartCom SSL.  However, I got wind that StartCom (along with WoSign) will soon be <a href="https://security.googleblog.com/2016/10/distrusting-wosign-and-startcom.html">distrusted</a> by Google Chrome, et al. after <a href="https://wiki.mozilla.org/CA:WoSign_Issues">some</a> <a href="https://www.computest.nl/blog/startencrypt-considered-harmful-today/">reviews</a> of their operation.  The good thing though, is that there's now a <a href="https://letsencrypt.org/">Let's Encrypt</a> initiative which provides free SSL certificates, so I figure it is high time for me to re-integrate SSL once more.</p>
]]>
        <![CDATA[<p>The Let's Encrypt site recommends the <a href="https://certbot.eff.org">CertBot</a> script as a starting point for integration, but upon grabbing the software, it wanted to install Python stuff into my system.  I don't really mind, but would rather opt for something that already uses already-installed libraries, so I looked for alternatives.  Being a Perl guy, I found <a href="https://github.com/do-know/Crypt-LE">Crypt::LE</a> (via <a href="https://zerossl.com/">ZeroSSL</a>) as an acceptable alternative, as it can leverage my existing Perl 5.26 environment.</p>

<p>On the other hand, my system Perl is of a different version (5.20,) so I need to do a bit of work to integrate Crypt::LE.  First off, I'd use <a href="https://metacpan.org/pod/PAR::Packer">PAR::Packer</a> and make a binary:</p>

<pre><code>$ cpanm PAR::Packer
$ cd Crypt-LE
$ pp -M Crypt::OpenSSL::Bignum -M Cpanel::JSON::XS -M IO::Socket::SSL -Ilib script/le.pl -o crypt-le
</code></pre>

<p>This lets me have a self-sufficient client that I can put to <code>/usr/local</code>, that doesn't even use the system Perl.  If I had Docker on my server, I would've just pulled the <a href="https://hub.docker.com/r/zerossl/client/">ZeroSSL client</a>, but right now I don't, so I make do :)</p>

<p>I can then make my cert:</p>

<pre><code># crypt-le --key account.key --email REDACTED --csr domain.csr --csr-key domain.key --crt domain.crt --generate-missing --domains www.domain.tld,domain.tld --unlink --path /my/path/to/.well-known/acme-challenge --live
</code></pre>

<p>And renewing my cert would just be same command above, just with a <code>--renew &lt;days&gt;</code> added.  Wrap that up in a script that can be put in crontab, and I'm all set.</p>

<p>After installing the cert at the usual places, I can then verify their correct installation with</p>

<pre><code>$ openssl s_client -showcerts -connect zakame.net:443
</code></pre>

<p>as well as with a proper browser, or two.</p>

<p>After this, I'm mulling whether to continue using Movable Type for this blog, or maybe move to other engines.  <a href="https://gohugo.io">Hugo</a> seems like a good candidate.</p>
]]>
    </content>
</entry>

<entry>
    <title>Hello again - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2015/05/hello-again.html" />
    <id>tag:blog.zakame.net,2015://2.9</id>

    <published>2015-05-11T11:16:26Z</published>
    <updated>2017-07-21T11:20:29Z</updated>

    <summary>Hello again! Testing posting using weblogger.el...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="emacs" label="emacs" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>Hello again! Testing posting using <a href="https://launchpad.net/weblogger-el">weblogger.el</a></p>
]]>
        <![CDATA[<p>Yes, it has been a long while since I've blogged. I'm such a lazy git, so I should try to change that. I'll probably post a bit more about Docker since I've been playing around with it along with some new tooling (such as docker-compose and swarm,) so better write what I know down for future reference.</p>

<p>Furthermore, I'm coming back to using Emacs, so, I should post some bits about it as well, maybe some pieces off my ~/.emacs.d/init.el configuration. Much of it is on GitHub though, and is constantly more updated there than elsewhere, so I'll probably concentrate on large bits of customization such as Helm and programming/IDE modes for Perl/Ruby. And probably, some bits off my other dotfiles as well... So, looking forward to writing again!</p>
]]>
    </content>
</entry>

<entry>
    <title>Termshow: running sshd in Docker under daemontools - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2013/12/termshow-running-sshd-in-docker-under-daemontools.html" />
    <id>tag:blog.zakame.net,2013://2.6</id>

    <published>2013-12-20T04:15:53Z</published>
    <updated>2017-07-21T11:21:04Z</updated>

    <summary>Following up with my previous post, let me show an example of setting up a container with sshd running by default, under daemontools supervision:...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="containers" label="containers" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="daemontools" label="daemontools" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="docker" label="docker" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="slackware" label="slackware" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ssh" label="ssh" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="virtualization" label="virtualization" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>Following up with <a href="http://blog.zakame.net/2013/12/docker-and-daemontools-best-buddies.html">my previous post</a>, let me show an example of setting up a container with sshd running by default, under daemontools supervision:</p>
]]>
        <![CDATA[<iframe src="https://showterm.io/1ff81b1db22fd9987df55#fast" width="680" height="480"></iframe>

<p>Key commands:</p>

<ul>
<li><code>update-service</code> from <code>daemontools-run</code> Ubuntu package is used here to add the service directory in <code>/etc/sshd</code>.  This is really just a fancy way in Ubuntu to do <code>cd /etc/service &amp;&amp; ln -sf /etc/ssh/service sshd</code> which would be done otherwise on other systems.</li>
<li><code>docker ps -l -q</code> is a very useful Docker idiom, so much that I've made and alias of it in my <code>.bashrc</code> as <code>docker last</code>.</li>
<li><code>docker inspect</code> can be used to retrieve external information about the running container, such as its IP address, that can then be used on the host to connect to (like in this example, via <code>ssh</code>.)</li>
</ul>

<p>You can get this image from the Docker index under <a href="https://index.docker.io/u/zakame/base/">zakame/base</a>, default root password is <code>docker</code>.  Additionally, I set <code>sshd</code> to not use PAM authentication here as I'm on a Slackware host, and I needed to make <code>/var/run/sshd</code> manually this directory is normally made at startup during <code>init</code>.</p>
]]>
    </content>
</entry>

<entry>
    <title>Happy Birthday, Perl! - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2013/12/happy-birthday-perl.html" />
    <id>tag:blog.zakame.net,2013://2.5</id>

    <published>2013-12-18T10:28:03Z</published>
    <updated>2013-12-19T01:33:32Z</updated>

    <summary>Wow, she is 26 today. Back in the day, she was just a humble replacement for awk and sed, then became great in the late 90&apos;s to 2000&apos;s as the CGI programming language. Now, with the advent of web applications...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="plack" label="plack" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="psgi" label="psgi" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p><a href="https://groups.google.com/forum/#!topic/comp.sources.unix/Njx6b6TiZos">Wow, she is 26 today.</a>  Back in the day, she was just a humble replacement for <code>awk</code> and <code>sed</code>, then became great in the late 90's to 2000's as <em>the</em> CGI programming language.  Now, with the advent of web applications programming, she's doing it better with <a href="http://www.catalystframework.org/" title="Catalyst">a</a> <a href="http://mojolicious.org" title="Mojolicious">lot</a> <a href="http://perldancer.org" title="Dancer">of</a> <a href="http://amon.64p.org" title="Amon2">frameworks</a> held together by better <a href="http://plackperl.org" title="PSGI/Plack">glue</a>.  And let's not forget the <a href="http://moose.iinteractive.com/en/" title="Moose">objects</a> and <a href="http://poe.perl.org/" title="POE">events</a>.</p>

<p>Looking forward to another great year building great stuff with Perl!</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Docker and daemontools: best buddies - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2013/12/docker-and-daemontools-best-buddies.html" />
    <id>tag:blog.zakame.net,2013://2.4</id>

    <published>2013-12-16T04:06:07Z</published>
    <updated>2017-07-21T11:21:55Z</updated>

    <summary>I&apos;ve been running docker for quite a while now, as I found it fun to use, and rather easy to deploy even on a Slackware system. It is even better to use it with daemontools, both to supervise the docker...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="containers" label="containers" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="daemontools" label="daemontools" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="devops" label="devops" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="docker" label="docker" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="slackware" label="slackware" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="virtualization" label="virtualization" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>I've been running <a href="http://www.docker.io">docker</a> for quite a while now, as I found it fun to use, and rather easy to deploy even on a Slackware system.  It is even better to use it with <a href="http://cr.yp.to/daemontools.html">daemontools</a>, both to supervise the docker process as well as to be an alternative to <code>init</code> inside containers.  Here are some notes regarding this kind of usage:</p>
]]>
        <![CDATA[<h3>Docker service under daemontools</h3>

<p>Docker has a simple server mode called using <code>docker -d</code>, which simply listens to a local socket (typically <code>/var/run/docker.sock</code>) and emits logs to <code>STDOUT</code>.  This mode is naturally suitable for running docker under daemontools as a <code>supervise</code> service, so much so that it is almost a no-brainer to configure:</p>

<pre><code>$ cat /service/docker/run
#!/bin/sh
exec 2&gt;&amp;1
exec docker -d
</code></pre>

<p>Notice that the docker output is redirected, which can then be collected in a logger subprocess like <code>multilog</code>:</p>

<pre><code>$ cat /service/docker/log/run
#!/bin/sh
exec multilog t ./main
</code></pre>

<h3>daemontools in Docker containers</h3>

<p>Docker containers can be thought of as lightweight virtual machines; some even view it as a better <code>chroot</code> environment with its own networking and namespaces separate from the host system.  Thus, one can run <code>init</code> like supervisor services inside these containers, and daemontools is a good choice for such a supervisor:</p>

<pre><code># docker run -i -t ubuntu /bin/bash
# sed -e 's/main$/main universe' /etc/apt/sources.list &gt; /etc/apt/sources.list.new
# mv /etc/apt/sources.list{.new,}
# apt-get update
# apt-get install daemontools-run
# sh -c 'exec /usr/bin/svscanboot &amp;'
# ps axf
... add daemons, scripts and install them in /etc/service
# exit
</code></pre>

<p>Once you've created an image, you can use <a href="http://docs.docker.io/en/latest/commandline/cli/#commit"><code>docker commit</code> with the <code>-run</code> option</a> to add a <code>Cmd</code> that will be run be default when creating container with <code>docker run -d</code>:</p>

<pre><code># $myservice_id=`docker ps -l -q`
# docker commit -run '{"Cmd": ["/usr/bin/svscanboot"]}' $myservice_id myservice
</code></pre>

<p>If you have services listening on ports, be sure to add a <code>PortSpecs</code> key in your <code>docker commit -run</code> invocation with the appropriate ports to be exposed on the container, like this:</p>

<pre><code># docker commit -run '{"Cmd": ["/usr/bin/svscanboot"], "PortSpecs": ["22", "80"]}' $myservice_id my_ssh_web_container
</code></pre>

<p>Once created, you can now run your container with <code>docker run -d</code>:</p>

<pre><code># docker run -d my_ssh_web_container
# docker inspect `docker ps -l -q` | grep IPAddress
... ssh or browse the IP address found above...
</code></pre>
]]>
    </content>
</entry>

<entry>
    <title>Hello, World! (and notes on MT under Plack) - Zakame::Blog</title>
    <link rel="alternate" type="text/html" href="https://zakame.net/blog/2013/12/hello-world.html" />
    <id>tag:blog.zakame.net,2013://2.3</id>

    <published>2013-12-10T08:18:51Z</published>
    <updated>2017-07-21T11:22:26Z</updated>

    <summary>So, I found myself installing Movable Type on my site to start posting once more. I set it up using the PSGI deployment notes from the GitHub docs, though there are a few things I missed that I should put...</summary>
    <author>
        <name>Zak B. Elep</name>
        <uri>https://zakame.net/</uri>
    </author>
    
    <category term="daemontools" label="daemontools" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="deployment" label="deployment" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="movabletype" label="movabletype" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="plack" label="plack" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="psgi" label="psgi" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="https://zakame.net/blog/">
        <![CDATA[<p>So, I found myself installing Movable Type on my site to start posting once more.  I set it up using the <a href="https://github.com/movabletype/Documentation/wiki/En-dev-bootstrap-mt-psgi">PSGI deployment notes</a> from the GitHub docs, though there are a few things I missed that I should put down:</p>
]]>
        <![CDATA[<ul>
<li>There's a lack of <code>cpanfile</code> listing down Plack, XMLRPC, and Starman dependencies, so install those manually according to the wiki doc.  In addition, install some graphics library like <a href="https://metacpan.org/pod/Imager">Imager</a> and set it in <code>mt-config.cgi</code> or MT will complain about a missing <code>ImageDriver</code>.</li>
<li>There are several config directives that need to be tweaked aside from <code>PIDFilePath</code> that need to be added:
<ul>
<li><code>CGIPath</code> should point to the URL going to the MT installation, normally this can be some path in <code>$url/cgi-bin/mt</code> but one can just shorten it to <code>$url/mt</code></li>
<li><code>StaticPath</code> must <em>not</em> be your website's document root, but rather the path where MT's static files will be (e.g. <code>/var/www/html/mt-static</code> if the website root is in <code>/var/www/html</code>)</li>
<li><code>StaticFilePath</code> should be set to correspond to the URL in <code>StaticPath</code></li>
</ul></li>
<li>Take care to set the first website root to a directory other than the MT directory; something like <code>/path/to/mt/html</code> would be ok.</li>
<li>Finally, deploy Starman with something like <a href="http://cr.yp.to/daemontools.html">daemontools</a> just like any proper PSGI application (I should put this under a separate note later :)</li>
</ul>
]]>
    </content>
</entry>

</feed>
