| categories |
|
||||||
|---|---|---|---|---|---|---|---|
| tags |
|
||||||
| weight | 2 | ||||||
| title | Node & Provider Development Environment | ||||||
| linkTitle | Node & Provider Setup | ||||||
| description | Set up your Kubernetes development environment for Akash node and provider contributions |
Set up a complete Kubernetes development environment for node and provider development.
This guide covers the complex setup required for contributing to Akash node and provider repositories, including local Kind clusters and remote SSH clusters.
For Console and website development, see Console & Website Setup - much simpler!
- Git - Version control
- GitHub Account - For forking and PRs
- Code Editor - VS Code, GoLand, or your preference
- Go - 1.25.0 or later (latest version)
- Docker Engine/Desktop - For Kind clusters
- GNU Make - 4.0 or later
- Bash - 4.0 or later
- Direnv - 2.32.x or later
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"# Core tools
brew install go node git make
# Additional utilities
brew install wget jq curl gnu-getopt direnv
# GNU Make (macOS default is outdated)
brew install make
export PATH="/usr/local/opt/make/libexec/gnubin:$PATH"Add to your ~/.zshrc or ~/.bashrc:
export PATH="/usr/local/opt/make/libexec/gnubin:$PATH"Direnv manages environment variables per project:
# Install
brew install direnv
# Add to ~/.zshrc
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
# Or add to ~/.bashrc
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
# Reload shell
source ~/.zshrc # or source ~/.bashrc# Update package list
sudo apt-get update
# Install Go
cd /tmp
wget https://go.dev/dl/go1.25.0.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.25.0.linux-amd64.tar.gz
# Add Go to PATH
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
# Verify
go version
# Install Node.js (via nvm recommended)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install 22
nvm use 22
# Install other tools
sudo apt-get install -y make git wget curl jq build-essential direnv
# Setup direnv
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
source ~/.bashrcUse Windows Subsystem for Linux 2:
# In PowerShell (Admin)
wsl --install -d Ubuntu
# Restart, then follow Linux instructions aboveThe node and provider repositories require a complete Kubernetes development environment. This guide covers both local and remote cluster setups.
This page covers setting up a development environment for both node and provider repositories. The provider repository contains all setup scripts as it depends on the node repository.
Development approaches:
- Local Kind Cluster (
kube) - Most common, runs locally with Docker - Single Node Cluster (
single) - All services run as Kubernetes deployments - Remote SSH Cluster (
ssh) - For testing GPU workloads and IP leases - Minikube - Alternative local cluster (not commonly used)
Core:
- Go - 1.25.0 or later (latest version required)
- Docker Engine/Desktop - For containerization
- GNU Make - 4.0 or later
- Bash - 4.0 or later
- Direnv - 2.32.x or later
- wget - For downloads
- realpath - Path utilities
Additional:
- unzip
- curl
- npm
- jq
- readlink
- git
macOS Specific:
- Homebrew
- gnu-getopt (
brew install gnu-getopt)
Verify versions:
go version
make --version
bash --version
direnv version# Clone repositories first
mkdir -p ~/go/src/github.com/akash-network
cd ~/go/src/github.com/akash-network
git clone https://github.com/akash-network/node.git
git clone https://github.com/akash-network/provider.git
# Run automated installer (macOS and Debian-based Linux)
./provider/script/install_dev_dependencies.shSupported platforms:
- **macOS
- **Debian-based Linux
- **Windows (not supported - use WSL2)
All development configurations are in the provider/_run directory:
provider/_run/
├── kube/ # Local Kind cluster (most common)
├── single/ # All services in Kubernetes
├── ssh/ # Remote cluster via SSH
└── minikube/ # Minikube setup
Commands are implemented as make targets. All runbooks share the same commands once set up.
Common parameters available across all runbooks:
| Parameter | Default | Applies To | Description |
|---|---|---|---|
SKIP_BUILD |
false | All | Skip binary rebuilds |
DSEQ |
1 | deployment-, lease-, bid-*, send-manifest | Deployment sequence |
OSEQ |
1 | deployment-, lease-, bid-*, send-manifest | Order sequence |
GSEQ |
1 | deployment-, lease-, bid-*, send-manifest | Group sequence |
KUSTOMIZE_INSTALLS |
Varies | kustomize-* | Components to install |
KUBE_ROLLOUT_TIMEOUT |
120 | All | Kubernetes rollout timeout (seconds) |
Usage:
KUBE_ROLLOUT_TIMEOUT=300 make kube-cluster-setup
DSEQ=5 GSEQ=2 make query-deploymentsPurpose: Complete local development environment using Kubernetes in Docker.
The Kind (Kubernetes in Docker) runbook creates a local cluster where:
- Node and provider run as host services
- Operators run as Kubernetes deployments
- Complete end-to-end testing capability
This is the most widely used development setup.
- Docker Desktop/Engine running
- Direnv configured
- All dependencies installed
Note: This requires three simultaneous terminals. We'll call them terminal1, terminal2, and terminal3.
Run on all three terminals:
cd ~/go/src/github.com/akash-network/provider/_run/kubeRun on terminal1 only:
# This may take several minutes
make kube-cluster-setupWhat this does:
- Creates a local Kind cluster
- Sets up ingress controller
- Configures networking
- Installs required components
If timeout occurs:
The ingress controller may take longer to initialize. If you see:
error: timed out waiting for the condition
make: *** [kube-setup-ingress-default] Error 1
Run with extended timeout:
cd ~/go/src/github.com/akash-network/provider/_run/kube
make kube-cluster-delete
make clean
make init
KUBE_ROLLOUT_TIMEOUT=300 make kube-cluster-setupGoreleaser version issue:
If you see Unable to find image 'ghcr.io/goreleaser/goreleaser-cross:v':
export GOVERSION_SEMVER=v1.24.2
KUBE_ROLLOUT_TIMEOUT=300 make kube-cluster-setupRun on terminal2:
make node-runExpected output:
- Node starts and begins syncing
- Blockchain state initializes
- RPC and API servers start
Keep this terminal running - you'll see node logs here.
Run on terminal1:
make provider-createWhat this does:
- Registers provider on the blockchain
- Creates provider account
- Sets provider attributes
Run on terminal3:
make provider-runExpected output:
- Provider connects to node
- Bidding engine starts
- Cluster monitoring begins
Keep this terminal running - you'll see provider logs here.
Run on terminal1:
# Create a test deployment
make deployment-create
# Query the deployment
make query-deployments
# Check for orders
make query-orders
# View provider bids
make query-bids
# Create a lease
make lease-create
# Verify lease
make query-leases
# Send deployment manifest
make send-manifest
# Check lease status
make provider-lease-status
# Test connectivity
make provider-lease-ping
# View deployment logs
make provider-lease-logsFull cleanup:
cd ~/go/src/github.com/akash-network/provider/_run/kube
make kube-cluster-delete
make clean
make initRestart services only:
# Stop services
make provider-stop
make node-stop
# Restart
make node-run # in terminal2
make provider-run # in terminal3Purpose: Test GPU workloads, IP leases, or production-like deployments.
The SSH runbook connects to a remote Kubernetes cluster for:
- GPU provider testing
- IP lease functionality
- Production environment simulation
- Complex networking scenarios
Remote Cluster:
- Kubernetes cluster with external API access
- SSH access to cluster nodes
- kubectl configured
- GPU drivers (for GPU testing)
Local Machine:
- SSH key configured
- kubectl installed
- Direnv configured
# Install containerd (if not already installed)
apt-get update && apt-get install -y containerd
# Install nerdctl for image management
wget https://github.com/containerd/nerdctl/releases/download/v1.7.0/nerdctl-1.7.0-linux-amd64.tar.gz
tar Cxzvvf /usr/local/bin nerdctl-1.7.0-linux-amd64.tar.gz
rm nerdctl-1.7.0-linux-amd64.tar.gz
# Verify installation
nerdctl --version# On remote cluster, create external kubeconfig
kubectl config view --raw > /tmp/external-kubeconfig.yaml
# Get cluster's external IP
EXTERNAL_IP=$(curl -s ifconfig.me)
echo "Cluster external IP: $EXTERNAL_IP"
# Replace localhost with external IP
sed -i "s|https://127.0.0.1:6443|https://$EXTERNAL_IP:6443|" /tmp/external-kubeconfig.yaml
# Skip TLS verification (development only!)
kubectl config set-cluster cluster.local \
--insecure-skip-tls-verify=true \
--kubeconfig /tmp/external-kubeconfig.yaml
# Test from remote host
KUBECONFIG=/tmp/external-kubeconfig.yaml kubectl get nodes# From your local machine
scp -i ~/.ssh/your-key root@<CLUSTER_IP>:/tmp/external-kubeconfig.yaml ~/.kube/remote-cluster-config
# Set KUBECONFIG
export KUBECONFIG=~/.kube/remote-cluster-config
# Test connection
kubectl get nodescd ~/go/src/github.com/akash-network/provider/_run/sshEdit .envrc:
vim .envrcAdd/verify these settings:
source_up .envrc
dotenv_if_exists dev.env
AP_RUN_NAME=$(basename "$(pwd)")
AP_RUN_DIR="${DEVCACHE_RUN}/${AP_RUN_NAME}"
export AKASH_HOME="${AP_RUN_DIR}/.akash"
export AKASH_KUBECONFIG=$KUBECONFIG
export AP_KUBECONFIG=$KUBECONFIG
export AP_RUN_NAME
export AP_RUN_DIR
export KUBE_SSH_NODES="root@<YOUR_CLUSTER_IP>"Reload environment:
direnv allow
# Verify
echo "KUBE_SSH_NODES: $KUBE_SSH_NODES"
echo "KUBECONFIG: $KUBECONFIG"make initFor standard workloads:
KUBE_ROLLOUT_TIMEOUT=300 make kube-cluster-setupFor GPU workloads:
KUBE_ROLLOUT_TIMEOUT=300 make kube-cluster-setup-gpuWhat this does:
- Creates namespaces
- Sets up ingress controller
- Installs Helm charts
- Configures GPU support (if GPU target)
Run these in separate terminals:
Terminal 1 - Start Node:
cd ~/go/src/github.com/akash-network/provider/_run/ssh
export KUBECONFIG=~/.kube/remote-cluster-config
direnv reload
make node-runTerminal 2 - Create Provider:
cd ~/go/src/github.com/akash-network/provider/_run/ssh
export KUBECONFIG=~/.kube/remote-cluster-config
direnv reload
make provider-createTerminal 3 - Run Provider:
cd ~/go/src/github.com/akash-network/provider/_run/ssh
export KUBECONFIG=~/.kube/remote-cluster-config
direnv reload
make provider-runSame commands as local Kind cluster:
make deployment-create
make query-deployments
make lease-create
make send-manifest
make provider-lease-statusSSH Permission Denied:
- Verify SSH key is loaded:
ssh-add -l - Test SSH access:
ssh root@<CLUSTER_IP>
Kubeconfig Access Issues:
- Verify external IP is reachable
- Check firewall rules for port 6443
- Ensure TLS verification is skipped
Image Upload Failures:
- Verify nerdctl is installed on nodes
- Check containerd is running
- Test:
ssh root@<CLUSTER_IP> nerdctl version
Timeout Errors:
- Increase timeout:
KUBE_ROLLOUT_TIMEOUT=600 - Check network latency
- Verify cluster resources
cd ~/go/src/github.com/akash-network/provider/_run/ssh
make initOnce any runbook is set up, these commands work across all environments:
Deployment Commands:
make deployment-create # Create test deployment
make deployment-update # Update deployment
make deployment-close # Close deploymentQuery Commands:
make query-deployments # List all deployments
make query-orders # List orders
make query-bids # List bids
make query-leases # List leases
make query-providers # List providersLease Commands:
make lease-create # Create lease from bid
make send-manifest # Send manifest to provider
make provider-lease-status # Check lease status
make provider-lease-logs # View deployment logs
make provider-lease-ping # Test connectivityProvider Commands:
make provider-create # Register provider
make provider-run # Start provider service
make provider-stop # Stop providerNode Commands:
make node-run # Start local node
make node-stop # Stop nodeDocker not running:
# macOS
open -a Docker
# Linux
sudo systemctl start dockerDirenv not loading:
# Check hook is configured
grep direnv ~/.zshrc
# If missing
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
source ~/.zshrc
# Allow in project
direnv allowPort already in use:
# Find process using port
lsof -i :8080 # or other port
# Kill process
kill -9 <PID>Kind cluster won't start:
# List existing clusters
kind get clusters
# Delete old cluster
kind delete cluster --name akash
# Retry setup
make kube-cluster-setupBuild fails with Go version error:
# Set Go version
export GOVERSION_SEMVER=v1.24.2
# Verify
echo $GOVERSION_SEMVER
# Retry build
make kube-cluster-setupProvider won't connect to node:
- Verify node is running in terminal2
- Check node logs for errors
- Ensure provider was created:
make query-providers
No bids on deployment:
- Check provider is running in terminal3
- Verify provider attributes match deployment requirements
- Check provider logs for errors
# Check cluster status
kubectl get nodes
kubectl get pods --all-namespaces
# Check kind cluster
kind get clusters
docker ps
# View provider logs
make provider-logs
# View node logs
make node-logs
# Check blockchain status
make query-block-resultsPlace custom SDL files in _run/kube/deployment.yaml (or ssh/single):
version: "2.0"
services:
web:
image: nginx:latest
expose:
- port: 80
to:
- global: true
profiles:
compute:
web:
resources:
cpu:
units: 0.5
memory:
size: 512Mi
storage:
size: 512Mi
placement:
akash:
pricing:
web:
denom: uact
amount: 1000
deployment:
web:
akash:
profile: web
count: 1Then deploy:
make deployment-createTest bid rejection:
# Set very low pricing
DSEQ=1 make deployment-create
# Provider should reject bidTest multiple deployments:
DSEQ=1 make deployment-create
DSEQ=2 make deployment-create
DSEQ=3 make deployment-create
make query-deploymentsTest deployment updates:
make deployment-create
# Modify deployment.yaml
make deployment-updateAfter setup:
- Explore
_run/kube/Makefileto see all available targets - Read provider logs to understand bidding logic
- Experiment with different SDL configurations
- Test various deployment scenarios
Other Development Guides:
- Console & Website Setup - Web development (easier)
- Getting Started - Make your first contribution
- Code Conventions - Coding standards
Resources:
- Node Repository - Blockchain node source
- Provider Repository - Provider services source
Install Go extension:
code --install-extension golang.goWorkspace settings (.vscode/settings.json):
{
"go.formatTool": "goimports",
"go.lintTool": "golangci-lint",
"go.useLanguageServer": true,
"editor.formatOnSave": true,
"[go]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"go.testFlags": ["-v"],
"go.testTimeout": "10s"
}- Open provider or node directory
- Configure Go SDK - Point to your Go 1.25+ installation
- Enable gofmt on save - Settings → Tools → File Watchers
- Set up golangci-lint - Settings → Tools → golangci-lint
- Configure Kubernetes - Settings → Languages & Frameworks → Kubernetes
- Enable Direnv - Settings → Plugins → Install Direnv plugin
All Akash Go projects use Makefiles:
# View all available commands
make help
# Run tests
make test
# Run linter
make lint
# Build binaries
make build
# Clean build artifacts
make clean
# Install dependencies
make cache# Keep your fork updated
git fetch upstream
git checkout main
git merge upstream/main
# Create feature branch
git checkout -b feature/your-feature
# Make changes, commit, push
git add .
git commit -s -m "feat: your change"
git push origin feature/your-featureRun all tests:
make testRun specific package tests:
go test ./pkg/specific-package
go test ./bidengine/...Run with coverage:
make test-coverageIntegration tests:
make test-integrationVerbose output:
go test -v ./...Problem: go, make, or node not in PATH
Solution:
# macOS - Add to ~/.zshrc
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
# Linux - Add to ~/.bashrc
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
# Reload
source ~/.zshrc # or ~/.bashrcProblem: make: unrecognized option '--version'
Solution:
brew install make
export PATH="/usr/local/opt/make/libexec/gnubin:$PATH"Problem: go: module not found
Solution:
# Clear module cache
go clean -modcache
# Re-download dependencies
go mod download
# Verify go.mod
go mod verifyProblem: Environment variables not loading
Solution:
# Re-allow direnv
direnv allow
# Check hook is installed
grep direnv ~/.zshrc # or ~/.bashrc
# If missing, add:
eval "$(direnv hook zsh)" # or bashProblem: Dev server won't start (port 3000 or 4321)
Solution:
# Find process using port
lsof -i :3000 # or :4321
# Kill process
kill -9 <PID>
# Or use different port
npm run dev -- --port 3001Problem: Can't write to directories
Solution:
# Fix ownership (macOS/Linux)
sudo chown -R $USER:$USER ~/path/to/repo
# Or use sudo for npm (not recommended)
# Instead, fix npm permissions:
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATHCreate .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}"
},
{
"name": "Attach to Process",
"type": "go",
"request": "attach",
"mode": "local",
"processId": "${command:pickProcess}"
}
]
}Create .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Next.js: debug server-side",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 9229
}
]
}# Use build cache
export GOCACHE=$HOME/.cache/go-build
# Parallel builds
make -j8 build# Use pnpm (faster alternative)
npm install -g pnpm
pnpm install
# Or use npm ci for clean installs
npm ciEnvironment set up? Great!
- Getting Started - Make your first contribution
- Code Conventions - Learn coding standards
- Pull Request Process - Submit your changes
Need help? Ask in Discord #developers!