mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 08:33:04 +00:00
updated docs
This commit is contained in:
parent
5547c8ccb5
commit
ec66213e2e
151
README.md
151
README.md
@ -9,11 +9,95 @@ A high-performance API Gateway and distributed platform built in Go. Provides a
|
|||||||
- **🔐 Authentication** - Wallet signatures, API keys, JWT tokens
|
- **🔐 Authentication** - Wallet signatures, API keys, JWT tokens
|
||||||
- **💾 Storage** - IPFS-based decentralized file storage with encryption
|
- **💾 Storage** - IPFS-based decentralized file storage with encryption
|
||||||
- **⚡ Cache** - Distributed cache with Olric (in-memory key-value)
|
- **⚡ Cache** - Distributed cache with Olric (in-memory key-value)
|
||||||
- **🗄️ Database** - RQLite distributed SQL with Raft consensus
|
- **🗄️ Database** - RQLite distributed SQL with Raft consensus + Per-namespace SQLite databases
|
||||||
- **📡 Pub/Sub** - Real-time messaging via LibP2P and WebSocket
|
- **📡 Pub/Sub** - Real-time messaging via LibP2P and WebSocket
|
||||||
- **⚙️ Serverless** - WebAssembly function execution with host functions
|
- **⚙️ Serverless** - WebAssembly function execution with host functions
|
||||||
- **🌐 HTTP Gateway** - Unified REST API with automatic HTTPS (Let's Encrypt)
|
- **🌐 HTTP Gateway** - Unified REST API with automatic HTTPS (Let's Encrypt)
|
||||||
- **📦 Client SDK** - Type-safe Go SDK for all services
|
- **📦 Client SDK** - Type-safe Go SDK for all services
|
||||||
|
- **🚀 App Deployments** - Deploy React, Next.js, Go, Node.js apps with automatic domains
|
||||||
|
- **🗄️ SQLite Databases** - Per-namespace isolated databases with IPFS backups
|
||||||
|
|
||||||
|
## Application Deployments
|
||||||
|
|
||||||
|
Deploy full-stack applications with automatic domain assignment and namespace isolation.
|
||||||
|
|
||||||
|
### Deploy a React App
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build your app
|
||||||
|
cd my-react-app
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Deploy to Orama Network
|
||||||
|
orama deploy static ./dist --name my-app
|
||||||
|
|
||||||
|
# Your app is now live at: https://my-app.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Next.js with SSR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd my-nextjs-app
|
||||||
|
npm run build
|
||||||
|
orama deploy nextjs . --name my-nextjs --ssr
|
||||||
|
|
||||||
|
# Live at: https://my-nextjs.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Go Backend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build for Linux
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o api main.go
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
orama deploy go ./api --name my-api
|
||||||
|
|
||||||
|
# API live at: https://my-api.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create SQLite Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create database
|
||||||
|
orama db create my-database
|
||||||
|
|
||||||
|
# Create schema
|
||||||
|
orama db query my-database "CREATE TABLE users (id INT, name TEXT)"
|
||||||
|
|
||||||
|
# Insert data
|
||||||
|
orama db query my-database "INSERT INTO users VALUES (1, 'Alice')"
|
||||||
|
|
||||||
|
# Query data
|
||||||
|
orama db query my-database "SELECT * FROM users"
|
||||||
|
|
||||||
|
# Backup to IPFS
|
||||||
|
orama db backup my-database
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full-Stack Example
|
||||||
|
|
||||||
|
Deploy a complete app with React frontend, Go backend, and SQLite database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Create database
|
||||||
|
orama db create myapp-db
|
||||||
|
orama db query myapp-db "CREATE TABLE users (id INT PRIMARY KEY, name TEXT)"
|
||||||
|
|
||||||
|
# 2. Deploy Go backend (connects to database)
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o api main.go
|
||||||
|
orama deploy go ./api --name myapp-api
|
||||||
|
|
||||||
|
# 3. Deploy React frontend (calls backend API)
|
||||||
|
cd frontend && npm run build
|
||||||
|
orama deploy static ./dist --name myapp
|
||||||
|
|
||||||
|
# Access:
|
||||||
|
# Frontend: https://myapp.orama.network
|
||||||
|
# Backend: https://myapp-api.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
**📖 Full Guide**: See [Deployment Guide](docs/DEPLOYMENT_GUIDE.md) for complete documentation, examples, and best practices.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@ -108,36 +192,63 @@ make build
|
|||||||
|
|
||||||
## CLI Commands
|
## CLI Commands
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
```bash
|
||||||
|
orama auth login # Authenticate with wallet
|
||||||
|
orama auth status # Check authentication
|
||||||
|
orama auth logout # Clear credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
### Application Deployments
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy applications
|
||||||
|
orama deploy static <path> --name myapp # React, Vue, static sites
|
||||||
|
orama deploy nextjs <path> --name myapp --ssr # Next.js with SSR
|
||||||
|
orama deploy go <path> --name myapp # Go binaries
|
||||||
|
orama deploy nodejs <path> --name myapp # Node.js apps
|
||||||
|
|
||||||
|
# Manage deployments
|
||||||
|
orama deployments list # List all deployments
|
||||||
|
orama deployments get <name> # Get deployment details
|
||||||
|
orama deployments logs <name> --follow # View logs
|
||||||
|
orama deployments delete <name> # Delete deployment
|
||||||
|
orama deployments rollback <name> --version 1 # Rollback to version
|
||||||
|
```
|
||||||
|
|
||||||
|
### SQLite Databases
|
||||||
|
|
||||||
|
```bash
|
||||||
|
orama db create <name> # Create database
|
||||||
|
orama db query <name> "SELECT * FROM t" # Execute SQL query
|
||||||
|
orama db list # List all databases
|
||||||
|
orama db backup <name> # Backup to IPFS
|
||||||
|
orama db backups <name> # List backups
|
||||||
|
```
|
||||||
|
|
||||||
### Network Status
|
### Network Status
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./bin/orama health # Cluster health check
|
orama health # Cluster health check
|
||||||
./bin/orama peers # List connected peers
|
orama peers # List connected peers
|
||||||
./bin/orama status # Network status
|
orama status # Network status
|
||||||
```
|
```
|
||||||
|
|
||||||
### Database Operations
|
### RQLite Operations
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./bin/orama query "SELECT * FROM users"
|
orama query "SELECT * FROM users"
|
||||||
./bin/orama query "CREATE TABLE users (id INTEGER PRIMARY KEY)"
|
orama query "CREATE TABLE users (id INTEGER PRIMARY KEY)"
|
||||||
./bin/orama transaction --file ops.json
|
orama transaction --file ops.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pub/Sub
|
### Pub/Sub
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./bin/orama pubsub publish <topic> <message>
|
orama pubsub publish <topic> <message>
|
||||||
./bin/orama pubsub subscribe <topic> 30s
|
orama pubsub subscribe <topic> 30s
|
||||||
./bin/orama pubsub topics
|
orama pubsub topics
|
||||||
```
|
|
||||||
|
|
||||||
### Authentication
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./bin/orama auth login
|
|
||||||
./bin/orama auth status
|
|
||||||
./bin/orama auth logout
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Serverless Functions (WASM)
|
## Serverless Functions (WASM)
|
||||||
@ -331,10 +442,12 @@ See `openapi/gateway.yaml` for complete API specification.
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
- **[Deployment Guide](docs/DEPLOYMENT_GUIDE.md)** - Deploy React, Next.js, Go apps and manage databases
|
||||||
- **[Architecture Guide](docs/ARCHITECTURE.md)** - System architecture and design patterns
|
- **[Architecture Guide](docs/ARCHITECTURE.md)** - System architecture and design patterns
|
||||||
- **[Client SDK](docs/CLIENT_SDK.md)** - Go SDK documentation and examples
|
- **[Client SDK](docs/CLIENT_SDK.md)** - Go SDK documentation and examples
|
||||||
- **[Gateway API](docs/GATEWAY_API.md)** - Complete HTTP API reference
|
- **[Gateway API](docs/GATEWAY_API.md)** - Complete HTTP API reference
|
||||||
- **[Security Deployment](docs/SECURITY_DEPLOYMENT_GUIDE.md)** - Production security hardening
|
- **[Security Deployment](docs/SECURITY_DEPLOYMENT_GUIDE.md)** - Production security hardening
|
||||||
|
- **[Testing Plan](docs/TESTING_PLAN.md)** - Comprehensive testing strategy and implementation
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,16 @@ func main() {
|
|||||||
case "auth":
|
case "auth":
|
||||||
cli.HandleAuthCommand(args)
|
cli.HandleAuthCommand(args)
|
||||||
|
|
||||||
|
// Deployment commands
|
||||||
|
case "deploy":
|
||||||
|
cli.HandleDeployCommand(args)
|
||||||
|
case "deployments":
|
||||||
|
cli.HandleDeploymentsCommand(args)
|
||||||
|
|
||||||
|
// Database commands
|
||||||
|
case "db":
|
||||||
|
cli.HandleDBCommand(args)
|
||||||
|
|
||||||
// Help
|
// Help
|
||||||
case "help", "--help", "-h":
|
case "help", "--help", "-h":
|
||||||
showHelp()
|
showHelp()
|
||||||
@ -132,19 +142,51 @@ func showHelp() {
|
|||||||
fmt.Printf(" auth status - Show detailed auth info\n")
|
fmt.Printf(" auth status - Show detailed auth info\n")
|
||||||
fmt.Printf(" auth help - Show auth command help\n\n")
|
fmt.Printf(" auth help - Show auth command help\n\n")
|
||||||
|
|
||||||
|
fmt.Printf("📦 Deployments:\n")
|
||||||
|
fmt.Printf(" deploy static <path> - Deploy a static site (React, Vue, etc.)\n")
|
||||||
|
fmt.Printf(" deploy nextjs <path> - Deploy a Next.js application\n")
|
||||||
|
fmt.Printf(" deploy go <path> - Deploy a Go backend\n")
|
||||||
|
fmt.Printf(" deploy nodejs <path> - Deploy a Node.js backend\n")
|
||||||
|
fmt.Printf(" deployments list - List all deployments\n")
|
||||||
|
fmt.Printf(" deployments get <name> - Get deployment details\n")
|
||||||
|
fmt.Printf(" deployments logs <name> - View deployment logs\n")
|
||||||
|
fmt.Printf(" deployments delete <name> - Delete a deployment\n")
|
||||||
|
fmt.Printf(" deployments rollback <name> - Rollback to previous version\n\n")
|
||||||
|
|
||||||
|
fmt.Printf("🗄️ Databases:\n")
|
||||||
|
fmt.Printf(" db create <name> - Create a SQLite database\n")
|
||||||
|
fmt.Printf(" db query <name> \"<sql>\" - Execute SQL query\n")
|
||||||
|
fmt.Printf(" db list - List all databases\n")
|
||||||
|
fmt.Printf(" db backup <name> - Backup database to IPFS\n")
|
||||||
|
fmt.Printf(" db backups <name> - List database backups\n\n")
|
||||||
|
|
||||||
fmt.Printf("Global Flags:\n")
|
fmt.Printf("Global Flags:\n")
|
||||||
fmt.Printf(" -f, --format <format> - Output format: table, json (default: table)\n")
|
fmt.Printf(" -f, --format <format> - Output format: table, json (default: table)\n")
|
||||||
fmt.Printf(" -t, --timeout <duration> - Operation timeout (default: 30s)\n")
|
fmt.Printf(" -t, --timeout <duration> - Operation timeout (default: 30s)\n")
|
||||||
fmt.Printf(" --help, -h - Show this help message\n\n")
|
fmt.Printf(" --help, -h - Show this help message\n\n")
|
||||||
|
|
||||||
fmt.Printf("Examples:\n")
|
fmt.Printf("Examples:\n")
|
||||||
|
fmt.Printf(" # Deploy a React app\n")
|
||||||
|
fmt.Printf(" cd my-react-app && npm run build\n")
|
||||||
|
fmt.Printf(" orama deploy static ./dist --name my-app\n\n")
|
||||||
|
|
||||||
|
fmt.Printf(" # Deploy a Next.js app with SSR\n")
|
||||||
|
fmt.Printf(" cd my-nextjs-app && npm run build\n")
|
||||||
|
fmt.Printf(" orama deploy nextjs . --name my-nextjs --ssr\n\n")
|
||||||
|
|
||||||
|
fmt.Printf(" # Create and use a database\n")
|
||||||
|
fmt.Printf(" orama db create my-db\n")
|
||||||
|
fmt.Printf(" orama db query my-db \"CREATE TABLE users (id INT, name TEXT)\"\n")
|
||||||
|
fmt.Printf(" orama db query my-db \"INSERT INTO users VALUES (1, 'Alice')\"\n\n")
|
||||||
|
|
||||||
|
fmt.Printf(" # Manage deployments\n")
|
||||||
|
fmt.Printf(" orama deployments list\n")
|
||||||
|
fmt.Printf(" orama deployments get my-app\n")
|
||||||
|
fmt.Printf(" orama deployments logs my-app --follow\n\n")
|
||||||
|
|
||||||
fmt.Printf(" # First node (creates new cluster)\n")
|
fmt.Printf(" # First node (creates new cluster)\n")
|
||||||
fmt.Printf(" sudo orama install --vps-ip 203.0.113.1 --domain node-1.orama.network\n\n")
|
fmt.Printf(" sudo orama install --vps-ip 203.0.113.1 --domain node-1.orama.network\n\n")
|
||||||
|
|
||||||
fmt.Printf(" # Join existing cluster\n")
|
|
||||||
fmt.Printf(" sudo orama install --vps-ip 203.0.113.2 --domain node-2.orama.network \\\n")
|
|
||||||
fmt.Printf(" --peers /ip4/203.0.113.1/tcp/4001/p2p/12D3KooW... --cluster-secret <hex>\n\n")
|
|
||||||
|
|
||||||
fmt.Printf(" # Service management\n")
|
fmt.Printf(" # Service management\n")
|
||||||
fmt.Printf(" orama status\n")
|
fmt.Printf(" orama status\n")
|
||||||
fmt.Printf(" orama logs node --follow\n")
|
fmt.Printf(" orama logs node --follow\n")
|
||||||
|
|||||||
897
docs/DEPLOYMENT_GUIDE.md
Normal file
897
docs/DEPLOYMENT_GUIDE.md
Normal file
@ -0,0 +1,897 @@
|
|||||||
|
# Orama Network Deployment Guide
|
||||||
|
|
||||||
|
Complete guide for deploying applications and managing databases on Orama Network.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Authentication](#authentication)
|
||||||
|
- [Deploying Static Sites (React, Vue, etc.)](#deploying-static-sites)
|
||||||
|
- [Deploying Next.js Applications](#deploying-nextjs-applications)
|
||||||
|
- [Deploying Go Backends](#deploying-go-backends)
|
||||||
|
- [Deploying Node.js Backends](#deploying-nodejs-backends)
|
||||||
|
- [Managing SQLite Databases](#managing-sqlite-databases)
|
||||||
|
- [How Domains Work](#how-domains-work)
|
||||||
|
- [Full-Stack Application Example](#full-stack-application-example)
|
||||||
|
- [Managing Deployments](#managing-deployments)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Orama Network provides a decentralized platform for deploying web applications and managing databases. Each deployment:
|
||||||
|
|
||||||
|
- **Gets a unique domain** automatically (e.g., `myapp.orama.network`)
|
||||||
|
- **Isolated per namespace** - your data and apps are completely separate from others
|
||||||
|
- **Served from IPFS** (static) or **runs as a process** (dynamic apps)
|
||||||
|
- **Fully managed** - automatic health checks, restarts, and logging
|
||||||
|
|
||||||
|
### Supported Deployment Types
|
||||||
|
|
||||||
|
| Type | Description | Use Case | Domain Example |
|
||||||
|
|------|-------------|----------|----------------|
|
||||||
|
| **Static** | HTML/CSS/JS files served from IPFS | React, Vue, Angular, plain HTML | `myapp.orama.network` |
|
||||||
|
| **Next.js** | Next.js with SSR support | Full-stack Next.js apps | `myapp.orama.network` |
|
||||||
|
| **Go** | Compiled Go binaries | REST APIs, microservices | `api.orama.network` |
|
||||||
|
| **Node.js** | Node.js applications | Express APIs, TypeScript backends | `backend.orama.network` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Before deploying, authenticate with your wallet:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Authenticate
|
||||||
|
orama auth login
|
||||||
|
|
||||||
|
# Check authentication status
|
||||||
|
orama auth whoami
|
||||||
|
```
|
||||||
|
|
||||||
|
Your API key is stored securely and used for all deployment operations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploying Static Sites
|
||||||
|
|
||||||
|
Deploy static sites built with React, Vue, Angular, or any static site generator.
|
||||||
|
|
||||||
|
### React/Vite Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Build your React app
|
||||||
|
cd my-react-app
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 2. Deploy the build directory
|
||||||
|
orama deploy static ./dist --name my-react-app --domain repoanalyzer.ai
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# 📦 Creating tarball from ./dist...
|
||||||
|
# ☁️ Uploading to Orama Network...
|
||||||
|
#
|
||||||
|
# ✅ Deployment successful!
|
||||||
|
#
|
||||||
|
# Name: my-react-app
|
||||||
|
# Type: static
|
||||||
|
# Status: active
|
||||||
|
# Version: 1
|
||||||
|
# Content CID: QmXxxx...
|
||||||
|
#
|
||||||
|
# URLs:
|
||||||
|
# • https://my-react-app.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Happens Behind the Scenes
|
||||||
|
|
||||||
|
1. **Tarball Creation**: CLI automatically creates a `.tar.gz` from your directory
|
||||||
|
2. **IPFS Upload**: Files are uploaded to IPFS and pinned across the network
|
||||||
|
3. **DNS Record**: A DNS record is created pointing `my-react-app.orama.network` to the gateway
|
||||||
|
4. **Instant Serving**: Your app is immediately accessible via the URL
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- ✅ **SPA Routing**: Unknown routes automatically serve `/index.html` (perfect for React Router)
|
||||||
|
- ✅ **Correct Content-Types**: Automatically detects and serves `.html`, `.css`, `.js`, `.json`, `.png`, etc.
|
||||||
|
- ✅ **Caching**: `Cache-Control: public, max-age=3600` headers for optimal performance
|
||||||
|
- ✅ **Zero Downtime Updates**: Use `--update` flag to update without downtime
|
||||||
|
|
||||||
|
### Updating a Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make changes to your app
|
||||||
|
# Rebuild
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Update deployment
|
||||||
|
orama deploy static ./dist --name my-react-app --update
|
||||||
|
|
||||||
|
# Version increments automatically (1 → 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploying Next.js Applications
|
||||||
|
|
||||||
|
Deploy Next.js apps with full SSR (Server-Side Rendering) support.
|
||||||
|
|
||||||
|
### Next.js with SSR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Build your Next.js app
|
||||||
|
cd my-nextjs-app
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 2. Deploy with SSR enabled
|
||||||
|
orama deploy nextjs . --name my-nextjs --ssr
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# 📦 Creating tarball from .
|
||||||
|
# ☁️ Uploading to Orama Network...
|
||||||
|
#
|
||||||
|
# ✅ Deployment successful!
|
||||||
|
#
|
||||||
|
# Name: my-nextjs
|
||||||
|
# Type: nextjs
|
||||||
|
# Status: active
|
||||||
|
# Version: 1
|
||||||
|
# Port: 10100
|
||||||
|
#
|
||||||
|
# URLs:
|
||||||
|
# • https://my-nextjs.orama.network
|
||||||
|
#
|
||||||
|
# ⚠️ Note: SSR deployment may take a minute to start. Check status with: orama deployments get my-nextjs
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Happens Behind the Scenes
|
||||||
|
|
||||||
|
1. **Tarball Upload**: Your `.next` build directory, `package.json`, and `public` are uploaded
|
||||||
|
2. **Home Node Assignment**: A node is chosen to host your app based on capacity
|
||||||
|
3. **Port Allocation**: A unique port (10100-19999) is assigned
|
||||||
|
4. **Systemd Service**: A systemd service is created to run `node server.js`
|
||||||
|
5. **Health Checks**: Gateway monitors your app every 30 seconds
|
||||||
|
6. **Reverse Proxy**: Gateway proxies requests from your domain to the local port
|
||||||
|
|
||||||
|
### Static Next.js Export (No SSR)
|
||||||
|
|
||||||
|
If you export Next.js to static HTML:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# next.config.js
|
||||||
|
module.exports = {
|
||||||
|
output: 'export'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build and deploy as static
|
||||||
|
npm run build
|
||||||
|
orama deploy static ./out --name my-nextjs-static
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploying Go Backends
|
||||||
|
|
||||||
|
Deploy compiled Go binaries for high-performance APIs.
|
||||||
|
|
||||||
|
### Go REST API Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Build your Go binary for Linux (if on Mac/Windows)
|
||||||
|
cd my-go-api
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o api main.go
|
||||||
|
|
||||||
|
# 2. Deploy the binary
|
||||||
|
orama deploy go ./api --name my-api
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# 📦 Creating tarball from ./api...
|
||||||
|
# ☁️ Uploading to Orama Network...
|
||||||
|
#
|
||||||
|
# ✅ Deployment successful!
|
||||||
|
#
|
||||||
|
# Name: my-api
|
||||||
|
# Type: go
|
||||||
|
# Status: active
|
||||||
|
# Version: 1
|
||||||
|
# Port: 10101
|
||||||
|
#
|
||||||
|
# URLs:
|
||||||
|
# • https://my-api.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Go API Code
|
||||||
|
|
||||||
|
```go
|
||||||
|
// main.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
port := os.Getenv("PORT")
|
||||||
|
if port == "" {
|
||||||
|
port = "8080"
|
||||||
|
}
|
||||||
|
|
||||||
|
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
users := []map[string]interface{}{
|
||||||
|
{"id": 1, "name": "Alice"},
|
||||||
|
{"id": 2, "name": "Bob"},
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(users)
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Printf("Starting server on port %s", port)
|
||||||
|
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Important Notes
|
||||||
|
|
||||||
|
- **Environment Variables**: The `PORT` environment variable is automatically set to your allocated port
|
||||||
|
- **Health Endpoint**: Recommended to implement `/health` for monitoring
|
||||||
|
- **Binary Requirements**: Must be Linux-compatible (GOOS=linux GOARCH=amd64)
|
||||||
|
- **Systemd Managed**: Runs as a systemd service with auto-restart on failure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deploying Node.js Backends
|
||||||
|
|
||||||
|
Deploy Node.js/Express/TypeScript backends.
|
||||||
|
|
||||||
|
### Express API Example
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Build your Node.js app (if using TypeScript)
|
||||||
|
cd my-node-api
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 2. Deploy (must include node_modules or use a bundler)
|
||||||
|
orama deploy nodejs ./dist --name my-node-api
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# 📦 Creating tarball from ./dist...
|
||||||
|
# ☁️ Uploading to Orama Network...
|
||||||
|
#
|
||||||
|
# ✅ Deployment successful!
|
||||||
|
#
|
||||||
|
# Name: my-node-api
|
||||||
|
# Type: nodejs
|
||||||
|
# Status: active
|
||||||
|
# Version: 1
|
||||||
|
# Port: 10102
|
||||||
|
#
|
||||||
|
# URLs:
|
||||||
|
# • https://my-node-api.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Node.js API
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// server.js
|
||||||
|
const express = require('express');
|
||||||
|
const app = express();
|
||||||
|
const port = process.env.PORT || 8080;
|
||||||
|
|
||||||
|
app.get('/health', (req, res) => {
|
||||||
|
res.json({ status: 'healthy' });
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/api/data', (req, res) => {
|
||||||
|
res.json({ message: 'Hello from Orama Network!' });
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`Server running on port ${port}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Managing SQLite Databases
|
||||||
|
|
||||||
|
Each namespace gets its own isolated SQLite databases.
|
||||||
|
|
||||||
|
### Creating a Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a new database
|
||||||
|
orama db create my-database
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# ✅ Database created: my-database
|
||||||
|
# Home Node: node-abc123
|
||||||
|
# File Path: /home/debros/.orama/data/sqlite/your-namespace/my-database.db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Executing Queries
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a table
|
||||||
|
orama db query my-database "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"
|
||||||
|
|
||||||
|
# Insert data
|
||||||
|
orama db query my-database "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')"
|
||||||
|
|
||||||
|
# Query data
|
||||||
|
orama db query my-database "SELECT * FROM users"
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# 📊 Query Result
|
||||||
|
# Rows: 1
|
||||||
|
#
|
||||||
|
# id | name | email
|
||||||
|
# ----------------+-----------------+-------------------------
|
||||||
|
# 1 | Alice | alice@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Listing Databases
|
||||||
|
|
||||||
|
```bash
|
||||||
|
orama db list
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# NAME SIZE HOME NODE CREATED
|
||||||
|
# my-database 12.3 KB node-abc123 2024-01-22 10:30
|
||||||
|
# prod-database 1.2 MB node-abc123 2024-01-20 09:15
|
||||||
|
#
|
||||||
|
# Total: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backing Up to IPFS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a backup
|
||||||
|
orama db backup my-database
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# ✅ Backup created
|
||||||
|
# CID: QmYxxx...
|
||||||
|
# Size: 12.3 KB
|
||||||
|
|
||||||
|
# List backups
|
||||||
|
orama db backups my-database
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# VERSION CID SIZE DATE
|
||||||
|
# 1 QmYxxx... 12.3 KB 2024-01-22 10:45
|
||||||
|
# 2 QmZxxx... 15.1 KB 2024-01-22 14:20
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Features
|
||||||
|
|
||||||
|
- ✅ **WAL Mode**: Write-Ahead Logging for better concurrency
|
||||||
|
- ✅ **Namespace Isolation**: Complete separation between namespaces
|
||||||
|
- ✅ **Automatic Backups**: Scheduled backups to IPFS every 6 hours
|
||||||
|
- ✅ **ACID Transactions**: Full SQLite transactional support
|
||||||
|
- ✅ **Concurrent Reads**: Multiple readers can query simultaneously
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How Domains Work
|
||||||
|
|
||||||
|
### Domain Assignment
|
||||||
|
|
||||||
|
When you deploy an application, it automatically gets a domain:
|
||||||
|
|
||||||
|
```
|
||||||
|
Format: {deployment-name}.orama.network
|
||||||
|
Example: my-react-app.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Node-Specific Domains (Optional)
|
||||||
|
|
||||||
|
For direct access to a specific node:
|
||||||
|
|
||||||
|
```
|
||||||
|
Format: {deployment-name}.{node-id}.orama.network
|
||||||
|
Example: my-react-app.node-7prvNa.orama.network
|
||||||
|
```
|
||||||
|
|
||||||
|
### DNS Resolution Flow
|
||||||
|
|
||||||
|
1. **Client**: Browser requests `my-react-app.orama.network`
|
||||||
|
2. **DNS**: CoreDNS server queries RQLite for DNS record
|
||||||
|
3. **Record**: Returns IP address of a gateway node
|
||||||
|
4. **Gateway**: Receives request with `Host: my-react-app.orama.network` header
|
||||||
|
5. **Routing**: Domain routing middleware looks up deployment by domain
|
||||||
|
6. **Response**:
|
||||||
|
- **Static**: Serves content from IPFS
|
||||||
|
- **Dynamic**: Reverse proxies to the app's local port
|
||||||
|
|
||||||
|
### Custom Domains (Future Feature)
|
||||||
|
|
||||||
|
Support for custom domains (e.g., `www.myapp.com`) with TXT record verification.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Full-Stack Application Example
|
||||||
|
|
||||||
|
Deploy a complete full-stack application with React frontend, Go backend, and SQLite database.
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ React Frontend (Static) │
|
||||||
|
│ Domain: myapp.orama.network │
|
||||||
|
│ Deployed to IPFS │
|
||||||
|
└─────────────────┬───────────────────────────┘
|
||||||
|
│
|
||||||
|
│ API Calls
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Go Backend (Dynamic) │
|
||||||
|
│ Domain: myapp-api.orama.network │
|
||||||
|
│ Port: 10100 │
|
||||||
|
│ Systemd Service │
|
||||||
|
└─────────────────┬───────────────────────────┘
|
||||||
|
│
|
||||||
|
│ SQL Queries
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ SQLite Database │
|
||||||
|
│ Name: myapp-db │
|
||||||
|
│ File: ~/.orama/data/sqlite/ns/myapp-db.db│
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 1: Create the Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create database
|
||||||
|
orama db create myapp-db
|
||||||
|
|
||||||
|
# Create schema
|
||||||
|
orama db query myapp-db "CREATE TABLE users (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
email TEXT UNIQUE NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)"
|
||||||
|
|
||||||
|
# Insert test data
|
||||||
|
orama db query myapp-db "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Deploy Go Backend
|
||||||
|
|
||||||
|
**Backend Code** (`main.go`):
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var db *sql.DB
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// DATABASE_NAME env var is automatically set by Orama
|
||||||
|
dbPath := os.Getenv("DATABASE_PATH")
|
||||||
|
if dbPath == "" {
|
||||||
|
dbPath = "/home/debros/.orama/data/sqlite/" + os.Getenv("NAMESPACE") + "/myapp-db.db"
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
db, err = sql.Open("sqlite3", dbPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
port := os.Getenv("PORT")
|
||||||
|
if port == "" {
|
||||||
|
port = "8080"
|
||||||
|
}
|
||||||
|
|
||||||
|
// CORS middleware
|
||||||
|
http.HandleFunc("/", corsMiddleware(routes))
|
||||||
|
|
||||||
|
log.Printf("Starting server on port %s", port)
|
||||||
|
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func routes(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/health":
|
||||||
|
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
|
||||||
|
case "/api/users":
|
||||||
|
if r.Method == "GET" {
|
||||||
|
getUsers(w, r)
|
||||||
|
} else if r.Method == "POST" {
|
||||||
|
createUser(w, r)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
|
rows, err := db.Query("SELECT id, name, email, created_at FROM users ORDER BY id")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var users []User
|
||||||
|
for rows.Next() {
|
||||||
|
var u User
|
||||||
|
rows.Scan(&u.ID, &u.Name, &u.Email, &u.CreatedAt)
|
||||||
|
users = append(users, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(users)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createUser(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var u User
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := db.Exec("INSERT INTO users (name, email) VALUES (?, ?)", u.Name, u.Email)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id, _ := result.LastInsertId()
|
||||||
|
u.ID = int(id)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
json.NewEncoder(w).Encode(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func corsMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||||
|
|
||||||
|
if r.Method == "OPTIONS" {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Deploy Backend**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build for Linux
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o api main.go
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
orama deploy go ./api --name myapp-api
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Deploy React Frontend
|
||||||
|
|
||||||
|
**Frontend Code** (`src/App.jsx`):
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
const [name, setName] = useState('');
|
||||||
|
const [email, setEmail] = useState('');
|
||||||
|
|
||||||
|
const API_URL = 'https://myapp-api.orama.network';
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchUsers();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchUsers = async () => {
|
||||||
|
const response = await fetch(`${API_URL}/api/users`);
|
||||||
|
const data = await response.json();
|
||||||
|
setUsers(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addUser = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
await fetch(`${API_URL}/api/users`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name, email }),
|
||||||
|
});
|
||||||
|
setName('');
|
||||||
|
setEmail('');
|
||||||
|
fetchUsers();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Orama Network Full-Stack App</h1>
|
||||||
|
|
||||||
|
<h2>Add User</h2>
|
||||||
|
<form onSubmit={addUser}>
|
||||||
|
<input
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
placeholder="Name"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
placeholder="Email"
|
||||||
|
type="email"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<button type="submit">Add User</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Users</h2>
|
||||||
|
<ul>
|
||||||
|
{users.map((user) => (
|
||||||
|
<li key={user.id}>
|
||||||
|
{user.name} - {user.email}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Deploy Frontend**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
orama deploy static ./dist --name myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Access Your App
|
||||||
|
|
||||||
|
Open your browser to:
|
||||||
|
- **Frontend**: `https://myapp.orama.network`
|
||||||
|
- **Backend API**: `https://myapp-api.orama.network/api/users`
|
||||||
|
|
||||||
|
### Full-Stack Summary
|
||||||
|
|
||||||
|
✅ **Frontend**: React app served from IPFS
|
||||||
|
✅ **Backend**: Go API running on allocated port
|
||||||
|
✅ **Database**: SQLite database with ACID transactions
|
||||||
|
✅ **Domains**: Automatic DNS for both services
|
||||||
|
✅ **Isolated**: All resources namespaced and secure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Managing Deployments
|
||||||
|
|
||||||
|
### List All Deployments
|
||||||
|
|
||||||
|
```bash
|
||||||
|
orama deployments list
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# NAME TYPE STATUS VERSION CREATED
|
||||||
|
# my-react-app static active 1 2024-01-22 10:30
|
||||||
|
# myapp-api go active 1 2024-01-22 10:45
|
||||||
|
# my-nextjs nextjs active 2 2024-01-22 11:00
|
||||||
|
#
|
||||||
|
# Total: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Deployment Details
|
||||||
|
|
||||||
|
```bash
|
||||||
|
orama deployments get my-react-app
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# Deployment: my-react-app
|
||||||
|
#
|
||||||
|
# ID: dep-abc123
|
||||||
|
# Type: static
|
||||||
|
# Status: active
|
||||||
|
# Version: 1
|
||||||
|
# Namespace: your-namespace
|
||||||
|
# Content CID: QmXxxx...
|
||||||
|
# Memory Limit: 256 MB
|
||||||
|
# CPU Limit: 50%
|
||||||
|
# Restart Policy: always
|
||||||
|
#
|
||||||
|
# URLs:
|
||||||
|
# • https://my-react-app.orama.network
|
||||||
|
#
|
||||||
|
# Created: 2024-01-22T10:30:00Z
|
||||||
|
# Updated: 2024-01-22T10:30:00Z
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View last 100 lines
|
||||||
|
orama deployments logs my-nextjs
|
||||||
|
|
||||||
|
# Follow logs in real-time
|
||||||
|
orama deployments logs my-nextjs --follow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rollback to Previous Version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rollback to version 1
|
||||||
|
orama deployments rollback my-nextjs --version 1
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# ⚠️ Rolling back 'my-nextjs' to version 1. Continue? (y/N): y
|
||||||
|
#
|
||||||
|
# ✅ Rollback successful!
|
||||||
|
#
|
||||||
|
# Deployment: my-nextjs
|
||||||
|
# Current Version: 1
|
||||||
|
# Rolled Back From: 2
|
||||||
|
# Rolled Back To: 1
|
||||||
|
# Status: active
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
orama deployments delete my-old-app
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# ⚠️ Are you sure you want to delete deployment 'my-old-app'? (y/N): y
|
||||||
|
#
|
||||||
|
# ✅ Deployment 'my-old-app' deleted successfully
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Deployment Issues
|
||||||
|
|
||||||
|
**Problem**: Deployment status is "failed"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check deployment details
|
||||||
|
orama deployments get my-app
|
||||||
|
|
||||||
|
# View logs for errors
|
||||||
|
orama deployments logs my-app
|
||||||
|
|
||||||
|
# Common issues:
|
||||||
|
# - Binary not compiled for Linux (GOOS=linux GOARCH=amd64)
|
||||||
|
# - Missing dependencies (node_modules not included)
|
||||||
|
# - Port already in use (shouldn't happen, but check logs)
|
||||||
|
# - Health check failing (ensure /health endpoint exists)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problem**: Can't access deployment URL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Check deployment status
|
||||||
|
orama deployments get my-app
|
||||||
|
|
||||||
|
# 2. Verify DNS (may take up to 10 seconds to propagate)
|
||||||
|
dig my-app.orama.network
|
||||||
|
|
||||||
|
# 3. For local development, add to /etc/hosts
|
||||||
|
echo "127.0.0.1 my-app.orama.network" | sudo tee -a /etc/hosts
|
||||||
|
|
||||||
|
# 4. Test with Host header
|
||||||
|
curl -H "Host: my-app.orama.network" http://localhost:6001/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Issues
|
||||||
|
|
||||||
|
**Problem**: Database not found
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all databases
|
||||||
|
orama db list
|
||||||
|
|
||||||
|
# Ensure database name matches exactly (case-sensitive)
|
||||||
|
# Databases are namespace-isolated
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problem**: SQL query fails
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check table exists
|
||||||
|
orama db query my-db "SELECT name FROM sqlite_master WHERE type='table'"
|
||||||
|
|
||||||
|
# Check syntax
|
||||||
|
orama db query my-db ".schema users"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentication Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Re-authenticate
|
||||||
|
orama auth logout
|
||||||
|
orama auth login
|
||||||
|
|
||||||
|
# Check token validity
|
||||||
|
orama auth status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Need Help?
|
||||||
|
|
||||||
|
- **Documentation**: Check `/docs` directory
|
||||||
|
- **Logs**: Gateway logs at `~/.orama/logs/gateway.log`
|
||||||
|
- **Issues**: Report bugs at GitHub repository
|
||||||
|
- **Community**: Join our Discord/Telegram
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
1. **Never commit sensitive data**: Use environment variables for secrets
|
||||||
|
2. **Validate inputs**: Always sanitize user input in your backend
|
||||||
|
3. **HTTPS only**: All deployments automatically use HTTPS in production
|
||||||
|
4. **CORS**: Configure CORS appropriately for your API
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
1. **Optimize builds**: Minimize bundle sizes (React, Next.js)
|
||||||
|
2. **Use caching**: Leverage browser caching for static assets
|
||||||
|
3. **Database indexes**: Add indexes to frequently queried columns
|
||||||
|
4. **Health checks**: Implement `/health` endpoint for monitoring
|
||||||
|
|
||||||
|
### Deployment Workflow
|
||||||
|
|
||||||
|
1. **Test locally first**: Ensure your app works before deploying
|
||||||
|
2. **Use version control**: Track changes in Git
|
||||||
|
3. **Incremental updates**: Use `--update` flag instead of delete + redeploy
|
||||||
|
4. **Backup databases**: Regular backups via `orama db backup`
|
||||||
|
5. **Monitor logs**: Check logs after deployment for errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- **Explore the API**: See `/docs/GATEWAY_API.md` for HTTP API details
|
||||||
|
- **Advanced Features**: Custom domains, load balancing, autoscaling (coming soon)
|
||||||
|
- **Production Deployment**: Install nodes with `orama install` for production clusters
|
||||||
|
- **Client SDK**: Use the Go/JS SDK for programmatic deployments
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Orama Network** - Decentralized Application Platform
|
||||||
|
|
||||||
|
Deploy anywhere. Access everywhere. Own everything.
|
||||||
@ -1,734 +0,0 @@
|
|||||||
# Gateway API Documentation
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The Orama Network Gateway provides a unified HTTP/HTTPS API for all network services. It handles authentication, routing, and service coordination.
|
|
||||||
|
|
||||||
**Base URL:** `https://api.orama.network` (production) or `http://localhost:6001` (development)
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
All API requests (except `/health` and `/v1/auth/*`) require authentication.
|
|
||||||
|
|
||||||
### Authentication Methods
|
|
||||||
|
|
||||||
1. **API Key** (Recommended for server-to-server)
|
|
||||||
2. **JWT Token** (Recommended for user sessions)
|
|
||||||
3. **Wallet Signature** (For blockchain integration)
|
|
||||||
|
|
||||||
### Using API Keys
|
|
||||||
|
|
||||||
Include your API key in the `Authorization` header:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -H "Authorization: Bearer your-api-key-here" \
|
|
||||||
https://api.orama.network/v1/status
|
|
||||||
```
|
|
||||||
|
|
||||||
Or in the `X-API-Key` header:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -H "X-API-Key: your-api-key-here" \
|
|
||||||
https://api.orama.network/v1/status
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using JWT Tokens
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -H "Authorization: Bearer your-jwt-token-here" \
|
|
||||||
https://api.orama.network/v1/status
|
|
||||||
```
|
|
||||||
|
|
||||||
## Base Endpoints
|
|
||||||
|
|
||||||
### Health Check
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /health
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": "ok",
|
|
||||||
"timestamp": "2024-01-20T10:30:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Status
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/status
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": "0.80.0",
|
|
||||||
"uptime": "24h30m15s",
|
|
||||||
"services": {
|
|
||||||
"rqlite": "healthy",
|
|
||||||
"ipfs": "healthy",
|
|
||||||
"olric": "healthy"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Version
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/version
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": "0.80.0",
|
|
||||||
"commit": "abc123...",
|
|
||||||
"built": "2024-01-20T00:00:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Authentication API
|
|
||||||
|
|
||||||
### Get Challenge (Wallet Auth)
|
|
||||||
|
|
||||||
Generate a nonce for wallet signature.
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/auth/challenge
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
|
|
||||||
"purpose": "login",
|
|
||||||
"namespace": "default"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
|
|
||||||
"namespace": "default",
|
|
||||||
"nonce": "a1b2c3d4e5f6...",
|
|
||||||
"purpose": "login",
|
|
||||||
"expires_at": "2024-01-20T10:35:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Verify Signature
|
|
||||||
|
|
||||||
Verify wallet signature and issue JWT + API key.
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/auth/verify
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
|
|
||||||
"signature": "0x...",
|
|
||||||
"nonce": "a1b2c3d4e5f6...",
|
|
||||||
"namespace": "default"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"jwt_token": "eyJhbGciOiJIUzI1NiIs...",
|
|
||||||
"refresh_token": "refresh_abc123...",
|
|
||||||
"api_key": "api_xyz789...",
|
|
||||||
"expires_in": 900,
|
|
||||||
"namespace": "default"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Refresh Token
|
|
||||||
|
|
||||||
Refresh an expired JWT token.
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/auth/refresh
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"refresh_token": "refresh_abc123..."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"jwt_token": "eyJhbGciOiJIUzI1NiIs...",
|
|
||||||
"expires_in": 900
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Logout
|
|
||||||
|
|
||||||
Revoke refresh tokens.
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/auth/logout
|
|
||||||
Authorization: Bearer your-jwt-token
|
|
||||||
|
|
||||||
{
|
|
||||||
"all": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "logged out successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Whoami
|
|
||||||
|
|
||||||
Get current authentication info.
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/auth/whoami
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"authenticated": true,
|
|
||||||
"method": "api_key",
|
|
||||||
"api_key": "api_xyz789...",
|
|
||||||
"namespace": "default"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Storage API (IPFS)
|
|
||||||
|
|
||||||
### Upload File
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/storage/upload
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: multipart/form-data
|
|
||||||
|
|
||||||
file: <binary data>
|
|
||||||
```
|
|
||||||
|
|
||||||
Or with JSON:
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/storage/upload
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"data": "base64-encoded-data",
|
|
||||||
"filename": "document.pdf",
|
|
||||||
"pin": true,
|
|
||||||
"encrypt": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cid": "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
|
|
||||||
"size": 1024,
|
|
||||||
"filename": "document.pdf"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get File
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/storage/get/:cid
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:** Binary file data or JSON (if `Accept: application/json`)
|
|
||||||
|
|
||||||
### Pin File
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/storage/pin
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"cid": "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
|
|
||||||
"replication_factor": 3
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cid": "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
|
|
||||||
"status": "pinned"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Unpin File
|
|
||||||
|
|
||||||
```http
|
|
||||||
DELETE /v1/storage/unpin/:cid
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "unpinned successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Pin Status
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/storage/status/:cid
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"cid": "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
|
|
||||||
"status": "pinned",
|
|
||||||
"replicas": 3,
|
|
||||||
"peers": ["12D3KooW...", "12D3KooW..."]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Cache API (Olric)
|
|
||||||
|
|
||||||
### Set Value
|
|
||||||
|
|
||||||
```http
|
|
||||||
PUT /v1/cache/put
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"key": "user:123",
|
|
||||||
"value": {"name": "Alice", "email": "alice@example.com"},
|
|
||||||
"ttl": 300
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "value set successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Value
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/cache/get?key=user:123
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"key": "user:123",
|
|
||||||
"value": {"name": "Alice", "email": "alice@example.com"}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Multiple Values
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/cache/mget
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"keys": ["user:1", "user:2", "user:3"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"results": {
|
|
||||||
"user:1": {"name": "Alice"},
|
|
||||||
"user:2": {"name": "Bob"},
|
|
||||||
"user:3": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Delete Value
|
|
||||||
|
|
||||||
```http
|
|
||||||
DELETE /v1/cache/delete?key=user:123
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "deleted successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Scan Keys
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/cache/scan?pattern=user:*&limit=100
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"keys": ["user:1", "user:2", "user:3"],
|
|
||||||
"count": 3
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Database API (RQLite)
|
|
||||||
|
|
||||||
### Execute SQL
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/rqlite/exec
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"sql": "INSERT INTO users (name, email) VALUES (?, ?)",
|
|
||||||
"args": ["Alice", "alice@example.com"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"last_insert_id": 123,
|
|
||||||
"rows_affected": 1
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Query SQL
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/rqlite/query
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"sql": "SELECT * FROM users WHERE id = ?",
|
|
||||||
"args": [123]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"columns": ["id", "name", "email"],
|
|
||||||
"rows": [
|
|
||||||
[123, "Alice", "alice@example.com"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Schema
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/rqlite/schema
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tables": [
|
|
||||||
{
|
|
||||||
"name": "users",
|
|
||||||
"schema": "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pub/Sub API
|
|
||||||
|
|
||||||
### Publish Message
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/pubsub/publish
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"topic": "chat",
|
|
||||||
"data": "SGVsbG8sIFdvcmxkIQ==",
|
|
||||||
"namespace": "default"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "published successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### List Topics
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/pubsub/topics
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"topics": ["chat", "notifications", "events"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Subscribe (WebSocket)
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/pubsub/ws?topic=chat
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Upgrade: websocket
|
|
||||||
```
|
|
||||||
|
|
||||||
**WebSocket Messages:**
|
|
||||||
|
|
||||||
Incoming (from server):
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "message",
|
|
||||||
"topic": "chat",
|
|
||||||
"data": "SGVsbG8sIFdvcmxkIQ==",
|
|
||||||
"timestamp": "2024-01-20T10:30:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Outgoing (to server):
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "publish",
|
|
||||||
"topic": "chat",
|
|
||||||
"data": "SGVsbG8sIFdvcmxkIQ=="
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Presence
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/pubsub/presence?topic=chat
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"topic": "chat",
|
|
||||||
"members": [
|
|
||||||
{"id": "user-123", "joined_at": "2024-01-20T10:00:00Z"},
|
|
||||||
{"id": "user-456", "joined_at": "2024-01-20T10:15:00Z"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Serverless API (WASM)
|
|
||||||
|
|
||||||
### Deploy Function
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/functions
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: multipart/form-data
|
|
||||||
|
|
||||||
name: hello-world
|
|
||||||
namespace: default
|
|
||||||
description: Hello world function
|
|
||||||
wasm: <binary WASM file>
|
|
||||||
memory_limit: 64
|
|
||||||
timeout: 30
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "fn_abc123",
|
|
||||||
"name": "hello-world",
|
|
||||||
"namespace": "default",
|
|
||||||
"wasm_cid": "QmXxx...",
|
|
||||||
"version": 1,
|
|
||||||
"created_at": "2024-01-20T10:30:00Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Invoke Function
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /v1/functions/hello-world/invoke
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Alice"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"result": "Hello, Alice!",
|
|
||||||
"execution_time_ms": 15,
|
|
||||||
"memory_used_mb": 2.5
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### List Functions
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/functions?namespace=default
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"functions": [
|
|
||||||
{
|
|
||||||
"name": "hello-world",
|
|
||||||
"description": "Hello world function",
|
|
||||||
"version": 1,
|
|
||||||
"created_at": "2024-01-20T10:30:00Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Delete Function
|
|
||||||
|
|
||||||
```http
|
|
||||||
DELETE /v1/functions/hello-world?namespace=default
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"message": "function deleted successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Function Logs
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/functions/hello-world/logs?limit=100
|
|
||||||
Authorization: Bearer your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"logs": [
|
|
||||||
{
|
|
||||||
"timestamp": "2024-01-20T10:30:00Z",
|
|
||||||
"level": "info",
|
|
||||||
"message": "Function invoked",
|
|
||||||
"invocation_id": "inv_xyz789"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Error Responses
|
|
||||||
|
|
||||||
All errors follow a consistent format:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": "NOT_FOUND",
|
|
||||||
"message": "user with ID '123' not found",
|
|
||||||
"details": {
|
|
||||||
"resource": "user",
|
|
||||||
"id": "123"
|
|
||||||
},
|
|
||||||
"trace_id": "trace-abc123"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Common Error Codes
|
|
||||||
|
|
||||||
| Code | HTTP Status | Description |
|
|
||||||
|------|-------------|-------------|
|
|
||||||
| `VALIDATION_ERROR` | 400 | Invalid input |
|
|
||||||
| `UNAUTHORIZED` | 401 | Authentication required |
|
|
||||||
| `FORBIDDEN` | 403 | Permission denied |
|
|
||||||
| `NOT_FOUND` | 404 | Resource not found |
|
|
||||||
| `CONFLICT` | 409 | Resource already exists |
|
|
||||||
| `TIMEOUT` | 408 | Operation timeout |
|
|
||||||
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests |
|
|
||||||
| `SERVICE_UNAVAILABLE` | 503 | Service unavailable |
|
|
||||||
| `INTERNAL` | 500 | Internal server error |
|
|
||||||
|
|
||||||
## Rate Limiting
|
|
||||||
|
|
||||||
The API implements rate limiting per API key:
|
|
||||||
|
|
||||||
- **Default:** 100 requests per minute
|
|
||||||
- **Burst:** 200 requests
|
|
||||||
|
|
||||||
Rate limit headers:
|
|
||||||
```
|
|
||||||
X-RateLimit-Limit: 100
|
|
||||||
X-RateLimit-Remaining: 95
|
|
||||||
X-RateLimit-Reset: 1611144000
|
|
||||||
```
|
|
||||||
|
|
||||||
When rate limited:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"code": "RATE_LIMIT_EXCEEDED",
|
|
||||||
"message": "rate limit exceeded",
|
|
||||||
"details": {
|
|
||||||
"limit": 100,
|
|
||||||
"retry_after": 60
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pagination
|
|
||||||
|
|
||||||
List endpoints support pagination:
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /v1/functions?limit=10&offset=20
|
|
||||||
```
|
|
||||||
|
|
||||||
Response includes pagination metadata:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"data": [...],
|
|
||||||
"pagination": {
|
|
||||||
"total": 100,
|
|
||||||
"limit": 10,
|
|
||||||
"offset": 20,
|
|
||||||
"has_more": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Webhooks (Future)
|
|
||||||
|
|
||||||
Coming soon: webhook support for event notifications.
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
- API Issues: https://github.com/DeBrosOfficial/network/issues
|
|
||||||
- OpenAPI Spec: `openapi/gateway.yaml`
|
|
||||||
- SDK Documentation: `docs/CLIENT_SDK.md`
|
|
||||||
@ -1,476 +0,0 @@
|
|||||||
# Orama Network - Security Deployment Guide
|
|
||||||
|
|
||||||
**Date:** January 18, 2026
|
|
||||||
**Status:** Production-Ready
|
|
||||||
**Audit Completed By:** Claude Code Security Audit
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
|
|
||||||
This document outlines the security hardening measures applied to the 4-node Orama Network production cluster. All critical vulnerabilities identified in the security audit have been addressed.
|
|
||||||
|
|
||||||
**Security Status:** ✅ SECURED FOR PRODUCTION
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Server Inventory
|
|
||||||
|
|
||||||
| Server ID | IP Address | Domain | OS | Role |
|
|
||||||
|-----------|------------|--------|-----|------|
|
|
||||||
| VPS 1 | 51.83.128.181 | node-kv4la8.debros.network | Ubuntu 22.04 | Gateway + Cluster Node |
|
|
||||||
| VPS 2 | 194.61.28.7 | node-7prvNa.debros.network | Ubuntu 24.04 | Gateway + Cluster Node |
|
|
||||||
| VPS 3 | 83.171.248.66 | node-xn23dq.debros.network | Ubuntu 24.04 | Gateway + Cluster Node |
|
|
||||||
| VPS 4 | 62.72.44.87 | node-nns4n5.debros.network | Ubuntu 24.04 | Gateway + Cluster Node |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Services Running on Each Server
|
|
||||||
|
|
||||||
| Service | Port(s) | Purpose | Public Access |
|
|
||||||
|---------|---------|---------|---------------|
|
|
||||||
| **orama-node** | 80, 443, 7001 | API Gateway | Yes (80, 443 only) |
|
|
||||||
| **rqlited** | 5001, 7002 | Distributed SQLite DB | Cluster only |
|
|
||||||
| **ipfs** | 4101, 4501, 8080 | Content-addressed storage | Cluster only |
|
|
||||||
| **ipfs-cluster** | 9094, 9098 | IPFS cluster management | Cluster only |
|
|
||||||
| **olric-server** | 3320, 3322 | Distributed cache | Cluster only |
|
|
||||||
| **anon** (Anyone proxy) | 9001, 9050, 9051 | Anonymity proxy | Cluster only |
|
|
||||||
| **libp2p** | 4001 | P2P networking | Yes (public P2P) |
|
|
||||||
| **SSH** | 22 | Remote access | Yes |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security Measures Implemented
|
|
||||||
|
|
||||||
### 1. Firewall Configuration (UFW)
|
|
||||||
|
|
||||||
**Status:** ✅ Enabled on all 4 servers
|
|
||||||
|
|
||||||
#### Public Ports (Open to Internet)
|
|
||||||
- **22/tcp** - SSH (with hardening)
|
|
||||||
- **80/tcp** - HTTP (redirects to HTTPS)
|
|
||||||
- **443/tcp** - HTTPS (Let's Encrypt production certificates)
|
|
||||||
- **4001/tcp** - libp2p swarm (P2P networking)
|
|
||||||
|
|
||||||
#### Cluster-Only Ports (Restricted to 4 Server IPs)
|
|
||||||
All the following ports are ONLY accessible from the 4 cluster IPs:
|
|
||||||
- **5001/tcp** - rqlite HTTP API
|
|
||||||
- **7001/tcp** - SNI Gateway
|
|
||||||
- **7002/tcp** - rqlite Raft consensus
|
|
||||||
- **9094/tcp** - IPFS Cluster API
|
|
||||||
- **9098/tcp** - IPFS Cluster communication
|
|
||||||
- **3322/tcp** - Olric distributed cache
|
|
||||||
- **4101/tcp** - IPFS swarm (cluster internal)
|
|
||||||
|
|
||||||
#### Firewall Rules Example
|
|
||||||
```bash
|
|
||||||
sudo ufw default deny incoming
|
|
||||||
sudo ufw default allow outgoing
|
|
||||||
sudo ufw allow 22/tcp comment "SSH"
|
|
||||||
sudo ufw allow 80/tcp comment "HTTP"
|
|
||||||
sudo ufw allow 443/tcp comment "HTTPS"
|
|
||||||
sudo ufw allow 4001/tcp comment "libp2p swarm"
|
|
||||||
|
|
||||||
# Cluster-only access for sensitive services
|
|
||||||
sudo ufw allow from 51.83.128.181 to any port 5001 proto tcp
|
|
||||||
sudo ufw allow from 194.61.28.7 to any port 5001 proto tcp
|
|
||||||
sudo ufw allow from 83.171.248.66 to any port 5001 proto tcp
|
|
||||||
sudo ufw allow from 62.72.44.87 to any port 5001 proto tcp
|
|
||||||
# (repeat for ports 7001, 7002, 9094, 9098, 3322, 4101)
|
|
||||||
|
|
||||||
sudo ufw enable
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. SSH Hardening
|
|
||||||
|
|
||||||
**Location:** `/etc/ssh/sshd_config.d/99-hardening.conf`
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
```bash
|
|
||||||
PermitRootLogin yes # Root login allowed with SSH keys
|
|
||||||
PasswordAuthentication yes # Password auth enabled (you have keys configured)
|
|
||||||
PubkeyAuthentication yes # SSH key authentication enabled
|
|
||||||
PermitEmptyPasswords no # No empty passwords
|
|
||||||
X11Forwarding no # X11 disabled for security
|
|
||||||
MaxAuthTries 3 # Max 3 login attempts
|
|
||||||
ClientAliveInterval 300 # Keep-alive every 5 minutes
|
|
||||||
ClientAliveCountMax 2 # Disconnect after 2 failed keep-alives
|
|
||||||
```
|
|
||||||
|
|
||||||
**Your SSH Keys Added:**
|
|
||||||
- ✅ `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPcGZPX2iHXWO8tuyyDkHPS5eByPOktkw3+ugcw79yQO`
|
|
||||||
- ✅ `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDgCWmycaBN3aAZJcM2w4+Xi2zrTwN78W8oAiQywvMEkubqNNWHF6I3...`
|
|
||||||
|
|
||||||
Both keys are installed on all 4 servers in:
|
|
||||||
- VPS 1: `/home/ubuntu/.ssh/authorized_keys`
|
|
||||||
- VPS 2, 3, 4: `/root/.ssh/authorized_keys`
|
|
||||||
|
|
||||||
### 3. Fail2ban Protection
|
|
||||||
|
|
||||||
**Status:** ✅ Installed and running on all 4 servers
|
|
||||||
|
|
||||||
**Purpose:** Automatically bans IPs after failed SSH login attempts
|
|
||||||
|
|
||||||
**Check Status:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl status fail2ban
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Security Updates
|
|
||||||
|
|
||||||
**Status:** ✅ All security updates applied (as of Jan 18, 2026)
|
|
||||||
|
|
||||||
**Update Command:**
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Let's Encrypt TLS Certificates
|
|
||||||
|
|
||||||
**Status:** ✅ Production certificates (NOT staging)
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
- **Provider:** Let's Encrypt (ACME v2 Production)
|
|
||||||
- **Auto-renewal:** Enabled via autocert
|
|
||||||
- **Cache Directory:** `/home/debros/.orama/tls-cache/`
|
|
||||||
- **Domains:**
|
|
||||||
- node-kv4la8.debros.network (VPS 1)
|
|
||||||
- node-7prvNa.debros.network (VPS 2)
|
|
||||||
- node-xn23dq.debros.network (VPS 3)
|
|
||||||
- node-nns4n5.debros.network (VPS 4)
|
|
||||||
|
|
||||||
**Certificate Files:**
|
|
||||||
- Account key: `/home/debros/.orama/tls-cache/acme_account+key`
|
|
||||||
- Certificates auto-managed by autocert
|
|
||||||
|
|
||||||
**Verification:**
|
|
||||||
```bash
|
|
||||||
curl -I https://node-kv4la8.debros.network
|
|
||||||
# Should return valid SSL certificate
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Cluster Configuration
|
|
||||||
|
|
||||||
### RQLite Cluster
|
|
||||||
|
|
||||||
**Nodes:**
|
|
||||||
- 51.83.128.181:7002 (Leader)
|
|
||||||
- 194.61.28.7:7002
|
|
||||||
- 83.171.248.66:7002
|
|
||||||
- 62.72.44.87:7002
|
|
||||||
|
|
||||||
**Test Cluster Health:**
|
|
||||||
```bash
|
|
||||||
ssh ubuntu@51.83.128.181
|
|
||||||
curl -s http://localhost:5001/status | jq '.store.nodes'
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected Output:**
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{"id":"194.61.28.7:7002","addr":"194.61.28.7:7002","suffrage":"Voter"},
|
|
||||||
{"id":"51.83.128.181:7002","addr":"51.83.128.181:7002","suffrage":"Voter"},
|
|
||||||
{"id":"62.72.44.87:7002","addr":"62.72.44.87:7002","suffrage":"Voter"},
|
|
||||||
{"id":"83.171.248.66:7002","addr":"83.171.248.66:7002","suffrage":"Voter"}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### IPFS Cluster
|
|
||||||
|
|
||||||
**Test Cluster Health:**
|
|
||||||
```bash
|
|
||||||
ssh ubuntu@51.83.128.181
|
|
||||||
curl -s http://localhost:9094/id | jq '.cluster_peers'
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected:** All 4 peer IDs listed
|
|
||||||
|
|
||||||
### Olric Cache Cluster
|
|
||||||
|
|
||||||
**Port:** 3320 (localhost), 3322 (cluster communication)
|
|
||||||
|
|
||||||
**Test:**
|
|
||||||
```bash
|
|
||||||
ssh ubuntu@51.83.128.181
|
|
||||||
ss -tulpn | grep olric
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Access Credentials
|
|
||||||
|
|
||||||
### SSH Access
|
|
||||||
|
|
||||||
**VPS 1:**
|
|
||||||
```bash
|
|
||||||
ssh ubuntu@51.83.128.181
|
|
||||||
# OR using your SSH key:
|
|
||||||
ssh -i ~/.ssh/ssh-sotiris/id_ed25519 ubuntu@51.83.128.181
|
|
||||||
```
|
|
||||||
|
|
||||||
**VPS 2, 3, 4:**
|
|
||||||
```bash
|
|
||||||
ssh root@194.61.28.7
|
|
||||||
ssh root@83.171.248.66
|
|
||||||
ssh root@62.72.44.87
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important:** Password authentication is still enabled, but your SSH keys are configured for passwordless access.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing & Verification
|
|
||||||
|
|
||||||
### 1. Test External Port Access (From Your Machine)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# These should be BLOCKED (timeout or connection refused):
|
|
||||||
nc -zv 51.83.128.181 5001 # rqlite API - should be blocked
|
|
||||||
nc -zv 51.83.128.181 7002 # rqlite Raft - should be blocked
|
|
||||||
nc -zv 51.83.128.181 9094 # IPFS cluster - should be blocked
|
|
||||||
|
|
||||||
# These should be OPEN:
|
|
||||||
nc -zv 51.83.128.181 22 # SSH - should succeed
|
|
||||||
nc -zv 51.83.128.181 80 # HTTP - should succeed
|
|
||||||
nc -zv 51.83.128.181 443 # HTTPS - should succeed
|
|
||||||
nc -zv 51.83.128.181 4001 # libp2p - should succeed
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Test Domain Access
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -I https://node-kv4la8.debros.network
|
|
||||||
curl -I https://node-7prvNa.debros.network
|
|
||||||
curl -I https://node-xn23dq.debros.network
|
|
||||||
curl -I https://node-nns4n5.debros.network
|
|
||||||
```
|
|
||||||
|
|
||||||
All should return `HTTP/1.1 200 OK` or similar with valid SSL certificates.
|
|
||||||
|
|
||||||
### 3. Test Cluster Communication (From VPS 1)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh ubuntu@51.83.128.181
|
|
||||||
# Test rqlite cluster
|
|
||||||
curl -s http://localhost:5001/status | jq -r '.store.nodes[].id'
|
|
||||||
|
|
||||||
# Test IPFS cluster
|
|
||||||
curl -s http://localhost:9094/id | jq -r '.cluster_peers[]'
|
|
||||||
|
|
||||||
# Check all services running
|
|
||||||
ps aux | grep -E "(orama-node|rqlited|ipfs|olric)" | grep -v grep
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Maintenance & Operations
|
|
||||||
|
|
||||||
### Firewall Management
|
|
||||||
|
|
||||||
**View current rules:**
|
|
||||||
```bash
|
|
||||||
sudo ufw status numbered
|
|
||||||
```
|
|
||||||
|
|
||||||
**Add a new allowed IP for cluster services:**
|
|
||||||
```bash
|
|
||||||
sudo ufw allow from NEW_IP_ADDRESS to any port 5001 proto tcp
|
|
||||||
sudo ufw allow from NEW_IP_ADDRESS to any port 7002 proto tcp
|
|
||||||
# etc.
|
|
||||||
```
|
|
||||||
|
|
||||||
**Delete a rule:**
|
|
||||||
```bash
|
|
||||||
sudo ufw status numbered # Get rule number
|
|
||||||
sudo ufw delete [NUMBER]
|
|
||||||
```
|
|
||||||
|
|
||||||
### SSH Management
|
|
||||||
|
|
||||||
**Test SSH config without applying:**
|
|
||||||
```bash
|
|
||||||
sudo sshd -t
|
|
||||||
```
|
|
||||||
|
|
||||||
**Reload SSH after config changes:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl reload ssh
|
|
||||||
```
|
|
||||||
|
|
||||||
**View SSH login attempts:**
|
|
||||||
```bash
|
|
||||||
sudo journalctl -u ssh | tail -50
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fail2ban Management
|
|
||||||
|
|
||||||
**Check banned IPs:**
|
|
||||||
```bash
|
|
||||||
sudo fail2ban-client status sshd
|
|
||||||
```
|
|
||||||
|
|
||||||
**Unban an IP:**
|
|
||||||
```bash
|
|
||||||
sudo fail2ban-client set sshd unbanip IP_ADDRESS
|
|
||||||
```
|
|
||||||
|
|
||||||
### Security Updates
|
|
||||||
|
|
||||||
**Check for updates:**
|
|
||||||
```bash
|
|
||||||
apt list --upgradable
|
|
||||||
```
|
|
||||||
|
|
||||||
**Apply updates:**
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
```
|
|
||||||
|
|
||||||
**Reboot if kernel updated:**
|
|
||||||
```bash
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security Improvements Completed
|
|
||||||
|
|
||||||
### Before Security Audit:
|
|
||||||
- ❌ No firewall enabled
|
|
||||||
- ❌ rqlite database exposed to internet (port 5001, 7002)
|
|
||||||
- ❌ IPFS cluster management exposed (port 9094, 9098)
|
|
||||||
- ❌ Olric cache exposed (port 3322)
|
|
||||||
- ❌ Root login enabled without restrictions (VPS 2, 3, 4)
|
|
||||||
- ❌ No fail2ban on 3 out of 4 servers
|
|
||||||
- ❌ 19-39 security updates pending
|
|
||||||
|
|
||||||
### After Security Hardening:
|
|
||||||
- ✅ UFW firewall enabled on all servers
|
|
||||||
- ✅ Sensitive ports restricted to cluster IPs only
|
|
||||||
- ✅ SSH hardened with key authentication
|
|
||||||
- ✅ Fail2ban protecting all servers
|
|
||||||
- ✅ All security updates applied
|
|
||||||
- ✅ Let's Encrypt production certificates verified
|
|
||||||
- ✅ Cluster communication tested and working
|
|
||||||
- ✅ External access verified (HTTP/HTTPS only)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Recommended Next Steps (Optional)
|
|
||||||
|
|
||||||
These were not implemented per your request but are recommended for future consideration:
|
|
||||||
|
|
||||||
1. **VPN/Private Networking** - Use WireGuard or Tailscale for encrypted cluster communication instead of firewall rules
|
|
||||||
2. **Automated Security Updates** - Enable unattended-upgrades for automatic security patches
|
|
||||||
3. **Monitoring & Alerting** - Set up Prometheus/Grafana for service monitoring
|
|
||||||
4. **Regular Security Audits** - Run `lynis` or `rkhunter` monthly for security checks
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Important Notes
|
|
||||||
|
|
||||||
### Let's Encrypt Configuration
|
|
||||||
|
|
||||||
The Orama Network gateway uses **autocert** from Go's `golang.org/x/crypto/acme/autocert` package. The configuration is in:
|
|
||||||
|
|
||||||
**File:** `/home/debros/.orama/configs/node.yaml`
|
|
||||||
|
|
||||||
**Relevant settings:**
|
|
||||||
```yaml
|
|
||||||
http_gateway:
|
|
||||||
https:
|
|
||||||
enabled: true
|
|
||||||
domain: "node-kv4la8.debros.network"
|
|
||||||
auto_cert: true
|
|
||||||
cache_dir: "/home/debros/.orama/tls-cache"
|
|
||||||
http_port: 80
|
|
||||||
https_port: 443
|
|
||||||
email: "admin@node-kv4la8.debros.network"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important:** There is NO `letsencrypt_staging` flag set, which means it defaults to **production Let's Encrypt**. This is correct for production deployment.
|
|
||||||
|
|
||||||
### Firewall Persistence
|
|
||||||
|
|
||||||
UFW rules are persistent across reboots. The firewall will automatically start on boot.
|
|
||||||
|
|
||||||
### SSH Key Access
|
|
||||||
|
|
||||||
Both of your SSH keys are configured on all servers. You can access:
|
|
||||||
- VPS 1: `ssh -i ~/.ssh/ssh-sotiris/id_ed25519 ubuntu@51.83.128.181`
|
|
||||||
- VPS 2-4: `ssh -i ~/.ssh/ssh-sotiris/id_ed25519 root@IP_ADDRESS`
|
|
||||||
|
|
||||||
Password authentication is still enabled as a fallback, but keys are recommended.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Emergency Access
|
|
||||||
|
|
||||||
If you get locked out:
|
|
||||||
|
|
||||||
1. **VPS Provider Console:** All major VPS providers offer web-based console access
|
|
||||||
2. **Password Access:** Password auth is still enabled on all servers
|
|
||||||
3. **SSH Keys:** Two keys configured for redundancy
|
|
||||||
|
|
||||||
**Disable firewall temporarily (emergency only):**
|
|
||||||
```bash
|
|
||||||
sudo ufw disable
|
|
||||||
# Fix the issue
|
|
||||||
sudo ufw enable
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Verification Checklist
|
|
||||||
|
|
||||||
Use this checklist to verify the security hardening:
|
|
||||||
|
|
||||||
- [ ] All 4 servers have UFW firewall enabled
|
|
||||||
- [ ] SSH is hardened (MaxAuthTries 3, X11Forwarding no)
|
|
||||||
- [ ] Your SSH keys work on all servers
|
|
||||||
- [ ] Fail2ban is running on all servers
|
|
||||||
- [ ] Security updates are current
|
|
||||||
- [ ] rqlite port 5001 is NOT accessible from internet
|
|
||||||
- [ ] rqlite port 7002 is NOT accessible from internet
|
|
||||||
- [ ] IPFS cluster ports 9094, 9098 are NOT accessible from internet
|
|
||||||
- [ ] Domains are accessible via HTTPS with valid certificates
|
|
||||||
- [ ] RQLite cluster shows all 4 nodes
|
|
||||||
- [ ] IPFS cluster shows all 4 peers
|
|
||||||
- [ ] All services are running (5 processes per server)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contact & Support
|
|
||||||
|
|
||||||
For issues or questions about this deployment:
|
|
||||||
|
|
||||||
- **Security Audit Date:** January 18, 2026
|
|
||||||
- **Configuration Files:** `/home/debros/.orama/configs/`
|
|
||||||
- **Firewall Rules:** `/etc/ufw/`
|
|
||||||
- **SSH Config:** `/etc/ssh/sshd_config.d/99-hardening.conf`
|
|
||||||
- **TLS Certs:** `/home/debros/.orama/tls-cache/`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
### January 18, 2026 - Production Security Hardening
|
|
||||||
|
|
||||||
**Changes:**
|
|
||||||
1. Added UFW firewall rules on all 4 VPS servers
|
|
||||||
2. Restricted sensitive ports (5001, 7002, 9094, 9098, 3322, 4101) to cluster IPs only
|
|
||||||
3. Hardened SSH configuration
|
|
||||||
4. Added your 2 SSH keys to all servers
|
|
||||||
5. Installed fail2ban on VPS 1, 2, 3 (VPS 4 already had it)
|
|
||||||
6. Applied all pending security updates (23-39 packages per server)
|
|
||||||
7. Verified Let's Encrypt is using production (not staging)
|
|
||||||
8. Tested all services: rqlite, IPFS, libp2p, Olric clusters
|
|
||||||
9. Verified all 4 domains are accessible via HTTPS
|
|
||||||
|
|
||||||
**Result:** Production-ready secure deployment ✅
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**END OF DEPLOYMENT GUIDE**
|
|
||||||
@ -1,760 +0,0 @@
|
|||||||
# Comprehensive Testing Plan
|
|
||||||
|
|
||||||
This document outlines the complete testing strategy for the namespace isolation and custom deployment system.
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
1. [Unit Tests](#unit-tests)
|
|
||||||
2. [Integration Tests](#integration-tests)
|
|
||||||
3. [End-to-End Tests](#end-to-end-tests)
|
|
||||||
4. [CLI Tests](#cli-tests)
|
|
||||||
5. [Performance Tests](#performance-tests)
|
|
||||||
6. [Security Tests](#security-tests)
|
|
||||||
7. [Chaos/Failure Tests](#chaos-failure-tests)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Unit Tests
|
|
||||||
|
|
||||||
### 1.1 Port Allocator Tests
|
|
||||||
|
|
||||||
**File**: `pkg/deployments/port_allocator_test.go`
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- ✅ Allocate first port (should be 10100)
|
|
||||||
- ✅ Allocate sequential ports
|
|
||||||
- ✅ Find gaps in allocation
|
|
||||||
- ✅ Handle port exhaustion (all 10000 ports used)
|
|
||||||
- ✅ Concurrent allocation with race detector
|
|
||||||
- ✅ Conflict retry with exponential backoff
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./pkg/deployments -run TestPortAllocator -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 Home Node Manager Tests
|
|
||||||
|
|
||||||
**File**: `pkg/deployments/home_node_test.go`
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- ✅ Assign namespace to node with lowest load
|
|
||||||
- ✅ Reuse existing home node for namespace
|
|
||||||
- ✅ Weight calculation (deployments, ports, memory, CPU)
|
|
||||||
- ✅ Handle no nodes available
|
|
||||||
- ✅ Node failure detection and reassignment
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./pkg/deployments -run TestHomeNodeManager -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.3 Health Checker Tests
|
|
||||||
|
|
||||||
**File**: `pkg/deployments/health/checker_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- Check static deployment (always healthy)
|
|
||||||
- Check dynamic deployment with health endpoint
|
|
||||||
- Mark as failed after 3 consecutive failures
|
|
||||||
- Record health check history
|
|
||||||
- Parallel health checking
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./pkg/deployments/health -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.4 Process Manager Tests
|
|
||||||
|
|
||||||
**File**: `pkg/deployments/process/manager_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- Create systemd service file
|
|
||||||
- Start deployment process
|
|
||||||
- Stop deployment process
|
|
||||||
- Restart deployment
|
|
||||||
- Read logs from journalctl
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./pkg/deployments/process -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.5 Deployment Service Tests
|
|
||||||
|
|
||||||
**File**: `pkg/gateway/handlers/deployments/service_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- Create deployment
|
|
||||||
- Get deployment by ID
|
|
||||||
- List deployments for namespace
|
|
||||||
- Update deployment
|
|
||||||
- Delete deployment
|
|
||||||
- Record deployment history
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./pkg/gateway/handlers/deployments -v
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Integration Tests
|
|
||||||
|
|
||||||
### 2.1 Static Deployment Integration Test
|
|
||||||
|
|
||||||
**File**: `tests/integration/static_deployment_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Setup**:
|
|
||||||
- Start test RQLite instance
|
|
||||||
- Start test IPFS node
|
|
||||||
- Start test gateway
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Upload static content tarball
|
|
||||||
2. Verify deployment created in database
|
|
||||||
3. Verify content uploaded to IPFS
|
|
||||||
4. Verify DNS record created
|
|
||||||
5. Test HTTP request to deployment domain
|
|
||||||
6. Verify content served correctly
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/integration -run TestStaticDeployment -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 Next.js SSR Deployment Integration Test
|
|
||||||
|
|
||||||
**File**: `tests/integration/nextjs_deployment_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Upload Next.js build
|
|
||||||
2. Verify systemd service created
|
|
||||||
3. Verify process started
|
|
||||||
4. Wait for health check to pass
|
|
||||||
5. Test HTTP request to deployment
|
|
||||||
6. Verify SSR response
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/integration -run TestNextJSDeployment -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 SQLite Database Integration Test
|
|
||||||
|
|
||||||
**File**: `tests/integration/sqlite_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Create SQLite database
|
|
||||||
2. Verify database file created on disk
|
|
||||||
3. Execute CREATE TABLE query
|
|
||||||
4. Execute INSERT query
|
|
||||||
5. Execute SELECT query
|
|
||||||
6. Backup database to IPFS
|
|
||||||
7. Verify backup CID recorded
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/integration -run TestSQLiteDatabase -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.4 Custom Domain Integration Test
|
|
||||||
|
|
||||||
**File**: `tests/integration/custom_domain_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Add custom domain to deployment
|
|
||||||
2. Verify TXT record verification token generated
|
|
||||||
3. Mock DNS TXT record lookup
|
|
||||||
4. Verify domain
|
|
||||||
5. Verify DNS A record created
|
|
||||||
6. Test HTTP request to custom domain
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/integration -run TestCustomDomain -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 Update and Rollback Integration Test
|
|
||||||
|
|
||||||
**File**: `tests/integration/update_rollback_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Deploy initial version
|
|
||||||
2. Update deployment with new content
|
|
||||||
3. Verify version incremented
|
|
||||||
4. Verify new content served
|
|
||||||
5. Rollback to previous version
|
|
||||||
6. Verify old content served
|
|
||||||
7. Verify history recorded correctly
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/integration -run TestUpdateRollback -v
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. End-to-End Tests
|
|
||||||
|
|
||||||
### 3.1 Full Static Deployment E2E Test
|
|
||||||
|
|
||||||
**File**: `tests/e2e/static_deployment_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Prerequisites**:
|
|
||||||
- Running RQLite cluster
|
|
||||||
- Running IPFS cluster
|
|
||||||
- Running gateway instances
|
|
||||||
- CoreDNS configured
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Create test React app
|
|
||||||
2. Build app (`npm run build`)
|
|
||||||
3. Deploy via CLI: `orama deploy static ./dist --name e2e-static`
|
|
||||||
4. Wait for deployment to be active
|
|
||||||
5. Resolve deployment domain via DNS
|
|
||||||
6. Make HTTPS request to deployment
|
|
||||||
7. Verify all static assets load correctly
|
|
||||||
8. Test SPA routing (fallback to index.html)
|
|
||||||
9. Update deployment
|
|
||||||
10. Verify zero-downtime update
|
|
||||||
11. Delete deployment
|
|
||||||
12. Verify cleanup
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/e2e -run TestStaticDeploymentE2E -v -timeout 10m
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 Full Next.js SSR Deployment E2E Test
|
|
||||||
|
|
||||||
**File**: `tests/e2e/nextjs_deployment_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Create test Next.js app with API routes
|
|
||||||
2. Build app (`npm run build`)
|
|
||||||
3. Deploy via CLI: `orama deploy nextjs . --name e2e-nextjs --ssr`
|
|
||||||
4. Wait for process to start and pass health check
|
|
||||||
5. Test static route
|
|
||||||
6. Test API route
|
|
||||||
7. Test SSR page
|
|
||||||
8. Update deployment with graceful restart
|
|
||||||
9. Verify health check before cutting over
|
|
||||||
10. Rollback if health check fails
|
|
||||||
11. Monitor logs during deployment
|
|
||||||
12. Delete deployment
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/e2e -run TestNextJSDeploymentE2E -v -timeout 15m
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 Full SQLite Database E2E Test
|
|
||||||
|
|
||||||
**File**: `tests/e2e/sqlite_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Create database via CLI: `orama db create e2e-testdb`
|
|
||||||
2. Create schema: `orama db query e2e-testdb "CREATE TABLE ..."`
|
|
||||||
3. Insert data: `orama db query e2e-testdb "INSERT ..."`
|
|
||||||
4. Query data: `orama db query e2e-testdb "SELECT ..."`
|
|
||||||
5. Verify results match expected
|
|
||||||
6. Backup database: `orama db backup e2e-testdb`
|
|
||||||
7. List backups: `orama db backups e2e-testdb`
|
|
||||||
8. Verify backup CID in IPFS
|
|
||||||
9. Restore from backup (if implemented)
|
|
||||||
10. Verify data integrity
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/e2e -run TestSQLiteDatabaseE2E -v -timeout 10m
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.4 DNS Resolution E2E Test
|
|
||||||
|
|
||||||
**File**: `tests/e2e/dns_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Flow**:
|
|
||||||
1. Create deployment
|
|
||||||
2. Query all 4 nameservers for deployment domain
|
|
||||||
3. Verify all return same IP
|
|
||||||
4. Add custom domain
|
|
||||||
5. Verify TXT record
|
|
||||||
6. Verify A record created
|
|
||||||
7. Query external DNS resolver
|
|
||||||
8. Verify domain resolves correctly
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/e2e -run TestDNSResolutionE2E -v -timeout 5m
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. CLI Tests
|
|
||||||
|
|
||||||
### 4.1 Deploy Command Tests
|
|
||||||
|
|
||||||
**File**: `tests/cli/deploy_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- Deploy static site
|
|
||||||
- Deploy Next.js with --ssr flag
|
|
||||||
- Deploy Node.js backend
|
|
||||||
- Deploy Go backend
|
|
||||||
- Handle missing arguments
|
|
||||||
- Handle invalid paths
|
|
||||||
- Handle network errors gracefully
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/cli -run TestDeployCommand -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 Deployments Management Tests
|
|
||||||
|
|
||||||
**File**: `tests/cli/deployments_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- List all deployments
|
|
||||||
- Get specific deployment
|
|
||||||
- Delete deployment with confirmation
|
|
||||||
- Rollback to version
|
|
||||||
- View logs with --follow
|
|
||||||
- Filter deployments by status
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/cli -run TestDeploymentsCommands -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 Database Command Tests
|
|
||||||
|
|
||||||
**File**: `tests/cli/db_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- Create database
|
|
||||||
- Execute query (SELECT, INSERT, UPDATE, DELETE)
|
|
||||||
- List databases
|
|
||||||
- Backup database
|
|
||||||
- List backups
|
|
||||||
- Handle SQL syntax errors
|
|
||||||
- Handle connection errors
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/cli -run TestDatabaseCommands -v
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.4 Domain Command Tests
|
|
||||||
|
|
||||||
**File**: `tests/cli/domain_test.go` (needs to be created)
|
|
||||||
|
|
||||||
**Test Cases**:
|
|
||||||
- Add custom domain
|
|
||||||
- Verify domain
|
|
||||||
- List domains
|
|
||||||
- Remove domain
|
|
||||||
- Handle verification failures
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test ./tests/cli -run TestDomainCommands -v
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Performance Tests
|
|
||||||
|
|
||||||
### 5.1 Concurrent Deployment Test
|
|
||||||
|
|
||||||
**Objective**: Verify system handles multiple concurrent deployments
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# Deploy 50 static sites concurrently
|
|
||||||
for i in {1..50}; do
|
|
||||||
orama deploy static ./test-site --name test-$i &
|
|
||||||
done
|
|
||||||
wait
|
|
||||||
|
|
||||||
# Verify all succeeded
|
|
||||||
orama deployments list | grep -c "active"
|
|
||||||
# Should output: 50
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 Port Allocation Performance Test
|
|
||||||
|
|
||||||
**Objective**: Measure port allocation speed under high contention
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```go
|
|
||||||
func BenchmarkPortAllocation(b *testing.B) {
|
|
||||||
// Setup
|
|
||||||
db := setupTestDB()
|
|
||||||
allocator := deployments.NewPortAllocator(db, logger)
|
|
||||||
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
for pb.Next() {
|
|
||||||
_, err := allocator.AllocatePort(ctx, "test-node", uuid.New().String())
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Command**:
|
|
||||||
```bash
|
|
||||||
go test -bench=BenchmarkPortAllocation -benchtime=10s ./pkg/deployments
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 DNS Query Performance Test
|
|
||||||
|
|
||||||
**Objective**: Measure CoreDNS query latency with RQLite backend
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# Warm up
|
|
||||||
for i in {1..1000}; do
|
|
||||||
dig @localhost test.orama.network > /dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
# Benchmark
|
|
||||||
ab -n 10000 -c 100 http://localhost:53/dns-query?name=test.orama.network
|
|
||||||
|
|
||||||
# Expected: <50ms p95 latency
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.4 Health Check Performance Test
|
|
||||||
|
|
||||||
**Objective**: Verify health checker handles 1000 deployments
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
- Create 1000 test deployments
|
|
||||||
- Start health checker
|
|
||||||
- Measure time to complete one check cycle
|
|
||||||
- Expected: <60 seconds for all 1000 checks
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Security Tests
|
|
||||||
|
|
||||||
### 6.1 Namespace Isolation Test
|
|
||||||
|
|
||||||
**Objective**: Verify users cannot access other namespaces' resources
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# User A deploys
|
|
||||||
export ORAMA_TOKEN="user-a-token"
|
|
||||||
orama deploy static ./site --name myapp
|
|
||||||
|
|
||||||
# User B attempts to access User A's deployment
|
|
||||||
export ORAMA_TOKEN="user-b-token"
|
|
||||||
orama deployments get myapp
|
|
||||||
# Expected: 404 Not Found or 403 Forbidden
|
|
||||||
|
|
||||||
# User B attempts to access User A's database
|
|
||||||
orama db query user-a-db "SELECT * FROM users"
|
|
||||||
# Expected: 404 Not Found or 403 Forbidden
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.2 SQL Injection Test
|
|
||||||
|
|
||||||
**Objective**: Verify SQLite handler sanitizes inputs
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# Attempt SQL injection in database name
|
|
||||||
orama db create "test'; DROP TABLE users; --"
|
|
||||||
# Expected: Validation error
|
|
||||||
|
|
||||||
# Attempt SQL injection in query
|
|
||||||
orama db query testdb "SELECT * FROM users WHERE id = '1' OR '1'='1'"
|
|
||||||
# Expected: Query executes safely (parameterized)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.3 Path Traversal Test
|
|
||||||
|
|
||||||
**Objective**: Verify deployment paths are sanitized
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# Attempt path traversal in deployment name
|
|
||||||
orama deploy static ./site --name "../../etc/passwd"
|
|
||||||
# Expected: Validation error
|
|
||||||
|
|
||||||
# Attempt path traversal in SQLite database name
|
|
||||||
orama db create "../../../etc/shadow"
|
|
||||||
# Expected: Validation error
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.4 Resource Exhaustion Test
|
|
||||||
|
|
||||||
**Objective**: Verify resource limits are enforced
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# Deploy 10001 sites (exceeds default limit)
|
|
||||||
for i in {1..10001}; do
|
|
||||||
orama deploy static ./site --name test-$i
|
|
||||||
done
|
|
||||||
# Expected: Last deployment rejected with quota error
|
|
||||||
|
|
||||||
# Create huge SQLite database
|
|
||||||
orama db query bigdb "CREATE TABLE huge (data TEXT)"
|
|
||||||
orama db query bigdb "INSERT INTO huge VALUES ('$(head -c 10G </dev/urandom | base64)')"
|
|
||||||
# Expected: Size limit enforced
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Chaos/Failure Tests
|
|
||||||
|
|
||||||
### 7.1 Node Failure Test
|
|
||||||
|
|
||||||
**Objective**: Verify system handles gateway node failure
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
1. Deploy app to node A
|
|
||||||
2. Verify deployment is healthy
|
|
||||||
3. Simulate node A crash: `systemctl stop orama-gateway`
|
|
||||||
4. Wait for failure detection
|
|
||||||
5. Verify namespace migrated to node B
|
|
||||||
6. Verify deployment restored from IPFS backup
|
|
||||||
7. Verify health checks pass on node B
|
|
||||||
|
|
||||||
### 7.2 RQLite Failure Test
|
|
||||||
|
|
||||||
**Objective**: Verify graceful degradation when RQLite is unavailable
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
1. Deploy app successfully
|
|
||||||
2. Stop RQLite: `systemctl stop rqlite`
|
|
||||||
3. Attempt new deployment (should fail gracefully with error message)
|
|
||||||
4. Verify existing deployments still serve traffic (cached)
|
|
||||||
5. Restart RQLite
|
|
||||||
6. Verify new deployments work
|
|
||||||
|
|
||||||
### 7.3 IPFS Failure Test
|
|
||||||
|
|
||||||
**Objective**: Verify handling of IPFS unavailability
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
1. Deploy static site
|
|
||||||
2. Stop IPFS: `systemctl stop ipfs`
|
|
||||||
3. Attempt to serve deployment (should fail or serve from cache)
|
|
||||||
4. Attempt new deployment (should fail with clear error)
|
|
||||||
5. Restart IPFS
|
|
||||||
6. Verify recovery
|
|
||||||
|
|
||||||
### 7.4 CoreDNS Failure Test
|
|
||||||
|
|
||||||
**Objective**: Verify DNS redundancy
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
1. Stop 1 CoreDNS instance
|
|
||||||
2. Verify DNS still resolves (3 of 4 servers working)
|
|
||||||
3. Stop 2nd CoreDNS instance
|
|
||||||
4. Verify DNS still resolves (2 of 4 servers working)
|
|
||||||
5. Stop 3rd CoreDNS instance
|
|
||||||
6. Verify DNS degraded but functional (1 of 4 servers)
|
|
||||||
7. Stop all 4 CoreDNS instances
|
|
||||||
8. Verify DNS resolution fails
|
|
||||||
|
|
||||||
### 7.5 Concurrent Update Test
|
|
||||||
|
|
||||||
**Objective**: Verify race conditions are handled
|
|
||||||
|
|
||||||
**Test**:
|
|
||||||
```bash
|
|
||||||
# Update same deployment concurrently
|
|
||||||
orama deploy static ./site-v2 --name myapp --update &
|
|
||||||
orama deploy static ./site-v3 --name myapp --update &
|
|
||||||
wait
|
|
||||||
|
|
||||||
# Verify only one update succeeded
|
|
||||||
# Verify database is consistent
|
|
||||||
# Verify no partial updates
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Test Execution Plan
|
|
||||||
|
|
||||||
### Phase 1: Unit Tests (Day 1)
|
|
||||||
- Run all unit tests
|
|
||||||
- Ensure 100% pass rate
|
|
||||||
- Measure code coverage (target: >80%)
|
|
||||||
|
|
||||||
### Phase 2: Integration Tests (Days 2-3)
|
|
||||||
- Run integration tests in isolated environment
|
|
||||||
- Fix any integration issues
|
|
||||||
- Verify database state consistency
|
|
||||||
|
|
||||||
### Phase 3: E2E Tests (Days 4-5)
|
|
||||||
- Run E2E tests in staging environment
|
|
||||||
- Test with real DNS, IPFS, RQLite
|
|
||||||
- Fix any environment-specific issues
|
|
||||||
|
|
||||||
### Phase 4: Performance Tests (Day 6)
|
|
||||||
- Run load tests
|
|
||||||
- Measure latency and throughput
|
|
||||||
- Optimize bottlenecks
|
|
||||||
|
|
||||||
### Phase 5: Security Tests (Day 7)
|
|
||||||
- Run security test suite
|
|
||||||
- Fix any vulnerabilities
|
|
||||||
- Document security model
|
|
||||||
|
|
||||||
### Phase 6: Chaos Tests (Day 8)
|
|
||||||
- Run failure scenario tests
|
|
||||||
- Verify recovery procedures
|
|
||||||
- Document failure modes
|
|
||||||
|
|
||||||
### Phase 7: Production Validation (Day 9-10)
|
|
||||||
- Deploy to production with feature flag OFF
|
|
||||||
- Run smoke tests in production
|
|
||||||
- Enable feature flag for 10% of traffic
|
|
||||||
- Monitor for 24 hours
|
|
||||||
- Gradually increase to 100%
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Test Environment Setup
|
|
||||||
|
|
||||||
### Local Development
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start test dependencies
|
|
||||||
docker-compose -f tests/docker-compose.test.yml up -d
|
|
||||||
|
|
||||||
# Run unit tests
|
|
||||||
make test-unit
|
|
||||||
|
|
||||||
# Run integration tests
|
|
||||||
make test-integration
|
|
||||||
|
|
||||||
# Run all tests
|
|
||||||
make test-all
|
|
||||||
```
|
|
||||||
|
|
||||||
### CI/CD Pipeline
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# .github/workflows/test.yml
|
|
||||||
name: Test
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
unit-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-go@v2
|
|
||||||
- run: go test ./pkg/... -v -race -coverprofile=coverage.out
|
|
||||||
|
|
||||||
integration-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
rqlite:
|
|
||||||
image: rqlite/rqlite
|
|
||||||
ipfs:
|
|
||||||
image: ipfs/go-ipfs
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-go@v2
|
|
||||||
- run: go test ./tests/integration/... -v -timeout 15m
|
|
||||||
|
|
||||||
e2e-tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: ./scripts/setup-test-env.sh
|
|
||||||
- run: go test ./tests/e2e/... -v -timeout 30m
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Success Criteria
|
|
||||||
|
|
||||||
### Unit Tests
|
|
||||||
- ✅ All tests pass
|
|
||||||
- ✅ Code coverage >80%
|
|
||||||
- ✅ No race conditions detected
|
|
||||||
|
|
||||||
### Integration Tests
|
|
||||||
- ✅ All happy path scenarios pass
|
|
||||||
- ✅ Error scenarios handled gracefully
|
|
||||||
- ✅ Database state remains consistent
|
|
||||||
|
|
||||||
### E2E Tests
|
|
||||||
- ✅ Full workflows complete successfully
|
|
||||||
- ✅ DNS resolution works across all nameservers
|
|
||||||
- ✅ Deployments accessible via HTTPS
|
|
||||||
|
|
||||||
### Performance Tests
|
|
||||||
- ✅ Port allocation: <10ms per allocation
|
|
||||||
- ✅ DNS queries: <50ms p95 latency
|
|
||||||
- ✅ Deployment creation: <30s for static, <2min for dynamic
|
|
||||||
- ✅ Health checks: Complete 1000 deployments in <60s
|
|
||||||
|
|
||||||
### Security Tests
|
|
||||||
- ✅ Namespace isolation enforced
|
|
||||||
- ✅ No SQL injection vulnerabilities
|
|
||||||
- ✅ No path traversal vulnerabilities
|
|
||||||
- ✅ Resource limits enforced
|
|
||||||
|
|
||||||
### Chaos Tests
|
|
||||||
- ✅ Node failure: Recovery within 5 minutes
|
|
||||||
- ✅ Service failure: Graceful degradation
|
|
||||||
- ✅ Concurrent updates: No race conditions
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ongoing Testing
|
|
||||||
|
|
||||||
After production deployment:
|
|
||||||
|
|
||||||
1. **Synthetic Monitoring**: Create test deployments every hour and verify they work
|
|
||||||
2. **Canary Deployments**: Test new versions with 1% of traffic before full rollout
|
|
||||||
3. **Load Testing**: Weekly load tests to ensure performance doesn't degrade
|
|
||||||
4. **Security Scanning**: Automated vulnerability scans
|
|
||||||
5. **Chaos Engineering**: Monthly chaos tests in staging
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Test Automation Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run all tests
|
|
||||||
make test-all
|
|
||||||
|
|
||||||
# Run unit tests only
|
|
||||||
make test-unit
|
|
||||||
|
|
||||||
# Run integration tests only
|
|
||||||
make test-integration
|
|
||||||
|
|
||||||
# Run E2E tests only
|
|
||||||
make test-e2e
|
|
||||||
|
|
||||||
# Run performance tests
|
|
||||||
make test-performance
|
|
||||||
|
|
||||||
# Run security tests
|
|
||||||
make test-security
|
|
||||||
|
|
||||||
# Run chaos tests
|
|
||||||
make test-chaos
|
|
||||||
|
|
||||||
# Generate coverage report
|
|
||||||
make test-coverage
|
|
||||||
|
|
||||||
# Run tests with race detector
|
|
||||||
make test-race
|
|
||||||
```
|
|
||||||
54
pkg/cli/deployment_commands.go
Normal file
54
pkg/cli/deployment_commands.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/DeBrosOfficial/network/pkg/cli/db"
|
||||||
|
"github.com/DeBrosOfficial/network/pkg/cli/deployments"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleDeployCommand handles deploy commands
|
||||||
|
func HandleDeployCommand(args []string) {
|
||||||
|
deployCmd := deployments.DeployCmd
|
||||||
|
deployCmd.SetArgs(args)
|
||||||
|
|
||||||
|
if err := deployCmd.Execute(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDeploymentsCommand handles deployments management commands
|
||||||
|
func HandleDeploymentsCommand(args []string) {
|
||||||
|
// Create root command for deployments management
|
||||||
|
deploymentsCmd := deployments.DeployCmd
|
||||||
|
deploymentsCmd.Use = "deployments"
|
||||||
|
deploymentsCmd.Short = "Manage deployments"
|
||||||
|
deploymentsCmd.Long = "List, get, delete, rollback, and view logs for deployments"
|
||||||
|
|
||||||
|
// Add management subcommands
|
||||||
|
deploymentsCmd.AddCommand(deployments.ListCmd)
|
||||||
|
deploymentsCmd.AddCommand(deployments.GetCmd)
|
||||||
|
deploymentsCmd.AddCommand(deployments.DeleteCmd)
|
||||||
|
deploymentsCmd.AddCommand(deployments.RollbackCmd)
|
||||||
|
deploymentsCmd.AddCommand(deployments.LogsCmd)
|
||||||
|
|
||||||
|
deploymentsCmd.SetArgs(args)
|
||||||
|
|
||||||
|
if err := deploymentsCmd.Execute(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDBCommand handles database commands
|
||||||
|
func HandleDBCommand(args []string) {
|
||||||
|
dbCmd := db.DBCmd
|
||||||
|
dbCmd.SetArgs(args)
|
||||||
|
|
||||||
|
if err := dbCmd.Execute(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user