Skip to content

Conversation

@zombiezen
Copy link
Contributor

@zombiezen zombiezen commented Dec 7, 2022

I've QA'd this manually and was able to connect to my Tailnet.

Unfortunately, I couldn't get the tailscale up to work as nicely in this model because the entrypoint does not have access to the Codespaces secrets. OTOH, this is now a one-time inconvenience and allows the user to go through the interactive login flow rather than always having to generate a key, since the state is persisted.

I was also dismayed that the user has to add runArgs, but the Dev Container spec does not include a metadata key for that. The spec is still evolving and it's probably just an oversight, so I've opened devcontainers/spec#153 to see if we can get that fixed.

I added a GitHub Actions workflow to publish the feature to GitHub Container Registry. The preferred distribution mechanism for Dev Container features is Docker images, but it doesn't matter what registry you use if you want to host elsewhere. I wasn't able to test the image deployment, so you may need to hack on it a little bit to get it to work. LMK if I can help.

Fixes #5

@zombiezen
Copy link
Contributor Author

@DentonGentry Would you be able to review this (or find someone who could)? I think this would simplify the Tailscale experience on GitHub Codespaces pretty dramatically. You would also need to update https://tailscale.com/kb/1160/github-codespaces/ with the new instructions: I've updated the README with the basic gist and some supporting links to assist.

@domkm
Copy link

domkm commented Dec 8, 2022

@zombiezen This looks very useful. How would one use it prior to Tailscale merging this PR? I attempted to publish it but the Action failed with:

[2022-12-08T23:26:08.714Z] (!) ERR: Failed to fetch devcontainer-collection.json
Error: The process '/usr/local/bin/devcontainer' failed with exit code 1
Error: (!) Failed to publish features.

@zombiezen
Copy link
Contributor Author

I tested locally by copying the tailscale feature directory to .devcontainer/tailscale and adding to the devcontainer.json file:

"runArgs": ["--device=/dev/net/tun"],
"features": {
  // ...
  "./tailscale": {}
  // ...
}

@domkm
Copy link

domkm commented Dec 9, 2022

@zombiezen Thanks. That built successfully but running sudo tailscale up --netfilter-mode=off or tailscale up errors with failed to connect to local tailscaled; it doesn't appear to be running (sudo systemctl start tailscaled ?). Running sudo systemctl start tailscaled errors with sudo: systemctl: command not found.

EDIT: Also, sudo tailscaled errors with getLocalBackend error: createEngine: tstun.New("tailscale0"): CreateTUN("tailscale0") failed; /dev/net/tun does not exist despite "runArgs": ["--device=/dev/net/tun"].

EDIT: Following this seems to fix the issue running sudo tailscaled.

@zombiezen
Copy link
Contributor Author

@domkm Was this running on GitHub Codespaces or on your local machine? Can you post both the devcontainer.json file and the content of the container file /tmp/tailscaled.log?

@domkm
Copy link

domkm commented Dec 9, 2022

@zombiezen Codespaces.


Here is likely the most relevant part of devcontainer.json:

  "dockerComposeFile": "../docker-compose.yml",
  "service": "devcontainer",
  "workspaceFolder": "/app/",
  "overrideCommand": true,
  "postStartCommand": "cp --update /opt/build/poetry/poetry.lock /app/ && mkdir -p /app/.git/hooks/ && cp --update /opt/build/git/* /app/.git/hooks/",
  "runArgs": ["--device=/dev/net/tun"],
  "features": {
    "./tailscale": {}
  },

You'd need at least the full devcontainer.json, Dockerfile, and docker-compose.yml to replicate it exactly, which will get unwieldy here because GitHub doesn't support attachments. However, it was set up with https://github.com/radix-ai/poetry-cookiecutter, so you should be able to generate the same code easily.


cat /tmp/tailscaled.log
cat: /tmp/tailscaled.log: No such file or directory

@zombiezen
Copy link
Contributor Author

What's the base distribution for the container image? And is there anything relevant in the container file /workspaces/.codespaces/.persistedshare/creation.log?

If nothing else, I'm suspecting that overrideCommand is preventing the entrypoint from starting tailscaled automatically.

@domkm
Copy link

domkm commented Dec 9, 2022

python:3.11-slim

I see a few error exits in /workspaces/.codespaces/.persistedshare/creation.log:

2022-12-09 21:35:01.936Z: $ /usr/bin/zsh -lic echo -n 5b0d7170f4e1fc937c32b6b7953535a1; cat /proc/self/environ; echo -n 5b0d7170f4e1fc937c32b6b7953535a1
2022-12-09 21:35:01.936Z: 
2022-12-09 21:35:01.936Z: 
2022-12-09 21:35:01.936Z: Exit code 1
2022-12-09 21:35:01.936Z: && echo '2022-12-09T18:07:08.51809921Z' > '/home/app/.vscode-remote/data/Machine/.onCreateCommandMarker'
2022-12-09 21:35:01.936Z: $08.51809921Z' > '/home/app/.vscode-remote/data/Machine/.updateContentCommandMarker'
2022-12-09 21:35:01.936Z: 
2022-12-09 21:35:01.936Z: 
2022-12-09 21:35:01.936Z: Exit code 1
2022-12-09 21:35:01.936Z: && echo '2022-12-09T18:07:08.51809921Z' > '/home/app/.vscode-remote/data/Machine/.updateContentCommandMarker'
2022-12-09 21:35:01.936Z: $08.51809921Z' > '/home/app/.vscode-remote/data/Machine/.postCreateCommandMarker'
2022-12-09 21:35:01.936Z: 
2022-12-09 21:35:01.936Z: 
2022-12-09 21:35:01.936Z: Exit code 1
2022-12-09 21:35:01.936Z: && echo '2022-12-09T18:07:08.51809921Z' > '/home/app/.vscode-remote/data/Machine/.postCreateCommandMarker'
2022-12-09 21:35:01.936Z: $54.365547483Z' > '/home/app/.vscode-remote/data/Machine/.postStartCommandMarker'
2022-12-09 21:35:01.963Z: 
2022-12-09 21:35:01.963Z: 
2022-12-09 21:35:01.963Z: && echo '2022-12-09T21:34:54.365547483Z' > '/home/app/.vscode-remote/data/Machine/.postStartCommandMarker'
2022-12-09 21:35:01.963Z: Running the postStartCommand from devcontainer.json...
2022-12-09 21:35:01.963Z: 
2022-12-09 21:35:02.215Z: Stop (288 ms): Run in container: /usr/bin/zsh -lic echo -n 5b0d7170f4e1fc937c32b6b7953535a1; cat /proc/self/environ; echo -n 5b0d7170f4e1fc937c32b6b7953535a1
2022-12-09 21:35:02.215Z: userEnvProbe PATHs:
2022-12-09 21:35:02.215Z: Probe:     '/opt/app-env/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/home/app/.antigen/bundles/zsh-users/zsh-syntax-highlighting:/home/app/.antigen/bundles/zsh-users/zsh-autosuggestions'
2022-12-09 21:35:02.215Z: Container: '/opt/app-env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
2022-12-09 21:35:02.215Z: $ /bin/sh -c cp --update /opt/build/poetry/poetry.lock /app/ && mkdir -p /app/.git/hooks/ && cp --update /opt/build/git/* /app/.git/hooks/
2022-12-09 21:35:02.299Z: Stop (95 ms): Run in container: /bin/sh -c cp --update /opt/build/poetry/poetry.lock /app/ && mkdir -p /app/.git/hooks/ && cp --update /opt/build/git/* /app/.git/hooks/

@zombiezen
Copy link
Contributor Author

Really seems like the entry point isn't getting called. Try removing the overrideCmd from your devcontainer.json.

README.md Outdated
Then launch your Codespace. After it starts up, run [`tailscale up`](https://tailscale.com/kb/1080/cli/#up):

```shell
sudo tailscale up --netfilter-mode=off
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could I ask why it sets --netfilter-mode=off? I wouldn't expect to need this in codespaces.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll defer to you: I was cargo-culting from 94af521 Removed for now, since I was able to QA without it and it seemed to work.

script_dir="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
scratch_dir="/tmp/tailscale"
mkdir -p "$scratch_dir"
trap 'rm -rf "$scratch_dir"' EXIT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this line: it seems like it deletes the /tmp/tailscale directory which the previous line should have just created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trap ... EXIT can be thought of like a defer in Go. It runs a command once the shell exits. More docs here: https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html

@nikolarobottesla
Copy link

FYI, This branch worked for me without issue. (once I added curl to my container)

I used the method described here: #6 (comment)

devcontainer.json

{
    "name": "Tailscale-Ansible Codespace",
    "dockerFile": "Dockerfile",
    "context": "..",
    "runArgs": ["--device=/dev/net/tun"],
    "features": {
    "./tailscale": {}
    }
}

Dockerfile

FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl gpg dnsutils git python3 python3-pip
RUN pip3 install ansible

Copy link
Contributor

@DentonGentry DentonGentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good. I'll merge it when a PR for the knowledgebase article is ready to merge along with it.

@mayakacz
Copy link

mayakacz commented Jan 3, 2023

@DentonGentry DentonGentry merged commit 36ff242 into tailscale:main Jan 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement as Dev Container "feature"?

5 participants