Using Rootbox
=============
Restrictions
************
Rootbox requires two things:
- A Linux system. Some others Unixes (like the BSDs) may work, but they're
untested.
- An file system with sparse file support to store the workspace directory (see
below). Rootbox relies on the magic of sparse files to easily create boxes and
images. (Note that only ext4 has been tested.)
Also, here's something import:
**ROOTBOX IS NOT SECURE.**
Let me repeat:
**ROOTBOX IS NOT SECURE.**
Third time's the charm:
**ROOTBOX IS NOT SECURE.**
Rootbox's "boxes" are not intended to be used like you would use containers.
They *are* designed to be created and easily distributed and portable
development environments, but they are *not* designed for running web servers or
untrusted code. Use containers for that!
Getting Started
***************
Just run::
curl -L https://goo.gl/H3OpCL | sudo sh
If you're not confortable with running random internet scripts, you can also
install it from GitHub instead::
git clone https://github.com/project-rootbox/rootbox.git
cd rootbox
sudo sh install.sh
Once that's done, you need to initialize the Rootbox workspace directory, which
is where all your images and boxes will be stored. You can do so using
``rootbox init``::
rootbox init
This will initialize Rootbox in ``$HOME/.rootbox``. If you want to use a
different directory, just say so::
rootbox init my_directory
This will create the directory and symlink it to ``$HOME/.rootbox``.
Note that, as already mentioned above, **this directory must be on a file system
with sparse file support**!
If at any point in the future, you want to use a different workspace directory,
you'll need to pass ``-f`` to force the reinitialization.
.. warning::
Do **NOT** tamper with the workspace directory! By that, I mean don't go
touching it in any way. Remember when I said that Rootbox uses sparse files?
Well, that means that, if you try to play with the directory or copy/move
files outside of it, there's a chance all the sparse files will inflate to
their full 128 GB size. Ouch!!
Concepts
********
Before we continue, I'd like to introduce some terms you'll see floating around
this document:
- **workspace**: As mention above, this is the directory where Rootbox will save
all your images and boxes (see below) into.
- **boxes**: Boxes are essentially Rootbox's version of containers. They hold
an `Alpine Linux `_ installation, as well as
whatever else you want to put in them. Note that, unlike containers, boxes are
intentionally insecure, and they aren't intended to be used for everything
that one might use containers for.
- **images**: Every box is base on an *image*. Images are just vanilla,
unmodified Alpine Linux installations.
- **bind mounts**: These allow you to "mount" external directories inside your
boxes.
Got that? Let's go on!
Creating an image
*****************
As already mentioned, images are unmodified installations of Alpine Linux, ready
to be converted to a box when desired. They're easy to create::
rootbox image.add 3.5
Here, we're using Alpine Linux 3.5, as passed to the version argument. Note that
the resulting image will be around 210 MB in size. This seems rather big, but
it also contains several development tools and libraries, such as GCC,
libstdc++, git, and more. If you want just a plain Alpine Linux installation,
then you can also pass ``-s``::
rootbox image.add 3.5 -s
This will create a *slim* or *nodev* image, which is significantly lighter
(around ~13 MB in size) but doesn't contain development tools inside. When you
create a slim image, you can later reference using ``VERSION-nodev``, like
``3.5-nodev``.
(You can also use ``image.list`` to list all your installed images and
``image.remove -v VERSION`` to remove one of your images.)
Creating a box
**************
Creating a new box is easy::
rootbox box.new mybox
Here, we're creating a box called *mybox*, using the Alpine Linux 3.5 image that
was created earlier. If you want to use a different image instead, use ``-v``::
rootbox box.new mybox -v 3.4
(To use the slim/nodev image, pass ``-v 3.5-nodev`` instead.)
You can also pass a list of bind mounts to be mounted whenever the box is run.
For example::
rootbox box.new mybox outside_directory///inside_directory
Now, whenever this box is run ``outside_directory`` will appear inside it as
``/inside_directory``. For instance, if you always want the current directory
to be mounted inside the box as ``/cwd``, you could run::
rootbox box.new -n mybox .///cwd
Absolute paths can be used, too::
rootbox box.new -n mybox /home/$USER///external_home
Running your boxes
******************
Now that a box has been created, let's run it! ::
rootbox box.run mybox
This will put you inside an ``ash`` shell inside your box. Take a look around
for a bit! Once you're done, you can Ctrl-D out of it.
Just like above, bind mounts can be created when the box is run::
rootbox box.run mybox .///cwd
These will be mounted in addition to any specified when creating the box for the
first time.
While inside the box, you can also install packages using the Alpine package
manager,
`apk `_, like
this::
sudo apk add clang
A command can also be passed via the command line::
rootbox box.run mybox -c 'echo 123'
If you're planning on running X11 applications inside your box, you'll need to
pass ``-x``::
rootbox box.run mybox -x
(Note that you may also need to run ``sudo apk add font-adobe-100dpi`` if you
run into problems involving missing fonts, e.g. you get boxes instead of text
in your programs.)
Box factories
*************
Factories are an imporant concept in Rootbox! A box factory is just a shell
script that's run inside your box upon creation to set things up. For instance,
you could create a factory ``clang.sh`` containing:
.. code-block:: shell
sudo apk add clang
To create a box using your factory, you can just run::
rootbox box.new mybox -f clang.sh
``-f`` takes a path to your box factory. However, things get fancier than that!
You can have one factory depend on another one. For instance, you might have
``llvm.sh`` to install llvm:
.. code-block:: shell
sudo apk add llvm
Then, ``clang.sh`` could be modified to read:
.. code-block:: shell
#:DEPENDS llvm.sh
sudo apk add clang
The ``#:DEPENDS`` means that ``llvm.sh`` must be run first. Now, when you use
``clang.sh`` as your box factory, ``llvm.sh`` will be run, too!
Box factories can also specify Alpine Linux versions that they work on:
.. code-block:: shell
#:VERSION 3.5 3.5-nodev
This factory will run under 3.5 and 3.5-nodev, but if you try to use it on an
Alpine 3.4 box, Rootbox won't let you.
Using factories from the internet
*********************************
If things weren't already awesome enough, you can load your factories straight
from the web or Git. If you have a factory up at GitHub, you could use it via::
rootbox box.new mybox -f git:myuser/myrepo@@mybranch///myfactory.sh
If ``@@mybranch`` is ommited, it defaults to *master*. If ``///myfactory.sh``
is ommited, it defaults to ``factory.sh``. For instance, to load ``factory.sh``
from ``CoolRootboxScripts/cool_scripts_set_1``::
rootbox box.new mybox -f git:CoolRootboxScripts/cool_scripts_set_1
To use ``my_other_factory.sh``::
rootbox box.new mybox -f git:CoolRootboxScripts/cool_scripts_set_1///my_other_factory.sh
To use it from the branch ``devel``::
rootbox box.new mybox -f git:CoolRootboxScripts/cool_scripts_set_1@@devel///my_other_factory.sh
GitLab is supported, too::
rootbox box.new mybox -f gitlab:MyGitlabUser/my_gitlab_repo@@branch///factory_name.sh
as well as any other plain old Git repository::
rootbox box.new mybox -f git:https://whatever.com/my_repo.git@@branch///factory_name.sh
In fact, factories can be pulled from anywhere on the internet::
rootbox box.new mybox -f url:https://mysite.com/some_cool_factory.sh
The syntax this time is a bit different: the url must point to an absolute URL
to the factory. If the URL ends with a slash (``/``), then ``factory.sh`` will
be appended to it.
These location formats can be used inside the ``DEPENDS`` section of a script,
too. You could have something like this:
.. code-block:: shell
# This is my cool factory script!
#:DEPENDS git:myuser/myrepo///myfactory.sh
#:DEPENDS url:rootbox_factories.com/myotherfactory.sh
There are several pre-made factories in the still-growing
`rootbox-factories `
repository. If you have a really cool idea for a factory that you figure would
be useful to a lot of people, you can open up an issue there as a request.
Managing, exporting, and importing your boxes
*********************************************
If you want to see a list of all the boxes that have been installed, just run::
rootbox box.list
You can get info about an individual box with ``box.info``::
rootbox box.info mybox
Boxes can be cloned::
rootbox box.clone source_box new_box
and deleted::
rootbox box.remove mybox
If you want to change your a box's settings later on, you can use
the ``box.update`` command set. For instance, you can use ``box.update.binds``
to update a box's default bind mounts::
rootbox box.update.binds mybox a///b # Add a///b to the default bind mounts.
rootbox box.update.binds mybox ^a///b # Remove it from the default bind mounts.
As you can see, prefixing a bind with ``^`` will remove it instead of adding it.
Similarly, ``box.update.factory`` can be used to run another factory once the
box has already been created::
rootbox box.update.factory mybox url:https://foo.bar/myfactory.sh
Exporting and importing your boxes
**********************************
Boxes can be exported using ``box.dist``. It works much like you'd expect by
now::
rootbox box.dist mybox
The default file name is ``.box``. In this case, it'll be
``mybox.box``. That can be overriden, of course::
rootbox box.dist mybox -o my_custom_name.box
In addition, you can apply compression using ``-c`` to make it a bit smaller::
rootbox box.dist mybox -o gzip_compressed.box.gz -c gzip
rootbox box.dist mybox -o bzip2_compressed.box.bz2 -c bzip2
Boxes can also be imported::
rootbox box.import mybox.box.gz mybox
Here, ``mybox.box.gz`` is being imported using the name ``mybox``. In fact,
boxes can be imported from virtually anywhere, using the exact same syntax as
used with box factories::
rootbox box.import url:rootbox_storage.com/1234567 mybox
rootbox box.import git:Cooluser101/myboxes///cool_stuff.box mybox
Some examples
*************
Building C
^^^^^^^^^^
Donald wants to create a box that can be used to statically compile his C
programs. Alpine Linux is great for static linking::
rootbox box.new static_c .///cwd
rootbox box.run static_c
# Inside the box...
cd /cwd
echo 'int main() {}' > x.c
gcc -static -o x x.c
exit
# Back outside again...
ldd x # statically linked
Building Nim
^^^^^^^^^^^^
Mary wants to create a box designed for building Nim programs. She can use
factories to automate...everything:
.. code-block:: shell
sudo apk add xz linenoise-dev libexecinfo-dev
curl -L https://nim-lang.org/download/nim-0.16.0.tar.xz -o nim.txz
tar xvf nim.txz
cd nim-0.16.0
./build.sh
bin/nim c koch
./koch boot -d:release -d:useLinenoise
sudo ./koch install /usr/local/bin
She can save this to ``nim-factory.sh``. Then, to create her image, she can
just run::
rootbox box.new nim .///cwd -f nim-factory.sh
If she uploads her Nim factory to GitHub in ``mary123/factories``, someone else
can use it, too::
rootbox box.new nim .///cwd -f git:mary123/factories///nim-factory.sh
If Robby wants to build a Nim program using Rootbox, he can create a factory,
too:
.. code-block:: shell
#:DEPENDS git:mary123/factories///nim-factory.sh
git clone https://github.com/bobby456/my-nim-program.git
cd my-nim-program
nim c my-program.nim
sudo cp my-program /usr/local/bin
Closing thoughts
****************
Rootbox is still in the beta stages. If you notice anything isn't working quite
correctly, feel free to report it to the
`GitHub repo `_.
Have fun playing with your boxes!!!