So, I’ve been doing a lot of work with Vagrant recently. Vagrant has been very handy when working in teams in order to have a common point of reference for development, especially when the application we were collaborating on requires helper services (such as Node servers and ElasticSearch) to be started.

Here are a couple of gotchas that caused me a whole bunch of headaches, hopefully this’ll make things easier for you.

Don’t mount to /home/vagrant

In hindsight, this is a stupidly obvious, but at the time I had tunnel vision with a couple of other things didn’t get this until I had an “oh” moment.

The problem was that after provisioning, vagrant ssh would not connect via public key. However, booting the VM by hand using VirtualBox, this would work.

When I finally picked through my VagrantFile, commenting things out until things worked again, I realised my mistake in a facepalming moment. Obvious when you think about it, when you mount your working directory at /home/vagrant you clobber the ~/.ssh/authorized_keys file that had been inserted by vagrant up.

Man, I felt so dumb.

Careful what box you use

If you start getting some weird problems booting your box, you might want to try switching the base box.

I was using the Official Ubuntu 16.04 build as my base, but I was having no end of problems provisioning. More often than not, randomly through the provisioning process, the file system would become read only. I’d have to reboot and restart with the --provision flag, often several times, before I was able to get a box built.

I switched to an unofficial 16.04 box, and these problems went away.

I’m sure there’s a root cause for this issue, I’ll investigate later, but for now, switching VMs resolved it.

Avoid vagrant-vbguest unless you have to

The plugin vagrant-vbguest will update the VirtualBox guest additions on the guest machine, during provisioning, if they are missing or out of date.

This sounds like a great idea, but in my experience, it seems to cause more harm than good. Often, the older guest additions will work just fine, and installing the new additions over them often breaks something.

My view now is very much “if it ain’t broke, don’t fix it!”.

Be careful calling scripts within your startup scripts

If your provisioning or startup script itself calls another shell script, for example to start up custom services, you’re likely going to run into problems on Windows host machines.

Problems I’ve seen:

default: nohup:
default: failed to run command '/path/to/script.sh'

or:

default: -bash: /path/to/script.sh: /bin/bash^M: bad interpreter: No such file or directory

Both of these stem from the same cause, namely your script has been imported from the Windows host and it still has Windows line endings.

There are a number of solutions you could adopt, and the preference would be to avoid using shell scripts within scripts – vagrant should automatically convert line endings in scripts in your Vagrantfile, so try and only call scripts from there. If you must call scripts within scripts, as I had to do on a couple of occasions, you’ll need to convert line endings.

If this is a new project, you could configure git to make sure shell scripts are always binary. Or, convert line endings of your script before execution, e.g:

sed -i -e 's/\r$//' /path/to/script.sh

Hope all this helps!

I hit a number of gotchas when upgrading my home and business web server from jessie to stretch, here they are in no particular order. Hopefully will save you some hair pulling…

Broken MariaDB install

Debian now ships with MariaDB by default, but when I upgraded mariadb-server would not install, meaning their were loads of broken dependencies. Dpkg exited with an error status, but with no indication as to what the actual error actually was.

Fixes suggested elsewhere (purging and reinstalling, moving /var/lib/mysql away and reinstalling, etc) did not help.

Eventually, I was able to manually execute mysql_install_db, which actually gave me some output. For me, the problem seemed to have been caused by the slow query logging entries, which are either unsupported in MariaDB or are named something else (I’ve not had a chance to check).

I commented out the following lines as follows:

# log_slow_queries  = /var/log/mysql/mysql-slow.log
# long_query_time = 2
# log-queries-not-using-indexes

… and apt-get was able to install the package.

Isolated /tmp

The version of systemd shipping with Debian 9 includes some security enhancements, including PrivateTmp, which isolates the temporary directory from users.

So, if you use your tmp directory to store e.g. cache data when developing websites, you’re going to need to store this somewhere else, otherwise file_exists and other file functions will not be able to read or write to them.

PHP 7

Ooooooo… boy.

Biggest hitter by far for me was that Debian 9 now ships with PHP7. Usefully, 5.6 is still available, so you have to switch to 7 manually (which means installing all the appropriate module again). Gotcha here is the mysql extension has been entirely removed, good thing too… however, if you’ve been running your server for a while like I have, you’re going to have a metric shittonne of things that need to be upgraded in order to work. Biggest pain in the bum was my ownCloud 8 server (made harder by the fact you can’t cross major versions in an upgrade, and the releases for those versions were no longer available until I nudged someone on IRC, also, pro tip, do the upgrade on PHP 5).

For scripts that either don’t have newer versions, or legacy stuff you don’t have time right now to allocate significant dev resources to, there is a mysql->mysqli shim available. This seems to work quite well in most cases, although of course it should be fairly high priority for you to migrate to PDO or similar!

Elgg and PHP 7

If you’re building sites on the 1.x.x branch of Elgg, you’re either going to have to upgrade to Elgg 2.x to run on PHP7, or use the shim.

I only have development sites running on PHP 7 at the moment, all of my clients that use < Elgg 2 are running on older PHP releases for now, but the shim works well in development and until I can manage those upgrades. If you use the shim you may need to comment out the following lines in executeQuery() in engine/classes/Elgg/Database.php:

if (!is_resource($dblink)) {
    throw new \DatabaseException("Connection to database was lost.");
}

…since the resource returned by the shim is a different type than expected.

That’s all so far, hope this will save you some stress!

Just a quicky for those who are trying to integrate SAML authentication into their app using SimpleSAMLPhp.

Here’s the problem: You’ve set up your client SP, and you’re talking to a remote IdP. You’ve tested your authentication using the SimpleSAML web interface on your SP, but whenever you try it from your app, you hit an exception.

SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
Backtrace:
0 /path/to/simplesamlphp-1.13.2/www/module.php:179 (N/A)
Caused by: Exception: The POST data we should restore was lost.
Backtrace:
1 /path/to/simplesamlphp-1.13.2/modules/core/www/postredirect.php:38 (require)
0 /path/to/simplesamlphp-1.13.2/www/module.php:134 (N/A)

Assuming no esoteric input filtering, the problem is likely to be in your cookie settings.

If your app creates its own session, it is likely to be creating its own cookie with its own name. E.g.

session_name('FooApp');

You must modify your SimpleSAMLPHP config to use the same session name by modifying config.php and setting 'session.phpsession.cookiename' => 'FooApp' to match.

Simple… but it took me quite a while of being convinced I’d screwed up the server config to track down!

Hope this saves someone some time.