Overview

This project sets up a multi-user, "Retro Unix" appliance on Ubuntu Server 24.04. It provides a classic Motif Window Manager (MWM) environment that is accessible via any modern web browser.

Key Features:


Architecture

Component Technology Role
OS Ubuntu Server 24.04 Base operating system (Headless).
Display Server Xorg / X11 The underlying graphical protocol (Wayland is not supported for MWM).
Window Manager MWM (Motif) Provides the window borders and "chiseled" look.
Session Manager XDM Handles graphical login and authentication.
Remote Display TigerVNC + Xinetd Spawns a virtual display for each incoming connection.
Web Gateway noVNC Bridges the VNC TCP traffic to WebSockets for browser access.

The Solution: Ansible Playbook

This playbook automates the entire stack. It installs packages, configures the network sockets, and sets up the "Skeleton" directory so new users get a pre-configured Motif environment (custom menus, colors, and startup scripts).

Save as: setup_motif_novnc.yml

---
- name: Setup Multi-User Motif with noVNC on Ubuntu 24.04
  hosts: all
  become: yes
  vars:
    # Standard ports
    vnc_port: 5900
    novnc_port: 6080
    
    # Paths (standard for Ubuntu 24.04)
    novnc_web_dir: "/usr/share/novnc"
    xvnc_binary: "/usr/bin/Xvnc"

  tasks:
    # =======================================================
    # 1. INSTALLATION
    # =======================================================
    - name: Update apt cache
      apt:
        update_cache: yes

    - name: Install Xorg, Motif, XDM, TigerVNC, and Fonts
      apt:
        name:
          - xorg
          - mwm
          - xterm
          - xdm
          - tigervnc-standalone-server
          - xfonts-base
          - xfonts-100dpi
          - xfonts-75dpi
          - x11-apps  # xclock, xeyes, xcalc
        state: present

    - name: Install noVNC and Websockify
      apt:
        name:
          - novnc
          - python3-websockify
          - python3-numpy
        state: present

    # =======================================================
    # 2. XDM CONFIGURATION (Enable Network Logins)
    # =======================================================
    - name: Enable XDMCP in xdm-config
      lineinfile:
        path: /etc/X11/xdm/xdm-config
        regexp: 'DisplayManager.requestPort:\\s*0'
        line: '! DisplayManager.requestPort: 0'
        backrefs: yes

    - name: Allow any host to connect in Xaccess
      lineinfile:
        path: /etc/X11/xdm/Xaccess
        regexp: '^#\\*\\s+#any host'
        line: '* #any host can get a login window'

    - name: Ensure XDM service is restarted
      systemd:
        name: xdm
        state: restarted
        enabled: yes

    # =======================================================
    # 3. SYSTEMD SOCKETS (Dynamic VNC Generation)
    # =======================================================
    - name: Create XVNC systemd socket
      copy:
        dest: /etc/systemd/system/xvnc.socket
        content: |
          [Unit]
          Description=XVNC Server Socket

          [Socket]
          ListenStream={{ vnc_port }}
          Accept=yes

          [Install]
          WantedBy=sockets.target

    - name: Create XVNC systemd service template
      copy:
        dest: /etc/systemd/system/[email protected]
        content: |
          [Unit]
          Description=XVNC Per-Connection Daemon
          Requires=xdm.service
          After=syslog.target network.target xdm.service

          [Service]
          # -inetd: Talk over network; -query localhost: Ask XDM for login
          ExecStart=-{{ xvnc_binary }} -inetd -query localhost -geometry 1280x960 -depth 24 -once -SecurityTypes=None
          User=nobody
          StandardInput=socket
          StandardError=syslog

          [Install]
          WantedBy=multi-user.target

    # =======================================================
    # 4. NOVNC WEB BRIDGE
    # =======================================================
    - name: Create noVNC systemd service
      copy:
        dest: /etc/systemd/system/novnc.service
        content: |
          [Unit]
          Description=noVNC Web Bridge
          After=network.target

          [Service]
          Type=simple
          User=nobody
          ExecStart=/usr/bin/websockify --web={{ novnc_web_dir }} {{ novnc_port }} localhost:{{ vnc_port }}
          Restart=on-failure

          [Install]
          WantedBy=multi-user.target

    # =======================================================
    # 5. USER SKELETON (Default Configs for New Users)
    # =======================================================
    - name: Create default .xsession script
      copy:
        dest: /etc/skel/.xsession
        mode: '0755'
        content: |
          #!/bin/sh
          [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
          xsetroot -solid "dark slate gray"
          xterm -geometry 80x24+10+10 -ls -title "Welcome" &
          exec mwm

    - name: Link .xinitrc to .xsession
      file:
        src: .xsession
        dest: /etc/skel/.xinitrc
        state: link
        force: yes

    - name: Create Motif Styling (.Xresources)
      copy:
        dest: /etc/skel/.Xresources
        content: |
          Mwm*activeBackground: #5D7990
          Mwm*activeForeground: white
          Mwm*background:       #C0C0C0
          Mwm*foreground:       black
          xterm*background:     black
          xterm*foreground:     white
          xterm*faceName:       Monospace
          xterm*faceSize:       10

    - name: Create Custom Root Menu (.mwmrc)
      copy:
        dest: /etc/skel/.mwmrc
        content: |
          Menu DefaultRootMenu
          {
              "Root Menu"             f.title
              "New Terminal"          f.exec "xterm &"
              "Applications"          f.menu AppsMenu
              "Shuffle Windows"       f.circle_down
              "Refresh Screen"        f.refresh
              no-label                f.separator
              "Restart MWM"           f.restart
              "Log Out"               f.quit_mwm
          }

          Menu AppsMenu
          {
              "Applications"          f.title
              "Calculator"            f.exec "xcalc &"
              "Clock"                 f.exec "xclock &"
              "Eyes"                  f.exec "xeyes &"
              no-label                f.separator
              "Top (Process)"         f.exec "xterm -T 'Top' -e top &"
              "Text Editor"           f.exec "xterm -T 'Nano' -e nano &"
          }

          Buttons DefaultButtonBindings
          {
              <Btn3Down>      root    f.menu DefaultRootMenu
          }

          Mwm*buttonBindings: DefaultButtonBindings

    # =======================================================
    # 6. START SERVICES
    # =======================================================
    - name: Reload Systemd and Start
      systemd:
        daemon_reload: yes

    - name: Enable/Start XVNC Socket
      systemd:
        name: xvnc.socket
        state: started
        enabled: yes

    - name: Enable/Start noVNC
      systemd:
        name: novnc
        state: started
        enabled: yes

How to Use

1. Run the Playbook

On the server (requires Ansible):

sudo apt install ansible
ansible-playbook -i "localhost," -c local setup_motif_novnc.yml