Skip to content

Commit 7f546ad

Browse files
committed
feat(arch): streamline signed driver packaging
Make Arch packages install the virtual display driver automatically, launch one-time signing authorization only when kernel enforcement requires it, and keep normal Arch and CachyOS installs confirmation-only. Validate real direct and DKMS signing in CI, normalize prerelease package versions, and document Linux 7.1 compatibility and deployment behavior. Generated with [Codex](https://openai.com/codex/) Model: GPT 5.6-Sol X-High
1 parent c9f2cbd commit 7f546ad

11 files changed

Lines changed: 126 additions & 45 deletions

File tree

.github/workflows/ci-archlinux.yml

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,12 @@ jobs:
6262
base-devel \
6363
cmake \
6464
cuda \
65+
dkms \
6566
git \
66-
namcap
67+
kmod \
68+
linux-headers \
69+
namcap \
70+
openssl
6771
pacman -Scc --noconfirm
6872
6973
- name: Checkout
@@ -73,6 +77,66 @@ jobs:
7377
fetch-depth: 1
7478
submodules: recursive
7579

80+
- name: Compile Vibeshine DRM against Arch kernel
81+
shell: bash
82+
run: |
83+
set -euo pipefail
84+
85+
mapfile -t kernel_build_dirs < <(
86+
find /usr/lib/modules -mindepth 2 -maxdepth 2 -type d -name build -print | sort
87+
)
88+
if (( ${#kernel_build_dirs[@]} != 1 )); then
89+
echo "::error::Expected exactly one Arch kernel header tree, found ${#kernel_build_dirs[@]}."
90+
printf '%s\n' "${kernel_build_dirs[@]}" >&2
91+
exit 1
92+
fi
93+
94+
kernel_release="$(basename "$(dirname "${kernel_build_dirs[0]}")")"
95+
module_build_dir="${RUNNER_TEMP}/vibeshine-drm-${kernel_release}"
96+
cp -a third-party/libvirtualdisplay/linux/vibeshine-drm "${module_build_dir}"
97+
MAKEFLAGS="-j$(nproc)" \
98+
"${module_build_dir}/build-module" "${kernel_release}" "${module_build_dir}"
99+
test -s "${module_build_dir}/vibeshine_drm.ko"
100+
101+
signing_key="${RUNNER_TEMP}/vibeshine-drm-mok.key"
102+
signing_certificate="${RUNNER_TEMP}/vibeshine-drm-mok.pub"
103+
openssl req -new -x509 -nodes -days 1 \
104+
-subj '/CN=Vibeshine CI module signing key/' \
105+
-newkey rsa:2048 -keyout "${signing_key}" \
106+
-addext 'extendedKeyUsage=codeSigning' \
107+
-outform DER -out "${signing_certificate}" >/dev/null 2>&1
108+
"${kernel_build_dirs[0]}/scripts/sign-file" sha256 \
109+
"${signing_key}" "${signing_certificate}" "${module_build_dir}/vibeshine_drm.ko"
110+
111+
certificate_serial="$(openssl x509 -inform DER -in "${signing_certificate}" -noout -serial)"
112+
certificate_serial="${certificate_serial#serial=}"
113+
module_sig_key="$(modinfo -F sig_key "${module_build_dir}/vibeshine_drm.ko")"
114+
module_sig_key="${module_sig_key//:/}"
115+
[[ "${module_sig_key^^}" == "${certificate_serial^^}" ]]
116+
[[ "$(modinfo -F signer "${module_build_dir}/vibeshine_drm.ko")" == \
117+
'Vibeshine CI module signing key' ]]
118+
119+
dkms_ci_version=0.0.1
120+
dkms_source="/usr/src/vibeshine-drm-${dkms_ci_version}"
121+
cp -a third-party/libvirtualdisplay/linux/vibeshine-drm "${dkms_source}"
122+
sed "s/@PROJECT_VERSION_NUMERIC@/${dkms_ci_version}/g" \
123+
"${dkms_source}/dkms.conf.in" >"${dkms_source}/dkms.conf"
124+
printf 'try_sign_modules=true\n' >/etc/dkms/framework.conf.d/vibeshine-ci.conf
125+
dkms add -m vibeshine-drm -v "${dkms_ci_version}"
126+
MAKEFLAGS="-j$(nproc)" dkms build \
127+
-m vibeshine-drm -v "${dkms_ci_version}" -k "${kernel_release}"
128+
dkms install -m vibeshine-drm -v "${dkms_ci_version}" -k "${kernel_release}"
129+
130+
dkms_module="$(modinfo -k "${kernel_release}" -n vibeshine_drm)"
131+
dkms_certificate_serial="$(openssl x509 -inform DER \
132+
-in /var/lib/dkms/mok.pub -noout -serial)"
133+
dkms_certificate_serial="${dkms_certificate_serial#serial=}"
134+
dkms_sig_key="$(modinfo -F sig_key "${dkms_module}")"
135+
dkms_sig_key="${dkms_sig_key//:/}"
136+
[[ -n "$(modinfo -F signer "${dkms_module}")" ]]
137+
[[ "${dkms_sig_key^^}" == "${dkms_certificate_serial^^}" ]]
138+
dkms remove -m vibeshine-drm -v "${dkms_ci_version}" --all
139+
76140
- name: Fix workspace permissions
77141
shell: bash
78142
run: |
@@ -163,10 +227,13 @@ jobs:
163227
package_info="$(bsdtar -xOf "${package}" .PKGINFO)"
164228
package_files="$(bsdtar -tf "${package}")"
165229
grep -qx 'depend = dkms' <<< "${package_info}"
166-
grep -qx 'depend = mokutil' <<< "${package_info}"
230+
grep -qx 'depend = mokutil>=0.7.2' <<< "${package_info}"
167231
grep -qx 'usr/libexec/vibeshine/vibeshine-drm-install' <<< "${package_files}"
168232
grep -qx 'usr/src/vibeshine-drm-[^/]*/dkms.conf' <<< "${package_files}"
169233
bsdtar -xOf "${package}" usr/libexec/vibeshine/vibeshine-drm-install | bash -n
234+
package_install_script="$(bsdtar -xOf "${package}" .INSTALL)"
235+
bash -n <<< "${package_install_script}"
236+
grep -Fq 'vibeshine-drm-install install-package' <<< "${package_install_script}"
170237
171238
- name: Copy Artifacts
172239
shell: bash

cmake/prep/special_package_configuration.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ elseif(UNIX)
7373

7474
# configure the arch linux pkgbuild
7575
if(${SUNSHINE_CONFIGURE_PKGBUILD})
76+
# Arch forbids hyphens in pkgver. Removing the SemVer prerelease
77+
# separator also keeps e.g. 1.19.0beta.4 ordered below 1.19.0.
78+
set(SUNSHINE_ARCH_PKGVER "${PROJECT_VERSION_FULL}")
79+
string(REPLACE "-" "" SUNSHINE_ARCH_PKGVER "${SUNSHINE_ARCH_PKGVER}")
80+
string(REPLACE "+" "." SUNSHINE_ARCH_PKGVER "${SUNSHINE_ARCH_PKGVER}")
7681
configure_file(packaging/linux/Arch/PKGBUILD PKGBUILD @ONLY)
7782
configure_file(packaging/linux/Arch/sunshine.install sunshine.install @ONLY)
7883
endif()

docs/configuration.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,7 +1226,7 @@ editing the `conf` file in a text editor. Use the examples as reference.
12261226
Replacing the module file does not replace a module already loaded by the compositor.
12271227
Compare <code>modinfo -F version vibeshine_drm</code> with
12281228
<code>cat /sys/module/vibeshine_drm/version</code> and reboot before testing when they differ.
1229-
The module targets Linux 7.2 or newer and exposes four independent virtual connectors
1229+
The module supports Linux 7.1 or newer and exposes four independent virtual connectors
12301230
with a deterministic HDR10 EDID, BT.2020/PQ metadata, 8-16 bits per component, and
12311231
10-bit RGB plane formats. Vibeshine enables one only for a stream, applies the requested
12321232
mode, layout, and HDR state through KScreen, captures that exact connector, and restores
@@ -1239,14 +1239,16 @@ editing the `conf` file in a text editor. Use the examples as reference.
12391239
fixed-rate KMS polling. KWin ScreenCast remains the recommended compositor capture path for SDR.
12401240
<br><br>
12411241
If the custom module cannot be built or loaded (including on older kernels or when
1242-
Secure Boot rejects an unsigned module), managed virtual displays remain unavailable.
1242+
the kernel rejects an untrusted module signature), managed virtual displays remain unavailable.
12431243
Vibeshine deliberately does not fall back to CPU-backed stock <code>vkms</code> scanout.
12441244
Arch Linux and CachyOS packages use DKMS to sign future rebuilds with a persistent local
1245-
key. When Secure Boot is enabled through shim, enroll that key once with
1246-
<code>sudo /usr/libexec/vibeshine/vibeshine-drm-install enroll-key</code>, reboot into the
1247-
MOK manager, and verify it afterward with
1248-
<code>/usr/libexec/vibeshine/vibeshine-drm-install signing-status</code>. Install the
1249-
matching kernel headers before retrying a failed module build.
1245+
key and verify the embedded signer before accepting the module. Stock Arch and CachyOS
1246+
kernels need no separate signing step: accepting the normal package-install confirmation
1247+
is enough, including with Secure Boot through Limine or systemd-boot. Only a custom kernel
1248+
that enforces trusted module signatures requires shim. The package installation detects
1249+
this and launches the one-time signing-key authorization prompt automatically; reboot and
1250+
approve the pending firmware confirmations once. Future updates remain automatic. Install
1251+
the matching kernel headers before retrying a failed module build.
12501252
</td>
12511253
</tr>
12521254
</table>
@@ -1491,7 +1493,7 @@ Terminate request. The original game client is unaffected. The default is
14911493
<td>Description</td>
14921494
<td colspan="2">
14931495
Perform additional HDR configuration for the display device.
1494-
@note{On Linux 7.2 or newer, the managed <code>vibeshine_drm</code> output advertises HDR10 and 10-bit formats. Managed display creation fails if that driver is unavailable rather than using CPU-backed stock VKMS.}
1496+
@note{On Linux 7.1 or newer, the managed <code>vibeshine_drm</code> output advertises HDR10 and 10-bit formats. Managed display creation fails if that driver is unavailable rather than using CPU-backed stock VKMS.}
14951497
</td>
14961498
</tr>
14971499
<tr>

docs/getting_started.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ Additional information:
653653
not support HDR.
654654
- You will need a desktop environment with a compositor that supports HDR rendering, such as Gamescope or KDE Plasma 6.
655655
- Native Vibeshine installations can provide private HDR10 virtual outputs through the
656-
`vibeshine_drm` module. It requires Linux 7.2 or newer and matching kernel headers. Its EDID
656+
`vibeshine_drm` module. It requires Linux 7.1 or newer and matching kernel headers. Its EDID
657657
advertises BT.2020, PQ, and HDR static metadata, while its connector and planes support 10-bit output.
658658
The driver notifies direct KMS capture when a presentation completes, so sparse changes are captured
659659
immediately and bursts are coalesced to the stream's requested maximum frame rate. Older module
@@ -682,19 +682,16 @@ Additional information:
682682

683683
On Arch Linux and CachyOS, install the matching headers for every kernel you boot (for example,
684684
`linux-headers` or `linux-cachyos-headers`). The native package uses DKMS and signs rebuilt
685-
modules automatically. A Secure Boot system using shim needs one additional enrollment:
686-
687-
```bash
688-
sudo /usr/libexec/vibeshine/vibeshine-drm-install enroll-key
689-
# Reboot, select "Enroll MOK", and enter the temporary password from the command above.
690-
/usr/libexec/vibeshine/vibeshine-drm-install signing-status
691-
modinfo -F signer vibeshine_drm
692-
```
693-
694-
This enrollment survives normal kernel and Vibeshine updates; DKMS continues using the same
695-
root-only signing key. The helper refuses to schedule MOK enrollment unless the current boot
696-
passed through shim, because direct Limine and systemd-boot paths do not make MOK keys available
697-
to the Linux kernel.
685+
modules automatically and verifies the signer embedded in every installed module. On stock Arch
686+
and CachyOS kernels this all happens during package installation: accept pacman's normal install
687+
confirmation and no separate signing or enrollment command is required, including when Secure
688+
Boot uses a direct Limine or systemd-boot chain.
689+
690+
Only a custom kernel configured to enforce trusted module signatures needs additional
691+
authorization. When that is detected, the package installation launches the one-time signing-key
692+
confirmation automatically. After confirming it, reboot and approve the pending firmware
693+
confirmations once; future kernel and Vibeshine updates remain automatic. If a noninteractive
694+
package frontend cannot display the prompt, retry the package installation from a terminal.
698695

699696
@seealso{[Arch wiki on HDR Support for Linux](https://wiki.archlinux.org/title/HDR_monitor_support) and
700697
[Reddit Guide for HDR Support for AMD GPUs](https://www.reddit.com/r/linux_gaming/comments/10m2gyx/guide_alpha_test_hdr_on_linux)}

docs/linux/AGENTS.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ If building on a fresh clone and seeing Boost errors:
5959

6060
## 2. Virtual Display Setup
6161

62-
### Preferred managed virtual displays (Linux 7.2+)
62+
### Preferred managed virtual displays (Linux 7.1+)
6363

6464
Native Vibeshine installations include the `vibeshine_drm` source. Native package hooks and
6565
`vibeshine-drm-setup.service` attempt to register it with DKMS or build it for the running kernel.
66-
It targets the Linux 7.2 DRM APIs and provides a separate `/sys/kernel/config/vibeshine-drm`
67-
namespace, so it can coexist with stock VKMS. Install (or retry) the module and enable the
68-
four-output private pool with:
66+
It targets the Linux 7.2 DRM APIs with a Linux 7.1 compatibility shim and provides a separate
67+
`/sys/kernel/config/vibeshine-drm` namespace, so it can coexist with stock VKMS. Install (or retry)
68+
the module and enable the four-output private pool with:
6969

7070
```bash
7171
sudo /usr/libexec/vibeshine/vibeshine-drm-install install
@@ -87,13 +87,14 @@ their modes, layout, and HDR state. Vibeshine routes managed HDR capture through
8787
the 10-bit scanout reaches VAAPI or NVENC; KWin ScreenCast remains recommended for SDR capture. If
8888
the custom module cannot build or load, managed virtual displays remain unavailable. The helper
8989
does not use stock VKMS because its CPU-backed scanout violates the managed-display latency
90-
contract. Secure Boot requires a trusted module signature.
90+
contract. Strict module-signature enforcement requires shim/MOK trust or a custom kernel key;
91+
stock Arch and CachyOS kernels allow a signed external module with the normal module taint.
9192

9293
### Reference-host forced-EDID setup
9394

9495
The setup below records this repository's older Linux 6.19 reference host. It remains useful for a
9596
physical dummy connector or a kernel that cannot run `vibeshine_drm`, but it is not required for the
96-
managed pool on Linux 7.2+.
97+
managed pool on Linux 7.1+.
9798

9899
Vibeshine streams to a **virtual display** on HDMI-A-2 (a physically disconnected port) using a custom EDID loaded by the kernel at boot.
99100

docs/linux/LEARNINGS.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ groups $USER | grep -E "input|video|render"
253253

254254
## 11. Virtual Display Setup (EDID Method)
255255

256-
> **Preferred current setup:** On Linux 7.2 or newer, native package hooks and
256+
> **Preferred current setup:** On Linux 7.1 or newer, native package hooks and
257257
> `vibeshine-drm-setup.service` attempt to build or register the packaged `vibeshine_drm` module.
258258
> Run `sudo /usr/libexec/vibeshine/vibeshine-drm-install install` to install or retry it manually,
259259
> then run `sudo systemctl enable --now vibeshine-vkms.service` to provision four dormant managed
@@ -266,8 +266,11 @@ groups $USER | grep -E "input|video|render"
266266
> and plane support. Managed HDR capture uses direct DRM/KMS so the 10-bit scanout reaches the
267267
> encoder; KWin ScreenCast remains the recommended SDR path. If the module cannot be built or
268268
> loaded, managed virtual displays remain unavailable rather than using CPU-backed stock VKMS.
269-
> Secure Boot requires a trusted module signature. The remainder of this
270-
> section documents the legacy forced-EDID method for a physical connector.
269+
> The installer signs and verifies each module automatically. Stock Arch and
270+
> CachyOS kernels permit an untrusted external signature with the normal module
271+
> taint. Strict signature enforcement requires shim/MOK enrollment plus
272+
> MOK-list trust; an `sbctl` EFI owner key is not a Linux module key. The remainder
273+
> of this section documents the legacy forced-EDID method for a physical connector.
271274
272275
### Problem
273276
Need to stream without physical monitor, or stream while monitor is off.

packaging/linux/Arch/PKGBUILD

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
: "${_commit:=@GITHUB_COMMIT@}"
88

99
pkgname='sunshine'
10-
pkgver=@PROJECT_VERSION@@SUNSHINE_SUB_VERSION@
10+
pkgver=@SUNSHINE_ARCH_PKGVER@@SUNSHINE_SUB_VERSION@
1111
pkgrel=1
1212
pkgdesc="@PROJECT_DESCRIPTION@"
1313
arch=('x86_64' 'aarch64')
@@ -48,7 +48,7 @@ depends=(
4848
'libxtst'
4949
'make'
5050
'miniupnpc'
51-
'mokutil'
51+
'mokutil>=0.7.2'
5252
'numactl'
5353
'openssl'
5454
'opus'
@@ -74,7 +74,7 @@ optdepends=(
7474
'libva-mesa-driver: AMD GPU encoding support'
7575
'linux-cachyos-headers: build the virtual-display module for the standard CachyOS kernel'
7676
'linux-headers: build the virtual-display module for the standard Arch kernel'
77-
'shim-signed: make enrolled MOK keys available to the Linux kernel under Secure Boot'
77+
'shim-signed: provide a signed shim boot chain for MOK trust on strict Secure Boot systems'
7878
)
7979

8080
provides=()

packaging/linux/Arch/sunshine.install

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,22 @@ do_udev_reload() {
1313
}
1414

1515
do_install_vibeshine_drm() {
16-
if /usr/libexec/vibeshine/vibeshine-drm-install install; then
16+
if /usr/libexec/vibeshine/vibeshine-drm-install install-package; then
1717
return 0
1818
else
1919
local install_rc=$?
2020
fi
21-
if ((install_rc == 4)); then
22-
echo "warning: Vibeshine DRM was updated, but the loaded module is stale; reboot before using managed virtual displays."
23-
else
24-
echo "warning: Vibeshine DRM installation failed; managed virtual displays are unavailable."
25-
fi
21+
case $install_rc in
22+
4)
23+
echo "warning: Vibeshine DRM was updated, but the loaded module is stale; reboot before using managed virtual displays."
24+
;;
25+
5)
26+
echo "Vibeshine DRM authorization is queued. Reboot and approve the pending MOK confirmations once."
27+
;;
28+
*)
29+
echo "warning: Vibeshine DRM installation failed; managed virtual displays are unavailable."
30+
;;
31+
esac
2632
}
2733

2834
post_install() {

src_assets/common/assets/web/public/assets/locale/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@
492492
"dd_virtual_display_scale": "Virtual Display Scale",
493493
"dd_virtual_display_scale_desc": "Overrides virtual display scaling. Automatic chooses the recommended scale for the requested display mode.",
494494
"virtual_display_outputs": "Linux private display connectors",
495-
"virtual_display_outputs_desc": "Optional comma-separated DRM connector names reserved for private streams. Leave empty to use the four-output managed pool. On Linux 7.2+, Vibeshine DRM provides GPU-attached HDR10 and 10-bit output; HDR uses direct KMS capture, KWin is recommended for SDR, and managed display creation fails if the custom driver is unavailable.",
495+
"virtual_display_outputs_desc": "Optional comma-separated DRM connector names reserved for private streams. Leave empty to use the four-output managed pool. On Linux 7.1+, Vibeshine DRM provides GPU-attached HDR10 and 10-bit output; HDR uses direct KMS capture, KWin is recommended for SDR, and managed display creation fails if the custom driver is unavailable.",
496496
"remote_monitor_mute_audio": "Mute audio on Remote Monitor",
497497
"remote_monitor_mute_audio_desc": "Send picture and input without sending game or desktop audio to the Remote Monitor client.",
498498
"remote_monitor_disconnect_on_stream_end": "Remove Remote Monitor when its stream ends",

src_assets/common/assets/web/public/assets/locale/ui/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,7 @@
15071507
"label": "Display scaling"
15081508
},
15091509
"virtual_display_outputs": {
1510-
"description": "Optional comma-separated DRM connector names reserved for private streams. Leave empty to use the four-output managed pool. On Linux 7.2+, Vibeshine DRM provides GPU-attached HDR10 and 10-bit output; HDR uses direct KMS capture, KWin is recommended for SDR, and managed display creation fails if the custom driver is unavailable.",
1510+
"description": "Optional comma-separated DRM connector names reserved for private streams. Leave empty to use the four-output managed pool. On Linux 7.1+, Vibeshine DRM provides GPU-attached HDR10 and 10-bit output; HDR uses direct KMS capture, KWin is recommended for SDR, and managed display creation fails if the custom driver is unavailable.",
15111511
"label": "Linux private display connectors"
15121512
},
15131513
"remote_monitor_mute_audio": {

0 commit comments

Comments
 (0)