Blank a Wayland kiosk screen over SSH and wake it later

6 min read · Published November 8, 2026

Point wlr-randr at the live Wayland session with XDG_RUNTIME_DIR=/run/user/1000 and WAYLAND_DISPLAY=wayland-0, switch the output off, and wake it by naming the exact mode, such as 1366x768 at 59.79 Hz. DDC/CI code D6 and HDMI CEC control the monitor itself when the compositor route fails.

A desktop installed from a current image runs Wayland, not X11, and that one change is why xset dpms, xrandr and vcgencmd display_power do nothing from an SSH shell: the first two need an X server that is no longer running, and the firmware call is retired on the Wayland stack. The working tool is wlr-randr, run as the desktop user with XDG_RUNTIME_DIR=/run/user/1000 and WAYLAND_DISPLAY=wayland-0. It turns the output off and brings it back by naming the exact mode. When the compositor refuses, ddcutil VCP code D6 or CEC standby talks to the monitor itself.

Why the old commands do nothing

Your commands failed for three separate reasons, and the kiosk is fine.

Since the Bookworm release, the default desktop session on these images is Wayland. xset and xrandr speak the X11 protocol, so with no X server they have nothing to talk to, and over SSH they also lack a DISPLAY variable. vcgencmd display_power belongs to the pre-Wayland video stack, and its display call returns nothing useful under Wayland. setterm blanks a virtual console, and the desktop sits on top of one, so the monitor never receives it.

The fix is a Wayland-native tool pointed at the running session.

What you need

  • SSH access to the kiosk.
  • The username the desktop session runs under.
  • wlr-randr installed on the kiosk.
  • The output name and mode string, copied from a wlr-randr listing.
  • For the fallbacks: ddcutil, or cec-client from the libcec and cec-utils packages.

Three routes switch a screen off, and they control different things:

Route What it switches Needs Weak point
wlr-randr --off The compositor's video output The desktop user's session and socket The wake must restate the exact mode
ddcutil VCP D6 The monitor's own power state A monitor that implements D6 wake Some models sleep but never wake on D6
CEC standby The monitor over the HDMI link A display that answers CEC Desktop activity can wake it again

What the command block does

An SSH shell owns no display, so wlr-randr started from one finds no session until you point it there. XDG_RUNTIME_DIR names the desktop user's runtime directory. WAYLAND_DISPLAY names the Wayland socket inside it. The sudo -u wrapper matters as much as the variables: the socket belongs to the account running the desktop, so the command runs as that user.

Blank and wake the screen over SSH

  1. SSH in and confirm the desktop user's uid: id -u kiosk prints 1000 in this example.
  2. Check the socket: ls /run/user/1000/ and look for wayland-0; some images print wayland-1.
  3. List the outputs and copy the mode string for the wake step:
sudo -u kiosk bash -c 'export XDG_RUNTIME_DIR=/run/user/1000
export WAYLAND_DISPLAY=wayland-0
wlr-randr'
  1. Blank the screen:
sudo -u kiosk bash -c 'export XDG_RUNTIME_DIR=/run/user/1000
export WAYLAND_DISPLAY=wayland-0
wlr-randr --output HDMI-A-1 --off'
  1. Wake it, naming the mode exactly as the listing printed it:
sudo -u kiosk bash -c 'export XDG_RUNTIME_DIR=/run/user/1000
export WAYLAND_DISPLAY=wayland-0
wlr-randr --output HDMI-A-1 --on --mode "1366x768, 59.79"'

If the kiosk has a touchscreen and you only want idle blanking, an input-timeout daemon blanks the panel after about 10 seconds with no input and wakes it on touch. It answers no SSH command, so it covers idle blanking only, not remote control.

Example: blanking HDMI-A-1 at 1366 x 768 on a live kiosk

Inputs, each read from the machine itself:

  • Desktop user kiosk, uid 1000, from id -u kiosk.
  • Runtime directory /run/user/1000, the uid appended to /run/user/.
  • Socket wayland-0, from ls /run/user/1000/.
  • Output HDMI-A-1 and mode 1366x768, 59.79, from the wlr-randr listing: 1366 x 768 pixels at 59.79 Hz.

The rule in words: an SSH shell starts with no display environment, so both variables must point into the desktop user's runtime directory before the tool reaches the compositor. The blank disables one named output. The wake re-enables it with the mode restated.

The arithmetic is two string builds. Runtime directory: /run/user/ plus 1000 gives /run/user/1000. Mode string: 1366x768 plus comma, space, 59.79 gives 1366x768, 59.79, exactly as the listing prints it.

Result: the panel goes dark, Chromium keeps its page in memory, and the wake line brings the same page back at 1366 x 768. Decision: one output and one mode means two fixed lines run this display for the life of the kiosk, so keep both in one script. With two outputs, keep a mode line for each, because each wake restates only its own mode.

How to check it worked

After step 4 the panel darkens. A monitor losing signal may show its own no-signal notice first, which is expected with --off. Confirm the session survived from SSH: pgrep -u kiosk chromium still prints a PID. Run step 5 and the same page comes back. If the wake leaves the panel dark, recheck the mode string first: copy it character for character from a fresh listing, comma and space included.

DDC/CI: putting the monitor itself to sleep

ddcutil writes to the monitor's own control registers over the display cable, so it works under Wayland, under X11, or with no desktop at all. VCP code D6 is the power control in the VESA monitor control command set: value 04 sleeps the display and value 01 wakes it. This is the pattern one floor used across three monitors on buses 6, 9 and 12:

ddcutil setvcp D6 04 -b 9 --sleep-multiplier .3
ddcutil setvcp D6 01 -b 9 --sleep-multiplier .1 --async --noverify

The -b number is the bus the display sits on, and each monitor gets its own line. The multiplier and flags are the values that worked on that floor, so keep them until your displays answer without them. Test the wake on every model before you standardize: one monitor there took the sleep value and never answered the wake value, so its only wake was the physical power button.

cec-client, from the libcec and cec-utils packages, puts a CEC-aware display into standby over the HDMI cable itself. A quick check that a display is likely to answer: ARC support marked on the port. One field observation to weigh: the Wayland session sometimes woke a CEC-slept display again when panel entries changed, so watch a blanked unit for a full shift before trusting the route. For what the display expects on the settings side, HDMI-CEC signage display control covers it.

Put it on a schedule

Both command blocks belong in one script, called from cron or a systemd timer as the desktop user. Blank at close, wake at open, and the screen follows the building. If you already time screen wake for machines, waking an HMI screen from screen saver on a PLC schedule is the same pattern from the control side. If the kiosk browser starts from an autostart entry, keep the session rules from setting up chromium kiosk autostart on a Linux panel; after a Bookworm-era update those entries break in ways that look like display faults, and fixing kiosk autostart after the Bookworm update walks the repair.

One rule from the floor: put a timer on a notice board, never on a screen an operator reads for live machine state during production. And if the job is only a notice board, shop-floor signage plays its playlist from a microSD card or USB stick with no subscription, and the kiosk box disappears from the install.

Recommendation: use wlr-randr whenever its listing shows your output: the session survives and the wake is repeatable because you restate the mode yourself. Keep ddcutil VCP D6 as the fallback where the compositor refuses, and CEC only on displays where you have watched the wake succeed. Whichever route you take, run the wake test by hand on every model once, before anything runs on a timer.

Questions

Why does the wake command need the exact mode string?

The working usage passes --mode with the string copied from the wlr-randr listing, comma and space included, for example '1366x768, 59.79'. Two modes can share a resolution and differ only in the refresh number, so that last number is what makes the string exact. Run the listing once at install time and store the line with your wake script.

The kiosk still runs X11. What works there?

The X tools. Export DISPLAY=:0 over SSH, then blank with xset dpms force off and wake with xset dpms force on, or switch the output with xrandr. They fail on Wayland because there is no X server to answer, which is the whole reason this page uses wlr-randr instead.

Can the blank and wake run on a timer?

Yes. Put both command blocks in one script and call it from cron or a systemd timer as the desktop user, with the same two variables exported. Test both directions by hand first, and keep the mode string inside the script; a timer cannot supply it for you.

What if wlr-randr lists nothing at all?

Then the desktop ships a compositor wlr-randr cannot talk to, and no environment variable fixes that. Stop at the listing stage and switch to the monitor-side routes: ddcutil with VCP code D6, or CEC standby. The socket and user checks only matter once the tool can reach the session.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote