8000 repo · DtxdF/AppJail Wiki · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Jesús Daniel Colmenares Oviedo edited this page May 18, 2023 · 1 revision

Using a custom repository in a jail with poudriere

Occasionally, we need to customize a port to suit our needs. We can use portsnap(8) to install a ports tree, run make config on the port we want to customize and install that port on our system. There are big problems with this approach. First, this approach does not scale very well if we have many servers or PCs. Second, we have to do the difficult task of keeping an eye on the custom ports that are installed. Third, updating many ports is not a very simple approach. One solution that works very well is Poudriere. From its README:

poudriere is a tool primarily designed to test package production on FreeBSD. However, most people will find it useful to bulk build ports for FreeBSD.

Its goals are to use modern facilities present in FreeBSD (such as ZFS, jails), to be easy to use and to depend only on base.

But instead of simply installing a port on our system, we can install a port in an isolated environment, a jail. Poudriere has the ability to create a repository of our packages. In this howto, we will create a custom repository to install our ports in a jail.

This howto does not show what Poudriere is capable of, please read the Poudriere manual and its wiki.

Requirements

Privileges

AppJail needs root access to do its job, however we can limit the access for some trusted users. See more details in Unprivileged users

Firewall

Setting up the firewall only takes a moment. See more details in Networking

Virtual network

Although we can use other networking options that AppJail supports, for simplicity we will use a virtual network. See more details of how to create a virtual network in Virtual network. This howto assumes a virtual network named testing, but you can use any virtual network you own.

Installing poudriere

I recommend installing ports-mgmt/poudriere-devel instead of ports-mgmt/poudriere because the former will become the next release, so it has newer and more interesting features that the latter may not have, and it is well tested as it is used for official FreeBSD package builds.

# cd /usr/ports/ports-mgmt/poudriere-devel
# make install clean

See /usr/local/etc/poudriere.conf before using it.

The ports tree

We need the ports tree, so to clone the main branch of the ports tree using git(1) we will do the following:

# poudriere ports -c -m git+ssh -p custom
[00:00:00] Creating custom fs at /usr/local/poudriere/ports/custom... done
[00:00:01] Cloning the ports tree... done
# poudriere ports -l
PORTSTREE METHOD  TIMESTAMP           PATH
custom    git+ssh 2023-05-17 22:38:01 /usr/local/poudriere/ports/custom

With -c we create. With -m git+ssh we clone the ports tree using git(1) via SSH. And with -p custom we name our ports tree custom.

The poudriere jail

As mentioned, Poudriere uses jails to build ports, so let's create one. To do this job we will use poudriere-jail(8):

# poudriere jail -c -j 132amd64 -p custom -a amd64 -v 13.2-RELEASE
[00:00:00] Creating 132amd64 fs at /usr/local/poudriere/jails/132amd64... done
[00:00:01] Fetching MANIFEST for FreeBSD 13.2-RELEASE amd64
MANIFEST                                              1046  B 4084 kBps    00s
[00:00:02] Fetching base for FreeBSD 13.2-RELEASE amd64
base.txz                                               190 MB  250 kBps 12m59s
[00:13:04] Extracting base... done
[00:14:12] Fetching src for FreeBSD 13.2-RELEASE amd64
src.txz                                                187 MB  389 kBps 08m12s
[00:22:28] Extracting src... done
[00:23:57] Fetching lib32 for FreeBSD 13.2-RELEASE amd64
lib32.txz                                               65 MB  580 kBps 01m55s
[00:25:54] Extracting lib32... done
[00:26:15] Cleaning up... done
[00:26:15] Recording filesystem state for clean... done
[00:26:16] Upgrading using http
Looking up update.FreeBSD.org mirrors... 2 mirrors found.
Fetching public key from update2.freebsd.org... done.
Fetching metadata signature for 13.2-RELEASE from update2.freebsd.org... done.
Fetching metadata index... done.
Fetching 1 metadata files... done.
Inspecting system... done.
Preparing to download files... done.

No updates needed to update system to 13.2-RELEASE-p0.
13.2-RELEASE
[00:26:20] Recording filesystem state for clean... done
[00:26:21] Jail 132amd64 13.2-RELEASE amd64 is ready to be used

With -c we create. With -j 132amd64 we name our jail 132amd64, an arbitrary name, but I recommend to name it FreeBSD version (without dots and hyphens) plus arch as it is easy to identify in the future.

Configuring the port

Configuring the port is one of the most fun parts of ports. Let's configure sysutils/htop.

# poudriere options -c -n -j 132amd64 -p custom sysutils/htop
[00:00:00] Working on options directory: /usr/local/etc/poudriere.d/132amd64-custom-options
[00:00:00] Using ports from: /usr/local/poudriere/ports/custom
[00:00:00] Appending to make.conf: /usr/local/etc/poudriere.d/make.conf
          ┌─────────────────────────────── htop-3.2.2_1 ─────────────────────────────────┐
          │ ┌──────────────────────────────────────────────────────────────────────────┐ │
          │ │+[x] LSOF  LiSt Open Files utility support                                │ │
          │ └──────────────────────────────────────────────────────────────────────────┘ │
          ├──────────────────────────────────────────────────────────────────────────────┤
          │                       <  OK  >            <Cancel>                           │
          └──────────────────────────────────────────────────────────────────────────────┘

With -c we create options. With -n we indicate to poudriere-options(8) not to be recursive, since we only want to configure the port and not its dependencies. With -j 132amd64 we indicate the jail. With -p custom we indicate the ports tree to use which will be concatenated with the jail name to save our options. sysutils/htop is the port to configure. When the dialog is displayed, we mark the LSOF option to install sysutils/htop with sysutils/lsof.

Building the repository

Since we customized the ports, it is time to build the repository.

# poudriere bulk -j 132amd64 -p custom -b latest sysutils/htop
[00:00:00] Creating the reference jail... done
[00:00:01] Mounting system devices for 132amd64-custom
[00:00:01] Mounting ccache from: /var/ccache
[00:00:01] Mounting ports from: /usr/local/poudriere/ports/custom
[00:00:01] Mounting packages from: /usr/local/poudriere/data/packages/132amd64-custom
[00:00:01] Mounting distfiles from: /usr/ports-devel/distfiles
[00:00:01] Copying /var/db/ports from: /usr/local/etc/poudriere.d/132amd64-custom-options
[00:00:01] Appending to make.conf: /usr/local/etc/poudriere.d/make.conf
/etc/resolv.conf -> /usr/local/poudriere/data/.m/132amd64-custom/ref/etc/resolv.conf
[00:00:01] Starting jail 132amd64-custom
[00:00:01] Will build as nobody:nobody (65534:65534)
[00:00:05] Logs: /usr/local/poudriere/data/logs/bulk/132amd64-custom/2023-05-18_08h53m59s
[00:00:05] Loading MOVED for /usr/local/poudriere/data/.m/132amd64-custom/ref/usr/ports
[00:00:07] Ports supports: FLAVORS SELECTED_OPTIONS
[00:00:07] Inspecting ports tree for modifications to git checkout... no
[00:00:35] Ports top-level git hash: 2e0d3fa0b
[00:00:35] Gathering ports metadata
[00:00:36] Calculating ports order and dependencies
[00:00:36] Trimming IGNORED and blacklisted ports
[00:00:36] Package fetch: Looking for missing packages to fetch from pkg+http://pkg.FreeBSD.org/${ABI}/latest
[00:00:36] Packge fetch: bootstrapping pkg
Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:13:amd64/latest, please wait...
[132amd64-custom] Installing pkg-1.19.1_1...
[132amd64-custom] Extracting pkg-1.19.1_1: 100%
Updating FreeBSD repository catalogue...
[132amd64-custom] Fetching meta.conf: 100%    163 B   0.2kB/s    00:01
[132amd64-custom] Fetching packagesite.pkg: 100%    7 MiB 770.4kB/s    00:09
Processing entries: 100%
FreeBSD repository update completed. 33157 packages processed.
All repositories are up to date.
[00:01:59] Package fetch: Will fetch 25 packages from remote or local pkg cache
Updating database digests format: 100%
The following packages will be fetched:

New packages to be FETCHED:
        autoconf: 2.71 (565 KiB: 1.35% of the 41 MiB to download)
        autoconf-switch: 20220527 (1 KiB: 0.00% of the 41 MiB to download)
        automake: 1.16.5 (551 KiB: 1.32% of the 41 MiB to download)
        ccache: 3.7.12_4 (128 KiB: 0.31% of the 41 MiB to download)
        gettext-runtime: 0.21.1 (166 KiB: 0.40% of the 41 MiB to download)
        gettext-tools: 0.21.1 (2 MiB: 6.12% of the 41 MiB to download)
        gmake: 4.3_2 (416 KiB: 0.99% of the 41 MiB to download)
        help2man: 1.49.3 (168 KiB: 0.40% of the 41 MiB to download)
        indexinfo: 0.3.1 (6 KiB: 0.01% of the 41 MiB to download)
        libffi: 3.4.4 (42 KiB: 0.10% of the 41 MiB to download)
        libiconv: 1.17 (617 KiB: 1.48% of the 41 MiB to download)
        libtextstyle: 0.21.1 (408 KiB: 0.98% of the 41 MiB to download)
        libtool: 2.4.7_1 (361 KiB: 0.86% of the 41 MiB to download)
        lsof: 4.97.0,8 (110 KiB: 0.26% of the 41 MiB to download)
        m4: 1.4.19,1 (251 KiB: 0.60% of the 41 MiB to download)
        mpdecimal: 2.5.1 (320 KiB: 0.77% of the 41 MiB to download)
        p5-Locale-gettext: 1.07 (16 KiB: 0.04% of the 41 MiB to download)
        p5-Locale-libintl: 1.33 (700 KiB: 1.67% of the 41 MiB to download)
        p5-Text-Unidecode: 1.30 (93 KiB: 0.22% of the 41 MiB to download)
        p5-Unicode-EastAsianWidth: 12.0 (9 KiB: 0.02% of the 41 MiB to download)
        perl5: 5.32.1_3 (14 MiB: 34.80% of the 41 MiB to download)
        pkgconf: 1.8.1,1 (67 KiB: 0.16% of the 41 MiB to download)
        python39: 3.9.16_2 (18 MiB: 43.02% of the 41 MiB to download)
        readline: 8.2.1 (367 KiB: 0.88% of the 41 MiB to download)
        texinfo: 7.0.3,1 (1 MiB: 3.24% of the 41 MiB to download)

Number of packages to be fetched: 25

The process will require 41 MiB more space.
41 MiB to be downloaded.
[132amd64-custom] Fetching lsof-4.97.0,8.pkg: 100%  110 KiB 112.5kB/s    00:01
[132amd64-custom] Fetching ccache-3.7.12_4.pkg: 100%  128 KiB 131.5kB/s    00:01
[132amd64-custom] Fetching indexinfo-0.3.1.pkg: 100%    6 KiB   5.7kB/s    00:01
[132amd64-custom] Fetching p5-Text-Unidecode-1.30.pkg: 100%   93 KiB  95.7kB/s    00:01
[132amd64-custom] Fetching mpdecimal-2.5.1.pkg: 100%  320 KiB 327.7kB/s    00:01
[132amd64-custom] Fetching libtool-2.4.7_1.pkg: 100%  361 KiB 369.8kB/s    00:01
[132amd64-custom] Fetching python39-3.9.16_2.pkg: 100%   18 MiB 708.6kB/s    00:26
[132amd64-custom] Fetching m4-1.4.19,1.pkg: 100%  251 KiB 257.2kB/s    00:01
[132amd64-custom] Fetching automake-1.16.5.pkg: 100%  551 KiB 563.9kB/s    00:01
[132amd64-custom] Fetching p5-Locale-gettext-1.07.pkg: 100%   16 KiB  16.8kB/s    00:01
[132amd64-custom] Fetching perl5-5.32.1_3.pkg: 100%   14 MiB 677.4kB/s    00:22
[132amd64-custom] Fetching gmake-4.3_2.pkg: 100%  416 KiB 426.0kB/s    00:01
[132amd64-custom] Fetching libtextstyle-0.21.1.pkg: 100%  408 KiB 417.9kB/s    00:01
[132amd64-custom] Fetching p5-Unicode-EastAsianWidth-12.0.pkg: 100%    9 KiB   9.6kB/s    00:01
[132amd64-custom] Fetching libffi-3.4.4.pkg: 100%   42 KiB  42.5kB/s    00:01
[132amd64-custom] Fetching readline-8.2.1.pkg: 100%  367 KiB 375.8kB/s    00:01
[132amd64-custom] Fetching texinfo-7.0.3,1.pkg: 100%    1 MiB 462.7kB/s    00:03
[132amd64-custom] Fetching help2man-1.49.3.pkg: 100%  168 KiB 171.5kB/s    00:01
[132amd64-custom] Fetching libiconv-1.17.pkg: 100%  617 KiB 632.3kB/s    00:01
[132amd64-custom] Fetching pkgconf-1.8.1,1.pkg: 100%   67 KiB  68.4kB/s    00:01
[132amd64-custom] Fetching gettext-tools-0.21.1.pkg: 100%    2 MiB 523.8kB/s    00:05
[132amd64-custom] Fetching gettext-runtime-0.21.1.pkg: 100%  166 KiB 170.3kB/s    00:01
[132amd64-custom] Fetching autoconf-switch-20220527.pkg: 100%    1 KiB   1.3kB/s    00:01
[132amd64-custom] Fetching p5-Locale-libintl-1.33.pkg: 100%  700 KiB 358.6kB/s    00:02
[132amd64-custom] Fetching autoconf-2.71.pkg: 100%  565 KiB 578.5kB/s    00:01
[00:03:15] Package fetch: Using cached copy of autoconf-2.71
[00:03:15] Package fetch: Using cached copy of automake-1.16.5
[00:03:15] Package fetch: Using cached copy of libffi-3.4.4
[00:03:15] Package fetch: Using cached copy of libtool-2.4.7_1
[00:03:15] Package fetch: Using cached copy of ccache-3.7.12_4
[00:03:15] Package fetch: Using cached copy of lsof-4.97.0,8
[00:03:15] Package fetch: Using cached copy of gmake-4.3_2
[00:03:15] Package fetch: Using cached copy of python39-3.9.16_2
[00:03:15] Package fetch: Using cached copy of autoconf-switch-20220527
[00:03:15] Package fetch: Using cached copy of gettext-tools-0.21.1
[00:03:15] Package fetch: Using cached copy of pkgconf-1.8.1,1
[00:03:15] Package fetch: Using cached copy of indexinfo-0.3.1
[00:03:15] Package fetch: Using cached copy of gettext-runtime-0.21.1
[00:03:15] Package fetch: Using cached copy of m4-1.4.19,1
[00:03:15] Package fetch: Using cached copy of mpdecimal-2.5.1
[00:03:15] Package fetch: Using cached copy of readline-8.2.1
[00:03:15] Package fetch: Using cached copy of libiconv-1.17
[00:03:15] Package fetch: Using cached copy of perl5-5.32.1_3
[00:03:15] Package fetch: Using cached copy of help2man-1.49.3
[00:03:15] Package fetch: Using cached copy of p5-Text-Unidecode-1.30
[00:03:15] Package fetch: Using cached copy of p5-Locale-libintl-1.33
[00:03:15] Package fetch: Using cached copy of libtextstyle-0.21.1
[00:03:15] Package fetch: Using cached copy of p5-Unicode-EastAsiached packages
[00:03:20] Unqueueing existing packages
[00:03:20] Unqueueing orphaned build dependencies
[00:03:21] Sanity checking build queue
[00:03:21] Processing PRIORITY_BOOST
[00:03:21] Balancing pool
[132amd64-custom] [2023-05-18_08h53m59s] [balancing_pool:] Queued: 27 Built: 0  Failed: 0  Skipped: 0  Ignored: 0  Fetched: 25 Tobuild: 2   Time: 00:03:15
[00:03:21] Recording filesystem state for prepkg... done
[00:03:22] Building 2 packages using up to 2 builders
[00:03:22] Hit CTRL+t at any time to see build progress and stats
[00:03:22] [01] [00:00:00] Builder starting
[00:03:24] [01] [00:00:02] Builder started
[00:03:24] [01] [00:00:00] Building ports-mgmt/pkg | pkg-1.19.1_1
[00:08:35] [01] [00:05:11] Finished ports-mgmt/pkg | pkg-1.19.1_1: Success
[00:08:35] [01] [00:00:00] Building sysutils/htop | htop-3.2.2_1
[00:09:38] [01] [00:01:03] Finished sysutils/htop | htop-3.2.2_1: Success
[00:09:39] Stopping 2 builders
[00:09:40] Creating pkg repository
Creating repository in /tmp/packages: 100%
Packing files for repository: 100%
[00:09:45] Committing packages to repository: /usr/local/poudriere/data/packages/132amd64-custom/.real_1684415024 via .latest symlink
[00:09:45] Removing old packages
[00:09:45] Built ports: ports-mgmt/pkg sysutils/htop
[00:09:45] Fetched ports: devel/libtool sysutils/lsof devel/autoconf-switch devel/libffi devel/autoconf devel/automake devel/gettext-tools devel/gmake devel/ccache lang/python39 print/indexinfo devel/pkgconf devel/gettext-runtime math/mpdecimal devel/m4 devel/readline converters/libiconv misc/help2man lang/perl5.32 converters/p5-Text-Unidecode devel/p5-Locale-libintl devel/p5-Locale-gettext devel/libtextstyle textproc/p5-Unicode-EastAsianWidth print/texinfo
[132amd64-custom] [2023-05-18_08h53m59s] [committing:] Queued: 27 Built: 2  Failed: 0  Skipped: 0  Ignored: 0  Fetched: 25 Tobuild: 0   Time: 00:09:39
[00:09:45] Logs: /usr/local/poudriere/data/logs/bulk/132amd64-custom/2023-05-18_08h53m59s
[00:09:45] Cleaning up
[00:09:45] Unmounting file systems

The -j 132amd64 argument is the jail name to use which will concatenate with the -p custom to create a jail to build our repository. Of course, there are many more tasks that Poudriere will do, such as mounting the custom ports tree on the jail, but this is beyond the scope of this howto. With -b latest Poudriere will try to get the prebuild dependencies instead of building them, but this will not happen unless we have the requirements specified in poudriere-bulk(8).

The HTTP server

We are going to install a simple, minimalist but very useful web server named darkhttpd. This web server is not suitable for all situations, but for simplicity we can use it for the moment. Of course, if you prefer to use NGINX or Apache, use it.

darkhttpd.makejail:

INCLUDE gh+AppJail-makejails/darkhttpd

OPTION virtualnet=testing:darkhttpd default
OPTION nat
OPTION expose=80

MOUNT /usr/local/poudriere/data/packages /usr/local/www/darkhttpd

Instead of installing a web server on the host, we can use a Makejail to create a jail with it. With OPTION virtualnet=testing:darkhttpd default we indicate that we want to use the virtual network testing with an interface named darkhttpd and mark this virtual network as default using the default option. With OPTION nat a NAT rule will be applied. With OPTION expose=80 a port forwarding rule will be applied, so that we can expose our web server externally. The MOUNT instruction will mount the directory used by Poudriere to store repositores in the directory used by Darkhttpd.

Now, run the previous Makejail.

# appjail makejail -j darkhttpd -f darkhttpd.makejail
[00:00:00] [ info  ] [darkhttpd] Building darkhttpd ...
[00:00:07] [ warn  ] [darkhttpd] darkhttpd is not running.
[00:00:09] [ info  ] [darkhttpd] Creating a standard jail (thin) ...
[00:00:11] [ info  ] [darkhttpd] Creating a thinjail ...
[00:00:14] [ info  ] [darkhttpd] Done.
[00:00:19] [ info  ] [darkhttpd] Starting darkhttpd...
testing
ea_darkhttpd
eb_darkhttpd
darkhttpd: created
add net default: gateway 10.42.0.1
defaultrouter: NO -> 10.42.0.1
Updating FreeBSD repository catalogue...
[darkhttpd.appjail] Fetching meta.conf: 100%    163 B   0.2kB/s    00:01
[darkhttpd.appjail] Fetching packagesite.pkg: 100%    7 MiB 573.0kB/s    00:12
Processing entries: 100%
FreeBSD repository update completed. 32882 packages processed.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        darkhttpd: 1.14

Number of packages to be installed: 1

19 KiB to be downloaded.
[darkhttpd.appjail] [1/1] Fetching darkhttpd-1.14.pkg: 100%   19 KiB  19.5kB/s    00:01
Checking integrity... done (0 conflicting)
[darkhttpd.appjail] [1/1] Installing darkhttpd-1.14...
===> Creating groups.
Creating group 'darkhttpd' with gid '688'.
===> Creating users
Creating user 'darkhttpd' with uid '688'.
[darkhttpd.appjail] [1/1] Extracting darkhttpd-1.14: 100%
darkhttpd_enable:  -> YES
Starting darkhttpd.
darkhttpd/1.14, copyright (c) 2003-2022 Emil Mikulic.
listening on: http://0.0.0.0:80/
set gid to 688
set uid to 688
# appjail fstab jail darkhttpd
NRO  ENABLED  NAME  DEVICE                              MOUNTPOINT                TYPE    OPTIONS  DUMP  PASS
0    1        -     /usr/local/poudriere/data/packages  /usr/local/www/darkhttpd  nullfs  rw       0     0
# appjail expose list darkhttpd
NRO  ENABLED  NAME  PORTS  PROTOCOL  NETWORK_NAME
0    1        -     80     tcp       testing

Profit!

We have finished all the requirements, so we can create the jail with our custom sysutils/htop.

Makejail:

OPTION virtualnet=testing:htop default
OPTION nat
OPTION start
OPTION overwrite
OPTION copydir=files
OPTION file=/usr/local/etc/pkg/repos/Custom.conf

PKG htop

We have used practically the same networking options as in the HTTP server. The new ones: OPTION overwrite to overwrite the jail if it exists, OPTION start to start the jail after its creation, OPTION copydir=files, which are in the same path as the Makejail, we indicate that the files directory will be used as copy directory which should mimic the root directory of the file system, and OPTION file=/usr/local/etc/pkg/repos/Custom.conf is the pkg(8) configuration file to use our custom repository.

files/usr/local/etc/pkg/repos/Custom.conf:

custom {
        url: "http://192.168.1.105/132amd64-custom",
        priority: 1
}

custom is the name of the repository. url is where packages are located. And priority is the priority of this repository. A repository with a higher priority has more preference than others with a lower priority.

The tree in the files directory is as follows:

# tree -pug
[drwxr-xr-x dtxdf-fbsd wheel   ]  .
├── [-rw-r--r-- root     wheel   ]  Makejail
└── [drwxr-xr-x root     wheel   ]  files
    └── [drwxr-xr-x root     wheel   ]  usr
        └── [drwxr-xr-x root     wheel   ]  local
            └── [drwxr-xr-x root     wheel   ]  etc
                └── [drwxr-xr-x root     wheel   ]  pkg
                    └── [drwxr-xr-x root     wheel   ]  repos
                        └── [-rw-r--r-- root     wheel   ]  Custom.conf

7 directories, 2 files

With a single command we install our custom port.

# appjail makejail -j htop
[00:00:00] [ info  ] [htop] Building htop ...
[00:00:05] [ warn  ] [htop] htop is not running.
[00:00:08] [ info  ] [htop] Creating a standard jail (thin) ...
[00:00:08] [ info  ] [htop] Creating a thinjail ...
[00:00:15] [ info  ] [htop] Done.
[00:00:21] [ info  ] [htop] Starting htop...
ea_htop
eb_htop
htop: created
add net default: gateway 10.42.0.1
defaultrouter: NO -> 10.42.0.1
Updating FreeBSD repository catalogue...
[htop.appjail] Fetching meta.conf: 100%    163 B   0.2kB/s    00:01
[htop.appjail] Fetching packagesite.pkg: 100%    7 MiB 491.2kB/s    00:14
Processing entries: 100%
FreeBSD repository update completed. 32882 packages processed.
Updating custom repository catalogue...
[htop.appjail] Fetching meta.conf: 100%    163 B   0.2kB/s    00:01
[htop.appjail] Fetching packagesite.pkg: 100%    9 KiB   9.5kB/s    00:01
Processing entries:  38%
Processing entries: 100%
custom repository update completed. 27 packages processed.
All repositories are up to date.
The following 2 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        htop: 3.2.2_1 [custom]
        lsof: 4.97.0,8 [custom]

Number of packages to be installed: 2

206 KiB to be downloaded.
[htop.appjail] [1/2] Fetching lsof-4.97.0,8.pkg: 100%  110 KiB 112.5kB/s    00:01
[htop.appjail] [2/2] Fetching htop-3.2.2_1.pkg: 100%   96 KiB  98.4kB/s    00:01
Checking integrity... done (0 conflicting)
[htop.appjail] [1/2] Installing lsof-4.97.0,8...
[htop.appjail] [1/2] Extracting lsof-4.97.0,8: 100%
[htop.appjail] [2/2] Installing htop-3.2.2_1...
[htop.appjail] [2/2] Extracting htop-3.2.2_1: 100%
=====
Message from lsof-4.97.0,8:

--
NOTE: Due to the way the FreeBSD build clusters make packages,
you may see a warning similar to the following:

lsof: WARNING: compiled for FreeBSD release 11.1-RELEASE-p6; this is 11.1-RELEASE-p4.

This is because the poudriere jails that build the packages don't have the
corresponding kernel installed, so they don't know that the kernel version is different.

This warning can be ignored if you are using a system that is updated via freebsd-update
and are using pre-built packages.
# appjail cmd jexec htop htop
    0[|                                                                       0.4%] Tasks: 5, 0 thr, 0 kthr; 1 running
    1[|                                                                       0.8%] Load average: 0.41 0.34 0.34
  Mem[|||||||||||||||||||||||||||||||||||||||||||||||||||||||            417M/977M] Uptime: 03:34:34
  Swp[|                                                                4.41M/2.00G]

  [Main]
  PID USER       PRI  NI  VIRT   RES S  CPU%▽MEM%   TIME+  Command
54504 root        23   0 16552  4416 R   0.6  0.4  0:00.04 htop
14627 root        20   0 18132  6804 S   0.0  0.7  0:00.04 sendmail: accepting connections
16595 smmsp       52   0 18132  6432 S   0.0  0.6  0:00.00 sendmail: Queue runner@00:30:00 for /var/spool/clientmqueue
18487 root        20   0 12940  2544 S   0.0  0.3  0:00.01 /usr/sbin/cron -s
85030 root        20   0 12896  2680 S   0.0  0.3  0:00.01 /usr/sbin/syslogd -s

F1|Help  F2|Setup F3|Search F4|Filter F5|Tree F6|SortBy F7|Nice -F8|Nice +F9|Kill  F10|Quit

htop:

After pressing the l key:

0