Today a friend remarked on his interest to learn Vagrant, 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.
So without further ado, the shortest path I know of for a busy dev to start playing with Vagrant:
Download the script below, stick it in your PATH, make it executable
Execute without args for the well-written help
…or run quick-vagrant.sh -c to spin up your first box…
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 a more neatly formatted cheat sheet.
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 contact me.
Jekyll can be run fairly easily on older (5.x and 6.x) versions of RHEL/CentOS, 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.
The first handy tool is Ruby Version Manager, or RVM. Here’s a handy cheat sheet – use that to install RVM and the latest version of Ruby, set the installed Ruby as the default, and install the Jekyll gem.
Once that’s done, you may run into this error when trying to use Jekyll:
Liquid Exception: Failed to get header
This Jekyll issue 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, pyenv to the rescue!
Use the pyenv installer to get pyenv set up and running on your server, and have a look at the pyenv command reference to install an appropriate version of Python and set it as the default. Note: If you’re running RHEL/CentOS 5.x, you’ll have one more hurdle to cross before using pyenv, see this post for detailed instructions.
If you’d also like to set up your Jekyll site to update from a git push, I’ve detailed one workable approach in this post – if you do use it, just make sure you put the necessary RVM/pyenv environment set up stuff in the .bashrc file of the user the git push command runs as on the server.
RHEL/CentOS 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 end of life.
Perhaps, like me, you have a need to run a more modern version of Python than 5.x installs by default. I recently found pyenv, and it looked to fit my needs perfectly, as I didn’t want to mess with the system version or build custom RPM’s.
Once I installed the build requirements, I used the handy pyenv-installer 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:
subprocess.CalledProcessError: Command '['wget', 'https://pypi.python.org/packages/source/s/setuptools/setuptools-7.0.zip', '--quiet', '--output-document', '/tmp/python-build.20141210170309.3741/Python-2.7.8/setuptools-7.0.zip']' returned non-zero exit status 1
After a bit of digging, I found that this was actually due to a bug in version 1.11 of wget. 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.
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 RPM build environment, I headed over to rpm.pbone.net to locate a suitable source RPM. wget-1.12-4.fc14.src.rpm 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…
I’ve fallen in love with automated server deployments in the last year, with my primary weapon being Salt.
One of the corner cases I’ve run into is adding sysctl settings specific to a feature set. For example, when a server needs Redis installed, I want to add the following kernel optimization via sysctl:
It’s sloppy to add this to /etc/sysctl.conf – 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.
Well, it turns out that RHEL/CentOSdoes have this support via /etc/sysctl.d. 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 /etc/sysctl.d will be read on boot, provided that the networking init script’s start action is called (it’s enabled by default).
Unfortunately, this is a bit of an odd placement for triggering a reload of the sysctl settings. I also wanted the ability to only reload the sysctl settings as part of a feature installation on a running server.
The path to get this feature turned out to be pretty short. /etc/init.d/functions contains an apply_sysctl function which handles all the dirty work of completely reloading all sysctl settings, including those placed in /etc/sysctl.d. This extremely short wrapper script does the job:
Armed with that script, I simply use Salt to automatically install it to /usr/local/bin on all servers, and call it any time a file in /etc/sysctl.d is added, removed, or modified.
I’ve recently decided that it’s a good idea to output server logs in JSON format. To this end, today I took some time to figure out how to do this for Nginx. The log_format parameter is the one you want to use, I simply added another named format to the http section of nginx.conf, 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 main format ported to JSON:
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:
Update 2015-02-19: 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.
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:
Resend all those messages to the new address
Remove the old stuck messages
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.
Caveat: I’ve tested this script extensively with Postfix on CentOS 5.x, but nowhere else, really. So test first, use at your own risk!
For those who haven’t read my initial post on the module, here is a quick summary:
High-level library for node database drivers.
Configurable connection pooling.
Issue multiple simultaneous queries, and get all results back in a callback when the last query completes.
Issue queries in series, getting the results for each previous query back before executing the next one.
Issue transactional queries, with automatic rollback on query failure.
This release includes a fairly comprehensive unit test suite for the core library, using the awesome mocha 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).
The module has been published to the npm registry, and a simple npm install db-query-assistant will now do the trick.
The 6.x-1.1 release of Sampler API 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.
Most of the fixes came out of the work I’m doing to get metrics collection fully deployed on drupal.org.