Docker Syslog Container for Sending Logs to CloudWatch

AWS’s CloudWatch Logs was first available about a year ago, and to my estimation has gone largely unnoticed. The initial iteration was pretty rough, but some recent changes have made it more useful, including the ability to search logs, and generate events for monitoring in CloudWatch from log content.

Unfortunately, the Cloudwatch Logs agent just watches log files on disk and doesn’t act as a syslog server. An AWS blog post explained how to get the the Cloudwatch Logs Agent running inside a container and monitoring the log output from rsyslogd, but the instructions used Amazon’s ECS service, which still doesn’t quite offer the flexibility that CoreOS or Deis offer IMHO. ECS does some magic behind the scenes in passing credentials around that you have to do yourself when using CoreOS.

I’ve just provided a GitHub repository with the tools to make this work pretty easily, as well as a Docker Image with some reasonable defaults.

When trying to pull all of this together to work, I discovered a problem due to a bug in the overlayfs that is in current Deis Releases which causes the AWS Logs agent not to notice changes in the syslog files. A workaround is available that reformats the host OS back to btrfs to solve that particular problem

Note when running on Deis 561+ to revert to btrfs

Deis add Key from an ssh-agent

Evidently it is not possible to add an SSH key directly from an SSH agent. Instead, you can grep the public key from your ~/.ssh/authorized_keys file then, have deis use that key. Or if you only have one line in ~/.ssh/authorized_keys, you can just tell deis to use that file directly with the command

deis keys:add ~/.ssh/authorized_keys

Unattended install of Cloudwatch Logs Agent

So far, I’m pretty impressed with cloudwatch logs. The interface for it isn’t as fancy, and search capability isn’t as deep as other tools like PaperTrail or Loggly, but the cost is significantly less, and I like the fact that you can store different log groups for different lengths of time.

I’m trying to get the cloudwatch logs agent to install as part of an automated script, and couldn’t find any easy instructions to do that, so here is how I got it working with a shell script on an Ubuntu 14.04 host

echo Creating cloudwatch config file in /root/awslogs.conf
cat <<EOF >/root/awslogs.conf
[general]
state_file = /var/awslogs/state/agent-state
## Your config file would have a lot more with the logs that you want to monitor and send to Cloudwatch
EOF

echo Creating aws credentials in /root/.aws/credentials
cat <<EOF > /root/.aws/credentials
[default]
aws_access_key_id = YOUR_AWS_ACCESS_KEY_HERE
aws_secret_access_key = YOUR_AWS_SECRET_KEY_HERE
EOF

echo Downloading cloudwatch logs setup agent
cd /root
wget https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py
echo running non-interactive cloudwatch-logs setup script
python ./awslogs-agent-setup.py --region us-west-2 --non-interactive --configfile=/root/awslogs.conf

DKIM / SPF / SpamAssassin test moved to dkimvalidator.com

For over 7 years, I’ve hosted an email validation tool on this site. I developed the tool back when I was doing a lot with email, and when DKIM and SPF was still pretty tricky to get working. Over the years it has become the single most popular page on the site, and Google likes it pretty well for certain DKIM and SPF keywords. (And strangely “brandon checketts dkim” pops up on Google search suggest you you try to google my name.

In any case, I’ve moved that functionality over to its own site now at http://dkimvalidator.com/ so that it has its own place to call home. It also got a (albeit weak) visual makeover, and all of the underlying libraries have been updated to the latest versions so that they are once again accurate and up-to-date.

Getting Ubuntu 14.04 php5enmod to understand module priority

Usage of Debian’s php5enmod module doesn’t seem to be documented anywhere except from the command line when calling it without any arguments:

user@host:~# php5enmod
WARNING:
usage: php5enmod [ -s ALL|sapi_name ] module_name [ module_name_2 ]

Unfortunately, that provides no information on how to customize the priority of a module when enabling it. Some others seem to think that you should be able to provide a priority level on the command line, but that doesn’t work.

It took some digging into the bash scripts to figure out how to make it work. The trick is to add a comment in the .ini file for the module. The comment must contain a very specific format of:


zend_extension = /usr/lib/php5/20121212/ioncube_loader_lin_5.5.so
; priority=1

The ‘priority’ line must be in that format exactly and most not contain any other spaces or characters. The line must start with a semicolon, followed by a space, followed by priority=, and finally the desired priority level. The only space on the line must be between the semicolon and the word ‘priority’.

Proposed Pattern for Deploying EC2 instances with Secure Credentials

After struggling with this problem in my mind for a while, I finally had the opportunity to experiment with Cloud Init and come up with a working solution for securely (I think) deploying code and credentials to a stock Ubuntu Instance on EC2.

My primary goals are:

  • Must use an stock AMI with no customization
  • Human readable user-data that contains appName, environment, and role.
  • user-data must be easily modified by a developer for their own app or environment
    (No forcing them to base64 encode, gzip, or use special tools)
  • Must be portable between providers.
    The example works with EC2, but initial ‘include’ file can be customized for each provider or OS.

The diagram below shows how this is to be accomplished

Proposed Cloud Init on Ubuntu / EC2 with secure credentials

I’ve successfully deployed several instances using this method and it seems to work well. Getting the cloud init include file, and the script

Troubleshooting /etc/cron.d/ on Ubuntu

On Debian-based systems, files in /etc/cron.d:
– must be owned by root
– must not be group or world writable
– may be symlinked, but the destination must follow the ownership and file permissions above
– Filenames must contain ONLY letters, numbers, underscores and hyphens. (not periods)
– must contain a username in the 6th column

From the man page:

Files in this directory have to be owned by root, do not need to be executable (they are configuration files, just like /etc/crontab) and must conform to the same naming convention as used by run-parts(8): they must consist solely of upper- and lower-case letters, digits, underscores, and hyphens. This means that they cannot contain any dots.

The man page also provides this explanation to this strange rule:

For example, any file containing dots will be ignored. This is done to prevent cron from running any of the files that are left by the Debian package management
system when handling files in /etc/cron.d/ as configuration files (i.e. files ending in .dpkg-dist, .dpkg-orig, and .dpkg-new).

Fix for MongoDB not reliably starting/stopping on Ubuntu

I spent the last several hours troubleshooting any annoying error with the mongodb init script on Ubuntu. The script would start the daemon easy enough, but would report a failure. When subsequently trying to stop the daemon, it would then then say it was successful, but in-fact, still be running.

Fortunately, I found that somebody else had already reported the bug, but the comments pointing developers to the wrong place – looking inside the mongod code instead of in the init script.

After digging in to it for longer than I’d like to have spent, I found the cause was the –make-pidfile option being used in the init script.

My understanding of this process is that the start-stop-daemon command was creating the pidfile (as root), before spawning the actual mongod process (as the mongodb user). mongod in some cases (at least when not configsvr=true) must fork again before saving its own pidfile. Since the file created by start-stop-daemon is being run as root, the less-privileged mongodb user can not overwrite it (perhaps this should be logged, or logged at a less verbose level?), leaving the pidfile containing a pid that is no longer correct.

On my machine, the pidfile created with the –make-pidfile options was consistently exactly three less than the PID shown in the output of ‘ps’

After making that change to the init file, I can now reliably start/stop the mongod process using the expected commands.

Hopefully that bug will be closed soon and released so that I don’t have to customize the init script on every mongo server I have.

GnuPG Encryption with PHP (on Ubuntu with Pecl)

Instructions for Getting this working on Ubuntu 12.04 and more modern systems than my previous post

Install the required system and pecl packages:

  # apt-get install gnupg  libgpgme11 libgpgme11-dev
  # pecl install gnupg
  # echo extension=gnupg.so > /etc/php5/conf.d/gnupg.ini
  # apache2ctl restart

Generate a Private key

 # gpg --homedir /path/to/your/directory --gen-key

On a virtual machine, if that stalls for a while, you may have to generate some “randomness” somehow. Try one of these commands in a separate session, according to this bug report:

 # find / -type f | xargs grep blahblahblha
 # tcpdump -i any > /dev/null

At this point, you should have a working GPG key in the home directory you specified. You can list your secret keys with the command:

 
  # gpg --homedir /path/to/your/directory -K

You’ll then want to export the key with the command:

 # gpg --homedir /path/to/your/directory --export-secret-key --armour

You’ll want to copy that secret key to another machine. DON’T LOSE IT or you won’t be able to decrypt anything. Once you’ve got it safely stored somewhere, you want to delete it from your web server:

 #  gpg --homedir /path/to/your/directory --delete-secret-key your@address.com

You can then make sure that the public key is still there. It is what you’ll need to encrypt messages:

 # gpg --homedir /path/to/your/directory -k

Finally, you’ll need the fingerprint for the key to refer to it within your PHP code.

 # gpg --homedir /path/to/your/directory --fingerprint 
pubring.gpg
-------------
pub   2048R/5BB54E26 2013-04-14 [expires: 2023-04-12]
      Key fingerprint = AAAA BBBB CCCC DDDD EEEE  FFFF 0000 1111 2222 3333
uid                  Your Name <your@address.com>
sub   2048R/2EF4937A 2013-04-14 [expires: 2023-04-12]

You can then use the gnupg pecl functions to encrypt a messages:

<?php
$CONFIG['gnupg_home'] = '/var/www/.gnupg';
$CONFIG['gnupg_fingerprint'] = 'FA451EE9877270EF1CFA99CE048A613921CCC3D6';

$data = 'this is some confidential information';

$gpg = new gnupg();
putenv("GNUPGHOME={$CONFIG['gnupg_home']}");
$gpg->seterrormode(GNUPG_ERROR_SILENT);
$gpg->addencryptkey($CONFIG['gnupg_fingerprint']);
$encrypted =  $this->gpg->encrypt($data);
echo "Encrypted text: \n$encrypted\n";

// Now you can store $encrypted somewhere.. perhaps in a MySQL text or blob field.

// Then use something like this to decrypt the data.
$passphrase = 'Your_secret_passphrase';
$gpg->adddecryptkey($CONFIG['gnugp_fingerprint'], $passphrase);
$decrypted = $gpg->decrypt($encrypted);

echo "Decrypted text: $decrypted";
?>

Monit CPU Usage problem

I just recently fixed an issue I wanted my Monit monitoring process to restart a daemon who was segfaulting and causing 100% CPU usage according to top and most other system tools. I had seen configuration examples where Monit could detect that and restart the process, so I figured that adding a configuration like that below would fix it easily enough:

check process foo with pidfile /var/run/foo.pid
  start program = "/etc/init.d/foo start" timeout 10 seconds
  stop program  = "/etc/init.d/foo stop"
  if cpu usage > 90% for 8 cycles then restart

After letting that run for a bunch of cycles the process remained running, and monit didn’t do anything to acknowledge it even in log files. (FYI, a “cycle” is defined in the Monitrc config file in the “set daemon” line and defaults to 120 seconds).

After some research, I finally came upon this post on the Monit mailing list where somebody describes that the CPU usage that Monit bases its numbers off is a percentage of the CPU available for all processors. My machine had 4 processors, so what was seeing as 100% CPU usage in top, monit would only see that as 25%.

I quickly changed my Monit config to check for CPU Usage > 22% as ween in the following. That now works perfectly, even acknowledging in the log each of the 8 times that the CPU was over the limit before restarting it:

check process foo with pidfile /var/run/foo.pid
  start program = "/etc/init.d/foo start" timeout 10 seconds
  stop program  = "/etc/init.d/foo stop"
  if cpu usage > 22% for 8 cycles then restart

…. Now I need to solve the real problem and see why the latest Mongo PHP pecl module is segfaulting….