PCs sind seit geraumer Zeit so schnell, dass sie sich die meiste Zeit mit Nichtstun beschäftigen können. Es ist daher naheliegend, einen einzigen Computer für mehrere Benutzer an mehreren Arbeitsplätzen zu verwenden, mit je einer Tastatur, Bildschirm und Maus. So spart man außerdem Geld, Zeit, Platz und Nerven. Und man lernt was.
Was braucht’s?
Der PC braucht pro Arbeitsplatz eine eigene Grafikkarte, und natürlich jeweils Monitor, Tastatur und Maus. Ich gehe unten mal von zwei Arbeitsplätzen aus. Im Rechner stecken also zwei Grafikkarten, und es sind zwei Tastaturen und zwei Mäuse angesteckt.
Wie funktioniert’s?
Jede Grafikkarte wird fest einem Arbeitsplatz („seat“) zugeordnet, genauso die Tastaturen und Mäuse. Die Soundkarte wird gemeinsam genutzt: Die Benutzer können sich so gegenseitig die Lautstärke verstellen, was je nach Charakter Vor- und Nachteil sein kann. USB-Geräte werden ebenfalls gemeinsam verwendet: USB-Sticks können von allen benutzt werden. Ebenso DVD-Brenner, Drucker usw.
Grundsätzlich kann man auch mehrere Soundkarten einsetzen und alle USB-Ports ganz streng Benutzern zuordnen. Ich gehe hier jedoch von einem Heimbüro aus, in dem Bequemlichkeit wichtig ist und sich die Nutzer nicht absichtlich auf die Nerven gehen wollen.
Los geht’s!
Soundkarte gemeinsam nutzen
Normalerweise startet systemd für jeden Benutzer, der sich am Rechner anmeldet, eine eigene Pulseaudio-Instanz. Der zuletzt angemeldete Nutzer bekommt die Soundkarte zugeteilt. Da bei Multiseat aber mehrerer Nutzer gleichzeitig angemeldet sind kann das so nicht funktionieren.
Man könnte nun für jeden Benutzer eine eigene Soundkarte kaufen, aber das ist unnötig.
Die Lösung: Nur eine einzige, systemweite Pulseaudio-Instanz für alle Benutzer verwenden.
- Zuerst das Starten der User-Instanzen abschalten:
systemctl --global --now mask pulseaudio.service systemctl --global --now mask pulseaudio.socket
- Einen neuen systemd-Service für Pulseaudio erstellen. Dazu folgende Datei „/etc/systemd/system/pulseaudio.service“ anlegen:
Description=PulseAudio Sound System After=dbus.service avahi-daemon.service network-online.target [Service] Type=notify ExecStart=/usr/bin/pulseaudio --system --daemonize=no --disallow-module-loading=0 --disallow-exit --log-target=journal Restart=always [Install] WantedBy=multi-user.target sound.target
- Den neuen Pulseaudio-Service aktivieren:
systemctl daemon-reload; systemctl --now enable pulseaudio.service
- Damit die Benutzern den neuen systemweiten Pulseaudio-Service nutzen dürfen, müssen sie Mitglied in der Gruppe „pulse-access“ sein. Hinzufügen eines einzelnen Benutzers geht so:
adduser <username> pulse-access
Wichtig zu wissen: Im systemweiten Modus – also ab jetzt – verwendet Pulseaudio nicht mehr die Konfigurationsdatei /etc/pulse/default.pa
sondern /etc/pulse/system.pa
.
Grafikkarte, Tastatur und Maus den Arbeitsplätzen zuordnen
Ein normales Linux-System kennt bereits das Konzept mehrerer Arbeitsplätze pro Rechner – standardmäßig werden schlicht sämtliche Geräte dem Arbeitsplatz „seat0“ zugewiesen: Stecken zwei Mäuse am Rechner, steuern beide den gleichen Mauszeiger.
# loginctl list-seats SEAT seat0
Die dem seat0 zugeteilten Geräte – und das sind zur Zeit noch alle – kann man mit loginctl seat-status seat0
anzeigen lassen:
seat0 Devices: ├─/sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input6 │ input:input6 "Power Button" ├─/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input5 │ input:input5 "Power Button" [...] ├─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/drm/card0 │ [MASTER] drm:card0 │ ├─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/drm/card0/card0-DP-1 │ │ [MASTER] drm:card0-DP-1 │ ├─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/drm/card0/card0-DVI-D-1 │ │ [MASTER] drm:card0-DVI-D-1 │ └─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/drm/card0/card0-HDMI-A-1 │ [MASTER] drm:card0-HDMI-A-1 ├─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/drm/renderD128 │ drm:renderD128 ├─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/graphics/fb0 │ [MASTER] graphics:fb0 "amdgpudrmfb" ├─/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.1/sound/card0 [...] ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/card1 │ [MASTER] drm:card1 │ ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/card1/card1-DP-2 │ │ [MASTER] drm:card1-DP-2 │ ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/card1/card1-DP-3 │ │ [MASTER] drm:card1-DP-3 │ ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/card1/card1-DVI-D-2 │ │ [MASTER] drm:card1-DVI-D-2 │ ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/card1/card1-HDMI-A-2 │ │ [MASTER] drm:card1-HDMI-A-2 │ └─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/card1/card1-HDMI-A-3 │ [MASTER] drm:card1-HDMI-A-3 ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/drm/renderD129 │ drm:renderD129 ├─/sys/devices/pci0000:00/0000:00:03.2/0000:09:00.0/graphics/fb1 │ [MASTER] graphics:fb1 "amdgpudrmfb" [...] ├─/sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5 │ usb:usb5 │ └─/sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5/5-2 │ usb:5-2 │ ├─/sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5/5-2/5-2.1/5-2.1:1.0/0003:0557:2213.0002/input/input1 │ │ input:input1 "ATEN Advance Tech Inc. KVM V1.2.116" │ └─/sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5/5-2/5-2.1/5-2.1:1.1/0003:0557:2213.0004/input/input3 │ input:input3 "ATEN Advance Tech Inc. KVM V1.2.116" └─/sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb6 usb:usb6 [...]
Man muss also nur die Geräte, die dem zweiten Arbeitsplatz gehören sollen, einem anderen Seat, z.B. „seat-anna“, zuteilen. Das sollte eine Grafikkarte (endet mit …/drm/cardN) sein:
loginctl attach seat-anna /sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/drm/card0
Und Annas Tastatur und Maus:
loginctl attach seat-anna /sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5/5-2/5-2.1/5-2.1:1.0/0003:0557:2213.0002/input/input1
loginctl attach seat-anna /sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5/5-2/5-2.1/5-2.1:1.1/0003:0557:2213.0004/input/input3
Wenn man will kann man auch ganze USB-Hubs einem Benutzer zuteilen. Alles, was daran angeschlossen wird, gehört dann ausschließlich diesem Benutzer. Da Annas Eingabegeräte beide an „usb5“ hängen würde statt der obigen zwei Befehle auch das hier funktionieren:
loginctl attach seat-anna /sys/devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5
loginctl baut udev-Regeln und speichert diese unter „/etc/udev/rules.d/<irgendeineNummer>-seat-<device>.rules“. Der Name des Seats wird als Tag zu den Geräten hinzugefügt. Mit loginctl flush-devices
könnte man sämtliche Zuordnungen wieder aufheben.
Display-Manager konfigurieren
Nach einigem Ausprobieren hat sich lightdm als der am besten geeignete Display Manager herausgestellt. Mit sddm, dem Standard-Display Manager von KDE/Plasma, ging Multiseat dagegen gar nicht.
Bei lightdm müssen für jeden Seat lediglich ein paar Zeilen am Ende der „/etc/lightdm/lightdm.conf“ hinzugefügt werden:
[Seat:seat0] xserver-command=/usr/lib/xorg/Xorg [Seat:seat-anna] xserver-command=/usr/lib/xorg/Xorg xserver-share=true
Laut „Quelle: Internet“ sollte bei allen Seats außer „seat0“ „xserver-share=true“ stehen.
Damit ist das Gröbste erledigt, das Anmelden sollte jetzt an beiden Arbeitsplätzen gelingen.
Feinschliff
USB-Geräte für alle
Damit angestöpselte USB-Geräte, wie z.B. USB-Sticks, Headsets oder Bluetooth-Dongles, von allen Arbeitsplätzen aus verwendet werden können (sofern der angemeldete Benutzer Mitglied der Gruppe „plugdev“ ist) folgende Datei anlegen:
Bis inklusive Debian 11: „/etc/polkit-1/localauthority/50-local.d/20-org.freedesktop.udisks2.pkla“:
[Storage Permissions] Identity=unix-group:plugdev Action=org.freedesktop.udisks2.*;org.blueman.*;org.freedesktop.pulseaudio;org.gtk.vfs.file-operations ResultAny=yes ResultInactive=yes ResultActive=yes
Ab Debian 12: „/etc/polkit-1/rules.d/20-org.freedesktop.udisks2.conf“:
polkit.addRule(function(action, subject) {
if ((action.startsWith("org.freedesktop.udisks2.") ||
action.startsWith("org.blueman.") ||
action.id == "org.freedesktop.pulseaudio" ||
action.id == "org.gtk.vfs.file-operations") &&
subject.isInGroup("plugdev"))
{
return polkit.Result.YES;
}
});
USB-Geräte einzelnen Seats zuweisen
Andere USB-Geräte (z.B. Gamepads) sollen dagegen nur an einem bestimmten Arbeitsplatz funktionieren. Dazu mit lsusb
die ID die Geräts herausfinden:
[...] Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 005 Device 004: ID 054c:09cc Sony Corp. DualShock 4 [CUH-ZCT2x] Bus 005 Device 003: ID 046a:0011 Cherry GmbH G83 (RS 6000) Keyboard [...]
Der DualShock4-Controller hat die Vendor-ID 054c und die Product-ID 09cc. Soll dieser dem „seat-anna“ zugeordnet werden, eine Datei „/etc/udev/rules.d/99-dualshock4-für-seat-anna.rules“ anlegen mit diesem Inhalt:
TAG=="seat", SUBSYSTEM=="usb", ATTR{idVendor}=="054c", ATTR{idProduct}=="09cc", ENV{ID_SEAT}="seat-anna"
Anschließend die Regel aktivieren mit:
udevadm control --reload-rules udevadm trigger
Achtung: Da hier nur nach Hersteller („idVendor“) und Produkt („idProduct“) separiert wird, werden so ALLE DualShock4-Controller stets dem „seat-anna“ zugewiesen! Sollen DualShock4-Controller an mehreren Seats verwendeten werden, dann muss man, wie oben mit Tastatur und Maus, USB-Ports den Seats zuweisen und die Controller immer in diesen Port anstecken.
Rechner herunterfahren
Soll der Rechner von allen Arbeitsplätzen aus (und nicht nur von seat0 aus) heruntergefahren werden können (sofern der angemeldete Benutzer Mitglied der Gruppe „powerdev“ ist):
Bis inklusive Debian 11: „/etc/polkit-1/localauthority/50-local.d/10-org.freedesktop.upower.pkla“:
[Suspend/hibernate permissions] Identity=unix-group:powerdev Action=org.freedesktop.upower.* ResultAny=yes ResultInactive=yes ResultActive=yes
Ab Debian 12: „/etc/polkit-1/rules.d/50-org.freedesktop.upower.conf“:
polkit.addRule(function(action, subject) {
if (action.startsWith("org.freedesktop.upower.") &&
subject.isInGroup("powerdev"))
{
return polkit.Result.YES;
}
});
Bluetooth und Audio
Da, abweichend vom Standard, Pulseaudio als systemweite Instanz läuft und nicht jeweils eine für jeden angemeldeten Benutzer, müssen einige Kleinigkeiten angepasst werden damit Audio über Bluetooth funktioniert:
Der User „pulse“ muss Mitglied der Gruppe „bluetooth“ werden:
adduser pulse bluetooth
Dann „/etc/dbus-1/system.d/pulseaudio-system.conf“ mit folgendem Inhalt anlegen:
<?xml version="1.0"?><!--*-nxml-*--> <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <policy user="pulse"> <allow own="org.pulseaudio.Server"/> <allow send_destination="org.pulseaudio.Server"/> <allow receive_sender="org.pulseaudio.Server"/> <allow send_destination="org.ofono"/> </policy>
Anschließend Dbus seine Konfigurationsdateien mit systemctl reload dbus
neu einlesen lassen.
Jetzt Pulseaudio das Nachladen von Modulen – in diesem Fall speziell das bluetooth-device-Modul, das für jedes Bluetooth-Gerät nachgeladen wird – erlauben:
Dafür in „/etc/pulse/daemon.conf“ diese Zeile hinzufügen:
allow-module-loading = yes
Und in „/etc/pulse/system.pa“ das hier hinzufügen um die Bluetooth-Basisunterstützung einzuschalten:
.ifexists module-bluetooth-policy.so load-module module-bluetooth-policy .endif .ifexists module-bluez5-discover.so load-module module-bluez5-discover .endif
Andere Einträge in dieser Datei, die „bluez“ oder „bluetooth“ enthalten müssen entfernt werden.
Pulseaudio darf beim Systemstart erst nach Bluetooth/bluez gestartet werden. Dazu in „/etc/systemd/system/pulseaudio.service“ die Zeile
After=dbus.service avahi-daemon.service network.target
erweitern zu:
After=dbus.service avahi-daemon.service network.target bluetooth.target
Anschließend Pulseaudio neu starten: systemctl daemon-reload; systemctl restart pulseaudio
Das war’s!
Updates:
Update 2019:
Alles funktioniert monatelang ganz wunderbar hervorragend – bis ich beschloss, eine zusätzliche PCIe-Karte in den Rechner einzubauen: Dadurch wurden die PCI-IDs durcheinandergewirbelt, die oben mit „loginctl attach“ den Seats zugewiesenen wurden. Damit’s wieder funktioniert einfach die Geräte, wie oben beschrieben, nochmal den Seats zuteilen, und schon läuft alles wieder wie gehabt.
Update 2021:
Update auf Debian 11 durchgeführt: Keine Probleme, keine Nacharbeit erforderlich. Daher Titel dieses Beitrags angepasst.
Update 2022:
DXVK, die D3D9/D3D10/D3D1-Implementierung in Vulkan, verwendet nicht die dem Seat zugeordenete Grafikkarte, sondern eine beliebige. Wenn’s bei einem Benutzer in Wine oder Proton ruckelt, mit vulkaninfo | grep "^GPU id"
den Namen „seiner“ GPU rausfinden und in die Umgebungsvariable DXVK_FILTER_DEVICE_NAME
eintragen.
Es reicht ein eindeutiger Teil der Ausgabe. z.B. bei „GPU id : 1 (AMD Radeon RX 550 Series (RADV POLARIS11))“ reicht export DXVK_FILTER_DEVICE_NAME=POLARIS11
.
Update 2023:
Update auf Debian 12 durchgeführt: Polkit-Regeln müssen vom pkla-Format in’s conf-Format konvertiert werden, habe den Text entsprechend angepasst. Ansonsten: Keine Probleme, keine weitere Nacharbeit erforderlich. Daher Titel dieses Beitrags wieder einmal angepasst.