Skip to content

Instantly share code, notes, and snippets.

@blalor
Last active May 9, 2023 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blalor/b0ba2fc2772f66549e4c36c52045b75c to your computer and use it in GitHub Desktop.
Save blalor/b0ba2fc2772f66549e4c36c52045b75c to your computer and use it in GitHub Desktop.
Tailscale Docker container as Nomad sidecar

This is possibly slightly incomplete as I stripped out an existing jobspec to share, but the meat is really in the run.sh template of the tailscale task. You'll need a reusable and ephemeral auth key.

# -*- terraform -*-
job "grafana" {
datacenters = ["dc1"]
type = "service"
group "grafana" {
network {
# bridge mode is required so that the tailscale container can access
# the service's ports.
mode = "bridge"
port "web" {
static = 3000
}
}
task "grafana" {
driver = "docker"
config {
## https://github.com/grafana/grafana/releases
image = "grafana/grafana-oss:9.3.1"
ports = ["web"]
}
} # task "grafana"
task "tailscale" {
driver = "docker"
lifecycle {
hook = "poststart"
sidecar = true
}
## https://github.com/tailscale/tailscale/blob/main/cmd/containerboot/main.go
## https://hub.docker.com/r/tailscale/tailscale
## https://tailscale.com/kb/1185/kubernetes/
env {
# https://login.tailscale.com/admin/settings/keys
# generate a reusable, ephemeral auth key.
TS_AUTH_KEY = "tskey-auth-bringyour-ownkey"
# stores no state; I don't know if this is a good idea, or bad
TS_STATE_DIR = "mem:"
## https://tailscale.com/kb/1112/userspace-networking/
TS_USERSPACE = "true"
# this will be a problem for multiple instances, and if the
# container respawns before tailscale's done its cleanup thing
# you'll get `grafana-N`
TS_HOSTNAME = "${NOMAD_GROUP_NAME}"
}
# create a wrapper script for containerboot that waits for tailscale
# to come up, then serves the web port and turns on funnel.
template {
destination = "local/run.sh"
data = <<__tmpl
#!/bin/sh
set -x -e -u -o pipefail
containerboot &
while ! tailscale --socket /tmp/tailscaled.sock status ; do
echo "status failed; pausing"
sleep 3
done
echo "status succeeded"
tailscale --socket /tmp/tailscaled.sock serve https / http://127.0.0.1:{{ env "NOMAD_ALLOC_PORT_web" }}
echo "served"
tailscale --socket /tmp/tailscaled.sock funnel 443 on
echo "funneling"
echo "waiting"
wait
__tmpl
}
config {
image = "ghcr.io/tailscale/tailscale:v1.40.0"
command = "/bin/sh"
args = ["${NOMAD_TASK_DIR}/run.sh"]
}
} # task "tailscale"
} # group
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment