/ChromeOS-Terminal-LXC-LXD

Guide to using other Linux containers with ChromeOS's Terminal (Crostini)

TL note:

All of this I found reading through several sources with a lot of overlapping information as I worked it out. Im just posting with future-self in mind who may not want to piece things together later, and to put it all in one place for anyone with the same goal.

Using other containers in ChromeOS (crostini) Terminal

This is a guide for setting up the default Terminal app offered by ChromeOS' crostini Linux env. The goal here is to use the Terminal with other Linux distros you may have installed alongside the default penguin (stripped-down) Debian container.

We can achieve the same within the crosh shell by just entering containers manually, but that removes access to several default hotkeys/behavior a slightly more hospitable terminal offers over a shell within Chrome. Also its annoying to do every time.

For our purposes, refer to this diagram to get an idea of where we are in namespaces.


Guide

crosh

We're starting off assuming you have already enabled Dev mode and Linux features are turned on.

Ctrl+Alt+t to open up crosh.
vmc at this level manages your VMs. Your shell should start with crosh> , letting you know we're at the topmost layer in our namespaces right now:

crosh

You can use vmc destroy vm_name and vmc start vm_name to quickly burn down or spin up new VMs. Use vmc list to check what VMs exist. create can also be used instead of start, the difference being that start fully initiates a VM and also enters it.

type vmc start termina to enter the default termina VM.

termina

Once in the termina layer, you can interact with LXC :

lxc launch remote:image
remote here being the name of the remote image source
image the name of the image we want to pull down over the internet

We can see what remote image servers we have on hand with lxc remote list

In this case, I have:

remote_list by default, which is fine because we can access what we need (or would want?) with this. I imagine we can add more image servers, but I did not.

We can check an image server's wares by going to its url. We can see that the images image server (confusingly named, though tru, I guess) offers many common Linux distributions.

We can use:
lxc launch images:distribution[/release][/architecture] container_name
to install images with varying degrees of specificity from there (values in [ ] are optional).


For example:
centos, release 7, for amd64 (64-bit) architechture from images with its default name
lxc launch images:centos/7/amd64

alpine, from its development branch edge image, named alp-edge
lxc launch images:alpine/edge alph-edge

kali container (all else default/current)
lxc launch images:kali


The ubuntu image server doesn't seem to offer as many properties, though does list both the release # and codename/'animal' adjective, meaning both
lxc launch ubuntu:21.04 and
lxc launch ubuntu:hirsute work.

For our purposes, we're temporarily spinning up an Ubuntu 18.04 image to steal its LXD install since (for me) that was quicker and easier than setting it up myself within the penguin container. I believe you can just install an LXD client manually inside the penguin container, though I used this method for its ease because of my unfamiliarity with LXC.

Do that with:

lxc launch ubuntu:18.04 ubuntu

If we lxc list, we see the current containers. Then we can just pull what we need from the ubuntu container to /tmp/ on the Chromebook, and push it to the penguin container with:

lxc file pull ubuntu/usr/bin/lxc /tmp/lxc
lxc file push /tmp/lxc penguin/usr/local/bin/

I tried copying directly from one container to the other but theres read-permissions across containers that stop you, which is why we use /tmp to hand it off

Then, still within termina, we enable some settings for LXD:
lxc config set core.https_address :8443
lxc config set core.trust_password somepassword

We can check they're applied with lxc config show.
Feel free to delete the Ubuntu 18.04 container once done copying LXC over
lxc delete container_name

Terminal

Now we can return to the Terminal to hook it up to LXD, giving us access to that chronos user in crosh (and lxc and our containers) from within penguin.

Start by getting the container's gateway with ip -4 route show, in this case 100.115.92.193 ip

This is the internal ip that connects the termina chronos user to its containers. We're going to connect so we can communicate with LXC within Terminal.
lxc remote add chronos <ip_address>
then we set chronos as the default.
lxc remote set-default chronos

lxc_remote

Now within the Terminal app / penguin container, you will send LXC commands 'up' a layer to be ran by termina. You can enter any container you launch with LXC using the command lxc exec container_name -- bash though I recommend aliasing to just the container name for convenience. You still have to switch containers but it can be a 1-step or start in .bashrc.

Now with a slightly better terminal ! 🎊

TL;DR

In Crosh

Ctrl + Alt + t

vmc start termina
  lxc launch ubuntu:18.04 owo
  lxc file pull owo/usr/bin/lxc /tmp/lxc
  lxc file push /tmp/lxc penguin/usr/local/bin/
  lxc delete owo -f
  lxc config set core.https_address :8443
  lxc config set core.trust_password "a'really,good;password:^)"

In Terminal

  lxc remote add chronos $(ip route show | awk '{print $3}' | head -n 1)
  lxc remote set-default chronos

lxc exec container_name -- bash

References:

Chrome Docs
Crostini Docs
Ubuntu Docs
post on /r/Crostini
Every help command