Intro
If you don’t have the patience to read to the end, you can find the code that I’m talking about in the post here
The other day I decided that is was time to upgrade my ubuntu 14.04 boxes to 16.04 since LTS end date of support is getting closer ( we are not quite there yet but better to get a head of this ). This should be really strait forward, just update the box string from ubuntu/trusty64 to ubuntu/xenial64 right? Yupp, that easy blog post over… not really though. For some reason canonical decided to change the embedded user from the standard vagrant user with the insecure ssh key to a “ubuntu” user, that can cause problems. First of if you are provisioning these ubuntu images and just want to use your old scripts that rightfully expect the user to be vagrant, they will no longer work. This also caused me problems since my workflow is that I create my own boxes from the official ubuntu box where I provision the software that I want to have on them and after the change the exported boxes no longer work.
Since I already posted creating local baseboxes I’m not going to cover that again, but just the hack around getting rid of the unwanted ubuntu user and adding in the default vagrant user.
The hack
This is by no means an elegant solution, but it works. Then again the most elegant way to handle this is simply for canonical to just have the default vagrant user in there to begin with.
So the actual code is here below, basically what I’m doing is just creating the default vagrant user and deleting the ubuntu user
create-base-box.sh
#!/usr/bin/env bash BOX_NAME=hx/ubuntu1604 TEST_IF_BOX_EXISTS=$(vagrant box list | grep $BOX_NAME) if [ "$1" = "-f" ]; then TEST_IF_BOX_EXISTS="" vagrant box remove $BOX_NAME if [ "$?" -ne 0 ]; then echo "Could not remove box, check if you have running machines using the box" exit 1 fi fi if [ "$TEST_IF_BOX_EXISTS" = "" ]; then echo "$BOX_NAME does not exist, creating $BOX_NAME" mv Vagrantfile Vagrantfile.tmp cp Vagrantfile.BaseBox Vagrantfile vagrant up basebox vagrant halt basebox sed -i 's|#basebox.ssh.|basebox.ssh.|g' Vagrantfile vagrant up basebox PORT=$(vagrant port | grep ' 22 (guest) => ' | awk '{print $5}') ssh -o "StrictHostKeyChecking no" vagrant@127.0.0.1 -p $PORT -i keys/vagrant "sudo /vagrant/scripts/remove-user.sh ubuntu" vagrant halt basebox VBOX_INSTANCE=$(vboxmanage list vms | grep -oP "${PWD##*/}_basebox_[0-9_]*") vagrant package --base $VBOX_INSTANCE --output base.box # Handle paths differently when using cygwin if $(pwd | grep -q cygdrive) ; then BOX_FILE_PATH=$(echo "$PWD" | sed -E 's/\/cygdrive\/([a-z])(.*)/file:\/\/\/\1:\2\/base.box/') else BOX_FILE_PATH=$(pwd | awk '{print "file:" $1 "/base.box"}') fi vagrant box add $BOX_NAME $BOX_FILE_PATH vagrant destroy -f rm -f base.box rm Vagrantfile mv Vagrantfile.tmp Vagrantfile echo "Done creating basebox..." else echo "$BOX_NAME exists, moving on..." fi
These lines here are a bit of a hack
PORT=$(vagrant port | grep ' 22 (guest) => ' | awk '{print $5}') ssh -o "StrictHostKeyChecking no" vagrant@127.0.0.1 -p $PORT -i keys/vagrant "sudo /vagrant/scripts/remove-user.sh ubuntu"
but I could not get the private_key_path to work, it always prompted me for a password so this is the way I did it.
Then there are two scripts I use, one for creating the vagrant user and one for deleting the ubuntu user.
create-vagrant-user.sh
#!/usr/bin/env bash echo "Renameing user" groupadd vagrant su -c "useradd vagrant -s /bin/bash -m -g vagrant -G vagrant" chown -R vagrant:vagrant /home/vagrant echo "vagrant:vagrant" | chpasswd adduser vagrant sudo echo %vagrant ALL=NOPASSWD:ALL > /etc/sudoers.d/vagrant chmod 0440 /etc/sudoers.d/vagrant usermod -a -G sudo vagrant mkdir -p /home/vagrant/.ssh chmod 700 /home/vagrant/.ssh touch /home/vagrant/.ssh/authorized_keys chmod 600 /home/vagrant/.ssh/authorized_keys chown -R vagrant:vagrant /home/vagrant curl -Ss -L https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub >> /home/vagrant/.ssh/authorized_keys echo "Done creating user"
remove-user.sh
#!/usr/bin/env bash echo "Removing user $1" userdel -r $1 rm -f /etc/sudoers.d/$1 echo "Done removing user"
Now we have to change the Vagrantfile.BaseBox ( see here for details on the pattern used. ). We have to add in two commented out lines that will be used in the create-base-box.sh. When we are provisioning in the software in the first step we log in with the ubuntu user, but when we are deleting that user, we have to log in with the vagrant user ( can’t delete the currently logged in user )
Vagrantfile.BaseBox
Vagrant.configure("2") do |config| config.vm.define "basebox" do |basebox| basebox.vm.box = "ubuntu/xenial64" basebox.vbguest.auto_update = false basebox.vm.synced_folder ".", "/vagrant", type: "virtualbox" basebox.ssh.insert_key = false #basebox.ssh.username = "vagrant" #basebox.ssh.password = "vagrant" basebox.vm.provision "shell", path: "scripts/create-vagrant-user.sh" #And add some provision steps you want here end end
And now when you run the create-base-box.sh you create and add the vagrant box to your vagrant boxes. Then you can use the box like so.
Vagrantfile