Skip to content
 
 

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cgwalters-devspace

This repository provides a manually triggered GitHub Actions workflow for a bounded, ephemeral RHEL 10 development runner. It provisions the exact rhel10-x86_64-16c-64g runner requested by infra#257, joins the bootc-dev tailnet with Tailscale workload identity federation, and provides either Tailscale SSH or ordinary OpenSSH for Unix user runner.

Prerequisites

An administrator must configure the non-secret repository variables TS_OAUTH_CLIENT_ID and TS_AUDIENCE. The Tailscale federated identity must allow this exact GitHub subject:

repo:bootc-dev@202312630/cgwalters-*-sandbox@*

The Tailscale identity needs writable auth_keys scope and the tag:bootc-dev-sandbox tag. Tailnet SSH policy must allow the intended source identity to reach that tag as OS user runner. No repository secret or OAuth client secret is used.

Use

The default mode enables Tailscale SSH. It authenticates the source tailnet identity/device through the Tailscale SSH policy:

gh workflow run "Tailscale development runner" --repo bootc-dev/cgwalters-devspace-sandbox \
  --ref main -f duration=30
tailscale ssh runner@<hostname-or-IP>
gh run cancel <run-id> --repo bootc-dev/cgwalters-devspace-sandbox

For ordinary OpenSSH, supply exactly one Ed25519 public-key line. The workflow does not enable Tailscale SSH in this mode; sshd listens only on the ephemeral node's Tailscale IPv4 address and additionally requires the matching private key:

gh workflow run "Tailscale development runner" --repo bootc-dev/cgwalters-devspace-sandbox \
  --ref main -f duration=30 -f ssh_public_key="$(<~/.ssh/id_ed25519.pub)"
ssh -i ~/.ssh/id_ed25519 runner@<tailscale-ip>

The recommended flow generates a temporary key, dispatches safely, polls for the matching run and Tailscale peer, connects with ordinary ssh, and cancels that exact run on exit (the private key is never uploaded):

./tools/devspace-ssh --duration 30

It uses the host Tailscale daemon from Toolbox when necessary. The existing tools/tailscale-client wrapper remains useful for status and ping; do not use it for tailscale ssh, because that subcommand can spawn a nested proxy which loses a non-default daemon socket.

The helper intentionally does not use gh run watch: this workflow waits in a keepalive step. It polls until the peer is available, connects, then cancels the exact run when the session ends. Ordinary sshd is governed by Tailscale network ACLs, not Tailscale SSH ACL rules. It prints each failed SSH attempt's stderr, uses a bounded retry deadline, and emits one final verbose diagnostic before failing.

In ordinary-SSH mode, the workflow installs and uses the stock packaged sshd.service. It replaces the disposable runner's /etc/ssh/sshd_config with a minimal hardened configuration bound only to the Tailscale IPv4, generates host keys, validates the configuration, and restarts that service. The keepalive checks the service's active state, MainPID and sshd_t SELinux context, and the exact Tailscale-bound port 22 every five seconds. SELinux must remain enforcing. If any check fails, the job prints bounded non-secret service, socket, journal, and recent SELinux AVC diagnostics and fails immediately. There is no restoration step because the runner is disposable; cancellation cleans up through runner disposal and Tailscale action logout.

From Toolbox, use the repository helper so the host Tailscale daemon socket is selected automatically for status and ping:

./tools/tailscale-client status --self

The helper uses the normal daemon socket when present, otherwise detects a container and uses /run/host/run/tailscale/tailscaled.sock. An explicit --socket argument is passed through unchanged; if neither socket is available, it reports how to fix the environment.

The duration choice is 30, 60, or 120 minutes. The job has an independent 125-minute timeout. Cancellation and expiry run the Tailscale action cleanup; the workflow prints only safe hostname, IPv4, and status information. Treat the runner as disposable and do not store secrets on it.

If dispatch is unavailable, verify that this workflow is on main. If joining fails, check both repository variables, the federated subject above, the identity's tag and scope, and device approval. A Tailscale 403 Unauthorized from tailscale up means the trust credential must be updated to allow the subject above. The workflow installs iptables and links the action's /usr/local/bin binaries into RHEL's sudo path before connecting; these are required by this runner image. If SSH fails after a successful join, check the tailnet ACL for the source identity, destination tag, and runner OS-user mapping. For ordinary OpenSSH, also check the supplied key and network ACL; Tailscale SSH ACL rules do not apply.

About

devspace for cgwalters

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages