Self-hosting Tanvrit Compute
> Running your own fleet of tanvrit-agent workers — the foundation of the > free tier. Self-hosted nodes are always free.
System requirements
- Supported OSes: macOS 13+, Linux (x86_64 / arm64), Windows 11 (Docker Desktop required)
- JVM: not required — the agent ships as a GraalVM native binary
- Docker: optional, required only for
DOCKERjobs - GPU: optional; NVIDIA (CUDA), AMD (ROCm), or Apple Silicon (Metal) are auto-detected
Install the agent
curl -fsSL https://compute.tanvrit.com/install.sh | sh
This downloads the appropriate tanvrit-agent binary for your platform and installs it to ~/.tanvrit/bin/.
Generate an API key in the portal
- Sign in at compute.tanvrit.com
- Open Settings → Agent API keys
- Click Generate key — the raw key is shown once. Copy it now.
Run the agent
export TANVRIT_SERVER_URL=https://api.tanvrit.com
export TANVRIT_API_KEY=<your-key>
export TANVRIT_NODE_NAME=${HOSTNAME}-prod # optional
export TANVRIT_MAX_JOBS=4 # concurrent jobs, default 2
export TANVRIT_LABELS=production,team-ml # extra labels beyond auto-detected
tanvrit-agent
Node identity — where the agent remembers who it is
On first run the agent writes agent-identity.properties (mode 0600) into $TANVRIT_STATE_DIR (default ~/.tanvrit/agent). It holds three things:
| key | what it is | |---|---| | agentId | a 256-bit random value generated once. Presented as X-Agent-Id on registration so the control plane recognises this installation on its next start. | | nodeId | the node this installation owns. Minted by the server; the agent adopts it and never proposes one. | | nodeKey | the node-scoped API key. Present so a restart authenticates as itself and does not register at all. |
Consequences worth knowing:
- Deleting the file is how you enrol a machine as a new node. The agent then
- A file the agent cannot read is left untouched. If the identity file exists
- Never bake it into a container image or a VM golden image. Every replica
- Two agents on one host need two
TANVRIT_STATE_DIRs. The agent takes an TANVRIT_ONCE=truewrites no file — ephemeral CI runners are meant to be- The file holds a live credential. It is
0600, it is never logged, and it
registers fresh and the old row ages out as OFFLINE.
but a read fails (permissions, a filesystem fault), the agent registers as a new node for that run only and writes nothing — so the next start recovers the real identity instead of having overwritten it.
would share one identity and duel over a single node row. Use a per-replica volume, or set TANVRIT_AGENT_ID to a value that is unique per replica.
exclusive lock on the directory; a second agent pointed at the same one logs a warning and registers as its own separate node rather than merging.
distinct short-lived nodes.
deliberately does not live under TANVRIT_WORK_DIR, which is job scratch that executors delete recursively.
| variable | default | purpose | |---|---|---| | TANVRIT_STATE_DIR | ~/.tanvrit/agent | where the identity file and lock live | | TANVRIT_AGENT_ID | (unset) | operator-supplied stable installation id; wins over the file, and lets a read-only rootfs keep one node row across restarts. Treat it as a secret: without a TANVRIT_API_KEY it is the whole proof that this machine is that node, so use 32+ random characters (openssl rand -hex 32). A shorter value is refused by the control plane and the machine registers anew on every restart. |
Running as a service
#### macOS (launchd)
<!-- ~/Library/LaunchAgents/com.tanvrit.agent.plist -->
<plist version="1.0">
<dict>
<key>Label</key><string>com.tanvrit.agent</string>
<key>ProgramArguments</key>
<array>
<string>/Users/you/.tanvrit/bin/tanvrit-agent</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>TANVRIT_API_KEY</key><string>YOUR_KEY</string>
</dict>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
</dict>
</plist>
Then launchctl load ~/Library/LaunchAgents/com.tanvrit.agent.plist.
#### Linux (systemd)
# /etc/systemd/system/tanvrit-agent.service
[Unit]
Description=Tanvrit Compute Agent
After=network-online.target
[Service]
Environment="TANVRIT_API_KEY=YOUR_KEY"
ExecStart=/home/ubuntu/.tanvrit/bin/tanvrit-agent
Restart=always
RestartSec=5
User=ubuntu
[Install]
WantedBy=multi-user.target
Then sudo systemctl enable --now tanvrit-agent.
Ephemeral mode (Kubernetes / CI)
To run as a one-shot worker (pick one job, run it, exit):
tanvrit-agent --once
# or
TANVRIT_ONCE=true tanvrit-agent
This is useful for Kubernetes Jobs or GitHub Actions runners where each build should get a fresh container.
Label pool design
The scheduler matches jobs to nodes by label. Common conventions:
| Label | Meaning | |--- |--- | | gpu, cuda | auto-added when a CUDA GPU is detected | | metal | auto-added on Apple Silicon | | rocm | auto-added on AMD GPUs | | docker | auto-added when the Docker daemon is reachable | | android-sdk | auto-added when ANDROID_HOME is set | | xcode | auto-added on macOS with Xcode installed | | production | manual — mark a node as production-only | | fleet:eu-west | manual — region / fleet grouping |
A job with labels: ["gpu", "cuda"] will only be dispatched to nodes whose label set is a superset.
Security notes
- The API key is stored on disk in plain text in the env file. Protect it
- Outbound-only: the agent connects to the control plane — no inbound ports
- Sensitive env vars (
TANVRIT_API_KEY,AWS_SECRET_ACCESS_KEY, - Rotate keys from the portal any time; old keys are invalidated immediately.
with filesystem permissions.
are opened on the host.
GITHUB_TOKEN) are stripped from the job environment before execution.