Skip to content

Commit a5b46c4

Browse files
committed
[Pulse] New Service
1 parent e69fcd3 commit a5b46c4

3 files changed

Lines changed: 128 additions & 0 deletions

File tree

services/pulse/.env

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#version=1.1
2+
#URL=https://github.com/tailscale-dev/ScaleTail
3+
#COMPOSE_PROJECT_NAME= # Optional: only use when running multiple deployments on the same infrastructure.
4+
5+
# Service Configuration
6+
SERVICE=pulse
7+
IMAGE_URL=rcourtman/pulse:latest
8+
9+
# Network Configuration
10+
SERVICEPORT=7655
11+
DNS_SERVER=9.9.9.9
12+
13+
# Tailscale Configuration
14+
# Auth key from https://tailscale.com/admin/authkeys
15+
TS_AUTHKEY=
16+
17+
# Time Zone setting for containers
18+
TZ=Europe/Amsterdam

services/pulse/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Pulse with Tailscale Sidecar Configuration
2+
3+
This Docker Compose configuration sets up [Pulse](https://hub.docker.com/r/rcourtman/pulse) with Tailscale as a sidecar so the dashboard is reachable only over your Tailnet at `https://pulse.<tailnet-name>.ts.net`.
4+
5+
## Pulse
6+
7+
Pulse is a modern, unified dashboard for monitoring your infrastructure across Proxmox, Docker, and Kubernetes. It consolidates metrics, alerts, and AI-powered insights from all your systems into a single interface, aimed at homelabs, sysadmins, and MSPs who want a "single pane of glass" without the complexity of an enterprise monitoring stack.
8+
9+
## Configuration Overview
10+
11+
The `tailscale-pulse` service runs the Tailscale client to join your Tailnet. The application service uses `network_mode: service:tailscale`, so Pulse listens on TCP `7655` inside the Tailscale container's network namespace and Tailscale Serve proxies HTTPS `443``127.0.0.1:7655`. `AllowFunnel` is `false`; the dashboard is **never** exposed to the public internet from this configuration.
12+
13+
## Setup
14+
15+
1. Clone the repository and navigate to the service directory:
16+
17+
```bash
18+
git clone https://github.com/tailscale-dev/ScaleTail.git
19+
cd ScaleTail/services/pulse
20+
```
21+
22+
2. Edit `.env` and paste your Tailscale auth key into `TS_AUTHKEY=`.
23+
24+
3. Pre-create the data directories so Docker does not create them as `root`:
25+
26+
```bash
27+
mkdir -p pulse-data ts/state
28+
```
29+
30+
4. Start the stack:
31+
32+
```bash
33+
docker compose up -d
34+
```
35+
36+
5. Open `https://pulse.<tailnet-name>.ts.net` from any Tailnet peer.
37+
38+
## Notes
39+
40+
- Pulse stores its state (Proxmox/Docker/Kubernetes credentials, alert rules, cached metrics) in `./pulse-data` mounted at `/data`. Treat this directory like a secrets vault — it contains tokens used to query your infrastructure.
41+
- The original upstream `docker run` uses `-p 7655:7655` to bind the port to all host interfaces. In this configuration that direct port mapping is intentionally **not** used — access is via Tailnet only. Uncomment the `ports:` block in `compose.yaml` only if you also want LAN access from non-Tailnet devices.
42+
- The upstream image's restart policy is `unless-stopped`; this configuration uses `restart: always` to match the rest of the ScaleTail catalog.
43+
44+
## Useful Links
45+
46+
- [rcourtman/pulse on Docker Hub](https://hub.docker.com/r/rcourtman/pulse)
47+
- [Tailscale Serve docs](https://tailscale.com/kb/1242/tailscale-serve)
48+
- [Tailscale Docker guide](https://tailscale.com/blog/docker-tailscale-guide)

services/pulse/compose.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
configs:
2+
ts-serve:
3+
content: |
4+
{"TCP":{"443":{"HTTPS":true}},
5+
"Web":{"$${TS_CERT_DOMAIN}:443":
6+
{"Handlers":{"/":
7+
{"Proxy":"http://127.0.0.1:7655"}}}},
8+
"AllowFunnel":{"$${TS_CERT_DOMAIN}:443":false}}
9+
10+
services:
11+
# Make sure you have updated/checked the .env file with the correct variables.
12+
# All the ${ xx } need to be defined there.
13+
# Tailscale Sidecar Configuration
14+
tailscale:
15+
image: tailscale/tailscale:latest # Image to be used
16+
container_name: tailscale-${SERVICE} # Name for local container management
17+
hostname: ${SERVICE} # Name used within your Tailscale environment
18+
environment:
19+
- TS_AUTHKEY=${TS_AUTHKEY}
20+
- TS_STATE_DIR=/var/lib/tailscale
21+
- TS_SERVE_CONFIG=/config/serve.json # Tailscale Serve configuration to expose the web interface on your local Tailnet
22+
- TS_USERSPACE=false
23+
- TS_ENABLE_HEALTH_CHECK=true # Enable healthcheck endpoint: "/healthz"
24+
- TS_LOCAL_ADDR_PORT=127.0.0.1:41234 # The <addr>:<port> for the healthz endpoint
25+
#- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS
26+
- TS_AUTH_ONCE=true
27+
configs:
28+
- source: ts-serve
29+
target: /config/serve.json
30+
volumes:
31+
- ./config:/config # Config folder used to store Tailscale files
32+
- ./ts/state:/var/lib/tailscale # Tailscale state
33+
devices:
34+
- /dev/net/tun:/dev/net/tun # Network configuration for Tailscale to work
35+
cap_add:
36+
- net_admin # Tailscale requirement
37+
#ports:
38+
# - 0.0.0.0:${SERVICEPORT}:${SERVICEPORT} # Uncomment ONLY if LAN exposure is wanted
39+
# If any DNS issues arise, use your preferred DNS provider by uncommenting the config below
40+
#dns:
41+
# - ${DNS_SERVER}
42+
healthcheck:
43+
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:41234/healthz"] # Check Tailscale has a Tailnet IP and is operational
44+
interval: 1m
45+
timeout: 10s
46+
retries: 3
47+
start_period: 10s
48+
restart: always
49+
50+
# ${SERVICE}
51+
application:
52+
image: ${IMAGE_URL} # Image to be used
53+
network_mode: service:tailscale # Sidecar configuration to route ${SERVICE} through Tailscale
54+
container_name: app-${SERVICE} # Name for local container management
55+
environment:
56+
- TZ=${TZ}
57+
volumes:
58+
- ./${SERVICE}-data:/data # Pulse persistent data (configs, alerts, cached metrics)
59+
depends_on:
60+
tailscale:
61+
condition: service_healthy
62+
restart: always

0 commit comments

Comments
 (0)