
It introduces a new '--state' flag (and TS_STATE environment variable) that accepts 'kube:<secret-name>' to specify the Kubernetes secret to use. The necessary RBAC permissions for the tsidp service account are documented in the README. Updates #15965 Signed-off-by: Raj Singh <raj@tailscale.com>
tsidp
- Tailscale OpenID Connect (OIDC) Identity Provider
tsidp
is an OIDC Identity Provider (IdP) server that integrates with your Tailscale network. It allows you to use Tailscale identities for authentication in applications that support OpenID Connect, enabling single sign-on (SSO) capabilities within your tailnet.
Prerequisites
- A Tailscale network (tailnet) with magicDNS and HTTPS enabled
- A Tailscale authentication key from your tailnet
- Docker installed on your system
Installation using Docker
Building from Source
# Clone the Tailscale repository
git clone https://github.com/tailscale/tailscale.git
cd tailscale
# Build and publish to your own registry
make publishdevtsidp REPO=ghcr.io/yourusername/tsidp TAGS=v0.0.1 PUSH=true
Running the Container
Replace YOUR_TAILSCALE_AUTHKEY
with your Tailscale authentication key:
docker run -d \
--name tsidp \
-p 443:443 \
-e TS_AUTHKEY=YOUR_TAILSCALE_AUTHKEY \
-e TAILSCALE_USE_WIP_CODE=1 \
-v tsidp-data:/var/lib/tsidp \
ghcr.io/yourusername/tsidp:v0.0.1 \
tsidp --hostname=idp --dir=/var/lib/tsidp
Verify Installation
docker logs tsidp
Visit https://idp.tailnet.ts.net
to confirm the service is running.
Usage Example: Proxmox Integration
Here's how to configure Proxmox to use tsidp
for authentication:
-
In Proxmox, navigate to Datacenter > Realms > Add OpenID Connect Server
-
Configure the following settings:
- Issuer URL:
https://idp.velociraptor.ts.net
- Realm:
tailscale
(or your preferred name) - Client ID:
unused
- Client Key:
unused
- Default:
true
- Autocreate users:
true
- Username claim:
email
- Issuer URL:
-
Set up user permissions:
- Go to Datacenter > Permissions > Groups
- Create a new group (e.g., "tsadmins")
- Click Permissions in the sidebar
- Add Group Permission
- Set Path to
/
for full admin access or scope as needed - Set the group and role
- Add Tailscale-authenticated users to the group
Configuration Options
The tsidp
server supports several command-line flags:
--verbose
: Enable verbose logging--port
: Port to listen on (default: 443)--local-port
: Allow requests from localhost--use-local-tailscaled
: Use local tailscaled instead of tsnet--hostname
: tsnet hostname--dir
: tsnet state directory; a default one will be created if not provided--state
: Path to tailscale state file. Can also be set to use a Kubernetes Secret with the formatkube:<secret-name>
. If unset,dir
is used for file-based state, or tsnet default ifdir
is also unset.
Environment Variables
TS_AUTHKEY
: Your Tailscale authentication key (required)TS_HOSTNAME
: Hostname for thetsidp
server (default: "idp", Docker only)TS_STATE_DIR
: Default state directory fortsnet
(default: "/var/lib/tsidp" in Docker). This variable typically sets the default for the--dir
flag in the Docker environment.tsnet
uses the directory specified by--dir
(or its internal default if--dir
is not set) for its persistent files (e.g., node keys).TAILSCALE_USE_WIP_CODE
: Enable work-in-progress code (default: "1")
Storing State in Kubernetes Secrets
When running tsidp
in a Kubernetes environment, you can configure it to store its state in a Kubernetes Secret. This is achieved by setting the --state
flag to kube:<your-secret-name>
. The Secret will be created by tsidp
if it doesn't already exist, and will be created in the same namespace where tsidp
is running.
Important: Each Pod must use its own unique Secret. Multiple Pods cannot share the same Secret for state storage.
For example:
./tsidp --state kube:my-tsidp-state-secret
StatefulSet Example for Multiple Pods
When deploying multiple tsidp
instances, use a StatefulSet to ensure each Pod gets its own unique Secret:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: tsidp
spec:
replicas: 1
serviceName: tsidp
selector:
matchLabels:
app: tsidp
template:
metadata:
labels:
app: tsidp
spec:
serviceAccountName: tsidp
containers:
- name: tsidp
image: tailscale/tsidp:unstable
args:
- tsidp
- --state=kube:$(POD_NAME)
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: TS_AUTHKEY
valueFrom:
secretKeyRef:
name: tsidp-auth
key: authkey
- name: TAILSCALE_USE_WIP_CODE
value: "1"
Required RBAC Permissions
If you use Kubernetes Secret storage, the service account under which tsidp
runs needs the following permissions on Secrets in the same namespace:
get
patch
(primary mechanism for writing state)create
(if the Secret does not already exist)update
(for backwards compatibility, though patch is preferred)
Additionally, the service account needs the following permissions on Events (for debugging purposes when Secret operations fail):
create
patch
get
Ensure that appropriate Role and RoleBinding are configured in your Kubernetes cluster.
Support
This is an experimental, work in progress, community project. For issues or questions, file issues on the GitHub repository.
License
BSD-3-Clause License. See LICENSE for details.