Options¶
Everything below is under gewis.servicePc, defined in
nix/modules/service-pc/.
Session¶
| Option | Default | Meaning |
|---|---|---|
enable |
false |
Turn the whole thing on |
user |
"gewis" |
Unprivileged user the session and its applications run as. The module creates it |
uid |
null |
Fixed uid, also used as the primary group's gid. Pin it where state outlives reinstalls |
workspaces |
1 |
Number of static workspaces |
multiMonitor |
false |
This host has more than one screen; enables per-monitor placement |
justPerfection |
false |
Load the Just Perfection extension |
shutdownAt |
"23:00" |
Daily power-off time, as a systemd calendar expression; null keeps the host running |
Touch¶
| Option | Default | Meaning |
|---|---|---|
touch.enable |
false |
This host is a touchscreen with no keyboard or mouse; enables the on-screen keyboard |
touch.vendorId |
"0eef" |
USB vendor ID of the panel, from lsusb |
touch.productId |
"0001" |
USB product ID of the panel, from lsusb |
See Touchscreens and workspaces.
Browsers¶
browsers is an attribute set; the name is the attribute key. The browser is
always Firefox. The policy file below is Firefox's and the launcher sets
MOZ_ENABLE_WAYLAND. Firefox force-installs uBlock Origin in every instance
through the ExtensionSettings policy, so ad blocking is on even though the
browsers are started straight onto a URL and never opened interactively.
| Option | Default | Meaning |
|---|---|---|
browsers.<name>.url |
null |
URL to open. Exactly one of this or urlFile |
browsers.<name>.urlFile |
null |
File read at launch, for when the URL is itself a secret |
browsers.<name>.kiosk |
false |
Fullscreen once the window appears, by sending F11 until it takes |
browsers.<name>.waitForUrl |
true |
Poll the URL before starting, so a fast-booting PC does not land on an error page |
browsers.<name>.waitTimeout |
120 |
Seconds to poll before starting anyway; 0 waits forever |
Each browser is a separate Firefox instance with its own profile at
~/.mozilla/firefox/service-pc-<name>, created on first start, and runs with
--new-instance so it
never hands its URL to another one and exits. Its window reports
firefox-<name> as its class, which is how the placement helper tells the
instances apart. A host that wants two pages on two screens names two browsers
and gives each a monitor:
multiMonitor = true;
browsers = {
pos = {
url = "https://sudosos.gewis.nl/pos";
monitor = 1;
kiosk = true;
};
dashboard = {
url = "https://grafana.gewis.nl/d/bar";
monitor = 2;
};
};
A browser is restarted whenever it exits, whatever the reason, so closing it over RDP just brings it back.
kiosk waits for the browser's window, raises it, and sends F11 through
ydotool, repeating the press until GNOME reports the window as fullscreen.
Firefox keeps only a fullscreen state it entered itself, and F11 is a toggle,
so each press is checked. Once fullscreen, it keeps sending a bare Shift
every couple of seconds for about a minute: Firefox leaves its toolbar showing
when F11 arrives while the address bar still has focus, which it does until
the page first paints, and only hides it on the next key press. A host with no
keyboard or mouse would otherwise show the toolbar until someone connects over
RDP. The window is long because $HOME does not survive a reboot, so every
boot is Firefox's first run on a new profile and the first paint is slow.
When it does not go fullscreen¶
kiosk runs as an ExecStartPost of the service-pc-browser-<name> user
unit, so everything it says is in that unit's journal. It is a user unit, so
ask for it by that name rather than with --user, which would look at root's
own manager:
The helper always logs why it gave up, and the four messages mean different things:
org.gnome.Shell.Extensions.Windows never answered— the window-calls extension is not running, so nothing here can work. It is pulled in automatically bykioskand byworkspace/monitor, but GNOME disables an extension that does not declare support for the running shell version. Check withgnome-extensions list --enabledin the session, and look forJS ERRORin the shell's own log:sudo journalctl -b _COMM=gnome-shell.no window with wm_class 'firefox-<name>' … saw: …— the extension answered, but nothing it listed matched. Thesaw:list is the set of classes Mutter actually reports; if Firefox is in there under another name, that name is what the helper should be matching on.ydotool failed: …— the keystroke never left the tool, and the message is ydotool's own. Almost alwaysydotooldnot running or its socket not readable; see the NFC page, which uses the same daemon.… is still not fullscreen after N F11 presses— the keystrokes went out and the window still is not fullscreen. The line after it dumps what GNOME reports for that window, so compare itswidth/heightagainst the monitor.
Applications¶
apps is an attribute set; the name is the attribute key. The session exports
NIXOS_OZONE_WL=1, so Chromium and Electron apps run natively on Wayland
instead of Xwayland, whether started by the module or from the app grid.
| Option | Default | Meaning |
|---|---|---|
apps.<name>.package |
required | Package providing the application |
apps.<name>.exec |
null |
Command to run; defaults to the package's meta.mainProgram |
apps.<name>.wmClass |
<name> |
Window class the placement helper matches on |
Placement¶
Each browser and each app takes these:
| Option | Default | Meaning |
|---|---|---|
workspace |
null |
One-based workspace to move the window to |
monitor |
null |
One-based logical monitor to move it to, and maximise it there |
A window is placed on one or the other, never both, and monitor requires
multiMonitor. Leaving both null lets GNOME put the window wherever it likes.
A window that is placed is also maximised, so it fills the screen it landed on.
NFC reader¶
| Option | Default | Meaning |
|---|---|---|
nfcReader.enable |
false |
Run the background NFC reader |
nfcReader.vendorId |
"072f" |
USB vendor ID, from lsusb |
nfcReader.productId |
"2200" |
USB product ID, from lsusb |
See NFC reader.
Remote access¶
| Option | Default | Meaning |
|---|---|---|
remote.enable |
false |
Remote control of the live session over RDP |
remote.port |
3389 |
Port the RDP server listens on |
remote.username |
null |
Username clients authenticate with; defaults to user |
remote.passwordFile |
required when enabled | File holding the password, readable by user |
remote.openFirewall |
false |
Open the port on every interface |
remote.firewallInterfaces |
[ ] |
Interfaces to open the port on |
See Remote access.