mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 03:43: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
|
||||
- **💾 Storage** - IPFS-based decentralized file storage with encryption
|
||||
- **⚡ 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
|
||||
- **⚙️ Serverless** - WebAssembly function execution with host functions
|
||||
- **🌐 HTTP Gateway** - Unified REST API with automatic HTTPS (Let's Encrypt)
|
||||
- **📦 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
|
||||
|
||||
@ -108,36 +192,63 @@ make build
|
||||
|
||||
## 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
|
||||
|
||||
```bash
|
||||
./bin/orama health # Cluster health check
|
||||
./bin/orama peers # List connected peers
|
||||
./bin/orama status # Network status
|
||||
orama health # Cluster health check
|
||||
orama peers # List connected peers
|
||||
orama status # Network status
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
### RQLite Operations
|
||||
|
||||
```bash
|
||||
./bin/orama query "SELECT * FROM users"
|
||||
./bin/orama query "CREATE TABLE users (id INTEGER PRIMARY KEY)"
|
||||
./bin/orama transaction --file ops.json
|
||||
orama query "SELECT * FROM users"
|
||||
orama query "CREATE TABLE users (id INTEGER PRIMARY KEY)"
|
||||
orama transaction --file ops.json
|
||||
```
|
||||
|
||||
### Pub/Sub
|
||||
|
||||
```bash
|
||||
./bin/orama pubsub publish <topic> <message>
|
||||
./bin/orama pubsub subscribe <topic> 30s
|
||||
./bin/orama pubsub topics
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
```bash
|
||||
./bin/orama auth login
|
||||
./bin/orama auth status
|
||||
./bin/orama auth logout
|
||||
orama pubsub publish <topic> <message>
|
||||
orama pubsub subscribe <topic> 30s
|
||||
orama pubsub topics
|
||||
```
|
||||
|
||||
## Serverless Functions (WASM)
|
||||
@ -331,10 +442,12 @@ See `openapi/gateway.yaml` for complete API specification.
|
||||
|
||||
## 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
|
||||
- **[Client SDK](docs/CLIENT_SDK.md)** - Go SDK documentation and examples
|
||||
- **[Gateway API](docs/GATEWAY_API.md)** - Complete HTTP API reference
|
||||
- **[Security Deployment](docs/SECURITY_DEPLOYMENT_GUIDE.md)** - Production security hardening
|
||||
- **[Testing Plan](docs/TESTING_PLAN.md)** - Comprehensive testing strategy and implementation
|
||||
|
||||
## Resources
|
||||
|
||||
|
||||
@ -76,6 +76,16 @@ func main() {
|
||||
case "auth":
|
||||
cli.HandleAuthCommand(args)
|
||||
|
||||
// Deployment commands
|
||||
case "deploy":
|
||||
cli.HandleDeployCommand(args)
|
||||
case "deployments":
|
||||
cli.HandleDeploymentsCommand(args)
|
||||
|
||||
// Database commands
|
||||
case "db":
|
||||
cli.HandleDBCommand(args)
|
||||
|
||||
// Help
|
||||
case "help", "--help", "-h":
|
||||
showHelp()
|
||||
@ -132,19 +142,51 @@ func showHelp() {
|
||||
fmt.Printf(" auth status - Show detailed auth info\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(" -f, --format <format> - Output format: table, json (default: table)\n")
|
||||
fmt.Printf(" -t, --timeout <duration> - Operation timeout (default: 30s)\n")
|
||||
fmt.Printf(" --help, -h - Show this help message\n\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(" 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(" orama status\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