# Service Documentation

Task-oriented recipes. Each section assumes you already have `splam` installed and running. See the [Tutorial](tutorial-getting-started.md) if not.

Every `systemd` unit file can name its own documentation in a `Documentation=` line, and most packaged units do. The **Doc** tab reads that line for the selected service and prints what it points at, so the upstream manual is one tab away from the status output you are trying to interpret.


# Read a service's own documentation

Select a service in the sidebar and open **Doc**. You get two things:

1.  The `Documentation=` references the unit file declares, listed exactly as they are written.
2.  The man pages those references name, rendered as plain text.

For `cron.service` on Ubuntu, that is one reference, `man:cron(8)`, followed by the whole of `cron(8)`. Nothing is fetched over the network and nothing is cached: the tab shells out each time you land on it, so it always reflects the unit file currently on disk.

Man hard-wraps its output to a fixed number of columns rather than leaving the browser to reflow it, so the tab measures itself and asks for a width that fits, between 60 and 220 columns. Widen the window and the page is re-rendered wider; make it narrow and the lines shorten rather than scrolling sideways.

Both roles see this tab. Reading a manual changes nothing, so `auditor` accounts get it on the same terms as `admin`, like **Status**, **Tasks**, **Logs**, and **Audit Trail**.


# Understand the reference types

`Documentation=` takes a space-separated list of URIs, in the maintainer's order of relevance, and a unit may mix schemes. Only `man:` entries are rendered as text; the rest are named and left for you to follow:

| Scheme | Example | What the tab does |
|----|----|----|
| `man:` | `man:cron(8)` | Renders the whole page inline. Several `man:` entries render one after another |
| `https:` or `http:` | `https://gitlab.com/apparmor/apparmor/wikis/home/` | Lists it as a clickable link, and repeats it under `Additional documentation:` |
| `info:` | `info:coreutils` | Lists it. Reading it means running `info coreutils` yourself |
| `file:` | `file:/usr/share/doc/foo/README` | Lists the path, does not read the file |

`systemd-journald.service` shows the first row doing its job: two `man:` entries, so the tab prints `systemd-journald.service(8)` and `journald.conf(5)` in full, around 700 lines. `apparmor.service` shows a mixed list, one man page plus a wiki URL.


# When there is nothing to show

Plenty of units declare no documentation at all. The tab says so:

``` verbatim
Documentation for accounts-daemon.service not known.
```

That is systemd reporting an empty `Documentation=`, not an error in `splam`. Three things to try, in order:

1.  Read the unit file itself with `systemctl cat accounts-daemon.service`. The `ExecStart=` line names the binary, and the binary usually has a man page of its own even when the unit doesn't name it.

2.  Check the package: `dpkg -S $(which accounts-daemon)` then `dpkg -L <package> | grep man`.

3.  Write your own notes for it on the **Tasks** tab, which is what that tab is for. See [How-To: Admin-Task Notes](01.04-how-to-admin-task-notes.md).


# Add documentation to a unit you own

For units your site ships, put the reference in the unit file:

``` ini
[Unit]
Description=Nightly LIMS export
Documentation=man:lims-export(1) https://wiki.example.org/lims/export
```

For a packaged unit you don't want to edit, use a drop-in so the change survives a package upgrade:

``` bash
sudo systemctl edit my-service.service
```

That opens an empty drop-in at `/etc/systemd/system/my-service.service.d/override.conf`. Add the `[Unit]` section above, save, then:

``` bash
sudo systemctl daemon-reload
```

The **Doc** tab picks it up on the next render. A drop-in `Documentation=` appends to whatever the packaged unit already declared; to replace the list instead, set `Documentation=` to an empty value on its own line first.


# Tell it apart from the Tasks tab

Both tabs describe the same service and they answer different questions:

|  | **Doc** | **Tasks** |
|----|----|----|
| Written by | The package maintainer, upstream | Your administrators |
| Source | `Documentation=` in the unit file | `SERVICE_INFO` and `service_info_overrides.json` |
| Changes when | You upgrade the package | Someone clicks **Configure** |
| Answers | What this service is and what its options mean | What we check here, what breaks here, what compliance expects |

On a regulated host the second column is the one an auditor will ask about, because it records local decisions. The first is reference material that arrived with the package. See [Explanation: Config Overrides](02.05-explanation-config-overrides.md) for where each is stored.


# Do it from a terminal instead

The tab runs the same commands you would:

``` bash
systemctl show --property=Documentation --value cron.service
systemctl help cron.service
```

The first prints the raw references, the second renders them. The app changes two things about the second, both in the environment it runs man in: the pager is forced to `cat`, since there is no terminal for a pager to draw on, and `MANWIDTH` is set from the width of the tab. To read the tab's exact output in a terminal, set both yourself:

``` bash
PAGER=cat MANWIDTH=120 systemctl help cron.service
```

`systemctl cat cron.service` is the companion worth knowing: it prints the unit file itself, drop-ins included, which is how you confirm a `Documentation=` line landed where you meant it to.


# Further reading

- [systemd.unit(5)](https://www.man7.org/linux/man-pages/man5/systemd.unit.5.html), which defines `Documentation=` and the unit search path the **Service** dropdown is built from

- [systemctl(1)](https://www.man7.org/linux/man-pages/man1/systemctl.1.html), for `help`, `show`, and `cat`
