Skip to content

Instantly share code, notes, and snippets.

@GrabbenD
Last active August 6, 2026 07:44
Show Gist options
  • Select an option

  • Save GrabbenD/810f6b7c308a18980762a19c063dba37 to your computer and use it in GitHub Desktop.

Select an option

Save GrabbenD/810f6b7c308a18980762a19c063dba37 to your computer and use it in GitHub Desktop.
Run Wayland Compostor - no Login Manager + no Getty + no File Descriptors + (optionally) no Scripts

This tutorial ensures there's no stdin/stdout/stderr (File Descriptors) as a potential performance optimization vector, furthermore no Login Manager is required nor a VT/Virtual Terminal (Getty/agetty). You can still execute a custom script (e.g. start.sh) but by default it skips login and spawns a Wayland compositor in TTYPath=/dev/tty1

Steps

  1. Open your desktop environment in a different TTY (e.g. CTRL+ALT+F2).

  2. Copy over all files to your editor.

  3. CTRL+F and searh for following hardcoded values and replace them with what fits your system:

    Value Description
    tty1 desired TTY number
    chvt 1 TTY number
    game your username
    /home/user/game PATH to your $HOME
    jay desired command
  4. Prepare the environment:

    #sudo rm /etc/systemd/system/getty@tty1.service.d/autologin.conf
    sudo nano /etc/systemd/system/ttylauncher.service                 # Paste content of the systemd unit from below
    sudo systemctl enable ttylauncher                                 # Auto start on boot
    sudo systemctl mask autovt@tty1.service                           # Prevent VT1 template unit from being triggered
    sudo systemctl disable --now getty@tty1.service                   # Disable login prompt
    sudo systemctl daemon-reload; sudo systemctl restart ttylauncher  # Run each time you make modifications
  5. Verify:

    $ sudo ls -l /proc/$(pgrep -x jay)/fd/{0,1,2}
    lr-x------ 1 game game 64 Aug  3 18:00 /proc/367459/fd/0 -> /dev/null
    l-wx------ 1 game game 64 Aug  3 18:00 /proc/367459/fd/1 -> /dev/null
    l-wx------ 1 game game 64 Aug  3 18:00 /proc/367459/fd/2 -> /dev/null

References

  • Script

    To run a script.sh instead of a command, tweak ttylauncher.service to use:

    ExecStart=/home/user/game/start.sh
  • Troubleshooting

    To collect logs with $ journalctl -f

    StandardOutput=journal
  • File Descriptors

    /usr/bin/file </dev/null 1>/dev/null 2>/dev/null is equivelent to:

    StandardInput=null
    StandardOutput=null
    StandardError=null

    /usr/bin/file <&- 1>&- 2>&- can be replicated with:

    StandardInput=closed
    StandardOutput=closed
    StandardError=closed

Documentation

Unit file (systemd)

Examples

#!/usr/bin/env bash
set -x
# Debug
#whoami; groups
# USER ENV
export UID="$(id -u)"
export GID="$(id -g)"
# Performance
export TZ=:/etc/localtime
# Wayland
export SDL_VIDEODRIVER='wayland,x11,windows'
export MOZ_ENABLE_WAYLAND=1
export ELECTRON_OZONE_PLATFORM_HINT='wayland'
export QT_QPA_PLATFORM='wayland;xcb'
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
export GDK_BACKEND='wayland,x11'
export CLUTTER_BACKEND='wayland'
# XDG
export XDG_RUNTIME_DIR="/run/user/${UID}"
export XDG_CONFIG_HOME="${HOME}/.config"
export XDG_CACHE_HOME="${HOME}/.cache"
export XDG_STATE_HOME="${HOME}/.local/state"
export XDG_DATA_HOME="${HOME}/.local/share"
export XDG_SESSION_TYPE='wayland'
export DBUS_STARTER_BUS_TYPE='session'
# Shell
#export SHELL=/usr/bin/bash
# Compositor
export XDG_CURRENT_DESKTOP='jay'
export XDG_SESSION_DESKTOP='jay'
export WAYLAND_DISPLAY='wayland-1'
#export JAY_LOG_LEVEL=trace
exec /usr/bin/jay run
[Unit]
Description=ttylauncher
After=sysinit.target
[Service]
Type=simple
User=game
WorkingDirectory=~
PAMName=login
RemainAfterExit=yes
Restart=always
RestartSec=5
StandardInput=null
StandardOutput=null
StandardError=null
TTYPath=/dev/tty1
ExecStartPre=+/usr/bin/chvt 1
ExecStart=/usr/bin/jay run
[Install]
WantedBy=multi-user.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment