<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Xylil</title>
 <link href="https://xylil.com/atom.xml" rel="self"/>
 <link href="https://xylil.com"/>
 <updated>2025-01-31T12:08:01-06:00</updated>
 <id>https://xylil.com</id>
 <author>
   <name>Chad Phillips</name>
   <email>thehunmonkgroup@gmail.com</email>
 </author>

 
 <entry>
   <title>Script for generating STIR/SHAKEN certificates (including self-signed)</title>
   <link href="https://xylil.com/2024/03/25/stir-shaken-certificate-creation-script/"/>
   <updated>2024-03-25T00:00:00-05:00</updated>
   <id>https://xylil.com/2024/03/25/stir-shaken-certificate-creation-script</id>
   <content type="html">
&lt;p&gt;While working on my company’s implemenation of &lt;a href=&quot;https://en.wikipedia.org/wiki/STIR/SHAKEN&quot;&gt;STIR/SHAKEN&lt;/a&gt;, I ran into a very basic issue – how do I easily create test self-signed SHAKEN certificates?&lt;/p&gt;

&lt;p&gt;While I did find a couple of posts on how to do this, I wanted a nice script that would accomplish the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Generate either a self-signed certificate or a key/CSR pair for use with an official certificate authority&lt;/li&gt;
  &lt;li&gt;Allow easy passing of the certificate subject information (Country, State, Locality, etc.)&lt;/li&gt;
  &lt;li&gt;Create certificate filenames with a unique identifier, to prevent name collisions (by default, the identifier is a UNIX timestamp)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is the script I came up with:&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/6c3ab5c681c005520a5d31d3b9ef1c91.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Credit to the original source posts, &lt;a href=&quot;https://astppbilling.org/how-to-generate-a-stir-shaken-certificate-how-to-use-it-in-freeswitch/&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://www.voizcall.com/blog/generate-self-signed-certificates-for-STIR-SHAKEN&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>FreeSWITCH Dbh &apos;fetch&apos; convenience functions for Lua</title>
   <link href="https://xylil.com/2020/07/01/freeswitch-dbh-fetch-convenience-functions-for-lua/"/>
   <updated>2020-07-01T00:00:00-05:00</updated>
   <id>https://xylil.com/2020/07/01/freeswitch-dbh-fetch-convenience-functions-for-lua</id>
   <content type="html">
&lt;p&gt;&lt;a href=&quot;https://freeswitch.org/confluence/display/FREESWITCH/Lua+with+Database#LuawithDatabase-freeswitch.Dbh&quot;&gt;freeswitch.Dbh&lt;/a&gt; is the method I’ve
chosen for connecting to a database via a &lt;a href=&quot;https://www.lua.org/&quot;&gt;Lua&lt;/a&gt; script in &lt;a href=&quot;https://freeswitch.com/&quot;&gt;FreeSWITCH&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The interface is simple to use, and provides all the basics needed to communicate with a database via a configured ODBC driver.&lt;/p&gt;

&lt;p&gt;One thing I found lacking, however, were ‘fetch’ type helper functions, that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Returned a multi-row result in a table of tables&lt;/li&gt;
  &lt;li&gt;Returned a single-row result in a table&lt;/li&gt;
  &lt;li&gt;Returned a single-row, single-column result directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below are the helper functions I came up with. You might also be able to extend the dbh object directly
 with methods – I just chose to pass the dbh object into a standalone function call.&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/f92ca495c4c366d74fa9269320806cec.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pacemaker NFSv4 resource agent for Debian</title>
   <link href="https://xylil.com/2020/06/05/pacemaker-nfsv4-resource-agent-for-debian/"/>
   <updated>2020-06-05T00:00:00-05:00</updated>
   <id>https://xylil.com/2020/06/05/pacemaker-nfsv4-resource-agent-for-debian</id>
   <content type="html">
&lt;p&gt;If you’re interested in running an NFSv4-only server in a
&lt;a href=&quot;https://wiki.clusterlabs.org/wiki/Pacemaker&quot;&gt;Pacemaker&lt;/a&gt; cluster on Debian,
you’ll probably find the default &lt;em&gt;nfsserver&lt;/em&gt; RA in the
&lt;a href=&quot;https://packages.debian.org/buster/pacemaker-resource-agents&quot;&gt;Debian-packaged resource agents&lt;/a&gt;
to be lacking.&lt;/p&gt;

&lt;p&gt;It suffers from serveral issues:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The default behavior is to use the NFS init script to handle
starting/stopping/monitoring the NFS server. This is broken in the monitor
case as the service is reported as &lt;em&gt;active&lt;/em&gt; even if it’s been killed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Starting/stopping the service is &lt;em&gt;dog&lt;/em&gt; slow. I’d venture to say at least
half of the total cluster failover time in my setup with the default RA was
consumed by starting/stopping the NFS daemon and all the related v2/v3
services.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So if you’re willing to go with NFSv4 only, here’s a much better approach:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Follow the &lt;a href=&quot;https://wiki.debian.org/NFSServerSetup&quot;&gt;Debian NFS server setup&lt;/a&gt;,
including the adjustments under &lt;em&gt;NFSv4 only&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Drop the below RA in a valid path for Pacemaker to find it, and make it
executable.&lt;/li&gt;
  &lt;li&gt;Configure your resource(s).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CAVEATS:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Does not work for v2/v3, and will not manage any of the services that are
v2/v3 only.&lt;/li&gt;
  &lt;li&gt;Only tested on Debian Buster, YMMV.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/1f17a103dffaa2e52e3d642cc7ef1eca.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fencing/STONITH IAM configuration on Google Cloud Platform (GCP)</title>
   <link href="https://xylil.com/2020/05/24/fencingstonith-configuration-on-google-cloud-platform-gcp/"/>
   <updated>2020-05-24T00:00:00-05:00</updated>
   <id>https://xylil.com/2020/05/24/fencingstonith-configuration-on-google-cloud-platform-gcp</id>
   <content type="html">
&lt;p&gt;UPDATE 2024-01-28: The fence_gce agent now additionally requires the &lt;em&gt;compute.zoneOperations.list&lt;/em&gt; permission in the &lt;em&gt;list.instances&lt;/em&gt; IAM role. I have updated the code to reflect this change.&lt;/p&gt;

&lt;p&gt;Having spent the better part of a day figuring this out, I thought it might be
nice to save others some time.&lt;/p&gt;

&lt;p&gt;My specific need was to configure &lt;a href=&quot;https://en.wikipedia.org/wiki/STONITH&quot;&gt;STONITH&lt;/a&gt;
for a &lt;a href=&quot;https://wiki.clusterlabs.org/wiki/Pacemaker&quot;&gt;Pacemaker&lt;/a&gt; cluster deployed on
&lt;a href=&quot;https://cloud.google.com/gcp&quot;&gt;Google Cloud Platform&lt;/a&gt;,
using &lt;a href=&quot;https://www.mankier.com/8/fence_gce&quot;&gt;fence_gce&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By far the trickiest part was figuring out Google’s extremely robust permissions
system to meet this case in the most secure manner. The goal: to allow each node
in a two-node cluster to fence the other node (by reset or poweroff), while restricting
each node to only be able to fence its peer, and nothing else.&lt;/p&gt;

&lt;p&gt;Below I’ll post some psuedo-code that should give you an idea about how to execute
this for your particular needs. I deployed this solution using
&lt;a href=&quot;https://www.terraform.io&quot;&gt;Terraform&lt;/a&gt;, but the concepts should be easily adaptable
to other use cases.&lt;/p&gt;

&lt;p&gt;In a nutshell:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create two custom IAM Roles (I called them &lt;em&gt;fencing&lt;/em&gt; and &lt;em&gt;list.instances&lt;/em&gt;):
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;fencing:&lt;/strong&gt; permissions to reset or stop a server and get access to its state&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;list.instances:&lt;/strong&gt; Permissions to list the available instances in a project
 &lt;em&gt;(this was a small security sacrific, I’d prefer that a node can’t see other
 nodes this way, but the fencing agent seems to require it, and as of this
 writing, there’s no clean way on GCP to restrict the nodes listed via the API)&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;For each instance in a cluster, create a Service Account, and configure the
instance run as that service account, granting all the default scopes and
the ‘compute-rw’ scope’&lt;/li&gt;
  &lt;li&gt;At the project level, add an IAM policy binding that binds all the instance
service accounts to the &lt;em&gt;list.instances&lt;/em&gt; role.&lt;/li&gt;
  &lt;li&gt;At the instance level, add an IAM policy binding that binds the &lt;em&gt;fencing&lt;/em&gt;
role to the instance service account for the instance that will fence the
instance in question. For example, if you have &lt;em&gt;data1&lt;/em&gt; and &lt;em&gt;data2&lt;/em&gt; instances
Then for the &lt;em&gt;data1&lt;/em&gt; instance you’ll bind &lt;em&gt;data2&lt;/em&gt;’s service account to the
&lt;em&gt;fencing&lt;/em&gt; role, and vice-versa. This allows each node to fence its peer,
but to have no other permissions for fencing, not even for itself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Psuedo-code:&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/86de76e41d6a0619d4bf918787375aff.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bash script to play a sound file every X seconds</title>
   <link href="https://xylil.com/2019/02/02/bash-play-sound-file-every-x-seconds/"/>
   <updated>2019-02-02T00:00:00-06:00</updated>
   <id>https://xylil.com/2019/02/02/bash-play-sound-file-every-x-seconds</id>
   <content type="html">
&lt;p&gt;As part of my continued efforts to improve awareness of my physical body
while I’m hacking away at a keyboard, I got the idea that it would be nice if
a pleasant sound played every X seconds to remind me stop slouching, relax,
etc.&lt;/p&gt;

&lt;p&gt;I wanted it to be simple, easy to start and stop, and easy to configure both
the time interval between plays and the file being played.&lt;/p&gt;

&lt;p&gt;Finding nothing of that ilk in some quick Google searches, I present the below
for your usage and hopefully increased awareness :)&lt;/p&gt;

&lt;p&gt;Run without arguments for the help.&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/f7eb52913c4049d5e35007def3bfe026.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Debian start a ramdisk on boot</title>
   <link href="https://xylil.com/2017/03/13/debian-start-a-ramdisk-on-boot/"/>
   <updated>2017-03-13T00:00:00-05:00</updated>
   <id>https://xylil.com/2017/03/13/debian-start-a-ramdisk-on-boot</id>
   <content type="html">
&lt;p&gt;I run some servers that use a &lt;a href=&quot;https://en.wikipedia.org/wiki/RAM_drive&quot;&gt;ramdisk&lt;/a&gt;
to increase performance for recording audio files. Since ramdisks evaporate on
a reboot, and I have services that depend on the ramdisk to operate properly,
I needed a way to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Automatically create the ramdisk on boot&lt;/li&gt;
  &lt;li&gt;Ensure it’s set up prior to the services that depend on it&lt;/li&gt;
  &lt;li&gt;Perform cleanup on the ramdisk when the server is shut down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The set of scripts below accomplish this nicely by leveraging
&lt;a href=&quot;https://www.freedesktop.org/wiki/Software/systemd&quot;&gt;systemd&lt;/a&gt;. Here’s a quick
rundown of what each does:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;ramdisk:&lt;/strong&gt; The script is written as a System V init script, and would be
placed at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/init/ramdisk&lt;/code&gt;. Does the work of:
    &lt;ul&gt;
      &lt;li&gt;Creating the ramdisk&lt;/li&gt;
      &lt;li&gt;Calling an optionally configured script to perform cleanup prior to tearing
down the ramdisk&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;customize:&lt;/strong&gt; This is an optional file to override the default settings of
the first script. Place it at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/default/ramdisk&lt;/code&gt; with any
customizations you like.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ramdisk.service:&lt;/strong&gt; systemd service file that calls the start/stop
  functions of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ramdisk&lt;/code&gt;. Place this anywhere systemd recognizes
  service scripts, and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl daemon-reload&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The nice thing about this setup through systemd is that any other systemd
services that depend on the ramdisk being set up can simply include this in
their service description:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Requires=ramdisk.service
After=ramdisk.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/036628570e3bedaf370579eab7c4738e.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ICE/CBP regulations summary for domestic travelers</title>
   <link href="https://xylil.com/2017/02/28/icecbp-regulations-summary-for-domestic-travelers/"/>
   <updated>2017-02-28T00:00:00-06:00</updated>
   <id>https://xylil.com/2017/02/28/icecbp-regulations-summary-for-domestic-travelers</id>
   <content type="html">
&lt;p&gt;The election of Donald Trump has roused me from my political slumber, to be
sure…&lt;/p&gt;

&lt;p&gt;I’m trying to stay informed, and also signed up for the excellent
&lt;a href=&quot;https://dailyaction.org&quot;&gt;Daily Action&lt;/a&gt; alerts, which keeps me plugged in to
things I can do every day to make my voice heard.&lt;/p&gt;

&lt;p&gt;Today’s alert was in reference to ICE/CBP’s
&lt;a href=&quot;https://www.theatlantic.com/politics/archive/2017/02/papers-please/517887&quot;&gt;request to see the ID of all passengers on a US domestic flight&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;According to the expert cited in that article, it’s highly unlikely that these
authorities have a legal right to demand you produce ID under these
circumstances.&lt;/p&gt;

&lt;p&gt;So today my little action of resistance was to print up a convenient
&lt;a href=&quot;/media/ice-cbp-regs.pdf&quot;&gt;half-page summary of the regulations&lt;/a&gt;
the expert referred to in that article. Two copies per page, should be small
enough to fold up and fit in a wallet, purse, or back pocket.&lt;/p&gt;

&lt;p&gt;I’ll be carrying mine around, at least for awhile, to remind myself that I
don’t want to live in a police state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HUGE DISCLAIMER:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I’m sharing is for &lt;em&gt;informational purposes only&lt;/em&gt;. I’m not an attorney,
and did not deeply vet this information, but simply looked up the US codes
referenced in the article and made them a bit easier to carry around.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>FreeSWITCH Kickstart, an automated server configuration tool</title>
   <link href="https://xylil.com/2016/04/06/freeswitch-kickstart-an-automated-server-configuration-tool/"/>
   <updated>2016-04-06T00:00:00-05:00</updated>
   <id>https://xylil.com/2016/04/06/freeswitch-kickstart-an-automated-server-configuration-tool</id>
   <content type="html">
&lt;h2 id=&quot;project-background&quot;&gt;Project background&lt;/h2&gt;

&lt;p&gt;Several years ago I began the journey to better systematize my server management workflow. At the time I was managing over 20 server instances, almost entirely ‘by hand’, meaning I did things like keeping checklists for the steps to rebuild critical servers, running software updates on each individually, etc. Then, I finally took the time to research &lt;a href=&quot;https://www.upguard.com/articles/the-7-configuration-management-tools-you-need-to-know&quot;&gt;server configuration management software&lt;/a&gt;, selected &lt;a href=&quot;http://saltstack.com&quot;&gt;Salt&lt;/a&gt; as my tool, and completely re-oriented my relationship to dealing with software updates, new server builds, etc.&lt;/p&gt;

&lt;p&gt;Managing a server this way means that you don’t change anything about the server directly, but instead write code that makes the changes for you. While this does involve a learning curve (it’s almost always faster to just run a command straight from the command line than write code to run the command for you), the benefits of this approach far outweigh the costs in the long run:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Automatically rebuild any server from scratch:&lt;/strong&gt; As long as you have data backups, it’s no longer a big deal if your server tanks. Rebuilding becomes a glorified version of rebooting your computer when it’s acting weird&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Consistency in dev -&amp;gt; staging -&amp;gt; production environments:&lt;/strong&gt; You can be much more sure that the server you’re doing development on is consistent with the server that will run in production. With tools like &lt;a href=&quot;https://www.vagrantup.com&quot;&gt;Vagrant&lt;/a&gt;, combined with server configuration management, you can run virtually the identical server on your laptop that you do for your customers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Clear documentation:&lt;/strong&gt; This cannot be underestimated. The exact steps to re-create your mission critical infrastructure is written in code, which means both certainty about how it works, and ease of transfer of this knowledge to other maintainers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though this approach is well known by hard core sysadmins, I suspect many people who could profit from it still have not taken the leap, either through ignorance or the barrier of the learning curve.&lt;/p&gt;

&lt;p&gt;Fast forward to last year, and I’m working on &lt;a href=&quot;http://circleanywhere.com/&quot;&gt;CircleAnywhere&lt;/a&gt;, an online group meditation platform, using &lt;a href=&quot;https://freeswitch.org&quot;&gt;FreeSWITCH&lt;/a&gt; for some of the video conferencing portions. Naturally the server, being mission-critical to the project, was built using a Salt configuration for all the reasons mentioned above. It was a fair amount of work to hammer out the deployment, and it occurred to me that a lot of the heavy lifting I had done was the same heavy lifting that anyone rolling out a new FreeSWITCH server (whether for local development or in production) had to do. So I decided to do just a little bit more work, and repackage my efforts for the good of others. :)&lt;/p&gt;

&lt;h2 id=&quot;freeswitch-kickstart&quot;&gt;FreeSWITCH Kickstart&lt;/h2&gt;

&lt;p&gt;Thus was born &lt;a href=&quot;https://github.com/thehunmonkgroup/freeswitch-kickstart&quot;&gt;FreeSWITCH Kickstart&lt;/a&gt;, a Vagrant/Salt configuration for automatically deploying a FreeSWITCH server for either development or production. Installation locally via Vagrant or remotely involves only a few simple steps (the most difficult of which is acquiring valid SSL certificates for production builds).&lt;/p&gt;

&lt;p&gt;The project strives to provide these three things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;An easy way to get up and running with a local FreeSWITCH development environment&lt;/li&gt;
  &lt;li&gt;A sane/convenient starting point for rolling a production server.&lt;/li&gt;
  &lt;li&gt;A nice starter template for admins who want their FreeSWITCH server under Salt server configuration management.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A &lt;strong&gt;ton&lt;/strong&gt; of stuff is done automagically for you – even if you don’t like/need it all, it’s still an awesome way to get going!&lt;/p&gt;

&lt;p&gt;I’ve written up a fairly comprehensive &lt;a href=&quot;https://github.com/thehunmonkgroup/freeswitch-kickstart/blob/master/FEATURES.md&quot;&gt;features list&lt;/a&gt;, so you know what you’re getting.&lt;/p&gt;

&lt;p&gt;I hope the community will benefit from this work, and doubly hope that others will offer refinements on this first effort. My intention is to maintain this project for the FreeSWITCH community, keeping it up to date with the installation procedure for the latest code and recommended operating system. If anyone would like to join me in maintainership of the project, I would certainly welcome it. :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Jester, FreeSWITCH, Lua, and my quest for an awesome scripting toolkit</title>
   <link href="https://xylil.com/2016/01/20/jester-freeswitch-lua-and-my-quest-for-an-awesome-scripting-toolkit/"/>
   <updated>2016-01-20T00:00:00-06:00</updated>
   <id>https://xylil.com/2016/01/20/jester-freeswitch-lua-and-my-quest-for-an-awesome-scripting-toolkit</id>
   <content type="html">
&lt;p&gt;Back in 2010, in collaboration with &lt;a href=&quot;http://www.star2star.com&quot;&gt;Star2Star Communications&lt;/a&gt;, I wrote a &lt;a href=&quot;http://www.lua.org&quot;&gt;Lua&lt;/a&gt; scripting library for &lt;a href=&quot;https://freeswitch.org&quot;&gt;FreeSWITCH&lt;/a&gt; called &lt;a href=&quot;https://github.com/thehunmonkgroup/jester&quot;&gt;Jester&lt;/a&gt;. Its most marketable highlight was a profile that offered a complete drop-in replacement for &lt;a href=&quot;http://www.voip-info.org/wiki/index.php?page_id=502&quot;&gt;Asterisk’s Comedian Mail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My deeper motivation for writing it was to try and bring some sanity and consistency to the process of implementing more advanced voice workflows. This motiviation arose from my own experience of the mishmash of dialplan XML and one-off Lua scripts that still to this day forms the foundation of my first major VoIP system. I began to believe that there must be a better way – if the goal was to do any number of fairly common things, like grab data from a database, send an email, talk to a webservice – can’t we basically standardize those into reusable units? So, Jester…&lt;/p&gt;

&lt;p&gt;Fast forward to 2016, and my toolkit, through almost complete lack of maintenance, had become legacy code. In addition, the years had revealed both the strengths and weaknesses of my original efforts, and I wanted to do something about it.&lt;/p&gt;

&lt;p&gt;In the last few weeks, I took the first big steps to revive and reshape Jester for a new and improved release. A lot of the hard work is now done:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Updated the entire codebase to be compatible with all 5.x versions of Lua, which means it will now run on anything from the terrifically old FreeSWITCH 1.0.7 to the very latest code.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Complete refactoring/update of the user documentation, now available &lt;a href=&quot;http://thehunmonkgroup.github.io/jester/doc&quot;&gt;online and nicely formatted&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Preserved the original Asterisk Comedian Mail replica, so it can still be used as a drop in replacement for those moving from Asterisk to FreeSWITCH&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Good progress on handling some of the original architectural issues&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Going forward, I’d love to get some other people on board with the project, particularly those interested in helping to turn Jester into a solid, well-used library for the land beyond the dialplan. I think the biggest reason for the initial flaws was that I didn’t have any other eyes on my designs.&lt;/p&gt;

&lt;p&gt;Please do contact me if you’re interested in teaming up.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>New release of Luchia, Lua API for CouchDB</title>
   <link href="https://xylil.com/2015/12/31/new-release-of-luchia-lua-api-for-couchdb/"/>
   <updated>2015-12-31T00:00:00-06:00</updated>
   <id>https://xylil.com/2015/12/31/new-release-of-luchia-lua-api-for-couchdb</id>
   <content type="html">
&lt;p&gt;Many years ago, I wrote &lt;a href=&quot;https://github.com/thehunmonkgroup/luchia&quot;&gt;Luchia&lt;/a&gt;, a &lt;a href=&quot;http://www.lua.org&quot;&gt;Lua&lt;/a&gt; API for &lt;a href=&quot;http://couchdb.apache.org&quot;&gt;Apache CouchDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The library worked great, and had fair unit/integration test coverage, but after many years it was no longer compatible with the newer versions of Lua.&lt;/p&gt;

&lt;p&gt;So, I took a few days recently to revive it and roll an updated release. It’s now compatible with Lua versions 5.1, 5.2, and 5.3, and also sports 100% unit test coverage.&lt;/p&gt;

&lt;p&gt;Installation via &lt;a href=&quot;https://luarocks.org&quot;&gt;LuaRocks&lt;/a&gt;, Lua’s package manager, is a breeze, just do:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;luarocks install luchia
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can check out a summary and API usage in the &lt;a href=&quot;http://thehunmonkgroup.github.io/luchia/doc/topics/INTRODUCTION.md.html&quot;&gt;online documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Luchia’ing. :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using Salt with services managed by Monit</title>
   <link href="https://xylil.com/2015/09/29/using-salt-with-services-managed-by-monit/"/>
   <updated>2015-09-29T00:00:00-05:00</updated>
   <id>https://xylil.com/2015/09/29/using-salt-with-services-managed-by-monit</id>
   <content type="html">
&lt;p&gt;I use &lt;a href=&quot;http://saltstack.com&quot;&gt;Salt&lt;/a&gt; for configuration management on all my newer servers. I’m particularly fond of its &lt;a href=&quot;https://docs.saltstack.com/en/latest/ref/states/requisites.html#watch&quot;&gt;watch&lt;/a&gt; requisite, and use it thoroughly to handle restarting all my Salt managed services if need be.&lt;/p&gt;

&lt;p&gt;This generally works without much fuss. However, when a service that’s managed by Salt is also being managed by &lt;a href=&quot;https://mmonit.com&quot;&gt;Monit&lt;/a&gt;, there’s a chicken and egg problem: when Salt automatically restarts a service using its standard method, Monit thinks the service has died, and problems ensue.&lt;/p&gt;

&lt;p&gt;I really wanted my Salt service management goodness and Monit, so after a bit of thinking I came up the the idea of creating a psuedo-service. Salt manages the psuedo-service instead of the regular service, and the psuedo-service simply wraps the Monit commands for starting, stopping, and restarting the service. This allows Salt to trigger service actions via Monit.&lt;/p&gt;

&lt;p&gt;This approach solved the issue beautifully without much code or effort. Below I’m including the &lt;a href=&quot;http://www.redhat.com/en/technologies/linux-platforms/enterprise-linux&quot;&gt;RHEL&lt;/a&gt;/&lt;a href=&quot;http://www.centos.org&quot;&gt;CentOS&lt;/a&gt; version of the psuedo-service – other platforms would require some minor adjustments, but the idea is the same.&lt;/p&gt;

&lt;p&gt;As seen from the line defining the service name, I manage this script in Salt as a template, so that I can install it for multiple services.&lt;/p&gt;

&lt;p&gt;Hope this helps anybody who gets stuck on this same issue!&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/f1b30f0940f66574191b.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Vagrant crash course for the busy developer</title>
   <link href="https://xylil.com/2015/05/12/vagrant-crash-course-for-the-busy-developer/"/>
   <updated>2015-05-12T00:00:00-05:00</updated>
   <id>https://xylil.com/2015/05/12/vagrant-crash-course-for-the-busy-developer</id>
   <content type="html">
&lt;p&gt;Today a friend remarked on his interest to learn &lt;a href=&quot;https://www.vagrantup.com&quot;&gt;Vagrant&lt;/a&gt;, and lack of time to do so. It occurred to me that the script I’ve been building to quickly knock up and down Vagrant VMs could be a handy aid along the shortest path for developers to begin their journey into this amazing toolset.&lt;/p&gt;

&lt;p&gt;So without further ado, the shortest path I know of for a busy dev to start playing with Vagrant:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Install &lt;a href=&quot;https://www.virtualbox.org/wiki/Downloads&quot;&gt;VirtualBox&lt;/a&gt; and &lt;a href=&quot;https://www.vagrantup.com/downloads.html&quot;&gt;Vagrant&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;…or for &lt;a href=&quot;https://github.com/Homebrew/homebrew-cask&quot;&gt;Homebrew Cask&lt;/a&gt; users, the even easier &lt;code&gt;brew cask install virtualbox vagrant&lt;/code&gt;…&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run the following from CLI:&lt;/p&gt;

    &lt;p&gt;&lt;code&gt;
vagrant box add bento/centos-7.1 --provider virtualbox&lt;br /&gt;
vagrant box add bento/debian-8.2 --provider virtualbox
&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;…or pick some other box you like &lt;a href=&quot;https://app.vagrantup.com/boxes/search&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Download the script below, stick it in your PATH, make it executable&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Execute without args for the well-written help&lt;/p&gt;

    &lt;p&gt;…or run &lt;code&gt;quick-vagrant.sh -c&lt;/code&gt; to spin up your first box…&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Enjoy :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also made the script a bit like a cheat sheet for Vagrant commands – if you search it for ‘vagrant’, you’ll see the first time any command is used, there’s a comment describing what it does. Or, here’s &lt;a href=&quot;http://www.wickedawesometech.us/2014/08/vagrant-cheatsheet.html&quot;&gt;a more neatly formatted cheat sheet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find this helpful getting up to speed, please pass it along to your busy developer friends! If you’d like to suggest improvements to the script, feel free to &lt;a href=&quot;/contact.html&quot;&gt;contact me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/1efccb1aca8ed023ba0e.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>General node init script for RHEL/CentOS 5.x/6.x</title>
   <link href="https://xylil.com/2015/03/16/general-node-init-script-for-rhelcentos-5x6x/"/>
   <updated>2015-03-16T00:00:00-05:00</updated>
   <id>https://xylil.com/2015/03/16/general-node-init-script-for-rhelcentos-5x6x</id>
   <content type="html">
&lt;p&gt;I wanted to have a general &lt;a href=&quot;http://www.redhat.com/en/technologies/linux-platforms/enterprise-linux&quot;&gt;RHEL&lt;/a&gt;/&lt;a href=&quot;http://www.centos.org&quot;&gt;CentOS&lt;/a&gt; init script that I could drop onto servers to start node processes. The features I wanted were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ability to reuse it for multiple node processes on the same server.&lt;/li&gt;
  &lt;li&gt;Ability to run as non-root user.&lt;/li&gt;
  &lt;li&gt;The classic service start/stop/restart/status functionality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had previously written a &lt;a href=&quot;/2012/03/13/redhat-init-script-for-nodejs-app-using-forever/&quot;&gt;node init script using forever&lt;/a&gt;, but I ended up not liking it. This script still isn’t perfect, but it seems more generally useful to me.&lt;/p&gt;

&lt;p&gt;Drop the script in &lt;code&gt;/etc/init.d/[name]&lt;/code&gt; and make it executable, the custom configuration in &lt;code&gt;/etc/sysconfig/[name]&lt;/code&gt;, and use &lt;code&gt;service [name] start&lt;/code&gt; to fire it up.&lt;/p&gt;

&lt;p&gt;true&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/0d5e587d52d9dd8056a9.js&quot;&gt; &lt;/script&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Installing Jekyll on RHEL/CentOS 5.x and 6.x with modern Ruby and Python versions</title>
   <link href="https://xylil.com/2015/01/20/installing-jekyll-on-rhelcentos-5x-and-6x-with-modern-ruby-and-python-versions/"/>
   <updated>2015-01-20T00:00:00-06:00</updated>
   <id>https://xylil.com/2015/01/20/installing-jekyll-on-rhelcentos-5x-and-6x-with-modern-ruby-and-python-versions</id>
   <content type="html">
&lt;p&gt;&lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; can be run fairly easily on older (5.x and 6.x) versions of &lt;a href=&quot;http://www.redhat.com/en/technologies/linux-platforms/enterprise-linux&quot;&gt;RHEL&lt;/a&gt;/&lt;a href=&quot;http://www.centos.org&quot;&gt;CentOS&lt;/a&gt;, even though the stock versions of the necessary software are too old. The key is to use some simple supporting software to install what you need in a clean way.&lt;/p&gt;

&lt;p&gt;The first handy tool is &lt;a href=&quot;https://rvm.io&quot;&gt;Ruby Version Manager&lt;/a&gt;, or RVM. Here’s a handy &lt;a href=&quot;http://cheat.errtheblog.com/s/rvm&quot;&gt;cheat sheet&lt;/a&gt; – use that to install RVM and the latest version of Ruby, set the installed Ruby as the default, and install the Jekyll gem.&lt;/p&gt;

&lt;p&gt;Once that’s done, you may run into this error when trying to use Jekyll:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Liquid Exception: Failed to get header
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/jekyll/jekyll/issues/1181&quot;&gt;This Jekyll issue&lt;/a&gt; indicates that Python greater than 2.6 and less the 3.x needs to be installed in order for syntax highlighting to work. Never fear, &lt;a href=&quot;https://github.com/yyuu/pyenv&quot;&gt;pyenv&lt;/a&gt; to the rescue!&lt;/p&gt;

&lt;p&gt;Use the &lt;a href=&quot;https://github.com/yyuu/pyenv-installer&quot;&gt;pyenv installer&lt;/a&gt; to get pyenv set up and running on your server, and have a look at the &lt;a href=&quot;https://github.com/yyuu/pyenv/blob/master/COMMANDS.md&quot;&gt;pyenv command reference&lt;/a&gt; to install an appropriate version of Python and set it as the default. &lt;em&gt;Note:&lt;/em&gt; If you’re running RHEL/CentOS 5.x, you’ll have one more hurdle to cross before using pyenv, see &lt;a href=&quot;/2015/01/19/installing-a-working-pyenv-on-rhelcentos-5x/&quot;&gt;this post&lt;/a&gt; for detailed instructions.&lt;/p&gt;

&lt;p&gt;If you’d also like to set up your Jekyll site to update from a &lt;a href=&quot;http://git-scm.com&quot;&gt;git&lt;/a&gt; push, I’ve detailed one workable approach in &lt;a href=&quot;/2012/03/03/deploying-a-jekyll-site-via-git/&quot;&gt;this post&lt;/a&gt; – if you do use it, just make sure you put the necessary RVM/pyenv environment set up stuff in the &lt;a href=&quot;http://unix.stackexchange.com/questions/129143/what-is-the-purpose-of-bashrc-and-how-does-it-work&quot;&gt;.bashrc&lt;/a&gt; file of the user the git push command runs as on the server.&lt;/p&gt;

&lt;p&gt;Happy Jekyll’ing!&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Installing a working pyenv on RHEL/CentOS 5.x</title>
   <link href="https://xylil.com/2015/01/19/installing-a-working-pyenv-on-rhelcentos-5x/"/>
   <updated>2015-01-19T00:00:00-06:00</updated>
   <id>https://xylil.com/2015/01/19/installing-a-working-pyenv-on-rhelcentos-5x</id>
   <content type="html">
&lt;p&gt;&lt;a href=&quot;http://www.redhat.com/en/technologies/linux-platforms/enterprise-linux&quot;&gt;RHEL&lt;/a&gt;/&lt;a href=&quot;http://www.centos.org&quot;&gt;CentOS&lt;/a&gt; 5.x has long since lost its freshness, but some of us are still running servers with it, and can do so for several more years before its &lt;a href=&quot;http://wiki.centos.org/FAQ/General#head-fe8a0be91ee3e7dea812e8694491e1dde5b75e6d&quot;&gt;end of life&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Perhaps, like me, you have a need to run a more modern version of &lt;a href=&quot;https://www.python.org&quot;&gt;Python&lt;/a&gt; than 5.x installs by default. I recently found &lt;a href=&quot;https://github.com/yyuu/pyenv&quot;&gt;pyenv&lt;/a&gt;, and it looked to fit my needs perfectly, as I didn’t want to mess with the system version or build custom RPM’s.&lt;/p&gt;

&lt;p&gt;Once I installed the &lt;a href=&quot;https://github.com/yyuu/pyenv/wiki/Common-build-problems#requirements&quot;&gt;build requirements&lt;/a&gt;, I used the handy &lt;a href=&quot;https://github.com/yyuu/pyenv-installer&quot;&gt;pyenv-installer&lt;/a&gt; project to get it up and running, then ran the simple command to install Python 2.7.8. Unfortunately, things hit a bump with this error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error message:
subprocess.CalledProcessError: Command &apos;[&apos;wget&apos;, &apos;https://pypi.python.org/packages/source/s/setuptools/setuptools-7.0.zip&apos;, &apos;--quiet&apos;, &apos;--output-document&apos;, &apos;/tmp/python-build.20141210170309.3741/Python-2.7.8/setuptools-7.0.zip&apos;]&apos; returned non-zero exit status 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After a bit of digging, I found that this was actually due to &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=674186&quot;&gt;a bug&lt;/a&gt; in version 1.11 of &lt;a href=&quot;https://www.gnu.org/software/wget&quot;&gt;wget&lt;/a&gt;. As far as I could tell, this issue was not fixed upstream until the 1.12 release, and CentOS 5.x is frozen at 1.11.&lt;/p&gt;

&lt;p&gt;I decided it was worth building a custom wget RPM package for my 5.x servers to get past this issue. After setting up my &lt;a href=&quot;http://wiki.centos.org/HowTos/SetupRpmBuildEnvironment&quot;&gt;RPM build environment&lt;/a&gt;, I headed over to &lt;a href=&quot;http://rpm.pbone.net&quot;&gt;rpm.pbone.net&lt;/a&gt; to locate a suitable source RPM. &lt;a href=&quot;http://rpm.pbone.net/index.php3?stat=26&amp;amp;dist=72&amp;amp;size=1633032&amp;amp;name=wget-1.12-4.fc14.src.rpm&quot;&gt;wget-1.12-4.fc14.src.rpm&lt;/a&gt; ended up suiting my needs – the newer versions of wget RPMs had some build dependencies that were a bit awkward to fulfill, and 1.12 would solve my problem, so…&lt;/p&gt;

&lt;p&gt;Per &lt;a href=&quot;http://wiki.centos.org/HowTos/RebuildSRPM&quot;&gt;http://wiki.centos.org/HowTos/RebuildSRPM&lt;/a&gt;, the –nomd5 switch is needed when installing newer fedora source RPMs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rpm --nomd5 -ivv wget-1.12-4.fc14.src.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From there it was simply a matter of building the RPM:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd /usr/src/redhat/SPECS
rpmbuild -bb wget.spec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then installing it, by finding the wget-1.12-4 RPM file in one of the subdirectories of /usr/src/redhat/RPMS, changing to that directory, and running:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum --nogpgcheck localinstall wget-1.14-3.x86_64.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After this, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyenv install [version]&lt;/code&gt; should work as advertized…Python for the modern age!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Automating sysctl deployments using sysctl.d on RHEL/CentOS 5.x, 6.x, 7.x</title>
   <link href="https://xylil.com/2015/01/08/automating-sysctl-deployments-using-sysctld-on-rhelcentos-5x-6x-7x/"/>
   <updated>2015-01-08T00:00:00-06:00</updated>
   <id>https://xylil.com/2015/01/08/automating-sysctl-deployments-using-sysctld-on-rhelcentos-5x-6x-7x</id>
   <content type="html">
&lt;p&gt;I’ve fallen in love with automated server deployments in the last year, with my primary weapon being &lt;a href=&quot;http://www.saltstack.com&quot;&gt;Salt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the corner cases I’ve run into is adding &lt;a href=&quot;http://linux.die.net/man/8/sysctl&quot;&gt;sysctl&lt;/a&gt; settings specific to a feature set. For example, when a server needs &lt;a href=&quot;http://redis.io&quot;&gt;Redis&lt;/a&gt; installed, I want to add the following kernel optimization via sysctl:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;    &lt;span class=&quot;py&quot;&gt;vm.overcommit_memory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s sloppy to add this to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.conf&lt;/code&gt; – too hard to maintain in a modular fashion. Wouldn’t it be nice if there was a place we could drop a file with that sysctl setting in it, which would be automatically read on boot? This would enable adding and removing multiple sysctl settings a breeze to automate.&lt;/p&gt;

&lt;p&gt;Well, it turns out that &lt;a href=&quot;http://www.redhat.com/en/technologies/linux-platforms/enterprise-linux&quot;&gt;RHEL&lt;/a&gt;/&lt;a href=&quot;http://www.centos.org&quot;&gt;CentOS&lt;/a&gt; &lt;em&gt;does&lt;/em&gt; have this support via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.d&lt;/code&gt;. While only RHEL/CentOS 7.x sports the directory out of the box, all three versions provide access to it via init scripts, and anything placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.d&lt;/code&gt; will be read on boot, provided that the networking init script’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start&lt;/code&gt; action is called (it’s enabled by default).&lt;/p&gt;

&lt;p&gt;Unfortunately, this is a bit of an odd placement for triggering a reload of the sysctl settings. I also wanted the ability to &lt;em&gt;only&lt;/em&gt; reload the sysctl settings as part of a feature installation on a running server.&lt;/p&gt;

&lt;p&gt;The path to get this feature turned out to be pretty short. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/init.d/functions&lt;/code&gt; contains an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply_sysctl&lt;/code&gt; function which handles all the dirty work of completely reloading all sysctl settings, including those placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.d&lt;/code&gt;. This extremely short wrapper script does the job:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;#! /bin/bash

# Source function library.
. /etc/init.d/functions

apply_sysctl&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/08b0b932dd948a80a193.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Armed with that script, I simply use Salt to automatically install it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt; on all servers, and call it any time a file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.d&lt;/code&gt; is added, removed, or modified.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nginx logs in JSON format</title>
   <link href="https://xylil.com/2012/07/14/nginx-logs-in-json-format/"/>
   <updated>2012-07-14T00:00:00-05:00</updated>
   <id>https://xylil.com/2012/07/14/nginx-logs-in-json-format</id>
   <content type="html">
&lt;p&gt;I’ve recently decided that it’s a good idea to output server logs in &lt;a href=&quot;http://www.json.org&quot;&gt;JSON&lt;/a&gt; format. To this end, today I took some time to figure out how to do this for &lt;a href=&quot;http://nginx.org&quot;&gt;Nginx&lt;/a&gt;. The &lt;code&gt;log_format&lt;/code&gt; parameter is the one you want to use, I simply added another named format to the &lt;code&gt;http&lt;/code&gt; section of &lt;code&gt;nginx.conf&lt;/code&gt;, which then allows the named format to be used in any other config file. Here’s what I whipped up – this is just the default &lt;code&gt;main&lt;/code&gt; format ported to JSON:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;log_format  json  &apos;{&apos;
                    &apos;&quot;remote_addr&quot;: &quot;$remote_addr&quot;,&apos;
                    &apos;&quot;remote_user&quot;: &quot;$remote_user&quot;,&apos;
                    &apos;&quot;time_local&quot;: &quot;$time_local&quot;,&apos;
                    &apos;&quot;request&quot;: &quot;$request&quot;,&apos;
                    &apos;&quot;status&quot;: $status,&apos;
                    &apos;&quot;body_bytes_sent&quot;: $body_bytes_sent,&apos;
                    &apos;&quot;http_referer&quot;: &quot;$http_referer&quot;,&apos;
                    &apos;&quot;http_user_agent&quot;: &quot;$http_user_agent&quot;,&apos;
                    &apos;&quot;http_x_forwarded_for&quot;: &quot;$http_x_forwarded_for&quot;&apos;
                  &apos;}&apos;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I formatted it one row per parameter in the config file, as it’s easier for me to read, but Nginx will concatenate all those separate strings into one line in the log file. Once this is done, use the format in any of places where it’s accepted, for example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;access_log /path/to/file/access.log json;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For more details on all this stuff, check out the &lt;a href=&quot;http://wiki.nginx.org/HttpLogModule&quot;&gt;online documentation&lt;/a&gt; for Nginx’s logging module.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Resend Postfix messages stuck in mail queue to another address</title>
   <link href="https://xylil.com/2012/07/06/resend-postfix-messages-stuck-in-mail-queue-to-another-address/"/>
   <updated>2012-07-06T00:00:00-05:00</updated>
   <id>https://xylil.com/2012/07/06/resend-postfix-messages-stuck-in-mail-queue-to-another-address</id>
   <content type="html">
&lt;p&gt;&lt;strong&gt;Update 2015-02-19:&lt;/strong&gt; Based on suggestions from David Keegel, I’ve tweaked the script to properly hold/unhold messages, and include the sender’s email address in the message envelope.&lt;/p&gt;

&lt;p&gt;Ever had somebody give you a bad email address, and the messages pile up in your Postfix mail queue? Even if you have the right address to send the stuck emails to, Postfix (at least on CentOS 5.x based on all my research) provides no easy way to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Resend all those messages to the new address&lt;/li&gt;
  &lt;li&gt;Remove the old stuck messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed this functionality badly for our business, where we unfortunately get bad email addresses given to us all the time. So, using my marginal bash skills and several hours of my time, I whipped up the script below to automate this process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat:&lt;/strong&gt; I’ve tested this script extensively with Postfix on CentOS 5.x, but nowhere else, really. So test first, use at your own risk!&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;#!/bin/bash

# This script allows sending of messages stuck in the Postfix queue to another
# email address.  Useful if the original email address is bad.

if [ $# -ne 2 ]; then
  echo &amp;quot;Usage: reroute-queued-email-messages.sh &amp;lt;oldaddress&amp;gt; &amp;lt;newaddress&amp;gt;&amp;quot;
  exit 1
fi

OLD_ADDRESS=&amp;quot;$1&amp;quot;
NEW_ADDRESS=&amp;quot;$2&amp;quot;

MAILQ=`which mailq`
POSTCAT=`which postcat`
POSTSUPER=`which postsuper`
SENDMAIL=`which sendmail`
TAIL=`which tail`
GREP=`which grep`
AWK=`which awk`
SED=`which sed`

# Pulls queue IDs for all messages sent to the original address.
function get_ids_by_address {
  $MAILQ | $TAIL -n +2 | $GREP -v &amp;#39;^ *(&amp;#39; | $AWK -v address=&amp;quot;$1&amp;quot; &amp;#39;BEGIN { RS = &amp;quot;&amp;quot; } { if ($8 == address) print $1 }&amp;#39;
}

MESSAGE_IDS=`get_ids_by_address $OLD_ADDRESS`

# Loop through each message ID, output the message, and pipe it through
# sendmail to the new address.
for message_id in $MESSAGE_IDS;
do 
  # Puts the message on hold.
  $POSTSUPER -h $message_id
  # Extract the sender.
  sender=`$POSTCAT -q $message_id | $GREP -m 1 &amp;#39;^From: &amp;#39; | $SED &amp;#39;/^From: */!d; s///; q&amp;#39;`
  # sed gets rid of the leading queue metadata, grep -v gets rid of the
  # metadata markers.
  $POSTCAT -q $message_id | $SED -n &amp;#39;/MESSAGE CONTENTS/,$p&amp;#39; | $GREP -v &amp;quot;^\*\*\*.*\*\*\*$&amp;quot; | sendmail -f &amp;quot;$sender&amp;quot; $NEW_ADDRESS
  echo &amp;quot;Delivered message ID $message_id to $NEW_ADDRESS&amp;quot;
done

echo -n &amp;quot;Remove old messages from mail queue? [y/N]: &amp;quot;
read delete

if [ &amp;quot;$delete&amp;quot; = &amp;quot;y&amp;quot; ]; then
  for message_id in $MESSAGE_IDS;
  do 
    # Deletes the message from the mail queue by queue ID.
    $POSTSUPER -d $message_id
    echo &amp;quot;Deleted message ID $message_id from queue&amp;quot;
  done
else
  for message_id in $MESSAGE_IDS;
  do
    # Takes the message off hold.
    $POSTSUPER -H $message_id
  done
  echo &amp;quot;The following messages were left in the mail queue:&amp;quot;
  echo &amp;quot;$MESSAGE_IDS&amp;quot;
fi

exit 0
&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/thehunmonkgroup/249d599f81380bf0efc8.js&quot;&gt; &lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>db-query-assistant package released</title>
   <link href="https://xylil.com/2012/04/28/db-query-assistant-package-released/"/>
   <updated>2012-04-28T00:00:00-05:00</updated>
   <id>https://xylil.com/2012/04/28/db-query-assistant-package-released</id>
   <content type="html">
&lt;p&gt;Today I’m happy to announce the official public release of &lt;a href=&quot;https://github.com/thehunmonkgroup/db-query-assistant&quot;&gt;db-query-assistant&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those who haven’t read my &lt;a href=&quot;/2012/03/14/node-db-query-assistant-initial-release&quot;&gt;initial post&lt;/a&gt; on the module, here is a quick summary:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;High-level library for node database drivers.&lt;/li&gt;
  &lt;li&gt;Configurable connection pooling.&lt;/li&gt;
  &lt;li&gt;Issue multiple simultaneous queries, and get all results back in a callback when the last query completes.&lt;/li&gt;
  &lt;li&gt;Issue queries in series, getting the results for each previous query back before executing the next one.&lt;/li&gt;
  &lt;li&gt;Issue transactional queries, with automatic rollback on query failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This release includes a fairly comprehensive unit test suite for the core library, using the awesome &lt;a href=&quot;http://visionmedia.github.com/mocha&quot;&gt;mocha&lt;/a&gt; test framework. I decided against unit tests for the drivers, as I feel those would be better served by integration tests (which I may add in the future).&lt;/p&gt;

&lt;p&gt;The module has been published to the &lt;a href=&quot;http://npmjs.org&quot;&gt;npm&lt;/a&gt; registry, and a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install db-query-assistant&lt;/code&gt; will now do the trick.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sampler API 6.x 1.1 released</title>
   <link href="https://xylil.com/2012/03/25/sampler-api-6x-11-released/"/>
   <updated>2012-03-25T00:00:00-05:00</updated>
   <id>https://xylil.com/2012/03/25/sampler-api-6x-11-released</id>
   <content type="html">
&lt;p&gt;The &lt;a href=&quot;http://drupal.org/node/1496956&quot;&gt;6.x-1.1&lt;/a&gt; release of &lt;a href=&quot;http://drupal.org/project/sampler&quot;&gt;Sampler API&lt;/a&gt; is now out and ready for download. This has a number of important bugfixes, as well as the addition of locking support so the same metric cannot be run again while already running.&lt;/p&gt;

&lt;p&gt;Most of the fixes came out of the work I’m doing to get metrics collection fully deployed on &lt;a href=&quot;http://drupal.org&quot;&gt;drupal.org&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>
