How to embed man in a strictly confined snap and have it invoked to display a custom man page

This topic is not about allowing snaps to publish their man pages on the host system, there’s another thread for this.

This is probably not a very common use case, but I figured I would document it in case other snaps need to do something similar: the upstream code for the chromium browser, when invoked with -h or --help, executes man chromium. This makes sense because the source for the man page is maintained upstream.

To make this work in a strictly confined snap without patching the upstream code, man-db and related packages have to be staged, a layout is required, and a few environment variables have to be set.

You can check out the relevant commit for the chromium snap, and I’m detailing the relevant changes here:

>>> snapcraft.yaml
[…]
layout:
  /usr/lib/man-db:
    bind: $SNAP/usr/lib/man-db
[…]
parts:
  manpage:
    plugin: nil
    stage-packages:
      - groff-base
      - libgdbm5
      - libpipeline1
      - man-db
[…]

The layout is needed for man to locate libman.so and libmandb.so, and the zsoelim executable.
The manpage part stages the packages that contain those, the man executable, and their minimal dependencies.

>>> launcher script
export MAN_TEST_DISABLE_SYSTEM_CONFIG=1
export MANPATH=$SNAP
export GROFF_FONT_PATH=$SNAP/usr/share/groff/current/font
export GROFF_TMAC_PATH=$SNAP/usr/share/groff/current/tmac

The MAN_TEST_DISABLE_SYSTEM_CONFIG environment variable is needed to have man ignore the absence of a manpath configuration file (/etc/manpath.config). An alternative solution would probably be to define another layout for this file (not tested).

MANPATH has to be set to a directory inside the snap that contains a man1 subdirectory, which itself contains the man page(s).

GROFF_FONT_PATH and GROFF_TMAC_PATH are required by nroff to find fonts and macro files.

And with that, invoking man something from inside your snap should work, provided it ships a man page for “something”.

2 Likes

you can now set these types of environment variables through the snapcraft.yaml directly, see:

apps:
  my-app:
    command: bin/do-something
    environment:
      VAR1: "1"
      VAR2: "something else"