Document fully standalone fully offline process #152

Open
opened 2026-06-27 19:10:29 +02:00 by utopiah · 15 comments
Owner

How to boot to WebXR, even offline :

preview

  • install Termux on device (requires developer mode)
  • install Termux:Boot (optionally setup ssh for convenience and set it up to start at boot)
  • in Termux install nodejs and git
  • clone this repository and follow the self hosted instructions for offline workshops
  • make a termux:Boot file for backend, e.g. cd ~/Prototypes/biggu/ ; HTTPS=true PORT=8081 npm run start
  • make another termux:Boot file to open the page at boot, via e.g. starting Wolvic or Meta Browser to open at https://localhost:8081

Note that none of the step documented here, beside optional rooting, risks bricking your device. At the very worst (which I can't imagine) you can always factory reset the headset by booting while holding the power and volume (-) buttons.

How to boot to WebXR, even offline : [![preview](https://video.benetou.fr/lazy-static/thumbnails/6db6bfb1-b6eb-4a3e-a2c1-a4ab6759a0c8.jpg)](https://video.benetou.fr/w/hb2PWdsfZqJAkuJHPwGW13) - install Termux on device (requires developer mode) - install Termux:Boot (optionally setup ssh for convenience and set it up to start at boot) - in Termux install nodejs and git - clone this repository and follow the [self hosted instructions](https://git.benetou.fr/utopiah/biggu_s_gate/src/branch/main/documentation#setup-for-fully-offline-workshop) for offline workshops - make a termux:Boot file for backend, e.g. cd ~/Prototypes/biggu/ ; HTTPS=true PORT=8081 npm run start - make another termux:Boot file to open the page at boot, via e.g. starting Wolvic or Meta Browser to open at https://localhost:8081 Note that none of the step documented here, beside optional rooting, risks bricking your device. At the very worst (which I can't imagine) you can always [factory reset the headset](https://www.meta.com/en-gb/help/quest/149134797159340/) by booting while holding the power and volume (-) buttons.
Author
Owner

Consider https://git.benetou.fr/utopiah/spasca-fot-sloan-q4/src/branch/main/data/index.html#L24

const aevrq = urlParams.get('autoenter_vr_quest');
if (aevrq && aevrq.length>1) setTimeout( _ => { AFRAME.scenes[0].enterVR() }, 2000) 

after chrome://flags disable "webxr user activation requirement"

thus instead opening https://localhost:8081/games.html?autoenter_vr_quest=true

Can be facilitated by opening via adb or ssh

am start -n com.oculus.vrshell/.MainActivity -d apk://com.oculus.browser -e uri chrome://flags/#webxr-enforce-user-activation

Consider https://git.benetou.fr/utopiah/spasca-fot-sloan-q4/src/branch/main/data/index.html#L24 ```javascript const aevrq = urlParams.get('autoenter_vr_quest'); if (aevrq && aevrq.length>1) setTimeout( _ => { AFRAME.scenes[0].enterVR() }, 2000) ``` after chrome://flags disable "webxr user activation requirement" thus instead opening https://localhost:8081/games.html?autoenter_vr_quest=true Can be facilitated by opening via adb or ssh `am start -n com.oculus.vrshell/.MainActivity -d apk://com.oculus.browser -e uri chrome://flags/#webxr-enforce-user-activation`
Author
Owner

Files in ~/.termux/Boot

start-sshd

As per official Termux documentation

#!/data/data/com.termux/files/usr/bin/sh
termux-wake-lock
sshd

start-webxr

sleep 20
am start -n com.oculus.vrshell/.MainActivity -d apk://com.oculus.browser -e uri https://localhost:8081/games.html?autoenter_vr_quest=true

start-webxr-backend

cd ~/Prototypes/biggu_s_gate ; HTTPS=true PORT=8081 npm start

Unfortunately unable to make this work on Wolvic due to

Files in `~/.termux/Boot` ## start-sshd As per official Termux documentation ``` #!/data/data/com.termux/files/usr/bin/sh termux-wake-lock sshd ``` ## start-webxr ``` sleep 20 am start -n com.oculus.vrshell/.MainActivity -d apk://com.oculus.browser -e uri https://localhost:8081/games.html?autoenter_vr_quest=true ``` ## start-webxr-backend ``` cd ~/Prototypes/biggu_s_gate ; HTTPS=true PORT=8081 npm start ``` Unfortunately unable to make this work on Wolvic due to - https://github.com/Igalia/wolvic/issues/1615 - https://github.com/Igalia/wolvic/issues/2014
Author
Owner

Consider adb shell am start -n com.android.settings/.Settings\$NetworkDashboardActivity (via https://stackoverflow.com/a/78723088/1442164 ) to add self-signed certificate, as unfortunately booting to immersive WebXR mode works online, with WiFi on at least, but not with WiFi off because it prompts for user interaction due to unknown certificate.

If the command above fails, can happy on Quest 2 with permission problems, try instead adb shell monkey -p com.android.settings -v 500 then go back. If somehow the back button fails then go on Settings, then open. You will get to Android global settings (no Quest settings, Android proper). From there :

  1. Security & privacy
  2. More security & privacy
  3. Encryption & credentials
  4. Install a certificate
  5. CA certificate
  6. Install anyway
  7. then locate the certificate file you generated from your local server
image.png

Note that using scrcpy allows one to do that setup without putting the headset one.

To select the right window, check resolution, e.g.

scrcpy --list-displays
[server] INFO: List of displays:
    --display-id=0    (10992x8000)...
    --display-id=40    (500x800)
    --display-id=78    (500x800)

shows 2 interesting windows, that have the typical setting size, namely 500x800 with display ID create chronologically.

Consequently one could use scrcpy --display-id=40 --no-audio first to open the settings app.

Then use the new scrcpy --display-id=78 --no-audio to actually configure the certificate settings.

Consider `adb shell am start -n com.android.settings/.Settings\$NetworkDashboardActivity` (via https://stackoverflow.com/a/78723088/1442164 ) to add self-signed certificate, as unfortunately booting to immersive WebXR mode works online, with WiFi on at least, but not with WiFi off because it prompts for user interaction due to unknown certificate. If the command above fails, can happy on Quest 2 with permission problems, try instead `adb shell monkey -p com.android.settings -v 500` then go back. If somehow the back button fails then go on Settings, then open. You will get to Android global settings (no Quest settings, Android proper). From there : 1. Security & privacy 2. More security & privacy 3. Encryption & credentials 4. Install a certificate 5. CA certificate 6. Install anyway 7. then locate the certificate file you generated from your local server <img width="521" alt="image.png" src="attachments/3a277999-c5d9-4630-82d9-acb433b29d16"> Note that using `scrcpy` allows one to do that setup without putting the headset one. To select the right window, check resolution, e.g. ``` scrcpy --list-displays [server] INFO: List of displays: --display-id=0 (10992x8000)... --display-id=40 (500x800) --display-id=78 (500x800) ``` shows 2 interesting windows, that have the typical setting size, namely 500x800 with display ID create chronologically. Consequently one could use `scrcpy --display-id=40 --no-audio` first to open the settings app. Then use the new `scrcpy --display-id=78 --no-audio` to actually configure the certificate settings.
Author
Owner

Adding a SAN to self-signed certificate via -addext 'subjectAltName = localhost' then installing that certificate.

That could be generated with e.g. openssl req -x509 -newkey rsa:3072 -nodes -keyout .https8443_key -out .https8443_certificate -extensions SAN -config <( echo "[SAN]\nsubjectAltName = localhost") -sha256 -days 995 -subj "/CN=localhost" but to verify as SAN is a relatively recent Chromium requirement and can be finicky.

PS: similar problem with CopyParty. Installing the generated certificate from /data/data/com.termux/files/home/.config/copyparty/cert.pem is not enough due to the lack of that field. It still creates a warning. Consider then --no-crt --cert server.crt --certkey server.key thus here python copyparty-sfx.py --allow-csrf --no-crt --cert ~/Prototypes/biggu_s_gate/server/cert.pem --certkey ~/Prototypes/biggu_s_gate/server/key.pem. This can then be added to ~/.termux/boot/copyparty and could be usable in WebXR locally. Through express-http-proxy it becomes usable while allowing CSRF in CopyParty. Note though that it would not be usable offline as the CopyParty server would be unreachable and the Quest can't be its own AP (feasible but requires root). Consider forcing more broadly via reverse proxy decorators https://github.com/villadora/express-http-proxy/issues/11#issuecomment-455706678

Adding a SAN to self-signed certificate via `-addext 'subjectAltName = localhost'` then installing that certificate. That could be generated with e.g. `openssl req -x509 -newkey rsa:3072 -nodes -keyout .https8443_key -out .https8443_certificate -extensions SAN -config <( echo "[SAN]\nsubjectAltName = localhost") -sha256 -days 995 -subj "/CN=localhost"` but to verify as SAN is a relatively recent Chromium requirement and can be finicky. PS: similar problem with CopyParty. Installing the generated certificate from `/data/data/com.termux/files/home/.config/copyparty/cert.pem` is not enough due to the lack of that field. It still creates a warning. Consider then `--no-crt --cert server.crt --certkey server.key` thus here `python copyparty-sfx.py --allow-csrf --no-crt --cert ~/Prototypes/biggu_s_gate/server/cert.pem --certkey ~/Prototypes/biggu_s_gate/server/key.pem`. This can then be added to `~/.termux/boot/copyparty` and could be usable in WebXR locally. Through `express-http-proxy` it becomes usable while allowing CSRF in CopyParty. Note though that it would not be usable offline as the CopyParty server would be unreachable and the Quest can't be its own AP (feasible but requires root). Consider forcing more broadly via reverse proxy decorators https://github.com/villadora/express-http-proxy/issues/11#issuecomment-455706678
Author
Owner

preview

Demo in 1min

[![preview](https://video.benetou.fr/lazy-static/thumbnails/6db6bfb1-b6eb-4a3e-a2c1-a4ab6759a0c8.jpg)](https://video.benetou.fr/w/hb2PWdsfZqJAkuJHPwGW13) Demo in 1min
Author
Owner

The process could be facilitated via WebUSB and potentially JavaScript libraries focusing on WebADB. GrapheneOS is using its WebInstaller but seems focused on fastboot which is too low level. Consider also https://github.com/GoogleChromeLabs/wadb

It would still requires developer mode, and validate access, but could make the setup easier for people who are not familiar with the console.

The process could be facilitated via WebUSB and potentially JavaScript libraries focusing on WebADB. GrapheneOS is using [its WebInstaller](https://github.com/GrapheneOS/grapheneos.org/blob/main/static/js/web-install.js) but seems focused on fastboot which is too low level. Consider also https://github.com/GoogleChromeLabs/wadb It would still requires developer mode, and validate access, but could make the setup easier for people who are not familiar with the console.
Author
Owner

Note also that since there is no introduction step, no room setup, no UI from the OS, one has to assume the user must be introduced to nearly everything.

In a novel space room setup will be prompted though, so consider some explanations e.g. https://copyparty.benetou.fr/Prototypes/ada_biggu_setup_steps/readme.md?v#lost-in-space-boundary-setup

It also means consideration on what to do when leaving, accidentally of not, immersive mode. See e.g. #38 (comment)

Note also that since there is no introduction step, no room setup, no UI from the OS, one has to assume the user must be introduced to nearly everything. In a novel space room setup will be prompted though, so consider some explanations e.g. https://copyparty.benetou.fr/Prototypes/ada_biggu_setup_steps/readme.md?v#lost-in-space-boundary-setup It also means consideration on what to do when leaving, accidentally of not, immersive mode. See e.g. https://git.benetou.fr/utopiah/biggu_s_gate/issues/38#issuecomment-1885
Author
Owner

Quest 2 test

  • via Privacy Quest, developer mode working via USB cable even though no visible option
  • Termux + Termux.Boot installed via F-Droid .apk download links then adb install
  • Termux can be started via adb but then not usable, launch from HMD instead (could look for the right intent or activity)
  • adb shell monkey -p com.termux 1 works
  • adb shell monkey -p com.termux.boot 1 works
  • pkg update; pkg upgrade -y ; pkg install -y vim openssh; sshd; whoami; passwd; does most of what must be done but upgrade needs few validations steps, obviously passwd too
  • scrcpy allows for typing in adb and thus easier ssh setup, needs the Termux window to be focused though (could see https://fabien.benetou.fr/Tools/Android to potentially directly only the right window, unfortunately specific the display seems to prevent keyboard usage, despite mouse working)
  • because the Termux setup steps are always the same, could be easier to adb push a script file with
    • pkg install openssh
    • mkdir .termux/boot
    • could echo the content of start-sshd in its file
    • whoami to get ssh username
    • passwd (which must be used interactively it seems, maybe adb shell input text exampleoftext could help)
    • sshd
    • ssh-copy-id for passwordless login
Quest 2 test - via [Privacy Quest](https://xdaforums.com/t/app-5-0-private-quest-vr-headset-management-tool.4695491/), developer mode working via USB cable even though no visible option - [Termux](https://f-droid.org/en/packages/com.termux/) + [Termux.Boot](https://f-droid.org/en/packages/com.termux.boot/) installed via F-Droid .apk download links then `adb install` - Termux can be started via `adb` but then not usable, launch from HMD instead (could look for the right intent or activity) - `adb shell monkey -p com.termux 1` works - `adb shell monkey -p com.termux.boot 1` works - `pkg update; pkg upgrade -y ; pkg install -y vim openssh; sshd; whoami; passwd;` does most of what must be done but upgrade needs few validations steps, obviously passwd too - `scrcpy` allows for typing in adb and thus easier `ssh` setup, needs the Termux window to be focused though (could see https://fabien.benetou.fr/Tools/Android to potentially directly only the right window, unfortunately specific the display seems to prevent keyboard usage, despite mouse working) - because the Termux setup steps are always the same, could be easier to `adb push` a script file with - pkg install openssh - mkdir .termux/boot - could echo the content of `start-sshd` in its file - whoami to get ssh username - passwd (which must be used interactively it seems, maybe `adb shell input text exampleoftext` could help) - sshd - ssh-copy-id for passwordless login
Author
Owner

Document also the update process. In theory once online, even if temporarily, git pull && npm i should be enough. Potentially new npm run commands might be required. It might be useful to add a dedicated command to package.json e.g. update_from_repository for git pull && npm i.

Overall it should be much simpler than the first setup.

Document also the update process. In theory once online, even if temporarily, `git pull && npm i` should be enough. Potentially new `npm run` commands might be required. It might be useful to add a dedicated command to `package.json` e.g. `update_from_repository` for `git pull && npm i`. Overall it should be much simpler than the first setup.
Author
Owner

Consider also https://github.com/ptrpaws/quest-ble-client/ in order to avoid terminal commands. It is still quite challenging for some user but shows the way toward a fully Web based setup.

Consider also https://github.com/ptrpaws/quest-ble-client/ in order to avoid terminal commands. It is still quite challenging for some user but shows the way toward a fully Web based setup.
Author
Owner

For headless setup on Q1, thus without PQ, see https://fabien.benetou.fr/Tools/Android#Quest

For headless setup on Q1, thus without PQ, see https://fabien.benetou.fr/Tools/Android#Quest
Author
Owner
  1. set Quest in developer mode
    1. using an official account, go to Meta Website and follow the process
      1. requires a phone and free of cost but require a stronger identification data, e.g. credit card information
      2. consider resetting the device and follow the next step if you want to insure anonymous usage
    2. no account, use Private Quest on another Android device to pair the device, enable developer mode
  2. install Termux and Termux Boot
    1. get the .apk files
    2. use adb via the command line with your device plugged in USB to adb install both
  3. edit the boot script that Termux will load as instructed above
    1. setup the local Web server (with its self-signed certificate)
    2. the trick here is to use am within Termux in order to open the browser pointing to that newly setup server
    3. set parameter in the browser to insure it does automatically enter immersive mode
    4. OS and thus browser accept self-signed certificate (might potentially require rooting, to verify)
  4. boot and test
1. set Quest in developer mode 1. using an official account, go to [Meta Website](https://developers.meta.com/horizon/documentation/native/android/mobile-device-setup/) and follow the process 1. requires a phone and free of cost but require a stronger identification data, e.g. credit card information 2. consider resetting the device and follow the next step if you want to insure anonymous usage 1. no account, use [Private Quest](https://xdaforums.com/t/app-5-0-private-quest-vr-headset-management-tool.4695491/) on another Android device to pair the device, enable developer mode 2. install Termux and Termux Boot 1. get the `.apk` files 2. use `adb` via the command line with your device plugged in USB to `adb install` both 1. edit the boot script that Termux will load as [instructed above](https://git.benetou.fr/utopiah/biggu_s_gate/issues/152#issuecomment-1888) 1. setup the local Web server (with its self-signed certificate) 2. the trick here is to use `am` within Termux in order to open the browser pointing to that newly setup server 3. set parameter in the browser to insure it does automatically [enter immersive mode](https://git.benetou.fr/utopiah/biggu_s_gate/issues/152#issuecomment-1887) 4. OS and thus browser [accept self-signed certificate](https://git.benetou.fr/utopiah/biggu_s_gate/issues/152#issuecomment-1890) (might potentially require rooting, to verify) 1. boot and test
Author
Owner

It is recommended to disable proximity sensor during the setup using

adb shell am broadcast -a com.oculus.vrpowermanager.prox_close

then enable it again after using

adb shell am broadcast -a com.oculus.vrpowermanager.automation_disable

Cf https://gist.github.com/t-34400/3bc5f81d9e40b69072c99d5d640b5c89#proximity-sensor

Consider also disabling guardian so that being out of boundary does not stop the display and thus your interactions with the HMD.

It is recommended to disable proximity sensor during the setup using `adb shell am broadcast -a com.oculus.vrpowermanager.prox_close` then enable it again after using `adb shell am broadcast -a com.oculus.vrpowermanager.automation_disable` Cf https://gist.github.com/t-34400/3bc5f81d9e40b69072c99d5d640b5c89#proximity-sensor Consider also disabling guardian so that being out of boundary does not stop the display and thus your interactions with the HMD.
Author
Owner

Consider WebUSB progress https://mastodon.pirateparty.be/@utopiah/117281115780037587 inspired by GrapheneOS Web setup

Consider WebUSB progress https://mastodon.pirateparty.be/@utopiah/117281115780037587 inspired by GrapheneOS Web setup
Author
Owner

On current Q2 setups (x4) still have to add certificates

On current Q2 setups (x4) still have to add certificates
Sign in to join this conversation.