Twingate headless client paired with Socat port forwarding feature
Inspired by docker-twingate-headless
Building blocks:
- Twingate headless client connecting to a private network like a "Service",
- Socat as a Port Forwarder making connections to a remote TCP listener possible,
- everything packed in a Docker container.
Twingate's Docker networking stack can be shared with other containers (see docs):
services:
twingate-service:
#...
prometheus-node-exporter:
#...
network_mode: "service:twingate-service"
ports:
- "9100:9100" # WARNING: Not supported when 'network_mode' is used!but network_mode makes usage of port mappings impossible. Thus, software like Prometheus Exporter turn harder to configure.
So, the idea is to create a Twingate Service Docker image with embedded Port Forwarder. The container will publish ports with forwarded remote data sources so consumers can easily get data, still staying "outside" the private network.
- Logs in unified format (all components publish logs in Twingate format)
- Optionally redirect Twingate log into Docker container's log (for connectivity issues debugging)
- Optionally to log list of available Twingate resources after successful connect
- Twingate Service Account with "Service Key" (json file).
Create a Docker compose file (compose.yml) like this:
services:
twingate-service:
image: twingate_service:latest
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
environment:
- 'SERVICE_KEY={ "version": "1", "network": "<secret>.twingate.com", "service_account_id": "<secret uuid>", "private_key": "-----BEGIN PRIVATE KEY-----\n<whole bag of secrets>\n-----END PRIVATE KEY-----", "key_id": "<secret token>", "expires_at": "2027-01-01T00:00:00+00:00", "login_path": "/api/v4/headless/login" }'
- PORT_MAPPINGS=80:sensors.raspberrypi.private:80;81:smarthome.raspberrypi.private:81
- LOG_RESOURCES=1
# Debugging Twingate connectivity issues:
#- LOG_TWINGATE=1
#- LOG_TWINGATE_TRUNCATE=1 # doesn't work without LOG_TWINGATE
ports:
- 8080:80
- 8081:81
restart: unless-stoppedNote
The "twingate_service" Docker image mentioned above is not published to any registry - you'll need to build it yourself by running the Dockerfile_build.ps1 script.
Then run it:
docker compose upOR
Create an .env file in the PARENT directory, for example:
SERVICE_KEY={ "version": "1", "network": "<secret>.twingate.com", "service_account_id": "<secret uuid>", "private_key": "-----BEGIN PRIVATE KEY-----\n<whole bag of secrets>\n-----END PRIVATE KEY-----", "key_id": "<secret token>", "expires_at": "2027-01-01T00:00:00+00:00", "login_path": "/api/v4/headless/login" }'
PORT_MAPPINGS=80:sensors.raspberrypi.private:80;81:smarthome.raspberrypi.private:81and use compose.yml from this project by running:
./compose_run.ps1SERVICE_KEY(string) - the Twingate's Service Key (the whole json as one line)SERVICE_KEY_PATH(string) - a path to a json file containing the Twingate's Service Key. This is an alternative way to specify credentialsPORT_MAPPINGS(string) - ports to map in the format of "LOCAL_PORT:REMOTE_HOST:REMOTE_PORT;..."- Example:
PORT_MAPPINGS="80:sensors.raspberrypi.private:80;81:smarthome.raspberrypi.private:81"
- Example:
LOG_TWINGATE(bool or int) - redirect Twingate log to a Docker container's logLOG_TWINGATE_TRUNCATE(bool or int) - truncate Twingate log before starting (requiresLOG_TWINGATEto be set as well)LOG_RESOURCES(bool or int) - log available Twingate resources after successfull connection
Won't fix:
- Though the projects aims to make logs of all its components look the same (see
log_transformer_*.shscripts), there are still some leftovers related to Twingate (some of its early log messages aren't well-formatted and thus left as is) - For some reason
--disable-colorsparameter doesn't work and "Twingate has been started" message appears green in logs
- Userspace Networking - allows to run without "TUN" device and root user.
This is a weekend project born from a fleeting idea I got while experimenting with Twingate Services.
The project is in the "Portfolio" status - no feature PRs are expected.
If you have ideas, feel free to open a discussion via "Issues".
- Twingate
- Socat
- Docker
- Bash
- Twingate Linux Headless Client (Docker Image) - this image provides a lightweight, self-contained way to run the Twingate Linux Client in headless mode using a Service Key.
- Headless Client Gateway - setup of a whole network Internet Gateway, utilizing the Twingate Headless Client.