Files
onix/SETUP.md
2025-10-15 18:14:31 +05:30

1985 lines
45 KiB
Markdown

# Beckn-ONIX Setup Guide
This comprehensive guide walks you through setting up Beckn-ONIX from development to production deployment.
## Table of Contents
1. [Prerequisites](#prerequisites)
2. [Development Setup](#development-setup)
3. [Production Setup](#production-setup)
4. [Configuration Guide](#configuration-guide)
5. [External Services Setup](#external-services-setup)
6. [GUI Component Setup](#gui-component-setup)
7. [Docker Deployment](#docker-deployment)
8. [Kubernetes Deployment](#kubernetes-deployment)
9. [Testing Your Setup](#testing-your-setup)
10. [Troubleshooting](#troubleshooting)
11. [Sample Payloads](#sample-payloads)
---
## Prerequisites
### System Requirements
- **Operating System**: Linux, macOS, or Windows (with WSL2)
- **CPU**: 2+ cores recommended
- **RAM**: 4GB minimum, 8GB recommended
- **Disk Space**: 2GB free space
### Software Requirements
#### Required
- **Go 1.23+**: [Download Go](https://golang.org/dl/)
- **Git**: [Download Git](https://git-scm.com/downloads)
- **Redis 6.0+**: For caching functionality
#### Optional (for production)
- **Docker 20.10+**: For containerized deployment
- **HashiCorp Vault 1.12+**: For secrets management
- **RabbitMQ 3.10+**: For async messaging
- **Kubernetes 1.25+**: For orchestrated deployment
### Verify Installation
```bash
# Check Go version
go version
# Expected: go version go1.23.x
# Check Git
git --version
# Check Docker (optional)
docker --version
# Check Redis
redis-cli --version
```
---
## Quick Start (Recommended)
### Option 1: ONIX Adapter Only (Fastest)
For just the ONIX adapter with Redis (no Vault required):
```bash
# Clone the repository
git clone https://github.com/beckn/beckn-onix.git
cd beckn-onix/install
# Run the automated setup
chmod +x setup.sh
./setup.sh
```
This will automatically:
- Start Redis container
- Build all plugins
- Build adapter server
- Start ONIX adapter in Docker using `local-simple.yaml` (with `simplekeymanager`)
- Create .env file
**Services Started:**
- Redis: localhost:6379
- ONIX Adapter: http://localhost:8081
**Key Management:** Uses `simplekeymanager` with embedded keys - no Vault setup required!
**Note:** Extract schemas before running: `unzip schemas.zip` (required for schema validation) and before running the automated setup, build the adapter image ,update docker-compose-adapter.yaml to use the correct image (optional)
```bash
# from the repository root
docker build -f Dockerfile.adapter-with-plugins -t beckn-onix:latest .
```
### Option 2: Complete Beckn Network
For a full local Beckn network with all components:
```bash
cd beckn-onix/install
chmod +x beckn-onix.sh
./beckn-onix.sh
# Choose option 3: "Set up a network on your local machine"
```
This will automatically:
- Install and configure Registry service
- Install and configure Gateway service
- Create BAP Protocol Server registry entries
- Create BPP Protocol Server registry entries
- Build ONIX adapter plugins
- **Detect config file** from `docker-compose-adapter.yml`
- **Extract keys** from protocol server configs (`bap-client.yml`, `bpp-client.yml`)
- **Auto-update simplekeymanager** in the detected config file with extracted keys
- Start ONIX Adapter with Redis
**Services Started:**
- Registry: http://localhost:3030
- Gateway: http://localhost:4030
- Sandbox API: http://localhost:3000
- ONIX Adapter: http://localhost:8081
- Redis: localhost:6379
**Note:** Extract schemas before running: `unzip schemas.zip` (required for schema validation) and before running the automated full-network setup, build the adapter image , update docker-compose-adapter.yaml to use the correct image(optional)
```bash
# from the repository root
docker build -f Dockerfile.adapter-with-plugins -t beckn-onix:latest .
```
**Intelligent Key Management:**
The script reads `docker-compose-adapter.yml` to detect which config file is being used (default: `local-simple.yaml`), extracts keys from protocol server configs, and automatically updates the `simplekeymanager` section in that config file - no manual configuration needed!
**Note:** Update `docker-compose-adapter.yml` to use the correct config file and correct image (optional):
- For combined setup (simplekeymanager): `CONFIG_FILE: "/app/config/local-simple.yaml"`
- For combined setup (keymanager with Vault): `CONFIG_FILE: "/app/config/local-dev.yaml"`
- For combined setup (production): `CONFIG_FILE: "/app/config/onix/adapter.yaml"`
- For BAP only: `CONFIG_FILE: "/app/config/onix-bap/adapter.yaml"`
- For BPP only: `CONFIG_FILE: "/app/config/onix-bpp/adapter.yaml"`
The script will automatically detect and configure whichever file you specify.
---
## Development Setup (Manual)
### Step 1: Clone the Repository
```bash
git clone https://github.com/beckn/beckn-onix.git
cd beckn-onix
```
### Step 2: Install Dependencies
```bash
# Download Go dependencies
go mod download
# Verify dependencies
go mod verify
```
### Step 3: Build the Application
```bash
# Build the main server binary
go build -o server cmd/adapter/main.go
# Make it executable
chmod +x server
```
### Step 4: Build Plugins
The application uses a plugin architecture. Build all plugins:
```bash
# Make the build script executable
chmod +x install/build-plugins.sh
# Build all plugins (run from project root)
./install/build-plugins.sh
```
This creates `.so` files in the `plugins/` directory:
- `cache.so` - Redis caching
- `router.so` - Request routing
- `signer.so` - Message signing
- `signvalidator.so` - Signature validation
- `schemavalidator.so` - JSON schema validation
- `keymanager.so` - Vault integration
- `simplekeymanager.so` - Simple key management (no Vault)
- `publisher.so` - RabbitMQ publishing
- `registry.so` - Registry lookup
- `dediregistry.so` - registry type plugin for public key lookup
- `encrypter.so` / `decrypter.so` - Encryption/decryption
- `reqpreprocessor.so` - Request preprocessing
### Step 5: Setup Redis (Local)
#### Option A: Using Docker
```bash
docker run -d \
--name redis-onix \
-p 6379:6379 \
redis:alpine
```
#### Option B: Native Installation
**macOS:**
```bash
brew install redis
brew services start redis
```
**Ubuntu/Debian:**
```bash
sudo apt update
sudo apt install redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server
```
**Verify Redis:**
```bash
redis-cli ping
# Expected: PONG
```
### Step 6: Setup Schemas
```bash
# Create schemas directory
mkdir -p schemas
# Extract schemas from the provided schemas.zip
unzip schemas.zip
# Create logs directory (optional)
mkdir -p logs
```
**Note:** The `schemas.zip` file is included in the repository. You must extract it before running the adapter for schema validation to work.
### Step 7: Configure for Local Development
For local development, use the existing `config/local-simple.yaml` which includes:
- All 4 modules (BAP + BPP)
- Simple key management (no Vault required)
- Redis caching
- Basic routing configuration
The file is pre-configured with embedded sample keys and ready to use for standalone testing.
**Note:** When using `beckn-onix.sh` (Option 2 in Quick Start), the script automatically extracts keys from protocol server configs and updates the `simplekeymanager` section in this file - no manual configuration needed!
### Step 8: Configuration Files Overview
The `config/` directory contains deployment configurations:
```
config/
├── local-dev.yaml # Local development with Vault
├── local-simple.yaml # Local development (no Vault)
├── local-routing.yaml # Local routing rules
├── local-simple-routing.yaml # Simple routing rules
├── local-simple-routing-BAPCaller.yaml # BAP caller routing
├── local-simple-routing-BPPReceiver.yaml # BPP receiver routing
├── onix/ # Combined BAP+BPP deployment
│ ├── adapter.yaml
│ ├── plugin.yaml
│ ├── bapTxnCaller-routing.yaml
│ ├── bapTxnReciever-routing.yaml
│ ├── bppTxnCaller-routing.yaml
│ └── bppTxnReciever-routing.yaml
├── onix-bap/ # BAP-only deployment
│ ├── adapter.yaml
│ ├── plugin.yaml
│ ├── bapTxnCaller-routing.yaml
│ └── bapTxnReciever-routing.yaml
└── onix-bpp/ # BPP-only deployment
├── adapter.yaml
├── plugin.yaml
├── bppTxnCaller-routing.yaml
└── bppTxnReciever-routing.yaml
```
Routing configuration files for local-simple are already provided and referenced in `local-simple.yaml`.
### Step 9: Run the Application
**Choose your key management approach:**
#### Option A: Simple Key Manager (Recommended for Local Development)
**No Vault setup required!** Use this for quick local testing.
```bash
# Run with local-simple.yaml (uses simplekeymanager plugin)
./server --config=config/local-simple.yaml
# Or run with go
go run cmd/adapter/main.go --config=config/local-simple.yaml
```
The `local-simple.yaml` config uses `simplekeymanager` plugin with embedded keys - no external dependencies needed.
**With Docker:**
```bash
cd install
docker compose -f docker-compose-adapter.yml up -d onix-adapter
```
The server will start on `http://localhost:8081`
---
#### Option B: HashiCorp Vault (Production-like Setup)
**Only use this if your config has `keymanager` plugin (not `simplekeymanager`).**
Configs that require Vault:
- `config/local-dev.yaml` - uses `keymanager` plugin
- `config/onix/adapter.yaml` - uses `secretskeymanager` plugin
#### Quick Setup (Recommended)
**Note:** Make sure Redis is already running from Step 5.
```bash
# Make the script executable
chmod +x start-vault.sh
# Run the automated setup script
./start-vault.sh
# This creates a .env.vault file with your credentials
# Source it and run the server
source .env.vault && ./server --config=config/local-dev.yaml
```
That's it! The script handles everything automatically.
#### Manual Setup (Advanced)
If you prefer to set up Vault manually or need custom configuration:
```bash
# 1. Start Vault container
docker run -d \
--name vault-dev \
--cap-add=IPC_LOCK \
-p 8200:8200 \
-e 'VAULT_DEV_ROOT_TOKEN_ID=root' \
hashicorp/vault:latest
# 2. Configure Vault (run the setup script)
chmod +x config/setup-vault.sh
./config/setup-vault.sh
# 3. Export the displayed credentials
export VAULT_ROLE_ID=<displayed-role-id>
export VAULT_SECRET_ID=<displayed-secret-id>
# 4. Run the server
./server --config=config/local-dev.yaml
```
#### What the Setup Does
- Starts Vault in development mode on port 8200
- Enables AppRole authentication
- Creates necessary policies and roles
- Sets up the KV secrets engine at path `beckn`
- Stores sample keys for both BAP and BPP
- Generates and saves credentials to `.env.vault`
#### Accessing Vault UI
- **URL:** http://localhost:8200
- **Token:** root
#### Troubleshooting
If you get "invalid role or secret ID" error, the SECRET_ID has expired. Simply run:
```bash
./start-vault.sh
source .env.vault
```
**Alternative: Simple Docker Run Command**
```bash
# Start Vault in dev mode with initial setup
docker run -d \
--name vault-dev \
--cap-add=IPC_LOCK \
-p 8200:8200 \
-e 'VAULT_DEV_ROOT_TOKEN_ID=root' \
-e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' \
hashicorp/vault:latest
# Wait for Vault to be ready
sleep 3
# Setup Vault using a single command
docker exec vault-dev sh -c "
export VAULT_ADDR='http://127.0.0.1:8200' &&
export VAULT_TOKEN='root' &&
vault secrets enable -path=beckn kv-v2 &&
vault kv put beckn/keys/bap private_key='sample_bap_private_key' public_key='sample_bap_public_key' &&
vault kv put beckn/keys/bpp private_key='sample_bpp_private_key' public_key='sample_bpp_public_key'
"
```
**Step 9b: Set Environment Variables and Run**
```bash
# Get the AppRole credentials from Vault container logs
docker logs vault-dev | grep "VAULT_ROLE_ID\|VAULT_SECRET_ID"
# Copy the displayed credentials and export them
# They will look something like this:
export VAULT_ROLE_ID='<role-id-from-logs>'
export VAULT_SECRET_ID='<secret-id-from-logs>'
# Run the server
./server --config=config/local-dev.yaml
# Or using go run
go run cmd/adapter/main.go --config=config/local-dev.yaml
```
**Note:** The Vault address is already configured in `config/local-dev.yaml` as `http://localhost:8200`. The docker-compose automatically sets up AppRole authentication and displays the credentials in the logs.
**Alternative: Create a startup script**
Create `run-with-vault.sh`:
```bash
#!/bin/bash
# Set Vault environment variables
export VAULT_ADDR=${VAULT_ADDR:-"http://localhost:8200"}
export VAULT_TOKEN=${VAULT_TOKEN:-"root"} # For dev mode
# Or use AppRole auth for production-like setup
# export VAULT_ROLE_ID=${VAULT_ROLE_ID:-"beckn-role-id"}
# export VAULT_SECRET_ID=${VAULT_SECRET_ID:-"beckn-secret-id"}
echo "Starting Beckn-ONIX with Vault key management..."
echo "Vault Address: $VAULT_ADDR"
# Check if Vault is accessible
if ! curl -s "$VAULT_ADDR/v1/sys/health" > /dev/null 2>&1; then
echo "Error: Cannot reach Vault at $VAULT_ADDR"
echo "Please start Vault first with: vault server -dev -dev-root-token-id='root'"
exit 1
fi
# Run the server
./server --config=config/local-dev.yaml
```
Make it executable and run:
```bash
chmod +x run-with-vault.sh
./run-with-vault.sh
```
The server will start on `http://localhost:8081`
### Step 10: Verify Setup
```bash
# Check health endpoint
curl http://localhost:8081/health
# Check if modules are loaded
curl http://localhost:8081/bap/receiver/
# Expected: 404 with proper error (means module is loaded)
```
---
## Production Setup
### Additional Requirements for Production
1. **HashiCorp Vault** for key management
2. **RabbitMQ** for message queuing
3. **TLS certificates** for secure communication
4. **Load balancer** for high availability
### Step 1: Setup HashiCorp Vault
#### Install Vault
```bash
# Download and install
wget https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
unzip vault_1.15.0_linux_amd64.zip
sudo mv vault /usr/local/bin/
```
#### Configure Vault
```bash
# Start Vault in dev mode (for testing only)
vault server -dev -dev-root-token-id="root"
# In production, use proper configuration
cat > vault-config.hcl <<EOF
storage "file" {
path = "/opt/vault/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 0
tls_cert_file = "/opt/vault/tls/cert.pem"
tls_key_file = "/opt/vault/tls/key.pem"
}
api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"
ui = true
EOF
vault server -config=vault-config.hcl
```
#### Setup Keys in Vault
```bash
# Login to Vault
export VAULT_ADDR='http://localhost:8200'
vault login token=root
# Enable KV secrets engine
vault secrets enable -path=beckn kv-v2
# Store signing keys
vault kv put beckn/keys/bap \
private_key="$(cat bap_private_key.pem)" \
public_key="$(cat bap_public_key.pem)"
vault kv put beckn/keys/bpp \
private_key="$(cat bpp_private_key.pem)" \
public_key="$(cat bpp_public_key.pem)"
```
### Step 2: Setup RabbitMQ
#### Using Docker
```bash
docker run -d \
--name rabbitmq-onix \
-p 5672:5672 \
-p 15672:15672 \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin123 \
rabbitmq:3-management
```
#### Configure Exchange and Queues
```bash
# Access RabbitMQ management UI
# http://localhost:15672 (admin/admin123)
# Or use CLI
docker exec rabbitmq-onix rabbitmqctl add_exchange beckn_exchange topic
docker exec rabbitmq-onix rabbitmqctl add_queue search_queue
docker exec rabbitmq-onix rabbitmqctl bind_queue search_queue beckn_exchange "*.search"
```
### Step 3: Production Configuration
Create `config/production.yaml`:
```yaml
appName: "beckn-onix-prod"
log:
level: info
destinations:
- type: file
config:
filename: /var/log/beckn-onix/app.log
maxSize: 100 # MB
maxBackups: 10
maxAge: 30 # days
- type: stdout
contextKeys:
- transaction_id
- message_id
- subscriber_id
- module_id
- domain
- action
http:
port: 8080
timeout:
read: 60
write: 60
idle: 120
tls:
enabled: true
certFile: /etc/ssl/certs/server.crt
keyFile: /etc/ssl/private/server.key
pluginManager:
root: ./plugins
modules:
- name: bapTxnReceiver
path: /bap/receiver/
handler:
type: std
role: bap
registryUrl: https://registry.ondc.org/lookup
plugins:
keyManager:
id: keymanager
config:
projectID: ${PROJECT_ID}
vaultAddr: ${VAULT_ADDR}
kvVersion: v2
cache:
id: cache
config:
addr: ${REDIS_ADDR}
password: ${REDIS_PASSWORD}
db: 0
poolSize: 100
schemaValidator:
id: schemavalidator
config:
schemaDir: ./schemas
strictMode: true
signValidator:
id: signvalidator
config:
publicKeyPath: beckn/keys
router:
id: router
config:
routingConfig: ./config/routing-prod.yaml
publisher:
id: publisher
config:
addr: ${RABBITMQ_ADDR}
username: ${RABBITMQ_USER}
password: ${RABBITMQ_PASS}
exchange: beckn_exchange
durable: true
useTLS: true
middleware:
- id: reqpreprocessor
config:
uuidKeys: transaction_id,message_id
role: bap
steps:
- validateSign
- addRoute
- validateSchema
- cache
- publish
# Add similar configuration for other modules...
```
### Step 4: Environment Variables
Create `.env.production`:
```bash
# Vault Configuration
VAULT_ADDR=https://vault.example.com:8200
VAULT_ROLE_ID=your-role-id
VAULT_SECRET_ID=your-secret-id
PROJECT_ID=beckn-onix-prod
# Redis Configuration
REDIS_ADDR=redis.example.com:6379
REDIS_PASSWORD=strong-redis-password
# RabbitMQ Configuration
RABBITMQ_ADDR=rabbitmq.example.com:5671
RABBITMQ_USER=beckn_user
RABBITMQ_PASS=strong-rabbitmq-password
# Application Configuration
LOG_LEVEL=info
CONFIG_FILE=/app/config/production.yaml
```
### Step 5: Systemd Service (Linux)
Create `/etc/systemd/system/beckn-onix.service`:
```ini
[Unit]
Description=Beckn ONIX Adapter
After=network.target redis.service
[Service]
Type=simple
User=beckn
Group=beckn
WorkingDirectory=/opt/beckn-onix
EnvironmentFile=/opt/beckn-onix/.env.production
ExecStart=/opt/beckn-onix/server --config=${CONFIG_FILE}
Restart=always
RestartSec=10
StandardOutput=append:/var/log/beckn-onix/stdout.log
StandardError=append:/var/log/beckn-onix/stderr.log
[Install]
WantedBy=multi-user.target
```
Enable and start:
```bash
sudo systemctl daemon-reload
sudo systemctl enable beckn-onix
sudo systemctl start beckn-onix
sudo systemctl status beckn-onix
```
---
## Configuration Guide
### Configuration Hierarchy
```
config/
├── local-dev.yaml # Local development with Vault
├── local-simple.yaml # Local development (no Vault)
├── local-routing.yaml # Local routing rules
├── local-simple-routing.yaml # Simple routing rules
├── local-simple-routing-BAPCaller.yaml # BAP caller routing
├── local-simple-routing-BPPReceiver.yaml # BPP receiver routing
├── onix/ # Combined BAP+BPP deployment
│ ├── adapter.yaml
│ ├── plugin.yaml
│ ├── bapTxnCaller-routing.yaml
│ ├── bapTxnReciever-routing.yaml
│ ├── bppTxnCaller-routing.yaml
│ └── bppTxnReciever-routing.yaml
├── onix-bap/ # BAP-only deployment
│ ├── adapter.yaml
│ ├── plugin.yaml
│ ├── bapTxnCaller-routing.yaml
│ └── bapTxnReciever-routing.yaml
└── onix-bpp/ # BPP-only deployment
├── adapter.yaml
├── plugin.yaml
├── bppTxnCaller-routing.yaml
└── bppTxnReciever-routing.yaml
```
### Module Configuration
Each module needs:
- **name**: Unique identifier
- **path**: HTTP endpoint path
- **handler**: Processing configuration
- **type**: Handler type (usually "std")
- **role**: "bap" or "bpp"
- **plugins**: Plugin configurations
- **steps**: Processing pipeline steps
### Plugin Configuration
#### Cache Plugin (Redis)
```yaml
cache:
id: cache
config:
addr: localhost:6379
password: "" # Optional
db: 0
poolSize: 50
minIdleConns: 10
maxRetries: 3
```
#### KeyManager Plugin (Vault)
```yaml
keyManager:
id: keymanager
config:
projectID: beckn-project
vaultAddr: http://localhost:8200
kvVersion: v2
mountPath: beckn
namespace: "" # Optional for Vault Enterprise
```
#### Publisher Plugin (RabbitMQ)
```yaml
publisher:
id: publisher
config:
addr: localhost:5672
username: guest
password: guest
exchange: beckn_exchange
exchangeType: topic
durable: true
autoDelete: false
useTLS: false
tlsConfig:
certFile: ""
keyFile: ""
caFile: ""
```
#### SchemaValidator Plugin
```yaml
schemaValidator:
id: schemavalidator
config:
schemaDir: ./schemas
strictMode: false
downloadSchemas: true
schemaURL: https://schemas.beckn.org
```
#### Router Plugin
```yaml
router:
id: router
config:
routingConfig: ./config/routing.yaml
defaultTimeout: 30
retryCount: 3
retryDelay: 1000 # milliseconds
```
### Routing Rules Configuration
```yaml
routingRules:
- domain: "ONDC:RET10"
version: "1.0.0"
targetType: "url" # or "publisher"
target:
url: "https://seller.example.com/beckn"
# OR for async
# queueName: "retail_queue"
# routingKey: "retail.*"
endpoints:
- search
- select
- init
- confirm
headers: # Optional additional headers
X-Custom-Header: "value"
timeout: 60 # seconds
retryPolicy:
maxRetries: 3
backoff: exponential
```
### Processing Steps
Available steps for configuration:
- **validateSign**: Validate incoming signatures
- **addRoute**: Determine routing based on rules
- **validateSchema**: Validate against JSON schemas
- **sign**: Sign outgoing requests
- **cache**: Cache requests/responses
- **publish**: Publish to message queue
- **encrypt**: Encrypt sensitive data
- **decrypt**: Decrypt encrypted data
---
## External Services Setup
### Redis Cluster (Production)
```yaml
# Redis cluster configuration
cache:
id: cache
config:
clusterAddrs:
- redis-node1:6379
- redis-node2:6379
- redis-node3:6379
password: ${REDIS_PASSWORD}
poolSize: 100
readTimeout: 3s
writeTimeout: 3s
```
### Vault High Availability
```yaml
# Vault HA configuration
keyManager:
id: keymanager
config:
vaultAddrs:
- https://vault1.example.com:8200
- https://vault2.example.com:8200
- https://vault3.example.com:8200
roleID: ${VAULT_ROLE_ID}
secretID: ${VAULT_SECRET_ID}
renewToken: true
tokenTTL: 3600
```
### RabbitMQ Cluster
```yaml
# RabbitMQ cluster configuration
publisher:
id: publisher
config:
clusterAddrs:
- amqp://user:pass@rabbitmq1:5672
- amqp://user:pass@rabbitmq2:5672
- amqp://user:pass@rabbitmq3:5672
haPolicy: all # all, exactly, nodes
connectionTimeout: 10s
channelMax: 2047
```
---
## GUI Component Setup
The GUI component provides a web interface for monitoring and management.
### Prerequisites
- Node.js 18+ and npm
### Installation
```bash
cd onix-gui/GUI
# Install dependencies
npm install
# Development mode
npm run dev
# Production build
npm run build
npm start
```
### Features
- **Dashboard**: Real-time metrics and status
- **Configuration Editor**: Visual YAML editor
- **Request Monitor**: Live request/response tracking
- **Plugin Manager**: Enable/disable plugins
- **Routing Rules**: Visual routing configuration
- **Logs Viewer**: Centralized log viewing
### Configuration
Create `onix-gui/GUI/.env.local`:
```bash
NEXT_PUBLIC_API_URL=http://localhost:8081
NEXT_PUBLIC_REFRESH_INTERVAL=5000
```
### Access
Open `http://localhost:3000` in your browser.
---
## Docker Deployment
### Build Docker Image
```bash
# Build the image
docker build -f Dockerfile.adapter -t beckn-onix:latest .
# Tag for registry (optional)
docker tag beckn-onix:latest registry.example.com/beckn-onix:v1.0.0
```
### Docker Compose Setup
**Important: Create docker.yaml config and plugins bundle first**
```bash
# Create symlink to existing config
cd config
ln -s onix/adapter.yaml docker.yaml
cd ..
# Build plugins first
./install/build-plugins.sh
# Create plugins bundle for Docker
cd plugins
zip -r plugins_bundle.zip *.so
cd ..
```
Create `docker-compose.yml`:
```yaml
version: '3.8'
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --appendonly yes
vault:
image: hashicorp/vault:latest
ports:
- "8200:8200"
environment:
VAULT_DEV_ROOT_TOKEN_ID: root
VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
cap_add:
- IPC_LOCK
volumes:
- vault-data:/vault/file
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin123
volumes:
- rabbitmq-data:/var/lib/rabbitmq
beckn-onix:
image: beckn-onix:latest
ports:
- "8081:8081"
depends_on:
- redis
- vault
- rabbitmq
environment:
VAULT_ADDR: http://vault:8200
VAULT_TOKEN: root
REDIS_ADDR: redis:6379
RABBITMQ_ADDR: rabbitmq:5672
RABBITMQ_USER: admin
RABBITMQ_PASS: admin123
volumes:
- ./config:/app/config
- ./schemas:/app/schemas
- ./plugins:/mnt/gcs/plugins
command: ["./server", "--config=/app/config/docker.yaml"]
volumes:
redis-data:
vault-data:
rabbitmq-data:
```
**Important: Build the image first**
```bash
# Build the beckn-onix image before running docker-compose
docker build -f Dockerfile.adapter -t beckn-onix:latest .
# Then run docker-compose
docker-compose up -d
```
---
## Kubernetes Deployment
### Kubernetes Manifests
Create namespace:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: beckn-onix
```
ConfigMap for configuration:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: beckn-onix-config
namespace: beckn-onix
data:
adapter.yaml: |
# Your configuration here
```
Deployment:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: beckn-onix
namespace: beckn-onix
spec:
replicas: 3
selector:
matchLabels:
app: beckn-onix
template:
metadata:
labels:
app: beckn-onix
spec:
containers:
- name: beckn-onix
image: registry.example.com/beckn-onix:v1.0.0
ports:
- containerPort: 8080
env:
- name: VAULT_ADDR
valueFrom:
secretKeyRef:
name: beckn-secrets
key: vault-addr
- name: REDIS_ADDR
value: redis-service:6379
volumeMounts:
- name: config
mountPath: /app/config
- name: plugins
mountPath: /app/plugins
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: config
configMap:
name: beckn-onix-config
- name: plugins
persistentVolumeClaim:
claimName: plugins-pvc
```
Service:
```yaml
apiVersion: v1
kind: Service
metadata:
name: beckn-onix-service
namespace: beckn-onix
spec:
selector:
app: beckn-onix
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
```
### Helm Chart
For easier deployment, use the Helm chart:
```bash
# Add repo
helm repo add beckn https://charts.beckn.org
# Install
helm install beckn-onix beckn/onix \
--namespace beckn-onix \
--create-namespace \
--values values.yaml
```
Example `values.yaml`:
```yaml
replicaCount: 3
image:
repository: registry.example.com/beckn-onix
tag: v1.0.0
pullPolicy: IfNotPresent
service:
type: LoadBalancer
port: 80
ingress:
enabled: true
hostname: beckn-onix.example.com
tls: true
redis:
enabled: true
auth:
enabled: true
password: secretpassword
vault:
enabled: true
server:
dev:
enabled: false
ha:
enabled: true
replicas: 3
rabbitmq:
enabled: true
auth:
username: beckn
password: secretpassword
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
```
---
## Testing Your Setup
### Health Check
```bash
# Basic health check
curl http://localhost:8081/health
# Expected response
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.0.0"
}
```
### Test Search Request
```bash
# Create a test search request (no Authorization header needed - ONIX auto-generates it)
curl -X POST http://localhost:8081/bap/caller/search \
-H "Content-Type: application/json" \
-d '{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "search",
"version": "1.0.0",
"bap_id": "test.bap.com",
"bap_uri": "https://test.bap.com/beckn",
"transaction_id": "'$(uuidgen)'",
"message_id": "'$(uuidgen)'",
"timestamp": "'$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")'",
"ttl": "PT30S"
},
"message": {
"intent": {
"item": {
"descriptor": {
"name": "coffee"
}
},
"fulfillment": {
"end": {
"location": {
"gps": "12.9715987,77.5945627",
"area_code": "560001"
}
}
},
"payment": {
"buyer_app_finder_fee_type": "percent",
"buyer_app_finder_fee_amount": "3"
}
}
}
}'
```
### Load Testing
Use Apache Bench or similar tools:
```bash
# Install ab
sudo apt-get install apache2-utils
# Simple load test (no Authorization header needed - ONIX auto-generates it)
ab -n 1000 -c 10 -p search.json -T application/json \
http://localhost:8081/bap/caller/search
```
### Integration Testing
Create test script `test_integration.sh`:
```bash
#!/bin/bash
# Test BAP endpoints
endpoints=(
"search"
"select"
"init"
"confirm"
"status"
"track"
"cancel"
"update"
"rating"
"support"
)
for endpoint in "${endpoints[@]}"; do
echo "Testing /bap/caller/$endpoint..."
response=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "http://localhost:8081/bap/caller/$endpoint" \
-H "Content-Type: application/json" \
-d @"test_payloads/${endpoint}.json")
if [ "$response" -eq 200 ] || [ "$response" -eq 202 ]; then
echo "$endpoint: SUCCESS"
else
echo "$endpoint: FAILED (HTTP $response)"
fi
done
```
---
## Troubleshooting
### Common Issues and Solutions
#### 1. Plugin Loading Failures
**Error**: `failed to load plugin: plugin.Open: plugin.so: cannot open shared object file`
**Solution**:
```bash
# Rebuild plugins from project root
./install/build-plugins.sh
# Check plugin files exist
ls -la plugins/
# Verify plugin compatibility
go version
file plugins/cache.so
```
**Error**: `plugin was built with a different version of package internal/godebugs`
**Solution**: Plugin version mismatch - rebuild with same Go version:
```bash
# Clean and rebuild plugins
rm -rf plugins/*.so
./install/build-plugins.sh
# Ensure same Go version for server and plugins
go version
```
#### 2. Redis Connection Issues
**Error**: `dial tcp 127.0.0.1:6379: connect: connection refused`
**Solution**:
```bash
# Check Redis is running
redis-cli ping
# Start Redis if not running
sudo systemctl start redis
# Check Redis configuration
redis-cli CONFIG GET bind
redis-cli CONFIG GET protected-mode
```
#### 3. Signature Validation Failures
**Error**: `signature validation failed: invalid signature`
**Solution**:
- Verify correct key pair is being used
- Check timestamp synchronization between systems
- Ensure signature includes all required headers
- Validate Base64 encoding of signature
```bash
# Generate test keys
openssl genpkey -algorithm ed25519 -out private_key.pem
openssl pkey -in private_key.pem -pubout -out public_key.pem
```
#### 4. Schema Validation Errors
**Error**: `schema validation failed: required property 'context' not found`
**Solution**:
- Verify schema files are in correct directory
- Check schema version matches protocol version
- Validate JSON structure
```bash
# Download latest schemas
wget https://schemas.beckn.org/core/v1.0.0.zip
unzip v1.0.0.zip -d schemas/
```
#### 5. Port Already in Use
**Error**: `listen tcp :8081: bind: address already in use`
**Solution**:
```bash
# Find process using port
lsof -i :8081
# Kill process
kill -9 <PID>
# Or use different port in config
```
#### 6. Vault Authentication Issues
**Error**: `vault: authentication failed`
**Solution**:
```bash
# Check Vault status
vault status
# Verify authentication
vault login -method=approle \
role_id=${VAULT_ROLE_ID} \
secret_id=${VAULT_SECRET_ID}
# Check policy permissions
vault policy read beckn-policy
```
### Debug Mode
Enable debug logging:
```yaml
log:
level: debug
destinations:
- type: stdout
config:
pretty: true
includeCalller: true
```
Or via environment variable:
```bash
LOG_LEVEL=debug ./server --config=config/adapter.yaml
```
### Performance Tuning
#### System Limits
```bash
# Increase file descriptors
ulimit -n 65536
# Add to /etc/security/limits.conf
beckn soft nofile 65536
beckn hard nofile 65536
```
#### Go Runtime
```bash
# Set GOMAXPROCS
export GOMAXPROCS=8
# Enable profiling
./server --config=config/adapter.yaml --profile
```
#### Redis Optimization
```bash
# Redis configuration
redis-cli CONFIG SET maxclients 10000
redis-cli CONFIG SET tcp-keepalive 60
redis-cli CONFIG SET timeout 300
```
---
## Sample Payloads
### Search Request (Retail)
```json
{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "search",
"version": "1.0.0",
"bap_id": "buyerapp.com",
"bap_uri": "https://buyerapp.com/beckn",
"transaction_id": "6d5f4c3b-2a1e-4b8c-9f7d-3e2a1b5c8d9f",
"message_id": "a9f8e7d6-c5b4-3a2e-1f0d-9e8c7b6a5d4f",
"timestamp": "2024-01-15T10:30:00.000Z",
"ttl": "PT30S"
},
"message": {
"intent": {
"item": {
"descriptor": {
"name": "Laptop"
}
},
"fulfillment": {
"type": "Delivery",
"end": {
"location": {
"gps": "12.9715987,77.5945627",
"area_code": "560001"
}
}
},
"payment": {
"buyer_app_finder_fee_type": "percent",
"buyer_app_finder_fee_amount": "3"
}
}
}
}
```
### Select Request
```json
{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "select",
"version": "1.0.0",
"bap_id": "buyerapp.com",
"bap_uri": "https://buyerapp.com/beckn",
"bpp_id": "sellerapp.com",
"bpp_uri": "https://sellerapp.com/beckn",
"transaction_id": "6d5f4c3b-2a1e-4b8c-9f7d-3e2a1b5c8d9f",
"message_id": "b8e7f6d5-c4a3-2b1e-0f9d-8e7c6b5a4d3f",
"timestamp": "2024-01-15T10:31:00.000Z",
"ttl": "PT30S"
},
"message": {
"order": {
"provider": {
"id": "P1",
"locations": [
{
"id": "L1"
}
]
},
"items": [
{
"id": "I1",
"quantity": {
"count": 2
}
}
],
"fulfillment": {
"end": {
"location": {
"gps": "12.9715987,77.5945627",
"address": {
"door": "21A",
"name": "ABC Apartments",
"building": "Tower 1",
"street": "100 Feet Road",
"locality": "Indiranagar",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560001"
}
},
"contact": {
"phone": "9876543210",
"email": "customer@example.com"
}
}
}
}
}
}
```
### Init Request
```json
{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "init",
"version": "1.0.0",
"bap_id": "buyerapp.com",
"bap_uri": "https://buyerapp.com/beckn",
"bpp_id": "sellerapp.com",
"bpp_uri": "https://sellerapp.com/beckn",
"transaction_id": "6d5f4c3b-2a1e-4b8c-9f7d-3e2a1b5c8d9f",
"message_id": "c7f6e5d4-b3a2-1e0f-9d8e-7c6b5a4d3e2f",
"timestamp": "2024-01-15T10:32:00.000Z",
"ttl": "PT30S"
},
"message": {
"order": {
"provider": {
"id": "P1",
"locations": [
{
"id": "L1"
}
]
},
"items": [
{
"id": "I1",
"quantity": {
"count": 2
},
"fulfillment_id": "F1"
}
],
"billing": {
"name": "John Doe",
"address": {
"door": "21A",
"name": "ABC Apartments",
"building": "Tower 1",
"street": "100 Feet Road",
"locality": "Indiranagar",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560001"
},
"email": "john.doe@example.com",
"phone": "9876543210",
"created_at": "2024-01-15T10:32:00.000Z",
"updated_at": "2024-01-15T10:32:00.000Z"
},
"fulfillment": {
"id": "F1",
"type": "Delivery",
"tracking": false,
"end": {
"location": {
"gps": "12.9715987,77.5945627",
"address": {
"door": "21A",
"name": "ABC Apartments",
"building": "Tower 1",
"street": "100 Feet Road",
"locality": "Indiranagar",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560001"
}
},
"contact": {
"phone": "9876543210",
"email": "customer@example.com"
}
}
},
"payment": {
"type": "ON-ORDER",
"collected_by": "BAP",
"buyer_app_finder_fee_type": "percent",
"buyer_app_finder_fee_amount": "3",
"settlement_details": [
{
"settlement_counterparty": "seller-app",
"settlement_phase": "sale-amount",
"settlement_type": "neft",
"settlement_bank_account_no": "1234567890",
"settlement_ifsc_code": "SBIN0001234",
"beneficiary_name": "Seller Name",
"bank_name": "State Bank of India",
"branch_name": "Koramangala"
}
]
}
}
}
}
```
### Confirm Request
```json
{
"context": {
"domain": "nic2004:52110",
"country": "IND",
"city": "std:080",
"action": "confirm",
"version": "1.0.0",
"bap_id": "buyerapp.com",
"bap_uri": "https://buyerapp.com/beckn",
"bpp_id": "sellerapp.com",
"bpp_uri": "https://sellerapp.com/beckn",
"transaction_id": "6d5f4c3b-2a1e-4b8c-9f7d-3e2a1b5c8d9f",
"message_id": "d8f7e6d5-c4b3-2a1e-0f9d-8e7c6b5a4d3f",
"timestamp": "2024-01-15T10:33:00.000Z",
"ttl": "PT30S"
},
"message": {
"order": {
"id": "ORDER123",
"state": "Created",
"provider": {
"id": "P1",
"locations": [
{
"id": "L1"
}
]
},
"items": [
{
"id": "I1",
"fulfillment_id": "F1",
"quantity": {
"count": 2
}
}
],
"quote": {
"price": {
"currency": "INR",
"value": "4000"
},
"breakup": [
{
"item_id": "I1",
"item_quantity": {
"count": 2
},
"title_type": "item",
"title": "Laptop",
"price": {
"currency": "INR",
"value": "3800"
}
},
{
"item_id": "F1",
"title_type": "delivery",
"title": "Delivery charges",
"price": {
"currency": "INR",
"value": "100"
}
},
{
"item_id": "F1",
"title_type": "packing",
"title": "Packing charges",
"price": {
"currency": "INR",
"value": "50"
}
},
{
"item_id": "I1",
"title_type": "tax",
"title": "Tax",
"price": {
"currency": "INR",
"value": "50"
}
}
],
"ttl": "P1D"
},
"payment": {
"uri": "https://ondc.transaction.com/payment",
"tl_method": "http/get",
"params": {
"transaction_id": "TXN123456",
"amount": "4000",
"currency": "INR"
},
"type": "ON-ORDER",
"status": "PAID",
"collected_by": "BAP",
"buyer_app_finder_fee_type": "percent",
"buyer_app_finder_fee_amount": "3",
"settlement_details": [
{
"settlement_counterparty": "seller-app",
"settlement_phase": "sale-amount",
"settlement_type": "neft",
"settlement_bank_account_no": "1234567890",
"settlement_ifsc_code": "SBIN0001234",
"beneficiary_name": "Seller Name",
"bank_name": "State Bank of India",
"branch_name": "Koramangala"
}
]
},
"fulfillment": {
"id": "F1",
"type": "Delivery",
"tracking": true,
"start": {
"location": {
"id": "L1",
"descriptor": {
"name": "Seller Store"
},
"gps": "12.9715987,77.5945627",
"address": {
"locality": "Koramangala",
"city": "Bengaluru",
"area_code": "560034",
"state": "Karnataka"
}
},
"time": {
"range": {
"start": "2024-01-15T11:00:00.000Z",
"end": "2024-01-15T12:00:00.000Z"
}
},
"contact": {
"phone": "9988776655",
"email": "seller@example.com"
}
},
"end": {
"location": {
"gps": "12.9715987,77.5945627",
"address": {
"door": "21A",
"name": "ABC Apartments",
"building": "Tower 1",
"street": "100 Feet Road",
"locality": "Indiranagar",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560001"
}
},
"time": {
"range": {
"start": "2024-01-15T14:00:00.000Z",
"end": "2024-01-15T18:00:00.000Z"
}
},
"person": {
"name": "John Doe"
},
"contact": {
"phone": "9876543210",
"email": "customer@example.com"
}
}
},
"created_at": "2024-01-15T10:33:00.000Z",
"updated_at": "2024-01-15T10:33:00.000Z"
}
}
}
```
### Authorization Header Structure
**Note:** ONIX adapter automatically generates and adds the Authorization signature header to outgoing requests. You don't need to manually create it when calling ONIX endpoints.
For reference, the Authorization header format is:
```
Authorization: Signature keyId="{subscriber_id}|{key_id}|{algorithm}",algorithm="{algorithm}",created="{created}",expires="{expires}",headers="(created) (expires) digest",signature="{base64_signature}"
```
Example of how ONIX generates it internally:
```bash
#!/bin/bash
# Variables
SUBSCRIBER_ID="buyerapp.com"
KEY_ID="key1"
ALGORITHM="ed25519"
CREATED=$(date +%s)
EXPIRES=$((CREATED + 300))
PRIVATE_KEY="path/to/private_key.pem"
# Create string to sign
STRING_TO_SIGN="(created): ${CREATED}
(expires): ${EXPIRES}
digest: SHA-256=${DIGEST}"
# Sign with Ed25519
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | \
openssl pkeyutl -sign -inkey $PRIVATE_KEY -rawin | \
base64 -w 0)
# Create header
AUTH_HEADER="Signature keyId=\"${SUBSCRIBER_ID}|${KEY_ID}|${ALGORITHM}\",algorithm=\"${ALGORITHM}\",created=\"${CREATED}\",expires=\"${EXPIRES}\",headers=\"(created) (expires) digest\",signature=\"${SIGNATURE}\""
echo $AUTH_HEADER
```
---
## Conclusion
This setup guide covers all aspects of deploying Beckn-ONIX from local development to production. Key points:
1. **Start Simple**: Begin with local development setup
2. **Test Thoroughly**: Use provided test scripts and payloads
3. **Scale Gradually**: Move from single instance to clustered deployment
4. **Monitor Continuously**: Use logs and metrics for observability
5. **Secure Always**: Implement proper authentication and encryption
For additional help:
- Check [GitHub Issues](https://github.com/beckn/beckn-onix/issues)
- Join [Community Discussions](https://github.com/beckn/beckn-onix/discussions)
- Review [API Documentation](https://docs.beckn.org)
Happy deploying! 🚀