mirror of
https://github.com/spoopyghosty0/frameport.git
synced 2026-10-06 11:00:57 +02:00
135 lines
6.5 KiB
Bash
135 lines
6.5 KiB
Bash
#!/usr/bin/env bash
|
|
# FramePort one-time Steam Frame setup. Run in the Frame's desktop terminal (SteamVR dashboard -> Launch a program
|
|
# -> Desktop, then System -> Konsole):
|
|
# curl -fsS <pc-ip>:<port>/<code> | bash
|
|
# (the FramePort app shows the exact line and serves this script while its Setup page is open).
|
|
#
|
|
# What it does (no password, no sudo):
|
|
# 1. authorizes the FramePort app's SSH key (no password needed afterwards)
|
|
# 2. configures podman for Lepton (avoids a kernel keyring leak after ~200 game starts)
|
|
# 3. turns on Developer Mode if it's off (Valve's own helper; it also enables the SSH server and announces the
|
|
# Frame on the network as a SteamOS devkit). Steam restarts for that, which closes Desktop Mode: the rest
|
|
# runs on its own as a user service and the Frame returns to its normal view.
|
|
# 4. asks Steam to install Valve's Lepton Android runtime if it's missing, then tells the app it's done
|
|
# Log of the part that runs on its own: ~/.cache/frameport-setup.log
|
|
set -euo pipefail
|
|
PC_URL="__PC_URL__" # filled in by the app when serving the script
|
|
PAIR_CODE="__PAIR_CODE__"
|
|
say() { printf '\n\033[1;36m==> %s\033[0m\n' "$*"; }
|
|
|
|
DEVKIT_HELPER=/usr/bin/steamos-polkit-helpers/steamos-devkit-mode
|
|
STEAM_CONFIG=~/.local/share/Steam/config/config.vdf
|
|
JOB=~/.cache/frameport-setup.sh
|
|
LOG=~/.cache/frameport-setup.log
|
|
|
|
# Desktop Mode on SteamOS is a nested Plasma session inside steam.service, with its own XDG_RUNTIME_DIR and D-Bus:
|
|
# systemctl/systemd-run --user only reach the user's systemd through the real runtime dir.
|
|
user_systemd() {
|
|
XDG_RUNTIME_DIR="/run/user/$(id -u)" DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" "$@"
|
|
}
|
|
|
|
say "FramePort setup for $(hostname) ($(. /etc/os-release; echo "$NAME $VERSION_ID"))"
|
|
|
|
say "Authorizing the FramePort app's key"
|
|
key=$(curl -fsS "$PC_URL/key?code=$PAIR_CODE")
|
|
[[ "$key" == ssh-ed25519\ * ]] || { echo "Could not fetch the app's key from $PC_URL (is the app still open?)"; exit 1; }
|
|
mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
|
|
grep -qxF "$key" ~/.ssh/authorized_keys || echo "$key" >> ~/.ssh/authorized_keys
|
|
|
|
say "Configuring podman for Lepton"
|
|
# rootless podman leaks one kernel keyring per container start; ~200 game launches would exhaust the quota
|
|
mkdir -p ~/.config/containers
|
|
grep -qs '^ *keyring *=' ~/.config/containers/containers.conf || printf '[containers]\nkeyring = false\n' >> ~/.config/containers/containers.conf
|
|
|
|
# The rest: Developer Mode (if needed), Lepton, telling the app. As a file, so it can run as its own user service:
|
|
# stopping Steam ends Desktop Mode and every program started in it, this terminal included.
|
|
mkdir -p ~/.cache
|
|
cat >"$JOB" <<'JOB'
|
|
set -u
|
|
MODE=$1 PC_URL=$2 PAIR_CODE=$3 CONFIG=$4 HELPER=$5
|
|
log() { echo "$(date +%T) $*"; }
|
|
if [[ $MODE == devmode ]]; then
|
|
sleep 5 # let the user read the terminal before Desktop Mode closes
|
|
# Steam re-applies "DevModeEnabled" from config.vdf at every start (calling Valve's helper) and rewrites
|
|
# config.vdf when it exits: stop Steam, set the value, run the helper (pkexec, allowed without a password), start.
|
|
log "stopping Steam"
|
|
systemctl --user stop steam.service
|
|
for _ in $(seq 40); do pgrep -x steam >/dev/null || break; sleep 1; done
|
|
if pgrep -x steam >/dev/null; then
|
|
log "Steam didn't stop"
|
|
systemctl --user start steam.service
|
|
exit 1
|
|
fi
|
|
cp "$CONFIG" "$CONFIG.before-frameport"
|
|
python3 - "$CONFIG" <<'PY'
|
|
import re, sys
|
|
path = sys.argv[1]
|
|
text = open(path, encoding="utf-8").read()
|
|
if re.search(r'"DevModeEnabled"\s+"\d+"', text):
|
|
text = re.sub(r'("DevModeEnabled"\s+)"\d+"', r'\1"1"', text)
|
|
else: # Steam keeps it in InstallConfigStore/developer
|
|
lines, keys, key, at = text.splitlines(keepends=True), [], None, None
|
|
for i, line in enumerate(lines):
|
|
s = line.strip()
|
|
if s == "{":
|
|
keys.append((key or "").lower())
|
|
if keys == ["installconfigstore", "developer"]:
|
|
at = ("in", i, line[:len(line) - len(line.lstrip())] + "\t")
|
|
break
|
|
elif s == "}":
|
|
if keys == ["installconfigstore"]: # end of the top section without a developer block
|
|
at = ("new", i, line[:len(line) - len(line.lstrip())] + "\t")
|
|
break
|
|
keys.pop()
|
|
elif re.fullmatch(r'"[^"]*"', s):
|
|
key = s.strip('"')
|
|
if at is None:
|
|
sys.exit("unexpected config.vdf layout")
|
|
kind, i, ind = at
|
|
if kind == "in":
|
|
lines.insert(i + 1, f'{ind}"DevModeEnabled"\t\t"1"\n')
|
|
else:
|
|
lines[i:i] = [f'{ind}"developer"\n', f"{ind}{{\n", f'{ind}\t"DevModeEnabled"\t\t"1"\n', f"{ind}}}\n"]
|
|
text = "".join(lines)
|
|
open(path, "w", encoding="utf-8").write(text)
|
|
PY
|
|
rc=$?
|
|
[[ $rc == 0 ]] && { "$HELPER" --enable; rc=$?; }
|
|
log "Developer Mode: $([[ $rc == 0 && -f /etc/steamos-devkit-enabled ]] && echo on || echo "failed ($rc)")"
|
|
systemctl --user start steam.service
|
|
[[ $rc == 0 ]] || exit 1
|
|
for _ in $(seq 90); do pgrep -x steam >/dev/null && break; sleep 1; done
|
|
sleep 20 # let Steam finish starting before asking it for anything
|
|
fi
|
|
if [[ -e ~/.local/share/Steam/steamapps/common/Lepton/lepton ]]; then
|
|
log "Lepton found"
|
|
else
|
|
log "asking Steam to install Lepton (confirm it in Steam)"
|
|
steam steam://install/3029110 >/dev/null 2>&1 &
|
|
fi
|
|
if curl -fsS "$PC_URL/paired?code=$PAIR_CODE&user=$(id -un)&host=$(hostname)" >/dev/null; then
|
|
log "told FramePort: done"
|
|
else
|
|
log "couldn't reach FramePort at $PC_URL"
|
|
fi
|
|
JOB
|
|
|
|
if [[ -f /etc/steamos-devkit-enabled ]]; then
|
|
say "Developer Mode is on"
|
|
bash "$JOB" finish "$PC_URL" "$PAIR_CODE" "$STEAM_CONFIG" "$DEVKIT_HELPER" 2>&1 | tee "$LOG"
|
|
say "Done. Return to FramePort on your PC: this Frame should now appear as connected."
|
|
exit 0
|
|
fi
|
|
|
|
say "Turning on Developer Mode"
|
|
if [[ ! -x "$DEVKIT_HELPER" || ! -f "$STEAM_CONFIG" ]] || \
|
|
! user_systemd systemd-run --user --collect --quiet --unit="frameport-setup-$$" \
|
|
bash -c 'bash "$0" "$@" >"$HOME/.cache/frameport-setup.log" 2>&1' \
|
|
"$JOB" devmode "$PC_URL" "$PAIR_CODE" "$STEAM_CONFIG" "$DEVKIT_HELPER"; then
|
|
echo "Couldn't turn it on automatically. Turn it on in Settings > System > Developer, then run this command again."
|
|
exit 1
|
|
fi
|
|
echo "Steam restarts to turn it on. That closes the desktop in a few seconds and the Frame returns to its"
|
|
echo "normal view; setup finishes on its own. If Steam asks to install Lepton, confirm it."
|
|
echo "Then return to FramePort on your PC: the Frame appears as connected within a minute."
|