Jetson Nano Headless Rendering

I found a solution! Turns out the .Xauthority file was only readable by the user, which was at the root of the segfault. Here are the steps I took to enable a shared X server that is automatically started on a headless board.

  1. Switch from graphical target to multi-user target
    > sudo systemctl set-default multi-user.target
    
  2. Create new dummy user that will auto login and launch X
    > sudo adduser startup
    

    choose a password (can leave other fields blank)

  3. Add the following at the end of the dummy user's .bashrc to automatically start X on login
    # Start X Server if no DISPLAY
    if [ -z "$DISPLAY" ]
    then
      DISPLAY=:0.0 glxinfo > /dev/null 2>&1
      if [ $? -ne 0 ]
      then
        echo "starting new x server at :0.0" > .xout.log
        startx -- :0 > /dev/null 2>&1 &
        sleep 5
        DISPLAY=:0.0 xhost + >> .xout.log 2>&1
      else
        echo "connecting to existing x server at :0.0"
      fi
      export DISPLAY=:0.0
    else
      echo "already configured for x server at $DISPLAY"
    fi
    
  4. Create .Xauthority file with proper read permissions
    > touch .Xauthority
    > chmod 644 .Xauthority
    
  5. Automatically log in dummy user on boot
    > sudo systemctl edit getty@tty1
    

    Add the following and save

    [Service]
    ExecStart=
    ExecStart=-/sbin/agetty -a startup --noclear %I $TERM
    
  6. Reboot

After this, any other user can connect via SSH and run programs that depend on X. One note is that the DISPLAY variable is not automatically set, so users will have to either prepend commands with DISPLAY=:0.0 or export DISPLAY=:0.0.