Besides my standard day-to-day laptop running Ubuntu, I also have a Chromebook I picked up a while back. I like the light weight and the long battery life for traveling around. ChromeOS along covers a lot of what I do daily, but I do like to have a few additional linux tools to get things done so I use crouton.
With crouton there’s a few manual steps involved in preparing the Chromebook but
they are well documented. You need to put it in developer mode, download the
script and kick it off. It takes a good while to run on that relatively limited
hardware but at the end you add your initial user account and have a mostly bare
bones Ubuntu install depending on the options selected. Currently I do crouton -t xenial -r xiwi,lxde-desktop
for my crouton setup. I can launch a full lxde
desktop or run GUI apps in a window on the ChromeOS desktop that way. I also had
to manually install and start sshd so Ansible running on my laptop could
connect.
At this point I could start creating my ansible roles and playbooks. One role
would be the crouton specific bits and then a separate role for common items. So
here’s ~/source/ansible-mystuff/roles/crouton/tasks/main.yml
:
---
- name: update /etc/rc.local
become: yes
copy:
src: rc.local
dest: /etc/rc.local
mode: 0755
This will be sourced automatically from the primary playbook in
~/source/ansible-mystuff/utilhost.yml
when called via ansible-playbook
:
---
- hosts: crouton
roles:
- role: crouton
- role: common
This is pretty small. The only real crouton-specific item provided via the role
is that /etc/rc.local
file which, because it has executable permissions, will
be sourced and executed when the crouton chroot is started (eg with sudo enter-chroot
from the Chrome developer shell accessed from Crosh) :
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# for ssh https://github.com/dnschneid/crouton/wiki/Running-servers-in-crouton
if [ ! -d /var/run/sshd ]; then
mkdir /var/run/sshd
fi
/usr/sbin/sshd
/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT
# for vpnc https://github.com/dnschneid/crouton/wiki/VPNC
stop shill
start shill BLACKLISTED_DEVICES=tun0
mkdir -p /run/resolvconf/interface
cp /etc/resolv.conf /run/resolvconf/resolv.conf
mv /etc/resolv.conf /run/resolvconf/interface/mlan0
ln -s /run/resolvconf/resolv.conf /etc/resolv.conf
resolvconf --enable-updates
exit 0
So this will add a few things, some of which are relevant to
roles/common/tasks/main.yml
but also start sshd
. As is my habit I link to
where I got info from for future reference in the comments (“wait, why did I
put that there?") In this case I’m working around the crouton chroot and
inability to run services via systemd in that particular setup at least for
now. The rest of the items are specific to vpnc which I use for some ad-hoc
client vpn connections. ChromeOS doesn’t natively support ipsec VPNs but I can
work around that with crouton.
It takes a bit of troubleshooting and research to build this up and get it right
so it’s restartable. Ansible’s idempotent execution model helps here so you can
run things repeatedly. For example I had to learn that I needed that mkdir -p /run/resolvconf/interface
at chroot start via trial and error. But then I put
it in the file and update my ansible task and capture that change via git. Now,
when I replace that Chromebook at some point, I can just roll it out via Ansible
and I won’t stumble across that same issue and have to research it anew or try
and hunt through various note files where I may or may not have captured the
detail. This way, it is captured both as documentation and it will get done.
If something changes in ChromeOS and this breaks, I’ll catch it, make the update, and push it out via Ansible rather than just fixing the change subject to future forgetfulness.
The other important bit is that this is testable. After I was confident I could do all the Ansible bits to the chroot, I complete wiped out the crouton chroot, built it from scratch (which does take a while) and pushed it all out in one pass with Ansible.
The rest of the action is in roles/common/tasks/main.yml
which I’ll dive into in
my next post