bsdpot / pot

pot: another container framework for FreeBSD, based on jails, ZFS and pf
BSD 3-Clause "New" or "Revised" License
343 stars 31 forks source link

[BUG] Pot lacks a documented update workflow for bases. #83

Open Crest opened 4 years ago

Crest commented 4 years ago

Describe the bug I found no documentation on how to apply security and errata updates and to a pot base.

To Reproduce Steps to reproduce the behavior:

  1. Create a base e.g. pot create-base -r 12.1
  2. Create a jail from the base e.g. pot create -v -b 12.1 -p azkaban
  3. Enter the jail with pot run azkaban
  4. Run freebsd-version inside the the jail. It shows that the jail runs an unpatched userland.
  5. The jail can't update itself because its jail root is a read-only nullfs mount.

Expected behavior I expect there to be a easy find and follow documentation covering how to keep the jail user lands up to date.

Additional context My host system is running FreeBSD 12.1-p2.

pizzamig commented 4 years ago

Thanks for reporting. We've been focused a lot around the container model, that we didn't provide enough attention to thin jails.

I'll write down here a couple of things, but I'm working on a web site with all the documentation here the WIP

Creating a base, a related pot is also created, and it can be used to modify the file system. The base pot for 12.1 is called base-12_1

# pot create-base -r 12.1
# pot run base-12_1
root@base-12_1:~ #

For now, you have to run freebsd-update manually. I'll see to automate this step, at least when it's created.

Crest commented 4 years ago

That still leaves the .osrelease file in the base root directory and the osrelease property of the jails derived from said base (before it was updated).

pizzamig commented 4 years ago

yes, a proper solution would be to access /bin/freebsd-version I'll look into it

pizzamig commented 4 years ago

I committed 2 main changes:

I'd like your feedback on three things I would do:

Crest commented 4 years ago

The first would be a slight problem for me because I'm currently working on stripping down the jails to just the linker, a handful of executables, their required libraries and filesystem components for the data. I would have to leave freebsd-version in every jail but it's just a 4.5kB static executable. So far I came up with a flavour that installs the required package(s) and deletes everything but a small whitelist to build a tiny image e.g. a rsync server jail in 2.5MB.

The second would be highly appreciated. Documentation what pot can and can't do would have saved me time reading the implementation and tracing its execution with sh -x and dtrace. That's how I learned about /tmp/tinirc as well. I had to set the jail command to #!/usr/bin/env -Srsync --daemon --config /usr/local/etc/rsync/rsyncd.conf to prevent the kernel from reaching the fallback to /bin/sh for executables with an unknown interpreter. I have yet to find a clean solution to run a jail without a shell and I'm uncertain how far outside pot's design my approach is and how much problems it will would cause in the future.

Such a command would be useful, but again documentation on how the different kind of jails pot can manage interact with the rest of FreeBSD is key to keep experienced users happy e.g. there is 1:1 relation ship between a base and its jail. The jail can be used to make changes to the jail.

A common pattern in all those cases is that pot interacts closely the rest of FreeBSD which is what makes it so flexible and powerful. This offers a lot of implied interfaces between pot and the rest of the system to users and an authoritative statement which of those interfaces are considered how stable would make it easier and safer to build with and on top of pot.

pizzamig commented 4 years ago

thanks for your feedback, it's really appreciated.

freebsd-version is a script and I'm parsing it to extract the USERLAND_VERSION variable the only value that I need. It's a bit dirty, but you can removing everything around :)

Documentation is a pain, but I'm trying to do my best. The current work-in-progress is at https://pot.pizzamig.dev while the sources https://github.com/pizzamig/pot-book . I'm trying to organize it different pages for different use cases. Currently, only getting started, Installation, images and network configuration are done.

I'm writing the thick jail section, I'll ask you for a review, if you available to help a bit!

Crest commented 4 years ago

Sorry jumping from ldd's output (not a dynamic executable) to the conclusion that it had to be a static executable was sloppy of me.

I'm willing to help improve the documentation.

urosgruber commented 4 years ago

So far I came up with a flavour that installs the required package(s) and deletes everything but a small whitelist to build a tiny image e.g. a rsync server jail in 2.5MB.

Would you mind sharing this flavuor?

Crest commented 4 years ago

My rsyncd flavour contains an empty rsyncd and this rsyncd.sh:

#!/bin/sh -e

# Use latest packages
mkdir -p /usr/local/etc/pkg/repos
echo 'FreeBSD: { url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest" }' > /usr/local/etc/pkg/repos/FreeBSD.conf

pkg bootstrap -y
pkg install -y rsync

chflags -R 0 /
find -ds / -not \( \
        -path '/' -or \
        -path '/dev' -or  \
        -path '/dev/*' -or \
        -path '/etc' -or \
        -path '/etc/pwd.db' -or \
        -path '/etc/spwd.db' -or \
        -path '/lib' -or \
        -path '/lib/libc.so*' -or \
        -path '/libexec' -or \
        -path '/libexec/ld-elf.so*' -or \
        -path '/tmp' -or \
        -path '/usr' -or \
        -path '/usr/bin' -or \
        -path '/usr/bin/env' -or \
        -path '/usr/local' -or \
        -path '/usr/local/bin' -or \
        -path '/usr/local/bin/rsync' -or \
        -path '/usr/local/etc' -or \
        -path '/usr/local/lib' -or \
        -path '/usr/local/lib/libiconv.so*' -or \
        -path '/root' -or \
        -path '/var/' -or \
        -path '/var/run' -or \
        -path '/var/run/ld-elf.so.hints' \
    \) -delete

The resulting pot is too limited to support all pot features e.g. there is no ifconfig for /tmp/tinirc to configure vnet interfaces. Heck there isn't even a /bin/sh for the !# line. Instead it uses !#/usr/bin/env to set env vars. This is an extreme example. It would probably be easier (and for sure faster) to start from an empty jail instead of deleting almost everything.