Skip to content

Commit cc16800

Browse files
committed
install: auto-bootstrap headless Linux GUI path for server autologin
1 parent 2cf6e05 commit cc16800

1 file changed

Lines changed: 176 additions & 7 deletions

File tree

install.sh

Lines changed: 176 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
307469
linux_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.
420582
SID=\$(loginctl list-sessions --no-legend | awk '\$3=="$TARGET_USER" && \$4=="seat0" && !/closing/{print \$1}')
421583
if [ -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"
424592
fi
425593
EOF
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]
433601
Type=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

Comments
 (0)