GPU node daemon for Worldland rental marketplace
The Node daemon manages GPU containers via Docker SDK, communicates with Hub via mTLS, and provides SSH access to rental sessions.
Requires: Docker with NVIDIA Container Toolkit, Ethereum wallet
# Build Node
go build -o node ./cmd/node
# Set up wallet private key
mkdir -p ~/.worldland && chmod 700 ~/.worldland
echo "your_64_char_private_key" > ~/.worldland/private-key.txt
chmod 600 ~/.worldland/private-key.txt
# Run Node (certificates auto-provisioned, GPU auto-detected!)
./node \
-hub 35.193.4.15:8443 \
-hub-http http://35.193.4.15:8080 \
-siwe-domain localhost:3000 \
-private-key-file ~/.worldland/private-key.txt \
-host $(curl -s ifconfig.me)That's it! GPU type and memory are automatically detected from NVML. Certificates are automatically issued and saved to ~/.worldland/certs/.
Required:
- Go 1.21.0 or higher (download)
- Docker 20.10+ (download)
- Kubernetes components (kubeadm, kubelet, kubectl) for cluster join
- containerd as container runtime
For GPU Nodes (optional):
- NVIDIA GPU with drivers installed
- NVIDIA Container Toolkit
Note: GPU is optional. Nodes without NVIDIA GPUs automatically register as "CPU Node".
Check versions:
go version # Should be go1.21.0 or higher
docker --version # Should be 20.10 or higher
kubeadm version # Should be v1.29+
kubectl version # Should be v1.29+
nvidia-smi # (GPU nodes only) Should show your GPU(s)Worldland Node supports Sign-In with Ethereum (SIWE) for provider registration and automatic certificate provisioning. This links your GPU node to your blockchain wallet address, enabling:
- Automatic provider registration with real wallet address
- Automatic mTLS certificate issuance (no manual cert setup!)
- Direct settlement of rental payments to your wallet
- On-chain identity verification
On first run with a private key, the Node automatically:
1. Detect GPU/CPU → determine node type
2. Login with SIWE (wallet authentication)
3. Request bootstrap certificate from Hub
4. Save certificates to ~/.worldland/certs/
5. Connect via mTLS
6. Register node (GPU or CPU)
7. Join K8s cluster (if kubeadm installed)
-
Get your Ethereum private key
Export your private key from MetaMask or another wallet. The key should be a 64-character hex string.
Security Warning: Never share your private key. Store it securely with restricted permissions.
-
Create a private key file
# Create secure directory mkdir -p ~/.worldland chmod 700 ~/.worldland # Save private key (without 0x prefix) echo "your_64_char_hex_private_key" > ~/.worldland/private-key.txt chmod 600 ~/.worldland/private-key.txt
-
Run Node (certificates auto-provisioned, GPU auto-detected!)
./node \ -hub 35.193.4.15:8443 \ -hub-http http://35.193.4.15:8080 \ -siwe-domain localhost:3000 \ -private-key-file ~/.worldland/private-key.txt \ -host $(curl -s ifconfig.me) \ -price-per-sec "1000000000"
Note:
-gpu-typeand-memory-gbare auto-detected from NVML.
First run output:
Worldland Node starting...
GPU detected: NVIDIA Tesla T4 (16 GB)
GPU detected - will register as GPU Node
Authenticating with wallet to Hub at http://35.193.4.15:8080...
Wallet address: 0xYourWalletAddress
SIWE authentication successful
Certificates not found, requesting bootstrap certificate from Hub...
Bootstrap certificates saved to /home/user/.worldland/certs
Certificate: /home/user/.worldland/certs/node.crt
Private Key: /home/user/.worldland/certs/node.key
CA Cert: /home/user/.worldland/certs/ca.crt
Expires: 2026-03-06T12:00:00Z
Node registered: node_abc123
Connected to Hub at 35.193.4.15:8443
Node ready - API on port 8444
Subsequent runs use the saved certificates automatically.
For cloud GPU VMs, complete these steps first:
1. Create GPU VM (GCP example):
gcloud compute instances create gpu-node \
--zone=us-central1-a \
--machine-type=n1-standard-4 \
--accelerator=type=nvidia-tesla-t4,count=1 \
--maintenance-policy=TERMINATE \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--boot-disk-size=100GB2. Install NVIDIA drivers (version 535 for kernel compatibility):
# Install driver detection utility
sudo apt-get update
sudo apt-get install -y ubuntu-drivers-common
# Install NVIDIA driver 535 (compatible with GCP kernels)
sudo ubuntu-drivers install nvidia:535
# Reboot to load driver
sudo reboot
# Verify after reboot
nvidia-smi3. Disable swap (required for Kubernetes):
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstabThe NVIDIA Container Toolkit enables Docker to access GPU hardware.
Ubuntu/Debian:
# Add NVIDIA package repository
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# Install toolkit
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
# Configure Docker
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockerVerify GPU access in Docker:
docker run --rm --gpus all nvidia/cuda:12.1-base nvidia-smiYou should see your GPU(s) listed. If this fails, check NVIDIA drivers and Container Toolkit installation.
Node joins the Worldland K8s cluster for workload orchestration. Install these components:
Ubuntu/Debian:
# Install prerequisites
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
# Add Kubernetes repository
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
# Install kubeadm, kubelet, kubectl
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
# Install and configure containerd
sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
# Configure kernel modules
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# Configure sysctl
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# Enable kubelet
sudo systemctl enable kubeletVerify installation:
kubeadm version
kubectl version --client
containerd --versioncd worldland-node
go mod downloadgo build -o node ./cmd/nodeNodes communicate with Hub using mTLS (mutual TLS). You need:
- CA certificate (from Hub's step-ca)
- Node certificate and private key
Option A: Get certificates from Hub administrator
If running in a production environment, request certificates from the Hub administrator.
Option B: Generate from step-ca (development)
Ensure step-ca is running (from worldland-hub):
cd ../worldland-hub
docker-compose up -d step-ca
# Wait for healthy status
docker-compose psGenerate Node certificate:
# Bootstrap step CLI with the CA
step ca bootstrap --ca-url https://localhost:9000 --fingerprint <ROOT_FINGERPRINT>
# Get certificate
step ca certificate node.worldland.io node.crt node.keyNote: The root fingerprint is shown when step-ca starts. Check logs with docker-compose logs step-ca.
Option C: Development without mTLS
For local development, the Hub can run without mTLS verification. See Hub README for dev mode configuration.
With wallet authentication, Node automatically registers with Hub on startup.
# Create secure directory for private key
mkdir -p ~/.worldland
chmod 700 ~/.worldland
# Save your Ethereum private key (64 hex characters, no 0x prefix)
echo "your_private_key_here" > ~/.worldland/private-key.txt
chmod 600 ~/.worldland/private-key.txtAlternative: Manual Registration (Development)
If not using wallet authentication, register manually via Hub API:
# Register node via Hub API (requires SIWE authentication)
curl -X POST http://localhost:8080/api/v1/nodes/register \
-H "Authorization: Bearer YOUR_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "0xYourWalletAddress",
"host_address": "your-public-hostname.com"
}'Save the returned node_id and use with -node-id flag.
| Flag | Required | Default | Description |
|---|---|---|---|
-hub |
No | localhost:8443 | Hub mTLS address |
-hub-http |
No | (derived) | Hub HTTP API URL for authentication |
-api-port |
No | 8444 | Node API port |
-host |
Yes | (none) | Public hostname for SSH |
-cert |
No | ~/.worldland/certs/node.crt | Node certificate file (auto-provisioned) |
-key |
No | ~/.worldland/certs/node.key | Node private key file (auto-provisioned) |
-ca |
No | ~/.worldland/certs/ca.crt | CA certificate file (auto-provisioned) |
-cert-dir |
No | ~/.worldland/certs | Directory for auto-generated certificates |
-node-id |
No | (auto) | Node ID (auto-assigned from certificate CN) |
-private-key |
No | (none) | Ethereum private key (hex) |
-private-key-file |
No | (none) | Path to file containing private key |
-siwe-domain |
No | (derived from hub-http) | SIWE domain for authentication (e.g., localhost:3000) |
-gpu-type |
No | (auto-detected) | GPU type for registration (auto-detected from NVML) |
-memory-gb |
No | (auto-detected) | GPU memory in GB (auto-detected from NVML) |
-price-per-sec |
No | 1000000000 | Price per second in wei |
Note: Either provide -private-key or -private-key-file for wallet authentication. If neither is provided, the Node runs in mock mode (development only) and requires -node-id.
With wallet authentication (recommended):
./node \
-hub localhost:8443 \
-hub-http http://localhost:8080 \
-siwe-domain localhost:3000 \
-private-key-file ~/.worldland/private-key.txt \
-host localhostGPU type and memory are auto-detected. Certificates are auto-provisioned to ~/.worldland/certs/.
Without wallet (mock mode):
./node \
-hub localhost:8443 \
-node-id test-node-123 \
-cert node.crt \
-key node.key \
-ca ca.crt \
-host localhost./node \
-hub 35.193.4.15:8443 \
-hub-http http://35.193.4.15:8080 \
-siwe-domain localhost:3000 \
-private-key-file /etc/worldland/private-key.txt \
-host $(curl -s ifconfig.me) \
-api-port 8444 \
-price-per-sec "1000000000"GPU type and memory are auto-detected from NVML. Certificates are auto-provisioned on first run.
Verify: Node should log:
Worldland Node starting...
GPU detected: NVIDIA Tesla T4 (16 GB)
GPU detected - will register as GPU Node
Authenticating with wallet to Hub at http://35.193.4.15:8080...
Wallet address: 0xYourWalletAddress
SIWE authentication successful
Bootstrap certificates saved to /home/user/.worldland/certs
Node registered: node_abc123
Connected to Hub at 35.193.4.15:8443
Node ready - API on port 8444
Node automatically detects NVIDIA GPUs using NVML (NVIDIA Management Library) and registers with the correct GPU type and memory.
If NVIDIA GPU is detected, the node automatically registers with actual GPU specifications:
Worldland Node starting...
GPU detected: NVIDIA Tesla T4 (16 GB)
GPU detected - will register as GPU Node
Node registered: node_abc123
The GPU type (e.g., "NVIDIA Tesla T4") and memory (e.g., 16 GB) are automatically detected from the hardware. You can override these with -gpu-type and -memory-gb flags if needed.
If no GPU is detected (NVML initialization fails), the node automatically registers as a "CPU Node":
Worldland Node starting...
No GPU detected (NVML: Initialization error) - will register as CPU Node
Node registered as: CPU Node (memory: 1GB)
CPU Nodes can still participate in the Worldland network for non-GPU workloads.
Verify GPU detection:
# Check what GPU Node sees
nvidia-smi # Shows GPU model and memory
./node -hub localhost:8443 -private-key-file ~/.worldland/private-key.txt -host localhost
# Look for "GPU detected: <model> (<memory> GB)" in startup logsworldland-node/
├── cmd/
│ └── node/ # Node binary entry point
├── internal/
│ ├── adapters/
│ │ └── nvml/ # NVIDIA GPU detection
│ ├── api/ # mTLS API handlers
│ ├── auth/ # SIWE wallet authentication
│ ├── container/ # Docker container management
│ ├── domain/ # Domain models (GPU specs, rentals)
│ ├── port/ # Dynamic SSH port allocation
│ ├── rental/ # Rental session management
│ └── services/ # Service orchestration
└── go.mod # Go dependencies
Cause: NVIDIA Container Toolkit not installed or GPU not detected.
Solution:
# Verify NVIDIA driver
nvidia-smi
# Verify Container Toolkit
docker run --rm --gpus all nvidia/cuda:12.1-base nvidia-smi
# If fails, reinstall Container Toolkit (see Installation)Cause: Certificate files not found or invalid.
Solution:
# Check files exist
ls -la node.crt node.key ca.crt
# Verify certificate format
openssl x509 -in node.crt -text -nooutCause: Hub not running, wrong address, or certificate mismatch.
Solution:
# Check Hub is running
curl http://localhost:8080/health
# Verify certificates match Hub's CA
# The ca.crt must be from the same step-ca that issued Hub's certificateCause: Missing -node-id flag and no wallet authentication configured.
Solution: Either:
- Use wallet authentication with
-private-key-file(recommended) - Or provide
-node-idfor mock mode
Cause: Wallet authentication failed with Hub.
Solution:
# Check Hub HTTP API is accessible
curl http://hub.worldland.io:8080/health
# Verify private key format (64 hex chars, no 0x prefix)
cat ~/.worldland/private-key.txt | wc -c # Should be 64 or 65
# Check Hub's SIWE domain configuration
# Hub must have SIWE_DOMAIN set to match the connectionCause: Private key is malformed.
Solution:
# Private key should be 64 hex characters
# Remove 0x prefix if present
# Remove any whitespace or newlines
# Verify key format
cat ~/.worldland/private-key.txt | tr -d '\n' | wc -c # Should be 64# Check Docker daemon can access GPU runtime
docker info | grep -i nvidia
# If missing, configure runtime
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart dockerCause: Kubernetes components not installed.
Solution:
# Install kubeadm, kubelet, kubectl (see Installation section 2)
sudo apt-get install -y kubelet kubeadm kubectlCause: Kubelet not running or misconfigured.
Solution:
# Check kubelet status
sudo systemctl status kubelet
# Check containerd
sudo systemctl status containerd
# Verify kernel modules
lsmod | grep br_netfilter
lsmod | grep overlay
# If missing, load them
sudo modprobe br_netfilter
sudo modprobe overlay-
mTLS Required: All Hub-Node communication uses mutual TLS. Never expose Node API without mTLS.
-
Certificate Storage: Store certificates in a secure location with restricted permissions:
chmod 600 node.key chmod 644 node.crt ca.crt
-
Network: Only expose the SSH ports to renters. The Node API (8444) should only be accessible to Hub.
MIT