From e2bbb611eaed34d95ce482986f6f512a77e0d593 Mon Sep 17 00:00:00 2001 From: Brandon Schneider Date: Tue, 19 May 2026 09:18:40 +0000 Subject: [PATCH] devcontainer: bake Tailscale static binary into Alpine image - Add iproute2 to apk dependencies (needed by tailscaled) - Download latest Tailscale stable release at build time via pkgs.tailscale.com and install tailscale + tailscaled to /usr/local/bin - Write a _ts_start() shell function into /home/researcher/.bashrc that: - starts tailscaled in userspace-networking mode (no TUN device, no root) - uses a per-user socket at ~/.local/share/tailscale/tailscaled.sock - is a no-op if the daemon is already running Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .devcontainer/Dockerfile | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 89b1009c..88201428 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -39,8 +39,20 @@ RUN apk add --no-cache \ bzip2-dev \ # rclone (Google Drive / S3 / etc.) rclone \ + # ip / iproute2 needed by tailscaled + iproute2 \ && : +# ── Tailscale (static binary — userspace networking, no root required) ──────── +RUN TSVER=$(curl -fsSL https://pkgs.tailscale.com/stable/ \ + | grep -oP 'tailscale_\K[0-9]+\.[0-9]+\.[0-9]+(?=_amd64\.tgz)' \ + | sort -V | tail -1) \ + && curl -fsSL "https://pkgs.tailscale.com/stable/tailscale_${TSVER}_amd64.tgz" \ + | tar -xz -C /tmp/ \ + && install -m 755 /tmp/tailscale_${TSVER}_amd64/tailscale /usr/local/bin/tailscale \ + && install -m 755 /tmp/tailscale_${TSVER}_amd64/tailscaled /usr/local/bin/tailscaled \ + && rm -rf /tmp/tailscale_${TSVER}_amd64 + # ── uv package manager ──────────────────────────────────────────────────────── RUN pipx install uv && cp /root/.local/bin/uv /usr/local/bin/uv && cp /root/.local/bin/uvx /usr/local/bin/uvx @@ -105,6 +117,27 @@ RUN curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh - # ── PATH ────────────────────────────────────────────────────────────────────── ENV PATH="/home/researcher/.elan/bin:/home/researcher/venv/bin:/home/researcher/.local/bin:${PATH}" +# ── Tailscale userspace auto-start snippet (written as researcher) ──────────── +RUN mkdir -p /home/researcher/.local/share/tailscale && \ + printf '%s\n' \ + '# ── Tailscale (userspace, no root required) ─────────────────────────────' \ + 'export TAILSCALE_SOCKET=/home/researcher/.local/share/tailscale/tailscaled.sock' \ + 'alias tailscale="tailscale --socket=$TAILSCALE_SOCKET"' \ + '_ts_start() {' \ + ' if ! /usr/local/bin/tailscale --socket=$TAILSCALE_SOCKET status &>/dev/null; then' \ + ' mkdir -p /home/researcher/.local/share/tailscale' \ + ' /usr/local/bin/tailscaled \\' \ + ' --tun=userspace-networking \\' \ + ' --socket=$TAILSCALE_SOCKET \\' \ + ' --statedir=/home/researcher/.local/share/tailscale/ \\' \ + ' --outbound-http-proxy-listen=localhost:1055 \\' \ + ' &>>/home/researcher/.local/share/tailscale/tailscaled.log &' \ + ' sleep 2' \ + ' fi' \ + '}' \ + '_ts_start' \ + >> /home/researcher/.bashrc + # ── rclone S3 gateway init script ───────────────────────────────────────────── COPY --chown=researcher:researcher .devcontainer/init-rclone-s3.sh /home/researcher/init-rclone-s3.sh RUN chmod +x /home/researcher/init-rclone-s3.sh