@@ -42,6 +42,8 @@ parse_args() {
4242 INSTALL_SERVER=false
4343 INSTALL_CLIENT=false
4444 AUTOLOGIN=false
45+ LIGHT_GUI=false
46+ LIGHT_GUI_FORCE=false
4547 SSO=false
4648 NO_AUTOSTART=false
4749 GOT_ROLE=false
@@ -52,9 +54,10 @@ parse_args() {
5254 client) INSTALL_CLIENT=true; GOT_ROLE=true ;;
5355 both) INSTALL_SERVER=true; INSTALL_CLIENT=true; GOT_ROLE=true ;;
5456 --autologin) AUTOLOGIN=true ;;
57+ --light-gui) LIGHT_GUI=true; LIGHT_GUI_FORCE=true ;;
5558 --sso) SSO=true ;;
5659 --no-autostart) NO_AUTOSTART=true ;;
57- * ) echo " Unknown argument: $_arg " ; echo " Usage: $0 [server|client|both] [--autologin] [--sso] [--no-autostart]" ; exit 1 ;;
60+ * ) echo " Unknown argument: $_arg " ; echo " Usage: $0 [server|client|both] [--autologin] [--light-gui] [-- sso] [--no-autostart]" ; exit 1 ;;
5861 esac
5962 done
6063}
@@ -77,6 +80,17 @@ apply_defaults() {
7780 echo " --autologin only applies to Linux server installs; ignoring"
7881 AUTOLOGIN=false
7982 fi
83+
84+ if [ " $LIGHT_GUI " = true ] && { [ " $OS " != " linux" ] || [ " $INSTALL_SERVER " != true ]; }; then
85+ echo " --light-gui only applies to Linux server installs; ignoring"
86+ LIGHT_GUI=false
87+ fi
88+
89+ # In autologin mode, a desktop stack is required for a recoverable remote
90+ # session. Enable lightweight GUI bootstrap automatically.
91+ if [ " $AUTOLOGIN " = true ] && [ " $OS " = " linux" ] && [ " $INSTALL_SERVER " = true ]; then
92+ LIGHT_GUI=true
93+ fi
8094}
8195
8296# Resolve the invoking non-root user and their home directory. SUDO_USER
@@ -185,6 +199,132 @@ linux_install_deps_pacman() {
185199 fi
186200}
187201
202+ # ===========================================================================
203+ # Linux server: optional lightweight GUI bootstrap (XFCE + LightDM)
204+ # ===========================================================================
205+ # For headless Ubuntu/Debian VMs, "install + run" often fails because no
206+ # display manager / desktop session exists, or Xorg cannot build a screen.
207+ # --light-gui installs a minimal desktop stack and configures a dummy X screen
208+ # when no physical monitor is connected.
209+
210+ linux_has_connected_display () {
211+ for _status in /sys/class/drm/* /status; do
212+ [ -f " $_status " ] || continue
213+ if grep -qx " connected" " $_status " 2> /dev/null; then
214+ return 0
215+ fi
216+ done
217+ return 1
218+ }
219+
220+ linux_install_dummy_xorg_conf () {
221+ echo " No connected monitor detected; configuring dummy Xorg screen (1920x1080)..."
222+ if [ -f /etc/X11/xorg.conf ] && [ ! -f /etc/X11/xorg.conf.phantom-bak ]; then
223+ sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.phantom-bak
224+ fi
225+ sudo tee /etc/X11/xorg.conf > /dev/null << 'EOF '
226+ # Written by phantom install.sh --light-gui
227+ Section "ServerLayout"
228+ Identifier "Layout0"
229+ Screen 0 "Screen0"
230+ EndSection
231+
232+ Section "Monitor"
233+ Identifier "Monitor0"
234+ HorizSync 28.0-80.0
235+ VertRefresh 48.0-75.0
236+ EndSection
237+
238+ Section "Device"
239+ Identifier "Device0"
240+ Driver "dummy"
241+ VideoRam 256000
242+ EndSection
243+
244+ Section "Screen"
245+ Identifier "Screen0"
246+ Device "Device0"
247+ Monitor "Monitor0"
248+ DefaultDepth 24
249+ SubSection "Display"
250+ Depth 24
251+ Modes "1920x1080"
252+ EndSubSection
253+ EndSection
254+ EOF
255+ }
256+
257+ linux_install_light_gui_apt () {
258+ echo " "
259+ echo " Installing lightweight GUI stack (XFCE + LightDM)..."
260+ sudo apt-get update -qq
261+ echo " lightdm shared/default-x-display-manager select lightdm" | sudo debconf-set-selections || true
262+ echo " /etc/X11/default-display-manager string /usr/sbin/lightdm" | sudo debconf-set-selections || true
263+ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
264+ xorg xfce4 lightdm xserver-xorg-video-dummy dbus-x11 x11-xserver-utils || true
265+
266+ sudo mkdir -p /etc/lightdm/lightdm.conf.d
267+ sudo tee /etc/lightdm/lightdm.conf.d/50-phantom-xfce.conf > /dev/null << 'EOF '
268+ [Seat:*]
269+ user-session=xfce
270+ autologin-session=xfce
271+ EOF
272+
273+ if [ " $AUTOLOGIN " = true ] && [ -n " $TARGET_USER " ] && [ " $TARGET_USER " != " root" ]; then
274+ sudo tee /etc/lightdm/lightdm.conf.d/60-phantom-autologin.conf > /dev/null << EOF
275+ [Seat:*]
276+ autologin-user=$TARGET_USER
277+ autologin-user-timeout=0
278+ EOF
279+ fi
280+
281+ if linux_has_connected_display; then
282+ echo " Physical display detected; skipping dummy Xorg config."
283+ else
284+ linux_install_dummy_xorg_conf
285+ fi
286+
287+ sudo systemctl disable gdm3 > /dev/null 2>&1 || true
288+ sudo systemctl enable lightdm > /dev/null 2>&1 || true
289+ echo " LightDM enabled (applies after reboot)."
290+ }
291+
292+ linux_setup_headless_dummy_apt () {
293+ echo " "
294+ echo " Installing headless X fallback (dummy screen)..."
295+ sudo apt-get update -qq
296+ sudo apt-get install -y --no-install-recommends xserver-xorg-video-dummy || true
297+ linux_install_dummy_xorg_conf
298+ }
299+
300+ linux_has_display_manager () {
301+ if [ -f /etc/gdm3/custom.conf ] || [ -d /etc/lightdm ] || [ -f /etc/lightdm/lightdm.conf ]; then
302+ return 0
303+ fi
304+ return 1
305+ }
306+
307+ linux_setup_light_gui_if_requested () {
308+ if [ " $LIGHT_GUI " != true ] || [ " $OS " != " linux" ] || [ " $INSTALL_SERVER " != true ]; then
309+ return 0
310+ fi
311+
312+ if have_cmd apt-get; then
313+ if [ " $LIGHT_GUI_FORCE " = true ] || ! linux_has_display_manager; then
314+ linux_install_light_gui_apt
315+ elif linux_has_connected_display; then
316+ echo " "
317+ echo " Display manager already installed and monitor is connected; skipping --light-gui bootstrap."
318+ else
319+ linux_setup_headless_dummy_apt
320+ fi
321+ else
322+ echo " "
323+ echo " WARN: --light-gui currently auto-installs only on apt-based distros."
324+ echo " Install manually: XFCE + LightDM + xserver dummy driver."
325+ fi
326+ }
327+
188328# ===========================================================================
189329# Linux server: /dev/uinput for keyboard injection
190330# ===========================================================================
@@ -290,7 +430,7 @@ linux_configure_autologin() {
290430 exit 1
291431 fi
292432
293- linux_autologin_gdm
433+ linux_autologin_configure_display_manager
294434 linux_autologin_disable_screenlock
295435 linux_autologin_reset_keyring
296436 linux_autologin_install_keyring_unlock
@@ -304,6 +444,28 @@ linux_configure_autologin() {
304444 echo " unencrypted. This is intended for dedicated remote-access VMs."
305445}
306446
447+ linux_autologin_configure_display_manager () {
448+ if [ -d /etc/lightdm ] || [ -f /etc/lightdm/lightdm.conf ]; then
449+ linux_autologin_lightdm
450+ return 0
451+ fi
452+ linux_autologin_gdm
453+ }
454+
455+ linux_autologin_lightdm () {
456+ sudo mkdir -p /etc/lightdm/lightdm.conf.d
457+ sudo tee /etc/lightdm/lightdm.conf.d/60-phantom-autologin.conf > /dev/null << EOF
458+ # Written by phantom install.sh --autologin
459+ [Seat:*]
460+ autologin-user=$TARGET_USER
461+ autologin-user-timeout=0
462+ autologin-session=xfce
463+ user-session=xfce
464+ EOF
465+ sudo systemctl enable lightdm > /dev/null 2>&1 || true
466+ echo " Enabled LightDM autologin for $TARGET_USER "
467+ }
468+
307469linux_autologin_gdm () {
308470 # 1. GDM autologin (Ubuntu 22/24 default DM)
309471 if [ -f /etc/gdm3/custom.conf ]; then
@@ -415,19 +577,25 @@ linux_autologin_install_watchdog() {
415577 # on U24 where TimedLogin does work natively.
416578 sudo tee /usr/local/bin/phantom-autologin-watchdog.sh > /dev/null << EOF
417579#!/bin/sh
418- # Kick gdm3 if there is no active seat0 session for $TARGET_USER .
580+ # Kick display manager if there is no active seat0 session for $TARGET_USER .
419581# Written by phantom install.sh --autologin.
420582SID=\$ (loginctl list-sessions --no-legend | awk '\$ 3=="$TARGET_USER " && \$ 4=="seat0" && !/closing/{print \$ 1}')
421583if [ -z "\$ SID" ]; then
422- logger "phantom-autologin-watchdog: no $TARGET_USER seat0, restarting gdm3"
423- systemctl restart gdm3
584+ DM=display-manager
585+ if systemctl is-enabled lightdm > /dev/null 2>&1 || systemctl is-active lightdm > /dev/null 2>&1; then
586+ DM=lightdm
587+ elif systemctl is-enabled gdm3 > /dev/null 2>&1 || systemctl is-active gdm3 > /dev/null 2>&1; then
588+ DM=gdm3
589+ fi
590+ logger "phantom-autologin-watchdog: no $TARGET_USER seat0, restarting \$ DM"
591+ systemctl restart "\$ DM"
424592fi
425593EOF
426594 sudo chmod +x /usr/local/bin/phantom-autologin-watchdog.sh
427595 sudo tee /etc/systemd/system/phantom-autologin-watchdog.service > /dev/null << EOF
428596[Unit]
429- Description=Re-trigger GDM autologin for $TARGET_USER if no seat0 session exists
430- After=gdm3 .service
597+ Description=Re-trigger display-manager autologin for $TARGET_USER if no seat0 session exists
598+ After=display-manager .service
431599
432600[Service]
433601Type=oneshot
@@ -597,6 +765,7 @@ main() {
597765 fi
598766
599767 if [ " $OS " = " linux" ] && [ " $INSTALL_SERVER " = true ]; then
768+ linux_setup_light_gui_if_requested
600769 linux_configure_uinput
601770 if [ " $NO_AUTOSTART " = false ]; then
602771 linux_install_autostart
0 commit comments