<!DOCTYPE html><html><head><title></title><style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style></head><body><div>Yeah, so far we (tailscale) haven't found a good way to run on the Steam Deck at bootup, and also survive the A/B OS updates. Systemd system extensions _can_ be activated during bootup, if you place the extension in one of the well-known locations (/var/lib/extensions would be the one to use on Deck, as iirc it survives A/B upgrades), and the systemd-sysext service is enabled.<br></div><div><br></div><div>I would check if systemd-sysext.service is enabled on the deck, and if not, file a request with Valve to enable that service in a future update. You should present it as enabling further customization of their platform.<br></div><div><br></div><div>Another possible reason that sysexts aren't working for you, is that the Deck's /etc/os-release doesn't define a SYSEXT_LEVEL, and the VERSION_ID changes with every OS update. Because of this, the system extension will refuse to activate after every update (either SYSEXT_LEVEL or VERSION_ID must match exactly), until you rebuild a new image with the right OS metadata. Asking Valve to set SYSEXT_LEVEL to a stable value would make it even easier to provide Deck OS extensions reliably :)<br></div><div><br></div><div>- Dave<br></div><div><br></div><div>On Thu, Oct 6, 2022, at 12:08, Arian van Putten wrote:<br></div><blockquote type="cite" id="qt" style=""><div dir="auto"><div><div>Afaik Portable services run in an isolated root and dont have access to the hosts rootfs.  You'd have go include iptables and all its dependencies in the portable services directory. If you don't want to do that you'd have to use BindReadOnlyPaths= to give the service access to the required host paths or you'd have to use a system extension.<br></div><div dir="auto"><br></div><div dir="auto">That's probably why they advice running as a system extension. <br></div><div dir="auto"><br></div><div dir="auto"><div>I think there are mechanisms for setting up system extensions on startup but I'm not familiar enough with the details. Maybe someone else in the list knows.<br></div><div dir="auto"><div dir="auto"><br></div><div dir="auto"><br></div></div></div><div><br></div><div><br></div><div class="qt-gmail_quote"><div dir="ltr" class="qt-gmail_attr">On Thu, 6 Oct 2022, 20:21 Duncan Gibson, <<a href="mailto:legowerewolf@gmail.com">legowerewolf@gmail.com</a>> wrote:<br></div><blockquote class="qt-gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(204, 204, 204);border-left-style:solid;border-left-width:1px;padding-left:1ex;"><div dir="ltr"><div>Hi, everyone.<br></div><div><br></div><div>The high-level overview: I'm trying to install <a href="https://tailscale.com/" target="_blank" rel="noreferrer">Tailscale</a> as a portable service on my Steam Deck. <br></div><div><br></div><div>Tailscale is a point-to-point VPN service, essentially a wrapper around Wireguard that helps with network setup and management. The Steam Deck is Valve's handheld PC running SteamOS 3, which is derived from Arch. It uses an A/B partition system for system files, meaning you can't install a service the normal way.<br></div><div><br></div><div>There <i>is</i> <a href="https://tailscale.com/blog/steam-deck/" target="_blank" rel="noreferrer">a guide to do this</a>, posted on their own blog, but it uses system extensions which aren't good for services that you want to run on startup. Indeed, following that guide puts me in a state where I have to manually start the daemon every time I reboot my Deck, even with the service enabled.<br></div><div><br></div><div>Let's move on to how I've started to do this.<br></div><div><br></div><div>Tailscale is available through most package managers, but they also publish <a href="https://pkgs.tailscale.com/stable/#static" target="_blank" rel="noreferrer">static binaries with systemd unit files</a>. <br></div><div><br></div><div>This script grabs that binary, extracts it, and moves it into a portable service directory structure.<br></div><div><br></div><div><div style="color:rgb(201, 209, 217);background-color:rgb(13, 17, 23);font-family:"Fira Code", "Cascadia Code", Consolas, "Courier New", monospace, Consolas, "Courier New", monospace;font-weight:normal;font-size:14px;line-height:19px;white-space:pre-wrap;"><div><span style="color:rgb(139, 148, 158);"># download and extract Tailscale</span><br></div><div><span style="color:rgb(201, 209, 217);">tarball=</span><span style="color:rgb(165, 214, 255);">"$(curl -s '<a href="https://pkgs.tailscale.com/stable/?mode=json" target="_blank" rel="noreferrer">https://pkgs.tailscale.com/stable/?mode=json</a>' </span><span style="color:rgb(255, 123, 114);">|</span><span style="color:rgb(165, 214, 255);"> jq -r .Tarballs.amd64)"</span><br></div><div><span style="color:rgb(201, 209, 217);">version=</span><span style="color:rgb(165, 214, 255);">"$(echo </span><span style="color:rgb(201, 209, 217);">${tarball}</span><span style="color:rgb(165, 214, 255);"> </span><span style="color:rgb(255, 123, 114);">|</span><span style="color:rgb(165, 214, 255);"> cut -d_ -f2)"</span><br></div><div><span style="color:rgb(201, 209, 217);">tar_dir=</span><span style="color:rgb(165, 214, 255);">"$(echo </span><span style="color:rgb(201, 209, 217);">${tarball}</span><span style="color:rgb(165, 214, 255);"> </span><span style="color:rgb(255, 123, 114);">|</span><span style="color:rgb(165, 214, 255);"> cut -d. -f1-3)"</span><br></div><div><span style="color:rgb(201, 209, 217);">curl -s </span><span style="color:rgb(165, 214, 255);">"<a href="https://pkgs.tailscale.com/stable/" target="_blank" rel="noreferrer">https://pkgs.tailscale.com/stable/</a></span><span style="color:rgb(201, 209, 217);">${tarball}</span><span style="color:rgb(165, 214, 255);">"</span><span style="color:rgb(201, 209, 217);"> -o tailscale.tgz</span><br></div><div><span style="color:rgb(201, 209, 217);">tar xzf tailscale.tgz</span><br></div><div><span style="color:rgb(121, 192, 255);">test</span><span style="color:rgb(201, 209, 217);"> -d $tar_dir</span><br></div><div><br></div><div><span style="color:rgb(139, 148, 158);"># Set up our target directory structure</span><br></div><div><span style="color:rgb(201, 209, 217);">mkdir -p tailscaled/{usr/{bin,sbin,lib/systemd/system},etc,proc,sys,dev,run,/var/tmp}</span><br></div><div><br></div><div><span style="color:rgb(139, 148, 158);"># Copy tailscale-distributed files to the right place</span><br></div><div><span style="color:rgb(201, 209, 217);">cp -rf $tar_dir/tailscaled tailscaled/usr/sbin/tailscaled</span><br></div><div><span style="color:rgb(201, 209, 217);">cp -rf $tar_dir/systemd/tailscaled.service tailscaled/usr/lib/systemd/system/tailscaled.service</span><br></div><div><br></div><div><span style="color:rgb(139, 148, 158);"># Write service os-release file</span><br></div><div><span style="color:rgb(121, 192, 255);">source</span><span style="color:rgb(201, 209, 217);"> /etc/os-release</span><br></div><div><span style="color:rgb(201, 209, 217);">cp -rf /etc/os-release tailscaled/etc/os-release</span><br></div></div></div><div><br></div><div>Not automated yet is patching the provided unit file - you need to remove the EnvironmentFile line and "--port $PORT $FLAGS" options, and add <br></div><div><div style="color:rgb(201, 209, 217);background-color:rgb(13, 17, 23);font-family:"Fira Code", "Cascadia Code", Consolas, "Courier New", monospace, Consolas, "Courier New", monospace;font-weight:normal;font-size:14px;line-height:19px;white-space:pre-wrap;"><div><span style="color:rgb(201, 209, 217);">[Exec]</span><br></div><div><span style="color:rgb(255, 123, 114);">Environment</span><span style="color:rgb(201, 209, 217);">=</span><span style="color:rgb(165, 214, 255);">"PATH=/usr/bin"</span><br></div></div></div><div><br></div><div>Attach the portable service: <span style=""><span class="font" style="font-family:monospace;">sudo portablectl attach ./tailscaled --profile=trusted</span></span><br></div><div>and try starting it: <span style=""><span class="font" style="font-family:monospace;">sudo systemctl start tailscaled</span></span><br></div><div><br></div><div>It fails, leaving this in the logs:<br></div><div><br></div><div><code>logtail started </code><br></div><div><code>Program starting: v1.30.2-t24c524c78-gc399ae6fa, Go 1.19.1-tsb13188dd36: []string{"/usr/sbin/tailscaled", "--state=/var/lib/tailscale/tailscaled.state", "--socket=/run/tailscale/tailscaled.sock"} </code><br></div><div><code>LogID: 0f59ed267a2b19cc28aac9ee7119914000ca478234af8d56893a025ae72cc647 </code><br></div><div><code>logpolicy: using $STATE_DIRECTORY, "/var/lib/tailscale" </code><br></div><div><code>wgengine.NewUserspaceEngine(tun "tailscale0") ... </code><br></div><div><code>wgengine.NewUserspaceEngine(tun "tailscale0") error: creating router: could not get iptables version: fork/exec /usr/bin/iptables: no such file or directory
flushing log. </code><br></div><div><code>logger closing down </code><br></div><div><code>createEngine: creating router: could not get iptables version: fork/exec /usr/bin/iptables: no such file or directory</code><br></div><div><br></div><div>iptables is, in fact, at /usr/bin/iptables, so what am I missing? Before I added the Environment line, I was getting errors that iptables wasn't on the PATH, so I suspect that now tailscaled can <i>see</i> iptables, but systemd isn't letting tailscaled run it.<br></div><div><br></div><div>Thanks for having a look at this.<br></div><div><div style="margin-left:40px;"><br></div></div></div></blockquote></div></div></div></blockquote><div><br></div></body></html>