Skip to content
Back to skills

Nodetool Deployment

BSecurity

Deploy or operate NodeTool servers and workers with Docker, SSH, Runpod, or cloud deployment configuration.

  • 552 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 1, 2026
ai-agentstypescriptrustbashsqlnodedockergcpapidatabasesecurity

Works with

  • api

Security analysis

B75/100
  • criticalAccesses sensitive system or user directories
  • criticalReads or references SSH private keys

Pro shows the line behind each finding and how to fix it

Scanned October 3, 2026

npx -y skills add nodetool-ai/nodetool --skill nodetool-deployment --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Nodetool Deployment?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Nodetool Deployment
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/nodetool-ai-nodetool-deployment/badge)](https://www.skillsdirectory.com/skills/nodetool-ai-nodetool-deployment)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: nodetool-deployment
description: "Deploy or operate NodeTool servers and workers with Docker, SSH, Runpod, or cloud deployment configuration."
---

You help users deploy NodeTool to various environments. Choose the right deployment type based on requirements.

# Decision Tree

```
Need GPU? ──yes──→ Own hardware? ──yes──→ Self-Hosted (Docker/SSH)
    │                    │
    no                   no──→ RunPod (serverless GPU)
    │
    ├── Need auth/storage? ──yes──→ Supabase + any deployment
    │
    └── Just API server? ──→ GCP Cloud Run or Self-Hosted
```

# Authentication Modes

The server picks its mode from the Supabase credentials alone. It never reads
`AUTH_PROVIDER`, `NODETOOL_SERVER_MODE`, or `SERVER_AUTH_TOKEN` to decide how
to authenticate. The deploy tooling writes those into container environments,
but they do not secure the server.

| Mode | Enabled by | Behavior |
|------|------------|----------|
| Local | Default | Loopback runs as user `"1"` with no token. Other sources get `401` unless listed in `NODETOOL_TRUST_LOCAL_NETWORKS`. |
| Supabase | `SUPABASE_URL` and `SUPABASE_KEY` both set | Every non-public request needs `Authorization: Bearer <supabase_jwt>`. |

A server that other people reach over a network needs Supabase mode. In Local
mode, Docker's published port arrives from the bridge gateway, not loopback, so
API calls return `401` until `NODETOOL_TRUST_LOCAL_NETWORKS` lists that range.
Every listed source is trusted as user `"1"` with no password, so list only
networks you control.

# Quick Start

```bash
nodetool deploy init              # Create deployment.yaml
nodetool deploy add <name>        # Add a deployment
nodetool deploy list              # List deployments
nodetool deploy show <name>       # Show config
nodetool deploy plan <name>       # Preview changes
nodetool deploy apply <name>      # Deploy
nodetool deploy status <name>     # Check status
nodetool deploy logs <name>       # View logs
nodetool deploy destroy <name>    # Tear down
```

# Environment Variables (All Deployments)

```bash
# Required
NODETOOL_ENV=production

# Auth: Supabase mode, required for network access by other users
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=<service-role-key>

# Security
SECRETS_MASTER_KEY=<strong-random-key>

# Database
DB_PATH=/workspace/nodetool.sqlite3

# API Keys (as needed)
OPENAI_API_KEY=<key>
ANTHROPIC_API_KEY=<key>
GEMINI_API_KEY=<key>
HF_TOKEN=<token>
FAL_API_KEY=<key>
OLLAMA_API_URL=http://localhost:11434
```

# Self-Hosted: Docker

## deployment.yaml
```yaml
deployments:
  my-server:
    type: docker
    host: 192.168.1.10
    ssh:
      user: ubuntu
      key_path: ~/.ssh/id_rsa
    container:
      name: nodetool-server
      port: 8000
      gpu: "0"                    # GPU device ID, or omit
    paths:
      workspace: /data/nodetool
      hf_cache: /data/hf-cache
    image:
      name: ghcr.io/nodetool-ai/nodetool
      tag: latest
```

## Docker Run (manual)
```bash
docker run --gpus all --memory 8g --cpus 4 \
  -p 7777:7777 \
  -e NODETOOL_ENV=production \
  -e SUPABASE_URL=https://your-project.supabase.co \
  -e SUPABASE_KEY=<service-role-key> \
  -e SECRETS_MASTER_KEY=<secret> \
  -v $(pwd)/workspace:/workspace \
  -v $(pwd)/hf-cache:/hf-cache:ro \
  -e HF_HOME=/hf-cache \
  nodetool:latest
```

## Resource Limits
```yaml
# Docker Compose
services:
  nodetool:
    mem_limit: 8g
    cpus: 4
    deploy:
      resources:
        reservations:
          devices:
            - capabilities: [gpu]
```

# Self-Hosted: SSH

```yaml
deployments:
  my-ssh:
    type: ssh
    host: 192.168.1.11
    ssh:
      user: ubuntu
      key_path: ~/.ssh/id_rsa
    port: 8000
    service_name: nodetool-8000
    paths:
      workspace: /home/ubuntu/nodetool
      hf_cache: /home/ubuntu/.cache/huggingface
```

# Self-Hosted: Local

```yaml
deployments:
  my-local:
    type: local
    host: localhost
    port: 8000
    paths:
      workspace: /home/me/.nodetool-workspace
      hf_cache: /home/me/.cache/huggingface/hub
```

# RunPod (Serverless GPU)

```bash
export RUNPOD_API_KEY="your-key"
nodetool deploy add my-runpod --type runpod
nodetool deploy apply my-runpod
```

Config fields: `template_id`, `endpoint_id`, `compute_type`, `gpu_types`, `gpu_count`, `workers_min`, `workers_max`, `env`

# GCP Cloud Run

```bash
gcloud auth login
nodetool deploy add my-gcp --type gcp
nodetool deploy apply my-gcp
```

Config fields: `service_name`, `region`, `registry`, `cpu`, `memory`, `gpu_type`, `gpu_count`, `min_instances`, `max_instances`, `concurrency`, `timeout`

# Supabase Integration

```bash
# Environment variables
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-service-role-key
ASSET_BUCKET=assets
ASSET_TEMP_BUCKET=assets-temp
```

**Setup steps:**
1. Create Supabase project
2. Create storage buckets: `assets`, `assets-temp`
3. Set bucket policies (public or signed URLs)
4. Copy service-role key (not anon key)
5. Set environment variables

# Server Startup

```bash
# Development
nodetool serve --host 127.0.0.1 --port 7777

# Production
nodetool serve --host 0.0.0.0 --port 7777

# Custom port
nodetool serve --port 8080

# From a NodeTool checkout, against the TypeScript sources
npm run build:packages && npm run dev:server
# Or directly:
PORT=7777 HOST=0.0.0.0 node packages/websocket/dist/server.js
```

# Workflow Sync

```bash
nodetool deploy workflows sync <deployment> <workflow-id>
nodetool deploy workflows list <deployment>
nodetool deploy workflows run <deployment> <workflow-id>
```

# Production Checklist

- [ ] Set `NODETOOL_ENV=production`
- [ ] Set strong `SECRETS_MASTER_KEY`
- [ ] Set `SUPABASE_URL` and `SUPABASE_KEY` so every request needs a token
- [ ] Never set `NODETOOL_TRUST_LOCAL_NETWORKS` on a reachable public port
- [ ] Configure API keys for needed providers
- [ ] Set resource limits (memory, CPU, GPU)
- [ ] Mount persistent volumes for workspace and model cache
- [ ] Set up health monitoring (`GET /health`, `GET /ready`)
- [ ] Configure logging (`NODETOOL_LOG_LEVEL=info`)
- [ ] Set up backups for `DB_PATH`

# Common Pitfalls

- **Using anon key for Supabase**: Use service-role key, not anon key
- **No persistent volume**: Data lost on container restart without `-v` mount
- **Port conflicts**: Check nothing else runs on 7777
- **Missing SECRETS_MASTER_KEY**: Required for encrypted secret storage in prod
- **Relying on `SERVER_AUTH_TOKEN` or `AUTH_PROVIDER`**: The server ignores both for auth. Only Supabase mode enforces tokens
- **HF cache not mounted**: Models re-download on every container start

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…