Files
mesh-catalog/modules/forticlient
jochen d0d5546088 Give the remaining tray applets their modules, each with one start
openrazer (the official driver, daemon and library), polychromatic (the
AUR tray, kept as found; its i3 line moves out of the i3 module into its
own node-display-session contribution), forticlient (the AUR VPN client:
its service declared, its configuration never read) and nm-applet (the
desktop half of NetworkManager, apart from the server-side module).

The openrazer daemon fails on both workstations because the account is
not in the openrazer group; openrazer_check names it and the README
carries the one-off step, since the account's user resource is zsh's.

desktop.go learns to tell a program from another sharing its 15-character
command name, so polychromatic's tools never count or end themselves, and
a copies test holds the six carriers to one text.
2026-10-05 15:10:30 +02:00
..

forticlient

The FortiClient VPN client on the workstations, as a module (novox/hq ADR 0208): its tray in the operator's session and the vendor's service behind it. It requires x11-display, so it is assigned only where a display server is held on the same machine.

This is the operator's work VPN. Nothing of its configuration is the mesh's: no profile, no credential, no gateway, no certificate is declared, read, printed or stored by the module or its tools. The tools report running and connected state only.

Owns

what where
the vendor's scheduler service, which holds the tunnel forticlient.service, running and enabled

Nothing else. It holds no seat, makes no contribution and writes no file.

  • The client is kept as found. forticlient-vpn (7.4.3) is not in the official repositories: on both workstations it is a foreign (AUR) package that repackages the vendor's build, installed explicitly. The host installs from the official repositories only, so the module cannot declare it. ADR 0205's pinned archive does not fit: it is a vendor binary set with a root service, a firewall helper and an install script. It waits for the mesh's package repository (research 027 question 1, option P2). Until then a fresh workstation installs it by hand.
  • The service is declared, and so depended on. forticlient.service is the package's unit, running and enabled on both workstations. Declared running and enabled, it is held in that state, and on a machine without the package the host refuses it by name (does not exist on this machine): loud, never a silent pass. The asus-zephyrus-g14 module does the same with its foreign daemons. The module never restarts it: a change to nothing of the module's would, and nothing of the module's changes.
  • The configuration stays the operator's, and unread. /etc/forticlient/, the client's database under /opt/forticlient/, the account's FortiClient settings, the VPN profiles, saved credentials and certificates are set in the client's own window. They are found (ADR 0182), and unlike any other found file, the tools do not even read them.

How it starts: the vendor's autostart entry, and nothing else

The tray has two processes: fortitraylauncher, which starts and watches fortitray. The package's install script links /etc/xdg/autostart/Fortitray.desktop to the package's /opt/forticlient/Fortitray.desktop (Exec=/opt/forticlient/fortitraylauncher). The session runs it once at login through the i3 module's dex --autostart --environment i3. That entry is the tray's one start. The module adds no xinitrc slot and no node-display-session exec, because either would start it a second time. The link is the vendor's, made by its install script; the mesh does not make or remove it.

The tunnel is not the tray's: the service's processes hold it, as root. Ending the tray leaves a connected tunnel connected.

Tools

They are served by the node's runtime as the operator account (ADR 0175).

tool does
forticlient_status (r)
  • the installed version, and that it is from outside the official repositories
  • the service: active, enabled
  • whether the launcher and the tray run: pid, since, and the scope or unit they run in
  • what starts the tray at login
  • connected or not, as the number of the client's tunnel interfaces that are up
forticlient_restart (a) asks the tray and its launcher to end (SIGTERM), forces them after 5 s, and starts the launcher in the operator's session as a transient user unit mesh-forticlient-tray, so it outlives the tools runtime. The launcher starts the tray. The service and the tunnel are not touched. Refused plainly when nobody is logged in to the desktop
forticlient_check (r)
  • the package is installed
  • the service is running and enabled
  • exactly one start: the vendor's entry is present and not hidden by an entry of the account, and dex is installed
  • no window-manager exec
  • one launcher and one tray run in a desktop session
Being connected is never a finding: that is the operator's to decide. Each finding says what to do

What the tools never touch, held by the tests (a fake machine carries a profile, a gateway, an address, a secret and a certificate where the client keeps them, and no answer may hold any of them):

  • no file under /etc/forticlient or the account's FortiClient settings is opened, and under /opt/forticlient only the tray's autostart entry, through its link (it names the launcher and nothing else);
  • the vendor's command-line client and fortivpn are never run, and its logs are never read;
  • a process is named by its command name only, never by its arguments;
  • connected is whether an interface named fctvpn… is up, from its flags. The interface's name (it carries an identifier) and its addresses are never answered. A tunnel of a kind that brings up no such interface (IPsec) is not seen, and the answer says not connected.

What changes when it is assigned

laptop desktop
package none: forticlient-vpn 7.4.3.5411, explicit, foreign the same
service none: running and enabled the same
tray none: dex starts it from the vendor's entry, in the login session's scope none on disk. No tray runs now: that session began before dex was installed, and the predecessor's window manager never started it. The next login is the first that starts it

Migration (ADR 0182)

Nothing is required on either machine. On the desktop, log out and in once, or run forticlient_restart, and the tray runs from its one start. forticlient_check then answers ok.

Leaves as found

Everything of the client's: its configuration and database, the VPN profiles and credentials, its logs, /etc/xdg/autostart/Fortitray.desktop (the vendor's link), the package itself.

Relies on

  • The package, installed by hand. Without it the host refuses the service by name.
  • i3's dex line for the start: XDG autostart has no seat. Assigned without i3, the tray does not start. forticlient_check says so.
  • A display server on the same machine (x11-display, ADR 0208 §3).