Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Chromium OS ft. Docker

Chromium OS is cool. Chromium OS with crouton is cooler. Chromium OS with Docker is even cooler. This is specifically a guide for the Chromebook Pixel 2 (2015), but I can't think of any reason it wouldn't work with other devices.

  1. Create a build environment
  2. Customize the kernel
  3. Build Chromium OS
  4. Flash Chromium OS to USB
  5. Install Chromium OS

P.S. Custom kernels are risky business and the buttons you press on your keyboard are your responsibility. Abandon all lawsuits, ye who enter here.

Create a build environment

We're going to use Ubuntu 14.04 (Trusty Tahr) as our build environment. Don't have it? Use a container. Or don't. Whatever. Let's install some dependencies.

sudo apt-get install -y git-core gitk git-gui subversion curl python xz-utils

Now that that's out of the way, we're going to set up our workspace.

mkdir "construction-zone"
cd "construction-zone"

git clone ""

cat > "/tmp/relax_requirements" <<EOF
Defaults !tty_tickets
Defaults timestamp_timeout=180
sudo mv "/tmp/relax_requirements" "/etc/sudoers.d/"
sudo chown "root" "/etc/sudoers.d/relax_requirements"

mkdir "chromium"
cd "chromium"

If you haven't configured git on this system (if you have to ask, you haven't), make sure to do that. You can substitute your email address and name if you feel like it, but it really doesn't matter if you're in a burner environment.

git config --global "dev@null"
git config --global "/dev/null"

The next step of the process is deciding which branch you'd like to use. There are tons of options, but in the interest of sanity I'll build the most recent official release at the time of writing.


So we've cloned some tools, screwed with /etc/sudoers, configured git, and entered a disappointingly empty directory. We'll fix that by downloading a ridiculous amount of data and filling this directory with more code than you'll probably read in your life. Probably.

repo init -u "" -b "$BRANCH"

You'll probably be asked whether you'd like to use terminal colors. I like pretty things, but if you're into the monochrome aesthetic you might want to pass on this one.

repo sync

Downloads will continue until morale improves.

Now you're going to have to choose a board. There's some great Chrome OS developer information if you've got a Chrome OS device, otherwise your board will probably be x86-generic or something. For example, if you've got a Chromebook Pixel 2 (2015), your board is going to be samus.


Customize the kernel

First, figure out which kernel you're installing. I was able to run uname -r on my Chromebook, but there's probably a better way to figure it out depending on the board you selected. Unfortunately I'm not familiar enough with it that I can help you with this step. Sorry.

I'm going to pretend that you're using Linux 3.14 because that's what I'm using and I'm lazy.


Now we need to add our kernel modules. For each item in this list you're going to make sure there's a corresponding kernel module loaded. There aren't very many changes, but the basic idea is that you want to set CONFIG_WHATEVER=y for each module, as you can see I've done below.

diff --git a/chromeos/config/base.config b/chromeos/config/base.config
index 3baf15b..9d687c8 100644
--- a/chromeos/config/base.config
+++ b/chromeos/config/base.config
@@ -61,7 +61,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
-# CONFIG_BLK_CGROUP is not set
 # CONFIG_BRCMSMAC is not set
@@ -138,12 +138,12 @@ CONFIG_CFG80211_WEXT=y
-# CONFIG_CGROUP_PERF is not set
 # CONFIG_CHARGER_BQ2415X is not set
 # CONFIG_CHARGER_LP8727 is not set
@@ -684,11 +684,13 @@ CONFIG_MAC80211_RC_MINSTREL_HT=y
 # CONFIG_MAC80211_TDLS_DEBUG is not set
 # CONFIG_MACB is not set
-# CONFIG_MACVLAN is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_MFD_88PM800 is not set
 # CONFIG_MFD_88PM805 is not set
@@ -925,11 +927,11 @@ CONFIG_NF_CT_NETLINK=y
 # CONFIG_NF_NAT_AMANDA is not set
 # CONFIG_NF_NAT_FTP is not set
 # CONFIG_NF_NAT_H323 is not set
 # CONFIG_NF_NAT_IRC is not set

Make these changes with nano, vim, emacs, ed, joe, or whatever you're most comfortable with.

$VISUAL "src/third_party/kernel/v$KERNEL_VERSION/chromeos/config"

Easy, right? Now in a perfect world we'd be done, but the homie Kees Cook is great at his job, and locked Chromium OS down so that bad guys can't mount symlinks. Unfortunately, Docker needs to mount symlinks, so we're going to disable the security system. We're almost done, just make the change below and we'll be done customizing the kernel.

diff --git a/security/chromiumos/lsm.c b/security/chromiumos/lsm.c
index c6e10c2..8c529e1 100644
--- a/security/chromiumos/lsm.c
+++ b/security/chromiumos/lsm.c
@@ -39,13 +39,13 @@ int chromiumos_security_sb_mount(const char *dev_name, struct path *path,
                char *cmdline;
                cmdline = printable_cmdline(current);
-               pr_notice("Mount path with symlinks prohibited - "
+               pr_notice("Mount path with symlinks allowed - "
                        "pid=%d cmdline=%s\n",
                        task_pid_nr(current), cmdline);
-       return error;
+       return 0;
 static void report_load(const char *origin, struct path *path, char *operation)

Again, just use whichever editor you prefer. Alternatively, use one you really hate to fulfill your masochistic needs. That's why you're building a custom Chromium OS kernel anyway, right?

$VISUAL src/third_party/kernel/v$KERNEL_VERSION/security/chromiumos/lsm.c

Build Chromium OS

We're done with the customizing, now let's just build the damn thing. This is also going to take a while, so clear your schedule (or buy a faster computer).

cros_sdk -- ./build_packages --board=${BOARD}

While building packages will get much faster after you've done it once, building an image is always going to take a similar amount of time. If you haven't figured this out by now, waiting is the name of the game.

cros_sdk -- ./build_image --board=${BOARD}

If you got through the ring of fire without errors, you're good!

If you didn't, you're screwed. I've never had an issue with either of these commands and I have no words of advice for those of you currently stuck in purgatory. Search engines are your friend.

Flash Chromium OS to USB

Plug your USB into your build machine. If that didn't work, flip it over. Lather, rinse, and repeat until the USB gods smile upon you.

cros_sdk -- cros flash --board=${BOARD} usb://

Follow the on-screen prompts, and please for the love of everything sacred please don't try to flash your USB webcam or anything weird. On second thought, please flash Chromium OS on your webcam and try to get Doom running on it.

P.S. Don't actually flash your webcam with Chromium OS unless you hate nice things.

Install Chromium OS

Now you've just gotta boot to USB and install. Just RTFM for your hardware, plug in the USB, do some voodoo magic (see: RTFM) and you'll have booted Chromium OS. Take a few minutes to test out your devices to make sure you're happy with your install, pop into VT2 (Ctrl+Alt+F2), log in as root, and install the OS.


Now reboot your machine, install Docker, and enjoy your new setup! Leave a comment below or get @ me if you have any questions, concerns, compliments, or family recipes you'd like to pass along.

Copy link

Great step-by-step and I enjoyed the humor.
One question though, about how much disk space does this use ?

Copy link

ghost commented Apr 2, 2016

It uses 65 GB of disk space on my AWS instance. The image it produces is 2.6GB.

@christianbundy I notice that these instructions have been updated within the last couple of months. Can you confirm you are using release-R47-7520.B and not something newer now?

Copy link

@brianmingus I actually went back to vanilla Chrome OS after a few weeks, I believe my revisions were just to fix typos. I'll update it if I get a more recent version of Chromium OS working though!

Copy link

iansltx commented Jul 11, 2016

@christianbundy Looks like the newest releases of CrOS have the ability to turn off symlink mount protection via a config flag. Forked this and am going through the steps on my HP Chromebook 13 G1 (chell). Fingers crossed that I get all the way through sometime today :)

Copy link

iansltx commented Jul 11, 2016

@christianbundy @brianmingus Building all the things In The Cloud (tm) (r) (wat). Given that, what do I need to pull down to local to write the flash image? If I only have to pull down the image and utils (where's the image?) I can do the flash from the very Chromebook I'll be flashing it to (also, the only Linux-on-the-metal machines I own are Chromebooks, so there's that).

Copy link

kdavh commented Aug 3, 2016

@christianbundy Can you comment on why you went back to vanilla Chrome OS after a few weeks? Was something not working as expected? I'm planning to use your method if you still think it's a good one.

Copy link

yubbie commented Mar 23, 2017

Should be $VISUAL "src/third_party/kernel/v$KERNEL_VERSION/chromeos/config/base.config"

Copy link

Copy link

hrqiang commented Apr 25, 2017

Trying to boot from USB, but got a single beep sound. Hardware is stumpy. Branch release-R59-9460.B. How to debug and verify the image? Thanks.

Copy link

deedubs commented Aug 8, 2017

For anyone wondering, you can unset CONFIG_SECURITY_CHROMIUMOS_NO_SYMLINK_MOUNT to avoid the code-change.

Copy link

@christianbundy how to change the kernel ? 3.14 has no overlayfs.

and for anyone else.
maybe you get emerge: there are no ebuilds to satisfy "sys-boot/chromeos-mrc" for /build/samus/. error with build samus.

see just move USE="bootimage cros_ec" from overlay
it works for now.
I think they will fix it later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment