diff --git a/.github/workflows/release-apt.yml b/.github/workflows/release-apt.yml index f8b9a91..1704be9 100644 --- a/.github/workflows/release-apt.yml +++ b/.github/workflows/release-apt.yml @@ -57,9 +57,9 @@ jobs: mkdir -p build/usr/local/bin go build -ldflags "$LDFLAGS" -o build/usr/local/bin/orama cmd/cli/main.go - go build -ldflags "$LDFLAGS" -o build/usr/local/bin/debros-node cmd/node/main.go + go build -ldflags "$LDFLAGS" -o build/usr/local/bin/orama-node cmd/node/main.go # Build the entire gateway package so helper files (e.g., config parsing) are included - go build -ldflags "$LDFLAGS" -o build/usr/local/bin/debros-gateway ./cmd/gateway + go build -ldflags "$LDFLAGS" -o build/usr/local/bin/orama-gateway ./cmd/gateway - name: Create Debian package structure run: | diff --git a/.gitignore b/.gitignore index e0f6ea4..91d8a2d 100644 --- a/.gitignore +++ b/.gitignore @@ -104,7 +104,7 @@ website/ terms-agreement -cli +./cli ./inspector results/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml index c28dfba..528209d 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -2,7 +2,7 @@ # Builds and releases orama (CLI) and orama-node binaries # Publishes to: GitHub Releases, Homebrew, and apt (.deb packages) -project_name: debros-network +project_name: orama-network env: - GO111MODULE=on @@ -75,7 +75,7 @@ nfpms: - orama vendor: DeBros homepage: https://github.com/DeBrosOfficial/network - maintainer: DeBros + maintainer: DeBros description: CLI tool for the Orama decentralized network license: MIT formats: @@ -97,7 +97,7 @@ nfpms: - orama-node vendor: DeBros homepage: https://github.com/DeBrosOfficial/network - maintainer: DeBros + maintainer: DeBros description: Node daemon for the Orama decentralized network license: MIT formats: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 5599b56..55b34bc 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -32,7 +32,7 @@ This Code applies within all project spaces and when an individual is officially ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainers at: security@debros.io +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainers at: security@orama.io All complaints will be reviewed and investigated promptly and fairly. diff --git a/Makefile b/Makefile index 1b7690f..541cc9b 100644 --- a/Makefile +++ b/Makefile @@ -81,47 +81,16 @@ build: deps go build -ldflags "$(LDFLAGS) -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildVersion=$(VERSION)' -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildCommit=$(COMMIT)' -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildTime=$(DATE)'" -o bin/gateway ./cmd/gateway @echo "Build complete! Run ./bin/orama version" -# Cross-compile all binaries for Linux (used with --pre-built flag on VPS) -# Builds: DeBros binaries + Olric + CoreDNS (with rqlite plugin) + Caddy (with orama DNS module) +# Cross-compile CLI for Linux (only binary needed locally; VPS builds everything else from source) build-linux: deps - @echo "Cross-compiling all binaries for linux/amd64 (version=$(VERSION))..." + @echo "Cross-compiling CLI for linux/amd64 (version=$(VERSION))..." @mkdir -p bin-linux - GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS_LINUX)" -trimpath -o bin-linux/identity ./cmd/identity - GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS_LINUX)" -trimpath -o bin-linux/orama-node ./cmd/node GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS_LINUX)" -trimpath -o bin-linux/orama cmd/cli/main.go - GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS_LINUX)" -trimpath -o bin-linux/rqlite-mcp ./cmd/rqlite-mcp - GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS_LINUX) -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildVersion=$(VERSION)' -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildCommit=$(COMMIT)' -X 'github.com/DeBrosOfficial/network/pkg/gateway.BuildTime=$(DATE)'" -trimpath -o bin-linux/gateway ./cmd/gateway - GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS_LINUX)" -trimpath -o bin-linux/orama-cli ./cmd/cli - @echo "Building Olric for linux/amd64..." - GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o bin-linux/olric-server github.com/olric-data/olric/cmd/olric-server - @echo "Building IPFS Cluster Service for linux/amd64..." - GOOS=linux GOARCH=amd64 GOBIN=$(CURDIR)/bin-linux go install -ldflags "-s -w" -trimpath github.com/ipfs-cluster/ipfs-cluster/cmd/ipfs-cluster-service@latest - @echo "✓ All Linux binaries built in bin-linux/" + @echo "✓ CLI built at bin-linux/orama" @echo "" @echo "Next steps:" - @echo " 1. Build CoreDNS: make build-linux-coredns" - @echo " 2. Build Caddy: make build-linux-caddy" - @echo " 3. Or build all: make build-linux-all" - -# Build CoreDNS with rqlite plugin for Linux -build-linux-coredns: - @bash scripts/build-linux-coredns.sh - -# Build Caddy with orama DNS module for Linux -build-linux-caddy: - @bash scripts/build-linux-caddy.sh - -# Build everything for Linux (all binaries + CoreDNS + Caddy) -build-linux-all: build-linux build-linux-coredns build-linux-caddy - @echo "" - @echo "✅ All Linux binaries ready in bin-linux/:" - @ls -la bin-linux/ - @echo "" - @echo "Deploy to VPS:" - @echo " scp bin-linux/* ubuntu@:/home/debros/bin/" - @echo " scp bin-linux/coredns ubuntu@:/usr/local/bin/coredns" - @echo " scp bin-linux/caddy ubuntu@:/usr/bin/caddy" - @echo " sudo orama install --pre-built --no-pull ..." + @echo " ./scripts/generate-source-archive.sh" + @echo " ./bin/orama install --vps-ip --nameserver --domain ..." # Install git hooks install-hooks: diff --git a/README.md b/README.md index 51e966c..faee6ee 100644 --- a/README.md +++ b/README.md @@ -360,13 +360,13 @@ All configuration lives in `~/.orama/`: ```bash # Check status -systemctl status debros-node +systemctl status orama-node # View logs -journalctl -u debros-node -f +journalctl -u orama-node -f # Check log files -tail -f /home/debros/.orama/logs/node.log +tail -f /home/orama/.orama/logs/node.log ``` ### Port Conflicts @@ -398,7 +398,7 @@ rqlite -H localhost -p 5001 ```bash # Production reset (⚠️ DESTROYS DATA) sudo orama uninstall -sudo rm -rf /home/debros/.orama +sudo rm -rf /home/orama/.orama sudo orama install ``` diff --git a/debian/control b/debian/control index 17673f4..ddd3cf8 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Section: net Priority: optional Architecture: amd64 Depends: libc6 -Maintainer: DeBros Team +Maintainer: DeBros Team Description: Orama Network - Distributed P2P Database System Orama is a distributed peer-to-peer network that combines RQLite for distributed SQL, IPFS for content-addressed storage, diff --git a/docs/CLEAN_NODE.md b/docs/CLEAN_NODE.md index 3cdffe1..7484de9 100644 --- a/docs/CLEAN_NODE.md +++ b/docs/CLEAN_NODE.md @@ -8,11 +8,11 @@ Run this as root or with sudo on the target VPS: ```bash # 1. Stop and disable all services -sudo systemctl stop debros-node debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy 2>/dev/null -sudo systemctl disable debros-node debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy 2>/dev/null +sudo systemctl stop orama-node orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy 2>/dev/null +sudo systemctl disable orama-node orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy 2>/dev/null # 2. Remove systemd service files -sudo rm -f /etc/systemd/system/debros-*.service +sudo rm -f /etc/systemd/system/orama-*.service sudo rm -f /etc/systemd/system/coredns.service sudo rm -f /etc/systemd/system/caddy.service sudo systemctl daemon-reload @@ -31,14 +31,14 @@ sudo ufw --force reset sudo ufw allow 22/tcp sudo ufw --force enable -# 5. Remove debros user and home directory -sudo userdel -r debros 2>/dev/null -sudo rm -rf /home/debros +# 5. Remove orama user and home directory +sudo userdel -r orama 2>/dev/null +sudo rm -rf /home/orama # 6. Remove sudoers files -sudo rm -f /etc/sudoers.d/debros-access -sudo rm -f /etc/sudoers.d/debros-deployments -sudo rm -f /etc/sudoers.d/debros-wireguard +sudo rm -f /etc/sudoers.d/orama-access +sudo rm -f /etc/sudoers.d/orama-deployments +sudo rm -f /etc/sudoers.d/orama-wireguard # 7. Remove CoreDNS config sudo rm -rf /etc/coredns @@ -62,17 +62,17 @@ echo "Node cleaned. Ready for fresh install." | Category | Paths | |----------|-------| -| **User** | `debros` system user and `/home/debros/` | -| **App data** | `/home/debros/.orama/` (configs, secrets, logs, IPFS, RQLite, Olric) | -| **Source code** | `/home/debros/src/` | -| **Binaries** | `/home/debros/bin/orama-node`, `/home/debros/bin/gateway` | -| **Systemd** | `debros-*.service`, `coredns.service`, `caddy.service`, `orama-deploy-*.service` | +| **User** | `orama` system user and `/home/orama/` | +| **App data** | `/home/orama/.orama/` (configs, secrets, logs, IPFS, RQLite, Olric) | +| **Source code** | `/home/orama/src/` | +| **Binaries** | `/home/orama/bin/orama-node`, `/home/orama/bin/gateway` | +| **Systemd** | `orama-*.service`, `coredns.service`, `caddy.service`, `orama-deploy-*.service` | | **WireGuard** | `/etc/wireguard/wg0.conf`, `wg-quick@wg0` systemd unit | | **Firewall** | All UFW rules (reset to default + SSH only) | -| **Sudoers** | `/etc/sudoers.d/debros-*` | +| **Sudoers** | `/etc/sudoers.d/orama-*` | | **CoreDNS** | `/etc/coredns/Corefile` | | **Caddy** | `/etc/caddy/Caddyfile`, `/var/lib/caddy/` (TLS certs) | -| **Anyone Relay** | `debros-anyone-relay.service`, `debros-anyone-client.service` | +| **Anyone Relay** | `orama-anyone-relay.service`, `orama-anyone-client.service` | | **Temp files** | `/tmp/orama`, `/tmp/network-source.*`, build dirs | ## What This Does NOT Remove @@ -121,18 +121,18 @@ for entry in "${NODES[@]}"; do IFS=: read -r userhost pass <<< "$entry" echo "Cleaning $userhost..." sshpass -p "$pass" ssh -o StrictHostKeyChecking=no "$userhost" 'bash -s' << 'CLEAN' -sudo systemctl stop debros-node debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy 2>/dev/null -sudo systemctl disable debros-node debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy 2>/dev/null -sudo rm -f /etc/systemd/system/debros-*.service /etc/systemd/system/coredns.service /etc/systemd/system/caddy.service /etc/systemd/system/orama-deploy-*.service +sudo systemctl stop orama-node orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy 2>/dev/null +sudo systemctl disable orama-node orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy 2>/dev/null +sudo rm -f /etc/systemd/system/orama-*.service /etc/systemd/system/coredns.service /etc/systemd/system/caddy.service /etc/systemd/system/orama-deploy-*.service sudo systemctl daemon-reload sudo systemctl stop wg-quick@wg0 2>/dev/null sudo wg-quick down wg0 2>/dev/null sudo systemctl disable wg-quick@wg0 2>/dev/null sudo rm -f /etc/wireguard/wg0.conf sudo ufw --force reset && sudo ufw allow 22/tcp && sudo ufw --force enable -sudo userdel -r debros 2>/dev/null -sudo rm -rf /home/debros -sudo rm -f /etc/sudoers.d/debros-access /etc/sudoers.d/debros-deployments /etc/sudoers.d/debros-wireguard +sudo userdel -r orama 2>/dev/null +sudo rm -rf /home/orama +sudo rm -f /etc/sudoers.d/orama-access /etc/sudoers.d/orama-deployments /etc/sudoers.d/orama-wireguard sudo rm -rf /etc/coredns /etc/caddy /var/lib/caddy sudo rm -f /tmp/orama /tmp/network-source.tar.gz sudo rm -rf /tmp/network-extract /tmp/coredns-build /tmp/caddy-build diff --git a/docs/COMMON_PROBLEMS.md b/docs/COMMON_PROBLEMS.md index 17ce745..fadd44d 100644 --- a/docs/COMMON_PROBLEMS.md +++ b/docs/COMMON_PROBLEMS.md @@ -41,7 +41,7 @@ You can find peer public keys with `wg show wg0`. Check the Olric config on each node: ```bash -cat /home/debros/.orama/data/namespaces//configs/olric-*.yaml +cat /home/orama/.orama/data/namespaces//configs/olric-*.yaml ``` If `bindAddr` is `0.0.0.0`, the node will try to bind to IPv6 on dual-stack hosts, breaking memberlist gossip. @@ -53,7 +53,7 @@ This was fixed in code (BindAddr validation in `SpawnOlric`), so new namespaces ### Check 3: Olric logs show "Failed UDP ping" constantly ```bash -journalctl -u debros-namespace-olric@.service --no-pager -n 30 +journalctl -u orama-namespace-olric@.service --no-pager -n 30 ``` If every UDP ping fails but TCP stream connections succeed, it's the WireGuard packet loss issue (see Check 1). @@ -69,7 +69,7 @@ If every UDP ping fails but TCP stream connections succeed, it's the WireGuard p **Fix:** Edit the gateway config manually: ```bash -vim /home/debros/.orama/data/namespaces//configs/gateway-*.yaml +vim /home/orama/.orama/data/namespaces//configs/gateway-*.yaml ``` Add/fix: @@ -95,7 +95,7 @@ This was fixed in code, so new namespaces get the correct config. **Check:** ```bash -ls /home/debros/.orama/data/namespaces//cluster-state.json +ls /home/orama/.orama/data/namespaces//cluster-state.json ``` If the file doesn't exist, the node can't restore the namespace. @@ -119,14 +119,14 @@ This was fixed in code — `ProvisionCluster` now saves state to all nodes (incl **Symptom:** After `orama upgrade --restart` or `orama prod restart`, namespace gateway/olric/rqlite services don't start. -**Cause:** `orama prod stop` disables systemd template services (`debros-namespace-gateway@.service`). They have `PartOf=debros-node.service`, but that only propagates restart to **enabled** services. +**Cause:** `orama prod stop` disables systemd template services (`orama-namespace-gateway@.service`). They have `PartOf=orama-node.service`, but that only propagates restart to **enabled** services. **Fix:** Re-enable the services before restarting: ```bash -systemctl enable debros-namespace-rqlite@.service -systemctl enable debros-namespace-olric@.service -systemctl enable debros-namespace-gateway@.service +systemctl enable orama-namespace-rqlite@.service +systemctl enable orama-namespace-olric@.service +systemctl enable orama-namespace-gateway@.service sudo orama prod restart ``` @@ -153,8 +153,8 @@ ssh -n user@host 'command' ## General Debugging Tips - **Always use `sudo orama prod restart`** instead of raw `systemctl` commands -- **Namespace data lives at:** `/home/debros/.orama/data/namespaces//` -- **Check service logs:** `journalctl -u debros-namespace-olric@.service --no-pager -n 50` +- **Namespace data lives at:** `/home/orama/.orama/data/namespaces//` +- **Check service logs:** `journalctl -u orama-namespace-olric@.service --no-pager -n 50` - **Check WireGuard:** `wg show wg0` — look for recent handshakes and transfer bytes - **Check gateway health:** `curl http://localhost:/v1/health` from the node itself - **Node IPs:** Check `scripts/remote-nodes.conf` for credentials, `wg show wg0` for WG IPs diff --git a/docs/DEPLOYMENT_GUIDE.md b/docs/DEPLOYMENT_GUIDE.md index 89dc3ac..730f0eb 100644 --- a/docs/DEPLOYMENT_GUIDE.md +++ b/docs/DEPLOYMENT_GUIDE.md @@ -369,7 +369,7 @@ 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 +# File Path: /home/orama/.orama/data/sqlite/your-namespace/my-database.db ``` ### Executing Queries @@ -588,7 +588,7 @@ 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" + dbPath = "/home/orama/.orama/data/sqlite/" + os.Getenv("NAMESPACE") + "/myapp-db.db" } var err error diff --git a/docs/DEVNET_INSTALL.md b/docs/DEVNET_INSTALL.md index 003c2e1..7467aea 100644 --- a/docs/DEVNET_INSTALL.md +++ b/docs/DEVNET_INSTALL.md @@ -41,7 +41,7 @@ Install nodes **one at a time**, waiting for each to complete before starting th ```bash # SSH: @ -sudo orama install --no-pull --pre-built \ +sudo orama install \ --vps-ip \ --domain \ --base-domain \ @@ -58,7 +58,7 @@ orama invite --expiry 24h ```bash # SSH: @ -sudo orama install --no-pull --pre-built \ +sudo orama install \ --join http:// --token \ --vps-ip \ --domain \ @@ -77,7 +77,7 @@ sudo orama install --no-pull --pre-built \ ```bash # SSH: @ -sudo orama install --no-pull --pre-built \ +sudo orama install \ --join http:// --token \ --vps-ip \ --domain \ @@ -96,7 +96,7 @@ sudo orama install --no-pull --pre-built \ ```bash # SSH: @ -sudo orama install --no-pull --pre-built \ +sudo orama install \ --join http:// --token \ --vps-ip \ --domain node4. \ @@ -115,7 +115,7 @@ sudo orama install --no-pull --pre-built \ ```bash # SSH: @ -sudo orama install --no-pull --pre-built \ +sudo orama install \ --join http:// --token \ --vps-ip \ --domain node5. \ @@ -134,7 +134,7 @@ sudo orama install --no-pull --pre-built \ ```bash # SSH: @ -sudo orama install --no-pull --pre-built \ +sudo orama install \ --join http:// --token \ --vps-ip \ --domain node6. \ @@ -155,5 +155,5 @@ curl -s http://localhost:5001/status | jq -r '.store.raft.state, .store.raft.num curl -s http://localhost:6001/health # Check Anyone relay (on nodes with relays) -systemctl status debros-anyone-relay +systemctl status orama-anyone-relay ``` diff --git a/docs/DEV_DEPLOY.md b/docs/DEV_DEPLOY.md index bfe3804..e4786e1 100644 --- a/docs/DEV_DEPLOY.md +++ b/docs/DEV_DEPLOY.md @@ -28,83 +28,29 @@ make test ## Deploying to VPS -There are two deployment workflows: **development** (fast iteration, no git required) and **production** (via git). +Source is always deployed via SCP (no git on VPS). The CLI is the only binary cross-compiled locally; everything else is built from source on the VPS. -### Development Deployment (Fast Iteration) - -Use this when iterating quickly — no need to commit or push to git. +### Deploy Workflow ```bash -# 1. Build the CLI for Linux -GOOS=linux GOARCH=amd64 go build -o orama-cli-linux ./cmd/cli +# 1. Cross-compile the CLI for Linux +make build-linux -# 2. Generate a source archive (excludes .git, node_modules, bin/, etc.) +# 2. Generate a source archive (includes CLI binary + full source) ./scripts/generate-source-archive.sh # Creates: /tmp/network-source.tar.gz -# 3. Copy CLI and source to the VPS -sshpass -p '' scp -o StrictHostKeyChecking=no orama-cli-linux ubuntu@:/tmp/orama -sshpass -p '' scp -o StrictHostKeyChecking=no /tmp/network-source.tar.gz ubuntu@:/tmp/ +# 3. Install on a new VPS (handles SCP, extract, and remote install automatically) +./bin/orama install --vps-ip --nameserver --domain --base-domain -# 4. On the VPS: extract source and install the CLI -ssh ubuntu@ -sudo rm -rf /home/debros/src && sudo mkdir -p /home/debros/src -sudo tar xzf /tmp/network-source.tar.gz -C /home/debros/src -sudo chown -R debros:debros /home/debros/src -sudo mv /tmp/orama /usr/local/bin/orama && sudo chmod +x /usr/local/bin/orama - -# 5. Upgrade using local source (skips git pull) -sudo orama upgrade --no-pull --restart +# Or upgrade an existing VPS +./bin/orama upgrade --restart ``` -### Development Deployment with Pre-Built Binaries (Fastest) - -Cross-compile everything locally and skip all Go compilation on the VPS. This is significantly faster because your local machine compiles much faster than the VPS. - -```bash -# 1. Cross-compile all binaries for Linux (DeBros + Olric + CoreDNS + Caddy) -make build-linux-all -# Outputs everything to bin-linux/ - -# 2. Generate a single deploy archive (source + pre-built binaries) -./scripts/generate-source-archive.sh -# Creates: /tmp/network-source.tar.gz (includes bin-linux/ if present) - -# 3. Copy the single archive to the VPS -sshpass -p '' scp -o StrictHostKeyChecking=no /tmp/network-source.tar.gz ubuntu@:/tmp/ - -# 4. Extract and install everything on the VPS -sshpass -p '' ssh -o StrictHostKeyChecking=no ubuntu@ \ - 'sudo bash -s' < scripts/extract-deploy.sh - -# 5. Install/upgrade with --pre-built (skips ALL Go compilation on VPS) -sudo orama install --no-pull --pre-built --vps-ip ... -# or -sudo orama upgrade --no-pull --pre-built --restart -``` - -**What `--pre-built` skips:** Go installation, `make build`, Olric `go install`, CoreDNS build, Caddy/xcaddy build. - -**What `--pre-built` still runs:** apt dependencies, RQLite/IPFS/IPFS Cluster downloads (pre-built binary downloads, fast), Anyone relay setup, config generation, systemd service creation. - -### Production Deployment (Via Git) - -For production releases — pulls source from GitHub on the VPS. - -```bash -# 1. Commit and push your changes -git push origin - -# 2. Build the CLI for Linux -GOOS=linux GOARCH=amd64 go build -o orama-cli-linux ./cmd/cli - -# 3. Deploy the CLI to the VPS -sshpass -p '' scp orama-cli-linux ubuntu@:/tmp/orama -ssh ubuntu@ "sudo mv /tmp/orama /usr/local/bin/orama && sudo chmod +x /usr/local/bin/orama" - -# 4. Run upgrade (downloads source from GitHub) -ssh ubuntu@ "sudo orama upgrade --branch --restart" -``` +The `orama install` command automatically: +1. Uploads the source archive via SCP +2. Extracts source to `/home/orama/src` and installs the CLI to `/usr/local/bin/orama` +3. Runs `orama install` on the VPS which builds all binaries from source (Go, CoreDNS, Caddy, Olric, etc.) ### Upgrading a Multi-Node Cluster (CRITICAL) @@ -115,10 +61,10 @@ ssh ubuntu@ "sudo orama upgrade --branch --restart" Always upgrade nodes **one at a time**, waiting for each to rejoin before proceeding: ```bash -# 1. Build locally -make build-linux-all +# 1. Build CLI + generate archive +make build-linux ./scripts/generate-source-archive.sh -# Creates: /tmp/network-source.tar.gz (includes bin-linux/) +# Creates: /tmp/network-source.tar.gz # 2. Upload to ONE node first (the "hub" node) sshpass -p '' scp /tmp/network-source.tar.gz ubuntu@:/tmp/ @@ -139,8 +85,7 @@ done ssh ubuntu@ 'curl -s http://localhost:5001/status | jq -r .store.raft.state' # 6. Upgrade FOLLOWER nodes one at a time -# First stop services, then upgrade, which restarts them -ssh ubuntu@ 'sudo orama prod stop && sudo orama upgrade --no-pull --pre-built --restart' +ssh ubuntu@ 'sudo orama prod stop && sudo orama upgrade --restart' # Wait for rejoin before proceeding to next node ssh ubuntu@ 'curl -s http://localhost:5001/status | jq -r .store.raft.num_peers' @@ -149,7 +94,7 @@ ssh ubuntu@ 'curl -s http://localhost:5001/status | jq -r .store.raft # Repeat for each follower... # 7. Upgrade the LEADER node last -ssh ubuntu@ 'sudo orama prod stop && sudo orama upgrade --no-pull --pre-built --restart' +ssh ubuntu@ 'sudo orama prod stop && sudo orama upgrade --restart' ``` #### What NOT to Do @@ -157,7 +102,7 @@ ssh ubuntu@ 'sudo orama prod stop && sudo orama upgrade --no-pull --p - **DON'T** stop all nodes, replace binaries, then start all nodes - **DON'T** run `orama upgrade --restart` on multiple nodes in parallel - **DON'T** clear RQLite data directories unless doing a full cluster rebuild -- **DON'T** use `systemctl stop debros-node` on multiple nodes simultaneously +- **DON'T** use `systemctl stop orama-node` on multiple nodes simultaneously #### Recovery from Cluster Split @@ -168,8 +113,8 @@ If nodes get stuck in "Candidate" state or show "leader not found" errors: 3. On each other node, clear RQLite data and restart: ```bash sudo orama prod stop - sudo rm -rf /home/debros/.orama/data/rqlite - sudo systemctl start debros-node + sudo rm -rf /home/orama/.orama/data/rqlite + sudo systemctl start orama-node ``` 4. The node should automatically rejoin using its configured `rqlite_join_address` @@ -180,7 +125,7 @@ ps aux | grep rqlited ``` If `-join` is missing, the node bootstrapped standalone. You'll need to either: -- Restart debros-node (it should detect empty data and use join) +- Restart orama-node (it should detect empty data and use join) - Or do a full cluster rebuild from CLEAN_NODE.md ### Deploying to Multiple Nodes @@ -201,9 +146,6 @@ To deploy to all nodes, repeat steps 3-5 (dev) or 3-4 (production) for each VPS | `--nameserver` | Configure this node as a nameserver (CoreDNS + Caddy) | | `--join ` | Join existing cluster via HTTPS URL (e.g., `https://node1.example.com`) | | `--token ` | Invite token for joining (from `orama invite` on existing node) | -| `--branch ` | Git branch to use (default: main) | -| `--no-pull` | Skip git clone/pull, use existing `/home/debros/src` | -| `--pre-built` | Skip all Go compilation, use pre-built binaries already on disk (see above) | | `--force` | Force reconfiguration even if already installed | | `--skip-firewall` | Skip UFW firewall setup | | `--skip-checks` | Skip minimum resource checks (RAM/CPU) | @@ -234,9 +176,6 @@ To deploy to all nodes, repeat steps 3-5 (dev) or 3-4 (production) for each VPS | Flag | Description | |------|-------------| -| `--branch ` | Git branch to pull from | -| `--no-pull` | Skip git pull, use existing source | -| `--pre-built` | Skip all Go compilation, use pre-built binaries already on disk | | `--restart` | Restart all services after upgrade | | `--anyone-relay` | Enable Anyone relay (same flags as install) | | `--anyone-bandwidth ` | Limit relay to N% of VPS bandwidth (default: 30, 0=unlimited) | @@ -247,7 +186,7 @@ To deploy to all nodes, repeat steps 3-5 (dev) or 3-4 (production) for each VPS Use these commands to manage services on production nodes: ```bash -# Stop all services (debros-node, coredns, caddy) +# Stop all services (orama-node, coredns, caddy) sudo orama prod stop # Start all services @@ -318,12 +257,7 @@ Before running `orama install` on a VPS, ensure: sudo systemctl stop ipfs ``` -3. **Ensure `make` is installed.** Required for building CoreDNS and Caddy from source: - ```bash - sudo apt-get install -y make - ``` - -4. **Stop any service on port 53** (for nameserver nodes). The installer handles `systemd-resolved` automatically, but other DNS services (like `bind9` or `dnsmasq`) must be stopped manually. +3. **Stop any service on port 53** (for nameserver nodes). The installer handles `systemd-resolved` automatically, but other DNS services (like `bind9` or `dnsmasq`) must be stopped manually. ## Recovering from Failed Joins diff --git a/docs/INSPECTOR.md b/docs/INSPECTOR.md index c8dcf39..57224bb 100644 --- a/docs/INSPECTOR.md +++ b/docs/INSPECTOR.md @@ -62,7 +62,7 @@ Multiple subsystems can be combined: `--subsystem rqlite,olric,dns` | **ipfs** | Daemon active, cluster active, swarm peer count, cluster peer count, cluster errors, repo usage %, swarm key present, bootstrap list empty, cross-node version consistency | | **dns** | CoreDNS active, Caddy active, ports (53/80/443), memory, restart count, log errors, Corefile exists, SOA/NS/wildcard/base-A resolution, TLS cert expiry, cross-node nameserver availability | | **wireguard** | Interface up, service active, correct 10.0.0.x IP, listen port 51820, peer count vs expected, MTU 1420, config exists + permissions 600, peer handshakes (fresh/stale/never), peer traffic, catch-all route detection, cross-node peer count + MTU consistency | -| **system** | Core services (debros-node, rqlite, olric, ipfs, ipfs-cluster, wg-quick), nameserver services (coredns, caddy), failed systemd units, memory/disk/inode usage, load average, OOM kills, swap, UFW active, process user (debros), panic count, expected ports | +| **system** | Core services (orama-node, rqlite, olric, ipfs, ipfs-cluster, wg-quick), nameserver services (coredns, caddy), failed systemd units, memory/disk/inode usage, load average, OOM kills, swap, UFW active, process user (orama), panic count, expected ports | | **network** | Internet reachability, default route, WireGuard route, TCP connection count, TIME_WAIT count, TCP retransmission rate, WireGuard mesh ping (all peers) | | **namespace** | Per-namespace: RQLite up + raft state + readyz, Olric memberlist, Gateway HTTP health. Cross-namespace: all-healthy check, RQLite quorum per namespace | diff --git a/e2e/env.go b/e2e/env.go index de551a8..5d874a3 100644 --- a/e2e/env.go +++ b/e2e/env.go @@ -297,7 +297,7 @@ func GetRQLiteNodes() []string { // queryAPIKeyFromRQLite queries the SQLite database directly for an API key func queryAPIKeyFromRQLite() (string, error) { // 1. Check environment variable first - if envKey := os.Getenv("DEBROS_API_KEY"); envKey != "" { + if envKey := os.Getenv("ORAMA_API_KEY"); envKey != "" { return envKey, nil } @@ -424,7 +424,7 @@ func GetAPIKey() string { cacheMutex.RUnlock() // 1. Check env var - if envKey := os.Getenv("DEBROS_API_KEY"); envKey != "" { + if envKey := os.Getenv("ORAMA_API_KEY"); envKey != "" { cacheMutex.Lock() apiKeyCache = envKey cacheMutex.Unlock() @@ -1188,8 +1188,8 @@ type E2ETestEnv struct { GatewayURL string APIKey string Namespace string - BaseDomain string // Domain for deployment routing (e.g., "dbrs.space") - Config *E2EConfig // Full E2E configuration (for production tests) + BaseDomain string // Domain for deployment routing (e.g., "dbrs.space") + Config *E2EConfig // Full E2E configuration (for production tests) HTTPClient *http.Client SkipCleanup bool } diff --git a/e2e/integration/domain_routing_test.go b/e2e/integration/domain_routing_test.go index 78ff76d..108770d 100644 --- a/e2e/integration/domain_routing_test.go +++ b/e2e/integration/domain_routing_test.go @@ -57,16 +57,16 @@ func TestDomainRouting_BasicRouting(t *testing.T) { t.Logf("✓ Standard domain routing works: %s", domain) }) - t.Run("Non-debros domain passes through", func(t *testing.T) { - // Request with non-debros domain should not route to deployment + t.Run("Non-orama domain passes through", func(t *testing.T) { + // Request with non-orama domain should not route to deployment resp := e2e.TestDeploymentWithHostHeader(t, env, "example.com", "/") defer resp.Body.Close() // Should either return 404 or pass to default handler assert.NotEqual(t, http.StatusOK, resp.StatusCode, - "Non-debros domain should not route to deployment") + "Non-orama domain should not route to deployment") - t.Logf("✓ Non-debros domains correctly pass through (status: %d)", resp.StatusCode) + t.Logf("✓ Non-orama domains correctly pass through (status: %d)", resp.StatusCode) }) t.Run("API paths bypass domain routing", func(t *testing.T) { diff --git a/e2e/shared/network_http_test.go b/e2e/shared/network_http_test.go index ad1b390..a149e23 100644 --- a/e2e/shared/network_http_test.go +++ b/e2e/shared/network_http_test.go @@ -118,7 +118,7 @@ func TestNetwork_ProxyAnonSuccess(t *testing.T) { Body: map[string]interface{}{ "url": "https://httpbin.org/get", "method": "GET", - "headers": map[string]string{"User-Agent": "DeBros-E2E-Test/1.0"}, + "headers": map[string]string{"User-Agent": "Orama-E2E-Test/1.0"}, }, } @@ -178,7 +178,7 @@ func TestNetwork_ProxyAnonPostRequest(t *testing.T) { Body: map[string]interface{}{ "url": "https://httpbin.org/post", "method": "POST", - "headers": map[string]string{"User-Agent": "DeBros-E2E-Test/1.0"}, + "headers": map[string]string{"User-Agent": "Orama-E2E-Test/1.0"}, "body": "test_data", }, } diff --git a/migrations/001_initial.sql b/migrations/001_initial.sql index 586c122..29036d1 100644 --- a/migrations/001_initial.sql +++ b/migrations/001_initial.sql @@ -1,4 +1,4 @@ --- DeBros Gateway - Initial database schema (SQLite/RQLite dialect) +-- Orama Gateway - Initial database schema (SQLite/RQLite dialect) -- This file scaffolds core tables used by the HTTP gateway for auth, observability, and namespacing. -- Apply via your migration tooling or manual execution in RQLite. diff --git a/migrations/002_core.sql b/migrations/002_core.sql index 790c506..9b5ddc1 100644 --- a/migrations/002_core.sql +++ b/migrations/002_core.sql @@ -1,4 +1,4 @@ --- DeBros Gateway - Core schema (Phase 2) +-- Orama Gateway - Core schema (Phase 2) -- Adds apps, nonces, subscriptions, refresh_tokens, audit_events, namespace_ownership -- SQLite/RQLite dialect diff --git a/migrations/003_wallet_api_keys.sql b/migrations/003_wallet_api_keys.sql index 6c9e725..13c54be 100644 --- a/migrations/003_wallet_api_keys.sql +++ b/migrations/003_wallet_api_keys.sql @@ -1,4 +1,4 @@ --- DeBros Gateway - Wallet to API Key linkage (Phase 3) +-- Orama Gateway - Wallet to API Key linkage (Phase 3) -- Ensures one API key per (namespace, wallet) and enables lookup BEGIN; diff --git a/pkg/auth/credentials.go b/pkg/auth/credentials.go index 926978a..c8bc5d8 100644 --- a/pkg/auth/credentials.go +++ b/pkg/auth/credentials.go @@ -169,10 +169,10 @@ func (creds *Credentials) UpdateLastUsed() { // GetDefaultGatewayURL returns the default gateway URL from environment config, env vars, or fallback func GetDefaultGatewayURL() string { // Check environment variables first (for backwards compatibility) - if envURL := os.Getenv("DEBROS_GATEWAY_URL"); envURL != "" { + if envURL := os.Getenv("ORAMA_GATEWAY_URL"); envURL != "" { return envURL } - if envURL := os.Getenv("DEBROS_GATEWAY"); envURL != "" { + if envURL := os.Getenv("ORAMA_GATEWAY"); envURL != "" { return envURL } diff --git a/pkg/auth/wallet.go b/pkg/auth/wallet.go index 5be457c..473871f 100644 --- a/pkg/auth/wallet.go +++ b/pkg/auth/wallet.go @@ -225,7 +225,7 @@ func (as *AuthServer) handleHealth(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]string{ "status": "ok", - "server": "debros-auth-callback", + "server": "orama-auth-callback", }) } diff --git a/pkg/certutil/cert_manager.go b/pkg/certutil/cert_manager.go index 7a23949..57cce40 100644 --- a/pkg/certutil/cert_manager.go +++ b/pkg/certutil/cert_manager.go @@ -115,8 +115,8 @@ func (cm *CertificateManager) generateCACertificate() ([]byte, []byte, error) { template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ - CommonName: "DeBros Network Root CA", - Organization: []string{"DeBros"}, + CommonName: "Orama Network Root CA", + Organization: []string{"Orama"}, }, NotBefore: time.Now(), NotAfter: time.Now().AddDate(10, 0, 0), // 10 year validity diff --git a/pkg/cli/auth_commands.go b/pkg/cli/auth_commands.go index b35b0e9..934d91a 100644 --- a/pkg/cli/auth_commands.go +++ b/pkg/cli/auth_commands.go @@ -66,7 +66,7 @@ func showAuthHelp() { fmt.Printf(" orama auth whoami # Check who you're logged in as\n") fmt.Printf(" orama auth logout # Clear all stored credentials\n\n") fmt.Printf("Environment Variables:\n") - fmt.Printf(" DEBROS_GATEWAY_URL - Gateway URL (overrides environment config)\n\n") + fmt.Printf(" ORAMA_GATEWAY_URL - Gateway URL (overrides environment config)\n\n") fmt.Printf("Authentication Flow (RootWallet):\n") fmt.Printf(" 1. Run 'orama auth login'\n") fmt.Printf(" 2. Your wallet address is read from RootWallet automatically\n") @@ -295,7 +295,7 @@ func handleAuthStatus() { // Uses the active environment or allows entering a custom domain func promptForGatewayURL() string { // Check environment variable first (allows override without prompting) - if url := os.Getenv("DEBROS_GATEWAY_URL"); url != "" { + if url := os.Getenv("ORAMA_GATEWAY_URL"); url != "" { return url } @@ -346,7 +346,7 @@ func promptForGatewayURL() string { // Used by other commands that don't need interactive node selection func getGatewayURL() string { // Check environment variable first (for backwards compatibility) - if url := os.Getenv("DEBROS_GATEWAY_URL"); url != "" { + if url := os.Getenv("ORAMA_GATEWAY_URL"); url != "" { return url } diff --git a/pkg/cli/cluster/commands.go b/pkg/cli/cluster/commands.go new file mode 100644 index 0000000..68fc725 --- /dev/null +++ b/pkg/cli/cluster/commands.go @@ -0,0 +1,80 @@ +package cluster + +import ( + "fmt" + "os" +) + +// HandleCommand handles cluster subcommands. +func HandleCommand(args []string) { + if len(args) == 0 { + ShowHelp() + return + } + + subcommand := args[0] + subargs := args[1:] + + switch subcommand { + case "status": + HandleStatus(subargs) + case "health": + HandleHealth(subargs) + case "rqlite": + HandleRQLite(subargs) + case "watch": + HandleWatch(subargs) + case "help": + ShowHelp() + default: + fmt.Fprintf(os.Stderr, "Unknown cluster subcommand: %s\n", subcommand) + ShowHelp() + os.Exit(1) + } +} + +// hasFlag checks if a flag is present in the args slice. +func hasFlag(args []string, flag string) bool { + for _, a := range args { + if a == flag { + return true + } + } + return false +} + +// getFlagValue returns the value of a flag from the args slice. +// Returns empty string if the flag is not found or has no value. +func getFlagValue(args []string, flag string) string { + for i, a := range args { + if a == flag && i+1 < len(args) { + return args[i+1] + } + } + return "" +} + +// ShowHelp displays help information for cluster commands. +func ShowHelp() { + fmt.Printf("Cluster Management Commands\n\n") + fmt.Printf("Usage: orama cluster [options]\n\n") + fmt.Printf("Subcommands:\n") + fmt.Printf(" status - Show cluster node status (RQLite + Olric)\n") + fmt.Printf(" Options:\n") + fmt.Printf(" --all - SSH into all nodes from remote-nodes.conf (TODO)\n") + fmt.Printf(" health - Run cluster health checks\n") + fmt.Printf(" rqlite - RQLite-specific commands\n") + fmt.Printf(" status - Show detailed Raft state for local node\n") + fmt.Printf(" voters - Show current voter list\n") + fmt.Printf(" backup [--output FILE] - Trigger manual backup\n") + fmt.Printf(" watch - Live cluster status monitor\n") + fmt.Printf(" Options:\n") + fmt.Printf(" --interval SECONDS - Refresh interval (default: 10)\n\n") + fmt.Printf("Examples:\n") + fmt.Printf(" orama cluster status\n") + fmt.Printf(" orama cluster health\n") + fmt.Printf(" orama cluster rqlite status\n") + fmt.Printf(" orama cluster rqlite voters\n") + fmt.Printf(" orama cluster rqlite backup --output /tmp/backup.db\n") + fmt.Printf(" orama cluster watch --interval 5\n") +} diff --git a/pkg/cli/cluster/health.go b/pkg/cli/cluster/health.go new file mode 100644 index 0000000..60b541f --- /dev/null +++ b/pkg/cli/cluster/health.go @@ -0,0 +1,244 @@ +package cluster + +import ( + "fmt" + "os" +) + +// checkResult represents the outcome of a single health check. +type checkResult struct { + Name string + Status string // "PASS", "FAIL", "WARN" + Detail string +} + +// HandleHealth handles the "orama cluster health" command. +func HandleHealth(args []string) { + fmt.Printf("Cluster Health Check\n") + fmt.Printf("====================\n\n") + + var results []checkResult + + // Check 1: RQLite reachable + status, err := queryRQLiteStatus() + if err != nil { + results = append(results, checkResult{ + Name: "RQLite reachable", + Status: "FAIL", + Detail: fmt.Sprintf("Cannot connect to RQLite: %v", err), + }) + printHealthResults(results) + os.Exit(1) + return + } + results = append(results, checkResult{ + Name: "RQLite reachable", + Status: "PASS", + Detail: fmt.Sprintf("HTTP API responding on %s", status.HTTP.Address), + }) + + // Check 2: Raft state is leader or follower (not candidate or shutdown) + raftState := status.Store.Raft.State + switch raftState { + case "Leader", "Follower": + results = append(results, checkResult{ + Name: "Raft state healthy", + Status: "PASS", + Detail: fmt.Sprintf("Node is %s", raftState), + }) + case "Candidate": + results = append(results, checkResult{ + Name: "Raft state healthy", + Status: "WARN", + Detail: "Node is Candidate (election in progress)", + }) + default: + results = append(results, checkResult{ + Name: "Raft state healthy", + Status: "FAIL", + Detail: fmt.Sprintf("Node is in unexpected state: %s", raftState), + }) + } + + // Check 3: Leader exists + if status.Store.Raft.Leader != "" { + results = append(results, checkResult{ + Name: "Leader exists", + Status: "PASS", + Detail: fmt.Sprintf("Leader: %s", status.Store.Raft.Leader), + }) + } else { + results = append(results, checkResult{ + Name: "Leader exists", + Status: "FAIL", + Detail: "No leader detected in Raft cluster", + }) + } + + // Check 4: Applied index is advancing (commit == applied means caught up) + if status.Store.Raft.AppliedIndex >= status.Store.Raft.CommitIndex { + results = append(results, checkResult{ + Name: "Log replication", + Status: "PASS", + Detail: fmt.Sprintf("Applied index (%d) >= commit index (%d)", + status.Store.Raft.AppliedIndex, status.Store.Raft.CommitIndex), + }) + } else { + lag := status.Store.Raft.CommitIndex - status.Store.Raft.AppliedIndex + severity := "WARN" + if lag > 1000 { + severity = "FAIL" + } + results = append(results, checkResult{ + Name: "Log replication", + Status: severity, + Detail: fmt.Sprintf("Applied index (%d) behind commit index (%d) by %d entries", + status.Store.Raft.AppliedIndex, status.Store.Raft.CommitIndex, lag), + }) + } + + // Check 5: Query nodes to validate cluster membership + nodes, err := queryRQLiteNodes(true) + if err != nil { + results = append(results, checkResult{ + Name: "Cluster nodes reachable", + Status: "FAIL", + Detail: fmt.Sprintf("Cannot query /nodes: %v", err), + }) + } else { + totalNodes := len(nodes) + voters := 0 + nonVoters := 0 + reachable := 0 + leaders := 0 + + for _, node := range nodes { + if node.Voter { + voters++ + } else { + nonVoters++ + } + if node.Reachable { + reachable++ + } + if node.Leader { + leaders++ + } + } + + // Check 5a: Node count + results = append(results, checkResult{ + Name: "Cluster membership", + Status: "PASS", + Detail: fmt.Sprintf("%d nodes (%d voters, %d non-voters)", totalNodes, voters, nonVoters), + }) + + // Check 5b: All nodes reachable + if reachable == totalNodes { + results = append(results, checkResult{ + Name: "All nodes reachable", + Status: "PASS", + Detail: fmt.Sprintf("%d/%d nodes reachable", reachable, totalNodes), + }) + } else { + unreachable := totalNodes - reachable + results = append(results, checkResult{ + Name: "All nodes reachable", + Status: "WARN", + Detail: fmt.Sprintf("%d/%d nodes reachable (%d unreachable)", reachable, totalNodes, unreachable), + }) + } + + // Check 5c: Exactly one leader + if leaders == 1 { + results = append(results, checkResult{ + Name: "Single leader", + Status: "PASS", + Detail: "Exactly 1 leader in cluster", + }) + } else if leaders == 0 { + results = append(results, checkResult{ + Name: "Single leader", + Status: "FAIL", + Detail: "No leader found among nodes", + }) + } else { + results = append(results, checkResult{ + Name: "Single leader", + Status: "FAIL", + Detail: fmt.Sprintf("Multiple leaders detected: %d (split-brain?)", leaders), + }) + } + + // Check 5d: Quorum check (majority of voters must be reachable) + quorum := (voters / 2) + 1 + reachableVoters := 0 + for _, node := range nodes { + if node.Voter && node.Reachable { + reachableVoters++ + } + } + if reachableVoters >= quorum { + results = append(results, checkResult{ + Name: "Quorum healthy", + Status: "PASS", + Detail: fmt.Sprintf("%d/%d voters reachable (quorum requires %d)", reachableVoters, voters, quorum), + }) + } else { + results = append(results, checkResult{ + Name: "Quorum healthy", + Status: "FAIL", + Detail: fmt.Sprintf("%d/%d voters reachable (quorum requires %d)", reachableVoters, voters, quorum), + }) + } + } + + printHealthResults(results) + + // Exit with non-zero if any failures + for _, r := range results { + if r.Status == "FAIL" { + os.Exit(1) + } + } +} + +// printHealthResults prints the health check results in a formatted table. +func printHealthResults(results []checkResult) { + // Find the longest check name for alignment + maxName := 0 + for _, r := range results { + if len(r.Name) > maxName { + maxName = len(r.Name) + } + } + + for _, r := range results { + indicator := " " + switch r.Status { + case "PASS": + indicator = "PASS" + case "FAIL": + indicator = "FAIL" + case "WARN": + indicator = "WARN" + } + + fmt.Printf(" [%s] %-*s %s\n", indicator, maxName, r.Name, r.Detail) + } + fmt.Println() + + // Summary + pass, fail, warn := 0, 0, 0 + for _, r := range results { + switch r.Status { + case "PASS": + pass++ + case "FAIL": + fail++ + case "WARN": + warn++ + } + } + fmt.Printf("Summary: %d passed, %d failed, %d warnings\n", pass, fail, warn) +} diff --git a/pkg/cli/cluster/rqlite.go b/pkg/cli/cluster/rqlite.go new file mode 100644 index 0000000..0c011e3 --- /dev/null +++ b/pkg/cli/cluster/rqlite.go @@ -0,0 +1,187 @@ +package cluster + +import ( + "fmt" + "io" + "net/http" + "os" + "strings" + "time" +) + +// HandleRQLite handles the "orama cluster rqlite" subcommand group. +func HandleRQLite(args []string) { + if len(args) == 0 { + showRQLiteHelp() + return + } + + subcommand := args[0] + subargs := args[1:] + + switch subcommand { + case "status": + handleRQLiteStatus() + case "voters": + handleRQLiteVoters() + case "backup": + handleRQLiteBackup(subargs) + case "help": + showRQLiteHelp() + default: + fmt.Fprintf(os.Stderr, "Unknown rqlite subcommand: %s\n", subcommand) + showRQLiteHelp() + os.Exit(1) + } +} + +// handleRQLiteStatus shows detailed Raft state for the local node. +func handleRQLiteStatus() { + fmt.Printf("RQLite Raft Status\n") + fmt.Printf("==================\n\n") + + status, err := queryRQLiteStatus() + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + + fmt.Printf("Node Configuration\n") + fmt.Printf(" Node ID: %s\n", status.Store.NodeID) + fmt.Printf(" Raft Address: %s\n", status.Store.Address) + fmt.Printf(" HTTP Address: %s\n", status.HTTP.Address) + fmt.Printf(" Data Directory: %s\n", status.Store.Dir) + fmt.Println() + + fmt.Printf("Raft State\n") + fmt.Printf(" State: %s\n", strings.ToUpper(status.Store.Raft.State)) + fmt.Printf(" Current Term: %d\n", status.Store.Raft.Term) + fmt.Printf(" Applied Index: %d\n", status.Store.Raft.AppliedIndex) + fmt.Printf(" Commit Index: %d\n", status.Store.Raft.CommitIndex) + fmt.Printf(" Leader: %s\n", status.Store.Raft.Leader) + + if status.Store.Raft.AppliedIndex < status.Store.Raft.CommitIndex { + lag := status.Store.Raft.CommitIndex - status.Store.Raft.AppliedIndex + fmt.Printf(" Replication Lag: %d entries behind\n", lag) + } else { + fmt.Printf(" Replication Lag: none (fully caught up)\n") + } + + if status.Node.Uptime != "" { + fmt.Printf(" Uptime: %s\n", status.Node.Uptime) + } + fmt.Println() +} + +// handleRQLiteVoters shows the current voter list from /nodes. +func handleRQLiteVoters() { + fmt.Printf("RQLite Cluster Voters\n") + fmt.Printf("=====================\n\n") + + nodes, err := queryRQLiteNodes(true) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + + voters := 0 + nonVoters := 0 + + fmt.Printf("%-20s %-30s %-8s %-10s %-10s\n", + "NODE ID", "ADDRESS", "ROLE", "LEADER", "REACHABLE") + fmt.Printf("%-20s %-30s %-8s %-10s %-10s\n", + strings.Repeat("-", 20), + strings.Repeat("-", 30), + strings.Repeat("-", 8), + strings.Repeat("-", 10), + strings.Repeat("-", 10)) + + for id, node := range nodes { + nodeID := id + if len(nodeID) > 20 { + nodeID = nodeID[:17] + "..." + } + + role := "non-voter" + if node.Voter { + role = "voter" + voters++ + } else { + nonVoters++ + } + + leader := "no" + if node.Leader { + leader = "yes" + } + + reachable := "no" + if node.Reachable { + reachable = "yes" + } + + fmt.Printf("%-20s %-30s %-8s %-10s %-10s\n", + nodeID, node.Address, role, leader, reachable) + } + + fmt.Printf("\nTotal: %d voters, %d non-voters\n", voters, nonVoters) + quorum := (voters / 2) + 1 + fmt.Printf("Quorum requirement: %d/%d voters\n", quorum, voters) +} + +// handleRQLiteBackup triggers a manual backup via the RQLite backup endpoint. +func handleRQLiteBackup(args []string) { + outputFile := getFlagValue(args, "--output") + if outputFile == "" { + outputFile = fmt.Sprintf("rqlite-backup-%s.db", time.Now().Format("20060102-150405")) + } + + fmt.Printf("RQLite Backup\n") + fmt.Printf("=============\n\n") + fmt.Printf("Requesting backup from %s/db/backup ...\n", rqliteBaseURL) + + client := &http.Client{Timeout: 60 * time.Second} + resp, err := client.Get(rqliteBaseURL + "/db/backup") + if err != nil { + fmt.Fprintf(os.Stderr, "Error: cannot connect to RQLite: %v\n", err) + os.Exit(1) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(resp.Body) + fmt.Fprintf(os.Stderr, "Error: backup request returned HTTP %d: %s\n", resp.StatusCode, string(body)) + os.Exit(1) + } + + outFile, err := os.Create(outputFile) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: cannot create output file: %v\n", err) + os.Exit(1) + } + defer outFile.Close() + + written, err := io.Copy(outFile, resp.Body) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: failed to write backup: %v\n", err) + os.Exit(1) + } + + fmt.Printf("Backup saved to: %s (%d bytes)\n", outputFile, written) +} + +// showRQLiteHelp displays help for rqlite subcommands. +func showRQLiteHelp() { + fmt.Printf("RQLite Commands\n\n") + fmt.Printf("Usage: orama cluster rqlite [options]\n\n") + fmt.Printf("Subcommands:\n") + fmt.Printf(" status - Show detailed Raft state for local node\n") + fmt.Printf(" voters - Show current voter list from cluster\n") + fmt.Printf(" backup - Trigger manual database backup\n") + fmt.Printf(" Options:\n") + fmt.Printf(" --output FILE - Output file path (default: rqlite-backup-.db)\n\n") + fmt.Printf("Examples:\n") + fmt.Printf(" orama cluster rqlite status\n") + fmt.Printf(" orama cluster rqlite voters\n") + fmt.Printf(" orama cluster rqlite backup --output /tmp/backup.db\n") +} diff --git a/pkg/cli/cluster/status.go b/pkg/cli/cluster/status.go new file mode 100644 index 0000000..50bb456 --- /dev/null +++ b/pkg/cli/cluster/status.go @@ -0,0 +1,248 @@ +package cluster + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "strings" + "time" +) + +const ( + rqliteBaseURL = "http://localhost:5001" + httpTimeout = 10 * time.Second +) + +// rqliteStatus represents the relevant fields from the RQLite /status endpoint. +type rqliteStatus struct { + Store struct { + Raft struct { + State string `json:"state"` + AppliedIndex uint64 `json:"applied_index"` + CommitIndex uint64 `json:"commit_index"` + Term uint64 `json:"current_term"` + Leader string `json:"leader"` + } `json:"raft"` + Dir string `json:"dir"` + NodeID string `json:"node_id"` + Address string `json:"addr"` + } `json:"store"` + HTTP struct { + Address string `json:"addr"` + } `json:"http"` + Node struct { + Uptime string `json:"uptime"` + } `json:"node"` +} + +// rqliteNode represents a node from the /nodes endpoint. +type rqliteNode struct { + ID string `json:"id"` + Address string `json:"addr"` + Leader bool `json:"leader"` + Voter bool `json:"voter"` + Reachable bool `json:"reachable"` + Time float64 `json:"time"` + TimeS string `json:"time_s"` +} + +// HandleStatus handles the "orama cluster status" command. +func HandleStatus(args []string) { + if hasFlag(args, "--all") { + fmt.Printf("Remote node aggregation via SSH is not yet implemented.\n") + fmt.Printf("Currently showing local node status only.\n\n") + } + + fmt.Printf("Cluster Status\n") + fmt.Printf("==============\n\n") + + // Query RQLite status + status, err := queryRQLiteStatus() + if err != nil { + fmt.Fprintf(os.Stderr, "Error querying RQLite status: %v\n", err) + fmt.Printf("RQLite may not be running on this node.\n\n") + } else { + printLocalStatus(status) + } + + // Query RQLite nodes + nodes, err := queryRQLiteNodes(true) + if err != nil { + fmt.Fprintf(os.Stderr, "Error querying RQLite nodes: %v\n", err) + } else { + printNodesTable(nodes) + } + + // Query Olric status (best-effort) + printOlricStatus() +} + +// queryRQLiteStatus queries the local RQLite /status endpoint. +func queryRQLiteStatus() (*rqliteStatus, error) { + client := &http.Client{Timeout: httpTimeout} + resp, err := client.Get(rqliteBaseURL + "/status") + if err != nil { + return nil, fmt.Errorf("connect to RQLite: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read response: %w", err) + } + + var status rqliteStatus + if err := json.Unmarshal(body, &status); err != nil { + return nil, fmt.Errorf("parse response: %w", err) + } + + return &status, nil +} + +// queryRQLiteNodes queries the local RQLite /nodes endpoint. +// If includeNonVoters is true, appends ?nonvoters to the query. +func queryRQLiteNodes(includeNonVoters bool) (map[string]*rqliteNode, error) { + client := &http.Client{Timeout: httpTimeout} + + url := rqliteBaseURL + "/nodes" + if includeNonVoters { + url += "?nonvoters" + } + + resp, err := client.Get(url) + if err != nil { + return nil, fmt.Errorf("connect to RQLite: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read response: %w", err) + } + + var nodes map[string]*rqliteNode + if err := json.Unmarshal(body, &nodes); err != nil { + return nil, fmt.Errorf("parse response: %w", err) + } + + return nodes, nil +} + +// printLocalStatus prints the local node's RQLite status. +func printLocalStatus(s *rqliteStatus) { + fmt.Printf("Local Node\n") + fmt.Printf(" Node ID: %s\n", s.Store.NodeID) + fmt.Printf(" Raft Address: %s\n", s.Store.Address) + fmt.Printf(" HTTP Address: %s\n", s.HTTP.Address) + fmt.Printf(" Raft State: %s\n", strings.ToUpper(s.Store.Raft.State)) + fmt.Printf(" Raft Term: %d\n", s.Store.Raft.Term) + fmt.Printf(" Applied Index: %d\n", s.Store.Raft.AppliedIndex) + fmt.Printf(" Commit Index: %d\n", s.Store.Raft.CommitIndex) + fmt.Printf(" Leader: %s\n", s.Store.Raft.Leader) + if s.Node.Uptime != "" { + fmt.Printf(" Uptime: %s\n", s.Node.Uptime) + } + fmt.Println() +} + +// printNodesTable prints a formatted table of all cluster nodes. +func printNodesTable(nodes map[string]*rqliteNode) { + if len(nodes) == 0 { + fmt.Printf("No nodes found in cluster.\n\n") + return + } + + fmt.Printf("Cluster Nodes (%d total)\n", len(nodes)) + fmt.Printf("%-20s %-30s %-8s %-10s %-10s %-12s\n", + "NODE ID", "ADDRESS", "VOTER", "LEADER", "REACHABLE", "LATENCY") + fmt.Printf("%-20s %-30s %-8s %-10s %-10s %-12s\n", + strings.Repeat("-", 20), + strings.Repeat("-", 30), + strings.Repeat("-", 8), + strings.Repeat("-", 10), + strings.Repeat("-", 10), + strings.Repeat("-", 12)) + + for id, node := range nodes { + nodeID := id + if len(nodeID) > 20 { + nodeID = nodeID[:17] + "..." + } + + voter := "no" + if node.Voter { + voter = "yes" + } + + leader := "no" + if node.Leader { + leader = "yes" + } + + reachable := "no" + if node.Reachable { + reachable = "yes" + } + + latency := "-" + if node.TimeS != "" { + latency = node.TimeS + } else if node.Time > 0 { + latency = fmt.Sprintf("%.3fs", node.Time) + } + + fmt.Printf("%-20s %-30s %-8s %-10s %-10s %-12s\n", + nodeID, node.Address, voter, leader, reachable, latency) + } + fmt.Println() +} + +// printOlricStatus attempts to query the local Olric status endpoint. +func printOlricStatus() { + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Get("http://localhost:3320/") + if err != nil { + fmt.Printf("Olric: not reachable on localhost:3320 (%v)\n\n", err) + return + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Printf("Olric: reachable but could not read response\n\n") + return + } + + if resp.StatusCode == http.StatusOK { + fmt.Printf("Olric: reachable (HTTP %d)\n", resp.StatusCode) + // Try to parse as JSON for a nicer display + var data map[string]interface{} + if err := json.Unmarshal(body, &data); err == nil { + for key, val := range data { + fmt.Printf(" %s: %v\n", key, val) + } + } else { + // Not JSON, print raw (truncated) + raw := strings.TrimSpace(string(body)) + if len(raw) > 200 { + raw = raw[:200] + "..." + } + if raw != "" { + fmt.Printf(" Response: %s\n", raw) + } + } + } else { + fmt.Printf("Olric: reachable but returned HTTP %d\n", resp.StatusCode) + } + fmt.Println() +} diff --git a/pkg/cli/cluster/watch.go b/pkg/cli/cluster/watch.go new file mode 100644 index 0000000..6066c39 --- /dev/null +++ b/pkg/cli/cluster/watch.go @@ -0,0 +1,136 @@ +package cluster + +import ( + "fmt" + "os" + "os/signal" + "strconv" + "strings" + "syscall" + "time" +) + +// HandleWatch handles the "orama cluster watch" command. +// It polls RQLite status and nodes at a configurable interval and reprints a summary. +func HandleWatch(args []string) { + interval := 10 * time.Second + + // Parse --interval flag + intervalStr := getFlagValue(args, "--interval") + if intervalStr != "" { + secs, err := strconv.Atoi(intervalStr) + if err != nil || secs < 1 { + fmt.Fprintf(os.Stderr, "Error: --interval must be a positive integer (seconds)\n") + os.Exit(1) + } + interval = time.Duration(secs) * time.Second + } + + // Set up signal handling for clean exit + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + + fmt.Printf("Watching cluster status (interval: %s, Ctrl+C to exit)\n\n", interval) + + // Initial render + renderWatchScreen() + + ticker := time.NewTicker(interval) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + renderWatchScreen() + case <-sigCh: + fmt.Printf("\nWatch stopped.\n") + return + } + } +} + +// renderWatchScreen clears the terminal and prints a summary of cluster state. +func renderWatchScreen() { + // Clear screen using ANSI escape codes + fmt.Print("\033[2J\033[H") + + now := time.Now().Format("2006-01-02 15:04:05") + fmt.Printf("Cluster Watch [%s]\n", now) + fmt.Printf("=======================================\n\n") + + // Query RQLite status + status, err := queryRQLiteStatus() + if err != nil { + fmt.Printf("RQLite: UNREACHABLE (%v)\n\n", err) + } else { + fmt.Printf("Local Node: %s\n", status.Store.NodeID) + fmt.Printf(" State: %-10s Term: %-6d Applied: %-8d Commit: %-8d\n", + strings.ToUpper(status.Store.Raft.State), + status.Store.Raft.Term, + status.Store.Raft.AppliedIndex, + status.Store.Raft.CommitIndex) + fmt.Printf(" Leader: %s\n", status.Store.Raft.Leader) + if status.Node.Uptime != "" { + fmt.Printf(" Uptime: %s\n", status.Node.Uptime) + } + fmt.Println() + } + + // Query nodes + nodes, err := queryRQLiteNodes(true) + if err != nil { + fmt.Printf("Nodes: UNAVAILABLE (%v)\n\n", err) + } else { + total := len(nodes) + voters := 0 + reachable := 0 + for _, n := range nodes { + if n.Voter { + voters++ + } + if n.Reachable { + reachable++ + } + } + + fmt.Printf("Cluster: %d nodes (%d voters), %d/%d reachable\n\n", + total, voters, reachable, total) + + // Compact table + fmt.Printf("%-18s %-28s %-7s %-7s %-7s\n", + "ID", "ADDRESS", "VOTER", "LEADER", "UP") + fmt.Printf("%-18s %-28s %-7s %-7s %-7s\n", + strings.Repeat("-", 18), + strings.Repeat("-", 28), + strings.Repeat("-", 7), + strings.Repeat("-", 7), + strings.Repeat("-", 7)) + + for id, node := range nodes { + nodeID := id + if len(nodeID) > 18 { + nodeID = nodeID[:15] + "..." + } + + voter := " " + if node.Voter { + voter = "yes" + } + + leader := " " + if node.Leader { + leader = "yes" + } + + up := "no" + if node.Reachable { + up = "yes" + } + + fmt.Printf("%-18s %-28s %-7s %-7s %-7s\n", + nodeID, node.Address, voter, leader, up) + } + } + + fmt.Printf("\nPress Ctrl+C to exit\n") +} diff --git a/pkg/cli/cluster_commands.go b/pkg/cli/cluster_commands.go new file mode 100644 index 0000000..882db1f --- /dev/null +++ b/pkg/cli/cluster_commands.go @@ -0,0 +1,10 @@ +package cli + +import ( + "github.com/DeBrosOfficial/network/pkg/cli/cluster" +) + +// HandleClusterCommand handles cluster management commands. +func HandleClusterCommand(args []string) { + cluster.HandleCommand(args) +} diff --git a/pkg/cli/environment.go b/pkg/cli/environment.go index 3c0ad0d..c3025e4 100644 --- a/pkg/cli/environment.go +++ b/pkg/cli/environment.go @@ -9,7 +9,7 @@ import ( "github.com/DeBrosOfficial/network/pkg/config" ) -// Environment represents a DeBros network environment +// Environment represents a Orama network environment type Environment struct { Name string `json:"name"` GatewayURL string `json:"gateway_url"` diff --git a/pkg/cli/production/commands.go b/pkg/cli/production/commands.go index b961520..a15c8e2 100644 --- a/pkg/cli/production/commands.go +++ b/pkg/cli/production/commands.go @@ -89,15 +89,11 @@ func ShowHelp() { fmt.Printf(" --ipfs-addrs ADDRS - IPFS swarm addresses (auto-discovered)\n") fmt.Printf(" --ipfs-cluster-peer ID - IPFS Cluster peer ID (auto-discovered)\n") fmt.Printf(" --ipfs-cluster-addrs ADDRS - IPFS Cluster addresses (auto-discovered)\n") - fmt.Printf(" --branch BRANCH - Git branch to use (main or nightly, default: main)\n") - fmt.Printf(" --no-pull - Skip git clone/pull, use existing /home/debros/src\n") fmt.Printf(" --ignore-resource-checks - Skip disk/RAM/CPU prerequisite validation\n") fmt.Printf(" --dry-run - Show what would be done without making changes\n") fmt.Printf(" upgrade - Upgrade existing installation (requires root/sudo)\n") fmt.Printf(" Options:\n") fmt.Printf(" --restart - Automatically restart services after upgrade\n") - fmt.Printf(" --branch BRANCH - Git branch to use (main or nightly)\n") - fmt.Printf(" --no-pull - Skip git clone/pull, use existing source\n") fmt.Printf(" migrate - Migrate from old unified setup (requires root/sudo)\n") fmt.Printf(" Options:\n") fmt.Printf(" --dry-run - Show what would be migrated without making changes\n") diff --git a/pkg/cli/production/install/orchestrator.go b/pkg/cli/production/install/orchestrator.go index 618bf2c..ce3e90b 100644 --- a/pkg/cli/production/install/orchestrator.go +++ b/pkg/cli/production/install/orchestrator.go @@ -30,7 +30,7 @@ type Orchestrator struct { // NewOrchestrator creates a new install orchestrator func NewOrchestrator(flags *Flags) (*Orchestrator, error) { - oramaHome := "/home/debros" + oramaHome := "/home/orama" oramaDir := oramaHome + "/.orama" // Normalize peers @@ -547,9 +547,9 @@ func (o *Orchestrator) installNamespaceTemplates() error { systemdDir := "/etc/systemd/system" templates := []string{ - "debros-namespace-rqlite@.service", - "debros-namespace-olric@.service", - "debros-namespace-gateway@.service", + "orama-namespace-rqlite@.service", + "orama-namespace-olric@.service", + "orama-namespace-gateway@.service", } installedCount := 0 diff --git a/pkg/cli/production/install/remote.go b/pkg/cli/production/install/remote.go new file mode 100644 index 0000000..6c31705 --- /dev/null +++ b/pkg/cli/production/install/remote.go @@ -0,0 +1,215 @@ +package install + +import ( + "fmt" + "os" + "strconv" + "strings" + + "github.com/DeBrosOfficial/network/pkg/inspector" +) + +// RemoteOrchestrator orchestrates a remote install via SSH. +// It uploads the source archive, extracts it on the VPS, and runs +// the actual install command remotely. +type RemoteOrchestrator struct { + flags *Flags + node inspector.Node + archive string +} + +// NewRemoteOrchestrator creates a new remote orchestrator. +// It resolves SSH credentials and checks prerequisites. +func NewRemoteOrchestrator(flags *Flags) (*RemoteOrchestrator, error) { + if flags.VpsIP == "" { + return nil, fmt.Errorf("--vps-ip is required\nExample: orama install --vps-ip 1.2.3.4 --nameserver --domain orama-testnet.network") + } + + // Check source archive exists + if _, err := os.Stat(sourceArchivePath); os.IsNotExist(err) { + return nil, fmt.Errorf("source archive not found at %s\nRun: make build-linux && ./scripts/generate-source-archive.sh", sourceArchivePath) + } + + // Resolve SSH credentials + node, err := resolveSSHCredentials(flags.VpsIP) + if err != nil { + return nil, fmt.Errorf("failed to resolve SSH credentials: %w", err) + } + + return &RemoteOrchestrator{ + flags: flags, + node: node, + archive: sourceArchivePath, + }, nil +} + +// Execute runs the full remote install process. +func (r *RemoteOrchestrator) Execute() error { + fmt.Printf("Installing on %s via SSH (%s@%s)...\n\n", r.flags.VpsIP, r.node.User, r.node.Host) + + // Step 1: Upload archive + fmt.Printf("Uploading source archive...\n") + if err := r.uploadArchive(); err != nil { + return fmt.Errorf("upload failed: %w", err) + } + fmt.Printf(" Done.\n\n") + + // Step 2: Extract on VPS + fmt.Printf("Extracting on VPS...\n") + if err := r.extractOnVPS(); err != nil { + return fmt.Errorf("extract failed: %w", err) + } + fmt.Printf(" Done.\n\n") + + // Step 3: Run remote install + fmt.Printf("Running install on VPS...\n\n") + if err := r.runRemoteInstall(); err != nil { + return err + } + + return nil +} + +// uploadArchive copies the source archive to the VPS. +func (r *RemoteOrchestrator) uploadArchive() error { + return uploadFile(r.node, r.archive, "/tmp/network-source.tar.gz") +} + +// extractOnVPS runs extract-deploy.sh on the VPS. +func (r *RemoteOrchestrator) extractOnVPS() error { + // Extract source archive and install only the CLI binary. + // All other binaries are built from source on the VPS during install. + extractCmd := r.sudoPrefix() + "bash -c '" + + `ARCHIVE="/tmp/network-source.tar.gz" && ` + + `SRC_DIR="/home/orama/src" && ` + + `BIN_DIR="/home/orama/bin" && ` + + `id -u orama &>/dev/null || useradd -m -s /bin/bash orama && ` + + `rm -rf "$SRC_DIR" && mkdir -p "$SRC_DIR" "$BIN_DIR" && ` + + `tar xzf "$ARCHIVE" -C "$SRC_DIR" && ` + + `chown -R orama:orama "$SRC_DIR" && ` + + // Install pre-built CLI binary (only binary cross-compiled locally) + `if [ -f "$SRC_DIR/bin-linux/orama" ]; then ` + + `cp "$SRC_DIR/bin-linux/orama" /usr/local/bin/orama && ` + + `chmod +x /usr/local/bin/orama; fi && ` + + `chown -R orama:orama "$BIN_DIR" && ` + + `echo "Extract complete."` + + "'" + + return runSSHStreaming(r.node, extractCmd) +} + +// runRemoteInstall executes `orama install` on the VPS. +func (r *RemoteOrchestrator) runRemoteInstall() error { + cmd := r.buildRemoteCommand() + return runSSHStreaming(r.node, cmd) +} + +// buildRemoteCommand constructs the `sudo orama install` command string +// with all flags passed through. +func (r *RemoteOrchestrator) buildRemoteCommand() string { + var args []string + if r.node.User != "root" { + args = append(args, "sudo") + } + args = append(args, "orama", "install") + + args = append(args, "--vps-ip", r.flags.VpsIP) + + if r.flags.Domain != "" { + args = append(args, "--domain", r.flags.Domain) + } + if r.flags.BaseDomain != "" { + args = append(args, "--base-domain", r.flags.BaseDomain) + } + if r.flags.Nameserver { + args = append(args, "--nameserver") + } + if r.flags.JoinAddress != "" { + args = append(args, "--join", r.flags.JoinAddress) + } + if r.flags.Token != "" { + args = append(args, "--token", r.flags.Token) + } + if r.flags.Force { + args = append(args, "--force") + } + if r.flags.SkipChecks { + args = append(args, "--skip-checks") + } + if r.flags.SkipFirewall { + args = append(args, "--skip-firewall") + } + if r.flags.DryRun { + args = append(args, "--dry-run") + } + + // Anyone relay flags + if r.flags.AnyoneRelay { + args = append(args, "--anyone-relay") + } + if r.flags.AnyoneClient { + args = append(args, "--anyone-client") + } + if r.flags.AnyoneExit { + args = append(args, "--anyone-exit") + } + if r.flags.AnyoneMigrate { + args = append(args, "--anyone-migrate") + } + if r.flags.AnyoneNickname != "" { + args = append(args, "--anyone-nickname", r.flags.AnyoneNickname) + } + if r.flags.AnyoneContact != "" { + args = append(args, "--anyone-contact", r.flags.AnyoneContact) + } + if r.flags.AnyoneWallet != "" { + args = append(args, "--anyone-wallet", r.flags.AnyoneWallet) + } + if r.flags.AnyoneORPort != 9001 { + args = append(args, "--anyone-orport", strconv.Itoa(r.flags.AnyoneORPort)) + } + if r.flags.AnyoneFamily != "" { + args = append(args, "--anyone-family", r.flags.AnyoneFamily) + } + if r.flags.AnyoneBandwidth != 30 { + args = append(args, "--anyone-bandwidth", strconv.Itoa(r.flags.AnyoneBandwidth)) + } + if r.flags.AnyoneAccounting != 0 { + args = append(args, "--anyone-accounting", strconv.Itoa(r.flags.AnyoneAccounting)) + } + + return joinShellArgs(args) +} + +// sudoPrefix returns "sudo " for non-root SSH users, empty for root. +func (r *RemoteOrchestrator) sudoPrefix() string { + if r.node.User == "root" { + return "" + } + return "sudo " +} + +// joinShellArgs joins arguments, quoting those with special characters. +func joinShellArgs(args []string) string { + var parts []string + for _, a := range args { + if needsQuoting(a) { + parts = append(parts, "'"+a+"'") + } else { + parts = append(parts, a) + } + } + return strings.Join(parts, " ") +} + +// needsQuoting returns true if the string contains characters +// that need shell quoting. +func needsQuoting(s string) bool { + for _, c := range s { + switch c { + case ' ', '$', '!', '&', '(', ')', '<', '>', '|', ';', '"', '`', '\\', '#', '^', '*', '?', '{', '}', '[', ']', '~': + return true + } + } + return false +} diff --git a/pkg/cli/production/install/ssh.go b/pkg/cli/production/install/ssh.go new file mode 100644 index 0000000..5fd8b71 --- /dev/null +++ b/pkg/cli/production/install/ssh.go @@ -0,0 +1,142 @@ +package install + +import ( + "bufio" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/DeBrosOfficial/network/pkg/inspector" +) + +const sourceArchivePath = "/tmp/network-source.tar.gz" + +// resolveSSHCredentials finds SSH credentials for the given VPS IP. +// First checks remote-nodes.conf, then prompts interactively. +func resolveSSHCredentials(vpsIP string) (inspector.Node, error) { + confPath := findRemoteNodesConf() + if confPath != "" { + nodes, err := inspector.LoadNodes(confPath) + if err == nil { + for _, n := range nodes { + if n.Host == vpsIP { + // Expand ~ in SSH key path + if n.SSHKey != "" && strings.HasPrefix(n.SSHKey, "~") { + home, _ := os.UserHomeDir() + n.SSHKey = filepath.Join(home, n.SSHKey[1:]) + } + return n, nil + } + } + } + } + + // Not found in config — prompt interactively + return promptSSHCredentials(vpsIP), nil +} + +// findRemoteNodesConf searches for the remote-nodes.conf file. +func findRemoteNodesConf() string { + candidates := []string{ + "scripts/remote-nodes.conf", + "../scripts/remote-nodes.conf", + "network/scripts/remote-nodes.conf", + } + for _, c := range candidates { + if _, err := os.Stat(c); err == nil { + return c + } + } + return "" +} + +// promptSSHCredentials asks the user for SSH credentials interactively. +func promptSSHCredentials(vpsIP string) inspector.Node { + reader := bufio.NewReader(os.Stdin) + + fmt.Printf("\nSSH credentials for %s\n", vpsIP) + fmt.Print(" SSH user (default: ubuntu): ") + user, _ := reader.ReadString('\n') + user = strings.TrimSpace(user) + if user == "" { + user = "ubuntu" + } + + fmt.Print(" SSH password: ") + password, _ := reader.ReadString('\n') + password = strings.TrimSpace(password) + + return inspector.Node{ + User: user, + Host: vpsIP, + Password: password, + } +} + +// uploadFile copies a local file to a remote host via SCP. +func uploadFile(node inspector.Node, localPath, remotePath string) error { + dest := fmt.Sprintf("%s@%s:%s", node.User, node.Host, remotePath) + + var cmd *exec.Cmd + if node.SSHKey != "" { + cmd = exec.Command("scp", + "-o", "StrictHostKeyChecking=no", + "-o", "ConnectTimeout=10", + "-i", node.SSHKey, + localPath, dest, + ) + } else { + if _, err := exec.LookPath("sshpass"); err != nil { + return fmt.Errorf("sshpass not found — install it: brew install hudochenkov/sshpass/sshpass") + } + cmd = exec.Command("sshpass", "-p", node.Password, + "scp", + "-o", "StrictHostKeyChecking=no", + "-o", "ConnectTimeout=10", + localPath, dest, + ) + } + + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + return fmt.Errorf("SCP failed: %w", err) + } + return nil +} + +// runSSHStreaming executes a command on a remote host via SSH, +// streaming stdout/stderr to the local terminal in real-time. +func runSSHStreaming(node inspector.Node, command string) error { + var cmd *exec.Cmd + if node.SSHKey != "" { + cmd = exec.Command("ssh", + "-o", "StrictHostKeyChecking=no", + "-o", "ConnectTimeout=10", + "-i", node.SSHKey, + fmt.Sprintf("%s@%s", node.User, node.Host), + command, + ) + } else { + cmd = exec.Command("sshpass", "-p", node.Password, + "ssh", + "-o", "StrictHostKeyChecking=no", + "-o", "ConnectTimeout=10", + fmt.Sprintf("%s@%s", node.User, node.Host), + command, + ) + } + + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin // Allow password prompts from remote sudo + + if err := cmd.Run(); err != nil { + return fmt.Errorf("SSH command failed: %w", err) + } + return nil +} + diff --git a/pkg/cli/production/invite/command.go b/pkg/cli/production/invite/command.go index d2240cd..61da2ec 100644 --- a/pkg/cli/production/invite/command.go +++ b/pkg/cli/production/invite/command.go @@ -68,7 +68,7 @@ func Handle(args []string) { // readNodeDomain reads the domain from the node config file func readNodeDomain() (string, error) { - configPath := "/home/debros/.orama/configs/node.yaml" + configPath := "/home/orama/.orama/configs/node.yaml" data, err := os.ReadFile(configPath) if err != nil { return "", fmt.Errorf("read config: %w", err) diff --git a/pkg/cli/production/lifecycle/post_upgrade.go b/pkg/cli/production/lifecycle/post_upgrade.go new file mode 100644 index 0000000..b259a65 --- /dev/null +++ b/pkg/cli/production/lifecycle/post_upgrade.go @@ -0,0 +1,143 @@ +package lifecycle + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "time" + + "github.com/DeBrosOfficial/network/pkg/cli/utils" +) + +// HandlePostUpgrade brings the node back online after an upgrade: +// 1. Resets failed + unmasks + enables all services +// 2. Starts services in dependency order +// 3. Waits for global RQLite to be ready +// 4. Waits for each namespace RQLite to be ready +// 5. Removes maintenance flag +func HandlePostUpgrade() { + if os.Geteuid() != 0 { + fmt.Fprintf(os.Stderr, "Error: post-upgrade must be run as root (use sudo)\n") + os.Exit(1) + } + + fmt.Printf("Post-upgrade: bringing node back online...\n") + + // 1. Get all services + services := utils.GetProductionServices() + if len(services) == 0 { + fmt.Printf(" Warning: no Orama services found\n") + return + } + + // Reset failed state + resetArgs := []string{"reset-failed"} + resetArgs = append(resetArgs, services...) + exec.Command("systemctl", resetArgs...).Run() + + // Unmask and enable all services + for _, svc := range services { + masked, err := utils.IsServiceMasked(svc) + if err == nil && masked { + exec.Command("systemctl", "unmask", svc).Run() + } + enabled, err := utils.IsServiceEnabled(svc) + if err == nil && !enabled { + exec.Command("systemctl", "enable", svc).Run() + } + } + fmt.Printf(" Services reset and enabled\n") + + // 2. Start services in dependency order + fmt.Printf(" Starting services...\n") + utils.StartServicesOrdered(services, "start") + fmt.Printf(" Services started\n") + + // 3. Wait for global RQLite (port 5001) to be ready + fmt.Printf(" Waiting for global RQLite (port 5001)...\n") + if err := waitForRQLiteReady(5001, 120*time.Second); err != nil { + fmt.Printf(" Warning: global RQLite not ready: %v\n", err) + } else { + fmt.Printf(" Global RQLite ready\n") + } + + // 4. Wait for each namespace RQLite with a global timeout of 5 minutes + nsPorts := getNamespaceRQLitePorts() + if len(nsPorts) > 0 { + fmt.Printf(" Waiting for %d namespace RQLite instances...\n", len(nsPorts)) + globalDeadline := time.Now().Add(5 * time.Minute) + + healthy := 0 + failed := 0 + for ns, port := range nsPorts { + remaining := time.Until(globalDeadline) + if remaining <= 0 { + fmt.Printf(" Warning: global timeout reached, skipping remaining namespaces\n") + failed += len(nsPorts) - healthy - failed + break + } + timeout := 90 * time.Second + if remaining < timeout { + timeout = remaining + } + fmt.Printf(" Waiting for namespace '%s' (port %d)...\n", ns, port) + if err := waitForRQLiteReady(port, timeout); err != nil { + fmt.Printf(" Warning: namespace '%s' RQLite not ready: %v\n", ns, err) + failed++ + } else { + fmt.Printf(" Namespace '%s' ready\n", ns) + healthy++ + } + } + fmt.Printf(" Namespace RQLite: %d healthy, %d failed\n", healthy, failed) + } + + // 5. Remove maintenance flag + if err := os.Remove(maintenanceFlagPath); err != nil && !os.IsNotExist(err) { + fmt.Printf(" Warning: failed to remove maintenance flag: %v\n", err) + } else { + fmt.Printf(" Maintenance flag removed\n") + } + + fmt.Printf("Post-upgrade complete. Node is back online.\n") +} + +// waitForRQLiteReady polls an RQLite instance's /status endpoint until it +// reports Leader or Follower state, or the timeout expires. +func waitForRQLiteReady(port int, timeout time.Duration) error { + deadline := time.Now().Add(timeout) + client := &http.Client{Timeout: 2 * time.Second} + url := fmt.Sprintf("http://localhost:%d/status", port) + + for time.Now().Before(deadline) { + resp, err := client.Get(url) + if err != nil { + time.Sleep(2 * time.Second) + continue + } + + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + + var status struct { + Store struct { + Raft struct { + State string `json:"state"` + } `json:"raft"` + } `json:"store"` + } + if err := json.Unmarshal(body, &status); err == nil { + state := status.Store.Raft.State + if state == "Leader" || state == "Follower" { + return nil + } + } + + time.Sleep(2 * time.Second) + } + + return fmt.Errorf("timeout after %s waiting for RQLite on port %d", timeout, port) +} diff --git a/pkg/cli/production/lifecycle/pre_upgrade.go b/pkg/cli/production/lifecycle/pre_upgrade.go new file mode 100644 index 0000000..16baf8e --- /dev/null +++ b/pkg/cli/production/lifecycle/pre_upgrade.go @@ -0,0 +1,132 @@ +package lifecycle + +import ( + "bufio" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/DeBrosOfficial/network/pkg/rqlite" + "go.uber.org/zap" +) + +const ( + maintenanceFlagPath = "/home/orama/.orama/maintenance.flag" +) + +// HandlePreUpgrade prepares the node for a safe rolling upgrade: +// 1. Checks quorum safety +// 2. Writes maintenance flag +// 3. Transfers leadership on global RQLite (port 5001) if leader +// 4. Transfers leadership on each namespace RQLite +// 5. Waits 15s for metadata propagation (H5 fix) +func HandlePreUpgrade() { + if os.Geteuid() != 0 { + fmt.Fprintf(os.Stderr, "Error: pre-upgrade must be run as root (use sudo)\n") + os.Exit(1) + } + + fmt.Printf("Pre-upgrade: preparing node for safe restart...\n") + + // 1. Check quorum safety + if warning := checkQuorumSafety(); warning != "" { + fmt.Fprintf(os.Stderr, " UNSAFE: %s\n", warning) + fmt.Fprintf(os.Stderr, " Aborting pre-upgrade. Use 'orama stop --force' to override.\n") + os.Exit(1) + } + fmt.Printf(" Quorum check passed\n") + + // 2. Write maintenance flag + if err := os.MkdirAll(filepath.Dir(maintenanceFlagPath), 0755); err != nil { + fmt.Fprintf(os.Stderr, " Warning: failed to create flag directory: %v\n", err) + } + if err := os.WriteFile(maintenanceFlagPath, []byte(time.Now().Format(time.RFC3339)), 0644); err != nil { + fmt.Fprintf(os.Stderr, " Warning: failed to write maintenance flag: %v\n", err) + } else { + fmt.Printf(" Maintenance flag written\n") + } + + // 3. Transfer leadership on global RQLite (port 5001) + logger, _ := zap.NewProduction() + defer logger.Sync() + + fmt.Printf(" Checking global RQLite leadership (port 5001)...\n") + if err := rqlite.TransferLeadership(5001, logger); err != nil { + fmt.Printf(" Warning: global leadership transfer: %v\n", err) + } else { + fmt.Printf(" Global RQLite leadership handled\n") + } + + // 4. Transfer leadership on each namespace RQLite + nsPorts := getNamespaceRQLitePorts() + for ns, port := range nsPorts { + fmt.Printf(" Checking namespace '%s' RQLite leadership (port %d)...\n", ns, port) + if err := rqlite.TransferLeadership(port, logger); err != nil { + fmt.Printf(" Warning: namespace '%s' leadership transfer: %v\n", ns, err) + } else { + fmt.Printf(" Namespace '%s' RQLite leadership handled\n", ns) + } + } + + // 5. Wait for metadata propagation (H5 fix: 15s, not 3s) + // The peer exchange cycle is 30s, but we force-triggered metadata updates + // via leadership transfer. 15s is sufficient for at least one exchange cycle. + fmt.Printf(" Waiting 15s for metadata propagation...\n") + time.Sleep(15 * time.Second) + + fmt.Printf("Pre-upgrade complete. Node is ready for restart.\n") +} + +// getNamespaceRQLitePorts scans namespace env files to find RQLite HTTP ports. +// Returns map of namespace_name → HTTP port. +func getNamespaceRQLitePorts() map[string]int { + namespacesDir := "/home/orama/.orama/data/namespaces" + ports := make(map[string]int) + + entries, err := os.ReadDir(namespacesDir) + if err != nil { + return ports + } + + for _, entry := range entries { + if !entry.IsDir() { + continue + } + ns := entry.Name() + envFile := filepath.Join(namespacesDir, ns, "rqlite.env") + port := parseHTTPPortFromEnv(envFile) + if port > 0 { + ports[ns] = port + } + } + + return ports +} + +// parseHTTPPortFromEnv reads an env file and extracts the HTTP port from +// the HTTP_ADDR=0.0.0.0:PORT line. +func parseHTTPPortFromEnv(envFile string) int { + f, err := os.Open(envFile) + if err != nil { + return 0 + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, "HTTP_ADDR=") { + addr := strings.TrimPrefix(line, "HTTP_ADDR=") + // Format: 0.0.0.0:PORT + if idx := strings.LastIndex(addr, ":"); idx >= 0 { + if port, err := strconv.Atoi(addr[idx+1:]); err == nil { + return port + } + } + } + } + return 0 +} diff --git a/pkg/cli/production/lifecycle/quorum.go b/pkg/cli/production/lifecycle/quorum.go new file mode 100644 index 0000000..6b438eb --- /dev/null +++ b/pkg/cli/production/lifecycle/quorum.go @@ -0,0 +1,145 @@ +package lifecycle + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "time" +) + +// checkQuorumSafety queries local RQLite to determine if stopping this node +// would break quorum. Returns a warning message if unsafe, empty string if safe. +func checkQuorumSafety() string { + // Query local RQLite status to check if we're a voter + status, err := getLocalRQLiteStatus() + if err != nil { + // RQLite may not be running — safe to stop + return "" + } + + raftState, _ := status["state"].(string) + isVoter, _ := status["voter"].(bool) + + // If we're not a voter, stopping is always safe for quorum + if !isVoter { + return "" + } + + // Query /nodes to count reachable voters + nodes, err := getLocalRQLiteNodes() + if err != nil { + return fmt.Sprintf("Cannot verify quorum safety (failed to query nodes: %v). This node is a %s voter.", err, raftState) + } + + reachableVoters := 0 + totalVoters := 0 + for _, node := range nodes { + voter, _ := node["voter"].(bool) + reachable, _ := node["reachable"].(bool) + if voter { + totalVoters++ + if reachable { + reachableVoters++ + } + } + } + + // After removing this voter, remaining voters must form quorum: + // quorum = (totalVoters / 2) + 1, so we need reachableVoters - 1 >= quorum + remainingVoters := reachableVoters - 1 + quorumNeeded := (totalVoters-1)/2 + 1 + + if remainingVoters < quorumNeeded { + role := raftState + if role == "Leader" { + role = "the LEADER" + } + return fmt.Sprintf( + "Stopping this node (%s, %s) would break RQLite quorum (%d/%d reachable voters would remain, need %d).", + role, "voter", remainingVoters, totalVoters-1, quorumNeeded) + } + + if raftState == "Leader" { + // Not quorum-breaking but warn about leadership + fmt.Printf(" Note: This node is the RQLite leader. Leadership will transfer on shutdown.\n") + } + + return "" +} + +// getLocalRQLiteStatus queries local RQLite /status and extracts raft info +func getLocalRQLiteStatus() (map[string]interface{}, error) { + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Get("http://localhost:5001/status") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var status map[string]interface{} + if err := json.Unmarshal(body, &status); err != nil { + return nil, err + } + + // Extract raft state from nested structure + store, _ := status["store"].(map[string]interface{}) + if store == nil { + return nil, fmt.Errorf("no store in status") + } + raft, _ := store["raft"].(map[string]interface{}) + if raft == nil { + return nil, fmt.Errorf("no raft in status") + } + + // Add voter status from the node info + result := map[string]interface{}{ + "state": raft["state"], + "voter": true, // Local node queries /status which doesn't include voter flag, assume voter if we got here + } + + return result, nil +} + +// getLocalRQLiteNodes queries local RQLite /nodes?nonvoters to get cluster members +func getLocalRQLiteNodes() ([]map[string]interface{}, error) { + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Get("http://localhost:5001/nodes?nonvoters&timeout=3s") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + // RQLite /nodes returns a map of node_id -> node_info + var nodesMap map[string]map[string]interface{} + if err := json.Unmarshal(body, &nodesMap); err != nil { + return nil, err + } + + var nodes []map[string]interface{} + for _, node := range nodesMap { + nodes = append(nodes, node) + } + + return nodes, nil +} + +// containsService checks if a service name exists in the service list +func containsService(services []string, name string) bool { + for _, s := range services { + if s == name { + return true + } + } + return false +} diff --git a/pkg/cli/production/lifecycle/restart.go b/pkg/cli/production/lifecycle/restart.go index 78b43f0..963b595 100644 --- a/pkg/cli/production/lifecycle/restart.go +++ b/pkg/cli/production/lifecycle/restart.go @@ -35,22 +35,22 @@ func HandleRestartWithFlags(force bool) { } } - fmt.Printf("Restarting all DeBros production services...\n") + fmt.Printf("Restarting all Orama production services...\n") services := utils.GetProductionServices() if len(services) == 0 { - fmt.Printf(" No DeBros services found\n") + fmt.Printf(" No Orama services found\n") return } // Ordered stop: gateway first, then node (RQLite), then supporting services fmt.Printf("\n Stopping services (ordered)...\n") shutdownOrder := [][]string{ - {"debros-gateway"}, - {"debros-node"}, - {"debros-olric"}, - {"debros-ipfs-cluster", "debros-ipfs"}, - {"debros-anyone-relay", "anyone-client"}, + {"orama-gateway"}, + {"orama-node"}, + {"orama-olric"}, + {"orama-ipfs-cluster", "orama-ipfs"}, + {"orama-anyone-relay", "anyone-client"}, {"coredns", "caddy"}, } diff --git a/pkg/cli/production/lifecycle/start.go b/pkg/cli/production/lifecycle/start.go index 823859e..22eef1a 100644 --- a/pkg/cli/production/lifecycle/start.go +++ b/pkg/cli/production/lifecycle/start.go @@ -16,11 +16,11 @@ func HandleStart() { os.Exit(1) } - fmt.Printf("Starting all DeBros production services...\n") + fmt.Printf("Starting all Orama production services...\n") services := utils.GetProductionServices() if len(services) == 0 { - fmt.Printf(" ⚠️ No DeBros services found\n") + fmt.Printf(" ⚠️ No Orama services found\n") return } diff --git a/pkg/cli/production/lifecycle/stop.go b/pkg/cli/production/lifecycle/stop.go index 600f70c..6ff6833 100644 --- a/pkg/cli/production/lifecycle/stop.go +++ b/pkg/cli/production/lifecycle/stop.go @@ -36,7 +36,7 @@ func HandleStopWithFlags(force bool) { } } - fmt.Printf("Stopping all DeBros production services...\n") + fmt.Printf("Stopping all Orama production services...\n") // First, stop all namespace services fmt.Printf("\n Stopping namespace services...\n") @@ -44,7 +44,7 @@ func HandleStopWithFlags(force bool) { services := utils.GetProductionServices() if len(services) == 0 { - fmt.Printf(" No DeBros services found\n") + fmt.Printf(" No Orama services found\n") return } @@ -53,12 +53,12 @@ func HandleStopWithFlags(force bool) { // Ordered shutdown: gateway first, then node (RQLite), then supporting services // This ensures we stop accepting requests before shutting down the database shutdownOrder := [][]string{ - {"debros-gateway"}, // 1. Stop accepting new requests - {"debros-node"}, // 2. Stop node (includes RQLite with leadership transfer) - {"debros-olric"}, // 3. Stop cache - {"debros-ipfs-cluster", "debros-ipfs"}, // 4. Stop storage - {"debros-anyone-relay", "anyone-client"}, // 5. Stop privacy relay - {"coredns", "caddy"}, // 6. Stop DNS/TLS last + {"orama-gateway"}, // 1. Stop accepting new requests + {"orama-node"}, // 2. Stop node (includes RQLite with leadership transfer) + {"orama-olric"}, // 3. Stop cache + {"orama-ipfs-cluster", "orama-ipfs"}, // 4. Stop storage + {"orama-anyone-relay", "anyone-client"}, // 5. Stop privacy relay + {"coredns", "caddy"}, // 6. Stop DNS/TLS last } // First, disable all services to prevent auto-restart @@ -157,7 +157,7 @@ func HandleStopWithFlags(force bool) { if hadError { fmt.Fprintf(os.Stderr, "\n⚠️ Some services may still be restarting due to Restart=always\n") - fmt.Fprintf(os.Stderr, " Check status with: systemctl list-units 'debros-*'\n") + fmt.Fprintf(os.Stderr, " Check status with: systemctl list-units 'orama-*'\n") fmt.Fprintf(os.Stderr, " If services are still restarting, they may need manual intervention\n") } else { fmt.Printf("\n✅ All services stopped and disabled (will not auto-start on boot)\n") @@ -168,7 +168,7 @@ func HandleStopWithFlags(force bool) { // stopAllNamespaceServices stops all running namespace services func stopAllNamespaceServices() { // Find all running namespace services using systemctl list-units - cmd := exec.Command("systemctl", "list-units", "--type=service", "--all", "--no-pager", "--no-legend", "debros-namespace-*@*.service") + cmd := exec.Command("systemctl", "list-units", "--type=service", "--all", "--no-pager", "--no-legend", "orama-namespace-*@*.service") output, err := cmd.Output() if err != nil { fmt.Printf(" ⚠️ Warning: Failed to list namespace services: %v\n", err) @@ -181,7 +181,7 @@ func stopAllNamespaceServices() { fields := strings.Fields(line) if len(fields) > 0 { serviceName := fields[0] - if strings.HasPrefix(serviceName, "debros-namespace-") { + if strings.HasPrefix(serviceName, "orama-namespace-") { namespaceServices = append(namespaceServices, serviceName) } } diff --git a/pkg/cli/production/logs/command.go b/pkg/cli/production/logs/command.go index 7c66baf..4af04b5 100644 --- a/pkg/cli/production/logs/command.go +++ b/pkg/cli/production/logs/command.go @@ -27,7 +27,7 @@ func Handle(args []string) { if err != nil { fmt.Fprintf(os.Stderr, "❌ %v\n", err) fmt.Fprintf(os.Stderr, "\nAvailable service aliases: node, ipfs, cluster, gateway, olric\n") - fmt.Fprintf(os.Stderr, "Or use full service name like: debros-node\n") + fmt.Fprintf(os.Stderr, "Or use full service name like: orama-node\n") os.Exit(1) } @@ -51,7 +51,7 @@ func showUsage() { fmt.Fprintf(os.Stderr, "\nService aliases:\n") fmt.Fprintf(os.Stderr, " node, ipfs, cluster, gateway, olric\n") fmt.Fprintf(os.Stderr, "\nOr use full service name:\n") - fmt.Fprintf(os.Stderr, " debros-node, debros-gateway, etc.\n") + fmt.Fprintf(os.Stderr, " orama-node, orama-gateway, etc.\n") } func handleMultipleServices(serviceNames []string, serviceAlias string, follow bool) { diff --git a/pkg/cli/production/migrate/command.go b/pkg/cli/production/migrate/command.go index b772a37..6543b51 100644 --- a/pkg/cli/production/migrate/command.go +++ b/pkg/cli/production/migrate/command.go @@ -28,7 +28,7 @@ func Handle(args []string) { os.Exit(1) } - oramaDir := "/home/debros/.orama" + oramaDir := "/home/orama/.orama" fmt.Printf("🔄 Checking for installations to migrate...\n\n") @@ -70,9 +70,9 @@ func Handle(args []string) { func stopOldServices() { oldServices := []string{ - "debros-ipfs", - "debros-ipfs-cluster", - "debros-node", + "orama-ipfs", + "orama-ipfs-cluster", + "orama-node", } fmt.Printf("\n Stopping old services...\n") @@ -141,9 +141,9 @@ func migrateConfigFiles(oramaDir string) { func removeOldServices() { oldServices := []string{ - "debros-ipfs", - "debros-ipfs-cluster", - "debros-node", + "orama-ipfs", + "orama-ipfs-cluster", + "orama-node", } fmt.Printf("\n Removing old service files...\n") diff --git a/pkg/cli/production/migrate/validator.go b/pkg/cli/production/migrate/validator.go index 1043872..71872cb 100644 --- a/pkg/cli/production/migrate/validator.go +++ b/pkg/cli/production/migrate/validator.go @@ -24,9 +24,9 @@ func (v *Validator) CheckNeedsMigration() bool { } oldServices := []string{ - "debros-ipfs", - "debros-ipfs-cluster", - "debros-node", + "orama-ipfs", + "orama-ipfs-cluster", + "orama-node", } oldConfigs := []string{ diff --git a/pkg/cli/production/status/command.go b/pkg/cli/production/status/command.go index ff43b38..40883ce 100644 --- a/pkg/cli/production/status/command.go +++ b/pkg/cli/production/status/command.go @@ -13,21 +13,21 @@ func Handle() { // Unified service names (no bootstrap/node distinction) serviceNames := []string{ - "debros-ipfs", - "debros-ipfs-cluster", + "orama-ipfs", + "orama-ipfs-cluster", // Note: RQLite is managed by node process, not as separate service - "debros-olric", - "debros-node", - "debros-gateway", + "orama-olric", + "orama-node", + "orama-gateway", } // Friendly descriptions descriptions := map[string]string{ - "debros-ipfs": "IPFS Daemon", - "debros-ipfs-cluster": "IPFS Cluster", - "debros-olric": "Olric Cache Server", - "debros-node": "DeBros Node (includes RQLite)", - "debros-gateway": "DeBros Gateway", + "orama-ipfs": "IPFS Daemon", + "orama-ipfs-cluster": "IPFS Cluster", + "orama-olric": "Olric Cache Server", + "orama-node": "Orama Node (includes RQLite)", + "orama-gateway": "Orama Gateway", } fmt.Printf("Services:\n") @@ -47,7 +47,7 @@ func Handle() { } fmt.Printf("\nDirectories:\n") - oramaDir := "/home/debros/.orama" + oramaDir := "/home/orama/.orama" if _, err := os.Stat(oramaDir); err == nil { fmt.Printf(" ✅ %s exists\n", oramaDir) } else { diff --git a/pkg/cli/production/uninstall/command.go b/pkg/cli/production/uninstall/command.go index 3f5eb4d..3ab0253 100644 --- a/pkg/cli/production/uninstall/command.go +++ b/pkg/cli/production/uninstall/command.go @@ -16,8 +16,8 @@ func Handle() { os.Exit(1) } - fmt.Printf("⚠️ This will stop and remove all DeBros production services\n") - fmt.Printf("⚠️ Configuration and data will be preserved in /home/debros/.orama\n\n") + fmt.Printf("⚠️ This will stop and remove all Orama production services\n") + fmt.Printf("⚠️ Configuration and data will be preserved in /home/orama/.orama\n\n") fmt.Printf("Continue? (yes/no): ") reader := bufio.NewReader(os.Stdin) @@ -30,12 +30,12 @@ func Handle() { } services := []string{ - "debros-gateway", - "debros-node", - "debros-olric", - "debros-ipfs-cluster", - "debros-ipfs", - "debros-anyone-client", + "orama-gateway", + "orama-node", + "orama-olric", + "orama-ipfs-cluster", + "orama-ipfs", + "orama-anyone-client", } fmt.Printf("Stopping services...\n") @@ -48,6 +48,6 @@ func Handle() { exec.Command("systemctl", "daemon-reload").Run() fmt.Printf("✅ Services uninstalled\n") - fmt.Printf(" Configuration and data preserved in /home/debros/.orama\n") - fmt.Printf(" To remove all data: rm -rf /home/debros/.orama\n\n") + fmt.Printf(" Configuration and data preserved in /home/orama/.orama\n") + fmt.Printf(" To remove all data: rm -rf /home/orama/.orama\n\n") } diff --git a/pkg/cli/production/upgrade/orchestrator.go b/pkg/cli/production/upgrade/orchestrator.go index 609433e..70c2845 100644 --- a/pkg/cli/production/upgrade/orchestrator.go +++ b/pkg/cli/production/upgrade/orchestrator.go @@ -26,7 +26,7 @@ type Orchestrator struct { // NewOrchestrator creates a new upgrade orchestrator func NewOrchestrator(flags *Flags) *Orchestrator { - oramaHome := "/home/debros" + oramaHome := "/home/orama" oramaDir := oramaHome + "/.orama" // Load existing preferences @@ -187,7 +187,7 @@ func (o *Orchestrator) Execute() error { fmt.Printf(" To apply changes, restart services:\n") fmt.Printf(" sudo systemctl daemon-reload\n") - fmt.Printf(" sudo systemctl restart debros-*\n") + fmt.Printf(" sudo systemctl restart orama-*\n") fmt.Printf("\n") return nil @@ -357,7 +357,7 @@ func (o *Orchestrator) stopServices() error { fmt.Printf("\n⏹️ Stopping all services before upgrade...\n") serviceController := production.NewSystemdController() - // First, stop all namespace services (debros-namespace-*@*.service) + // First, stop all namespace services (orama-namespace-*@*.service) fmt.Printf(" Stopping namespace services...\n") if err := o.stopAllNamespaceServices(serviceController); err != nil { fmt.Printf(" ⚠️ Warning: Failed to stop namespace services: %v\n", err) @@ -365,15 +365,15 @@ func (o *Orchestrator) stopServices() error { // Stop services in reverse dependency order services := []string{ - "caddy.service", // Depends on node - "coredns.service", // Depends on node - "debros-gateway.service", // Legacy - "debros-node.service", // Depends on cluster, olric - "debros-ipfs-cluster.service", // Depends on IPFS - "debros-ipfs.service", // Base IPFS - "debros-olric.service", // Independent - "debros-anyone-client.service", // Client mode - "debros-anyone-relay.service", // Relay mode + "caddy.service", // Depends on node + "coredns.service", // Depends on node + "orama-gateway.service", // Legacy + "orama-node.service", // Depends on cluster, olric + "orama-ipfs-cluster.service", // Depends on IPFS + "orama-ipfs.service", // Base IPFS + "orama-olric.service", // Independent + "orama-anyone-client.service", // Client mode + "orama-anyone-relay.service", // Relay mode } for _, svc := range services { unitPath := filepath.Join("/etc/systemd/system", svc) @@ -393,7 +393,7 @@ func (o *Orchestrator) stopServices() error { // stopAllNamespaceServices stops all running namespace services func (o *Orchestrator) stopAllNamespaceServices(serviceController *production.SystemdController) error { // Find all running namespace services using systemctl list-units - cmd := exec.Command("systemctl", "list-units", "--type=service", "--state=running", "--no-pager", "--no-legend", "debros-namespace-*@*.service") + cmd := exec.Command("systemctl", "list-units", "--type=service", "--state=running", "--no-pager", "--no-legend", "orama-namespace-*@*.service") output, err := cmd.Output() if err != nil { return fmt.Errorf("failed to list namespace services: %w", err) @@ -405,7 +405,7 @@ func (o *Orchestrator) stopAllNamespaceServices(serviceController *production.Sy fields := strings.Fields(line) if len(fields) > 0 { serviceName := fields[0] - if strings.HasPrefix(serviceName, "debros-namespace-") { + if strings.HasPrefix(serviceName, "orama-namespace-") { if err := serviceController.StopService(serviceName); err != nil { fmt.Printf(" ⚠️ Warning: Failed to stop %s: %v\n", serviceName, err) } else { @@ -428,9 +428,9 @@ func (o *Orchestrator) installNamespaceTemplates() error { systemdDir := "/etc/systemd/system" templates := []string{ - "debros-namespace-rqlite@.service", - "debros-namespace-olric@.service", - "debros-namespace-gateway@.service", + "orama-namespace-rqlite@.service", + "orama-namespace-olric@.service", + "orama-namespace-gateway@.service", } installedCount := 0 @@ -636,7 +636,7 @@ func (o *Orchestrator) restartServices() error { services := utils.GetProductionServices() // Re-enable all services BEFORE restarting them. - // orama prod stop disables services, and debros-node's PartOf= dependency + // orama prod stop disables services, and orama-node's PartOf= dependency // won't propagate restart to disabled services. We must re-enable first // so that all services restart with the updated binary. for _, svc := range services { @@ -664,13 +664,13 @@ func (o *Orchestrator) restartServices() error { // Define the order for rolling restart - node service first (contains RQLite) // This ensures the cluster can reform before other services start priorityOrder := []string{ - "debros-node", // Start node first - contains RQLite cluster - "debros-olric", // Distributed cache - "debros-ipfs", // IPFS daemon - "debros-ipfs-cluster", // IPFS cluster - "debros-gateway", // Gateway (legacy) - "coredns", // DNS server - "caddy", // Reverse proxy + "orama-node", // Start node first - contains RQLite cluster + "orama-olric", // Distributed cache + "orama-ipfs", // IPFS daemon + "orama-ipfs-cluster", // IPFS cluster + "orama-gateway", // Gateway (legacy) + "coredns", // DNS server + "caddy", // Reverse proxy } // Restart services in priority order with health checks @@ -685,7 +685,7 @@ func (o *Orchestrator) restartServices() error { fmt.Printf(" ✓ Started %s\n", svc) // For the node service, wait for RQLite cluster health - if svc == "debros-node" { + if svc == "orama-node" { fmt.Printf(" Waiting for RQLite cluster to become healthy...\n") if err := o.waitForClusterHealth(2 * time.Minute); err != nil { fmt.Printf(" ⚠️ Cluster health check warning: %v\n", err) @@ -793,7 +793,7 @@ func (o *Orchestrator) waitForClusterHealth(timeout time.Duration) error { // by looking for the systemd service file or the anonrc config file. func detectAnyoneRelay(oramaDir string) bool { // Check if systemd service file exists - if _, err := os.Stat("/etc/systemd/system/debros-anyone-relay.service"); err == nil { + if _, err := os.Stat("/etc/systemd/system/orama-anyone-relay.service"); err == nil { return true } // Check if anonrc config exists diff --git a/pkg/cli/utils/install.go b/pkg/cli/utils/install.go index bc01c07..c153e8f 100644 --- a/pkg/cli/utils/install.go +++ b/pkg/cli/utils/install.go @@ -77,7 +77,7 @@ func ShowDryRunSummaryWithRelay(vpsIP, domain, branch string, peers []string, jo } else { fmt.Printf(" - anyone-client (npm)\n") } - fmt.Printf(" - DeBros binaries (built from %s branch)\n", branch) + fmt.Printf(" - Orama binaries (built from %s branch)\n", branch) fmt.Printf("\n🔐 Secrets that would be generated:\n") fmt.Printf(" - Cluster secret (64-hex)\n") @@ -89,14 +89,14 @@ func ShowDryRunSummaryWithRelay(vpsIP, domain, branch string, peers []string, jo fmt.Printf(" - %s/configs/olric/config.yaml\n", oramaDir) fmt.Printf("\n⚙️ Systemd services that would be created:\n") - fmt.Printf(" - debros-ipfs.service\n") - fmt.Printf(" - debros-ipfs-cluster.service\n") - fmt.Printf(" - debros-olric.service\n") - fmt.Printf(" - debros-node.service (includes embedded gateway + RQLite)\n") + fmt.Printf(" - orama-ipfs.service\n") + fmt.Printf(" - orama-ipfs-cluster.service\n") + fmt.Printf(" - orama-olric.service\n") + fmt.Printf(" - orama-node.service (includes embedded gateway + RQLite)\n") if relayInfo != nil && relayInfo.Enabled { - fmt.Printf(" - debros-anyone-relay.service (relay operator mode)\n") + fmt.Printf(" - orama-anyone-relay.service (relay operator mode)\n") } else { - fmt.Printf(" - debros-anyone-client.service\n") + fmt.Printf(" - orama-anyone-client.service\n") } fmt.Printf("\n🌐 Ports that would be used:\n") diff --git a/pkg/cli/utils/systemd.go b/pkg/cli/utils/systemd.go index ef5f38d..e35a2ff 100644 --- a/pkg/cli/utils/systemd.go +++ b/pkg/cli/utils/systemd.go @@ -23,23 +23,23 @@ type PortSpec struct { } var ServicePorts = map[string][]PortSpec{ - "debros-gateway": { + "orama-gateway": { {Name: "Gateway API", Port: constants.GatewayAPIPort}, }, - "debros-olric": { + "orama-olric": { {Name: "Olric HTTP", Port: constants.OlricHTTPPort}, {Name: "Olric Memberlist", Port: constants.OlricMemberlistPort}, }, - "debros-node": { + "orama-node": { {Name: "RQLite HTTP", Port: constants.RQLiteHTTPPort}, {Name: "RQLite Raft", Port: constants.RQLiteRaftPort}, }, - "debros-ipfs": { + "orama-ipfs": { {Name: "IPFS API", Port: 4501}, {Name: "IPFS Gateway", Port: 8080}, {Name: "IPFS Swarm", Port: 4101}, }, - "debros-ipfs-cluster": { + "orama-ipfs-cluster": { {Name: "IPFS Cluster API", Port: 9094}, }, } @@ -63,13 +63,13 @@ func DefaultPorts() []PortSpec { func ResolveServiceName(alias string) ([]string, error) { // Service alias mapping (unified - no bootstrap/node distinction) aliases := map[string][]string{ - "node": {"debros-node"}, - "ipfs": {"debros-ipfs"}, - "cluster": {"debros-ipfs-cluster"}, - "ipfs-cluster": {"debros-ipfs-cluster"}, - "gateway": {"debros-gateway"}, - "olric": {"debros-olric"}, - "rqlite": {"debros-node"}, // RQLite logs are in node logs + "node": {"orama-node"}, + "ipfs": {"orama-ipfs"}, + "cluster": {"orama-ipfs-cluster"}, + "ipfs-cluster": {"orama-ipfs-cluster"}, + "gateway": {"orama-gateway"}, + "olric": {"orama-olric"}, + "rqlite": {"orama-node"}, // RQLite logs are in node logs } // Check if it's an alias @@ -153,18 +153,18 @@ func IsServiceMasked(service string) (bool, error) { return false, nil } -// GetProductionServices returns a list of all DeBros production service names that exist, +// GetProductionServices returns a list of all Orama production service names that exist, // including both global services and namespace-specific services func GetProductionServices() []string { // Global/default service names globalServices := []string{ - "debros-gateway", - "debros-node", - "debros-olric", - "debros-ipfs-cluster", - "debros-ipfs", - "debros-anyone-client", - "debros-anyone-relay", + "orama-gateway", + "orama-node", + "orama-olric", + "orama-ipfs-cluster", + "orama-ipfs", + "orama-anyone-client", + "orama-anyone-relay", } var existing []string @@ -179,10 +179,10 @@ func GetProductionServices() []string { // Discover namespace service instances from the namespaces data directory. // We can't rely on scanning /etc/systemd/system because that only contains - // template files (e.g. debros-namespace-gateway@.service) with no instance name. + // template files (e.g. orama-namespace-gateway@.service) with no instance name. // Restarting a template without an instance is a no-op. // Instead, scan the data directory where each subdirectory is a provisioned namespace. - namespacesDir := "/home/debros/.orama/data/namespaces" + namespacesDir := "/home/orama/.orama/data/namespaces" nsEntries, err := os.ReadDir(namespacesDir) if err == nil { serviceTypes := []string{"rqlite", "olric", "gateway"} @@ -195,7 +195,7 @@ func GetProductionServices() []string { // Only add if the env file exists (service was provisioned) envFile := filepath.Join(namespacesDir, ns, svcType+".env") if _, err := os.Stat(envFile); err == nil { - svcName := fmt.Sprintf("debros-namespace-%s@%s", svcType, ns) + svcName := fmt.Sprintf("orama-namespace-%s@%s", svcType, ns) existing = append(existing, svcName) } } @@ -304,7 +304,7 @@ func StartServicesOrdered(services []string, action string) { for _, svc := range services { matched := false for _, svcType := range NamespaceServiceOrder { - prefix := "debros-namespace-" + svcType + "@" + prefix := "orama-namespace-" + svcType + "@" if strings.HasPrefix(svc, prefix) { nsServices[svcType] = append(nsServices[svcType], svc) matched = true @@ -348,4 +348,3 @@ func StartServicesOrdered(services []string, action string) { } } } - diff --git a/pkg/client/defaults.go b/pkg/client/defaults.go index 712563e..fcbb816 100644 --- a/pkg/client/defaults.go +++ b/pkg/client/defaults.go @@ -13,7 +13,7 @@ import ( // These can be overridden by environment variables or config. func DefaultBootstrapPeers() []string { // Check environment variable first - if envPeers := os.Getenv("DEBROS_BOOTSTRAP_PEERS"); envPeers != "" { + if envPeers := os.Getenv("ORAMA_BOOTSTRAP_PEERS"); envPeers != "" { peers := splitCSVOrSpace(envPeers) // Filter out empty strings result := make([]string, 0, len(peers)) diff --git a/pkg/client/defaults_test.go b/pkg/client/defaults_test.go index cbc7561..9341508 100644 --- a/pkg/client/defaults_test.go +++ b/pkg/client/defaults_test.go @@ -8,11 +8,11 @@ import ( ) func TestDefaultBootstrapPeersNonEmpty(t *testing.T) { - old := os.Getenv("DEBROS_BOOTSTRAP_PEERS") - t.Cleanup(func() { os.Setenv("DEBROS_BOOTSTRAP_PEERS", old) }) + old := os.Getenv("ORAMA_BOOTSTRAP_PEERS") + t.Cleanup(func() { os.Setenv("ORAMA_BOOTSTRAP_PEERS", old) }) // Set a valid peer validPeer := "/ip4/127.0.0.1/tcp/4001/p2p/12D3KooWHbcFcrGPXKUrHcxvd8MXEeUzRYyvY8fQcpEBxncSUwhj" - _ = os.Setenv("DEBROS_BOOTSTRAP_PEERS", validPeer) + _ = os.Setenv("ORAMA_BOOTSTRAP_PEERS", validPeer) peers := DefaultBootstrapPeers() if len(peers) == 0 { t.Fatalf("expected non-empty default peers") diff --git a/pkg/config/database_config.go b/pkg/config/database_config.go index c8ea6e6..e905006 100644 --- a/pkg/config/database_config.go +++ b/pkg/config/database_config.go @@ -27,7 +27,7 @@ type DatabaseConfig struct { RaftElectionTimeout time.Duration `yaml:"raft_election_timeout"` // default: 5s RaftHeartbeatTimeout time.Duration `yaml:"raft_heartbeat_timeout"` // default: 2s RaftApplyTimeout time.Duration `yaml:"raft_apply_timeout"` // default: 30s - RaftLeaderLeaseTimeout time.Duration `yaml:"raft_leader_lease_timeout"` // default: 5s + RaftLeaderLeaseTimeout time.Duration `yaml:"raft_leader_lease_timeout"` // default: 2s (must be <= heartbeat timeout) // Dynamic discovery configuration (always enabled) ClusterSyncInterval time.Duration `yaml:"cluster_sync_interval"` // default: 30s diff --git a/pkg/config/paths.go b/pkg/config/paths.go index d092770..53f2ab4 100644 --- a/pkg/config/paths.go +++ b/pkg/config/paths.go @@ -20,7 +20,7 @@ func ExpandPath(path string) (string, error) { return path, nil } -// ConfigDir returns the path to the DeBros config directory (~/.orama). +// ConfigDir returns the path to the Orama config directory (~/.orama). func ConfigDir() (string, error) { home, err := os.UserHomeDir() if err != nil { diff --git a/pkg/coredns/README.md b/pkg/coredns/README.md index 9d5d562..ec2bb50 100644 --- a/pkg/coredns/README.md +++ b/pkg/coredns/README.md @@ -119,7 +119,7 @@ sudo chmod +x /usr/local/bin/coredns # 2. Create directories sudo mkdir -p /etc/coredns sudo mkdir -p /var/lib/coredns -sudo chown debros:debros /var/lib/coredns +sudo chown orama:orama /var/lib/coredns # 3. Copy configuration sudo cp configs/coredns/Corefile /etc/coredns/ @@ -425,8 +425,8 @@ Adjust in `client.go` if needed for higher load. ```bash # Increase file descriptor limit # Add to /etc/security/limits.conf: -debros soft nofile 65536 -debros hard nofile 65536 +orama soft nofile 65536 +orama hard nofile 65536 ``` ## Next Steps diff --git a/pkg/deployments/process/manager.go b/pkg/deployments/process/manager.go index de9076d..cea60cd 100644 --- a/pkg/deployments/process/manager.go +++ b/pkg/deployments/process/manager.go @@ -20,7 +20,7 @@ import ( // Manager manages deployment processes via systemd (Linux) or direct process spawning (macOS/other) type Manager struct { - logger *zap.Logger + logger *zap.Logger useSystemd bool // For non-systemd mode: track running processes @@ -310,8 +310,8 @@ After=network.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory={{.WorkDir}} {{range .Env}}Environment="{{.}}" @@ -373,7 +373,7 @@ WantedBy=multi-user.target return err } - // Use sudo tee to write to systemd directory (debros user needs sudo access) + // Use sudo tee to write to systemd directory (orama user needs sudo access) cmd := exec.Command("sudo", "tee", serviceFile) cmd.Stdin = &buf output, err := cmd.CombinedOutput() diff --git a/pkg/deployments/process/manager_test.go b/pkg/deployments/process/manager_test.go index 11db1b3..9f9ba4b 100644 --- a/pkg/deployments/process/manager_test.go +++ b/pkg/deployments/process/manager_test.go @@ -91,7 +91,7 @@ func TestGetStartCommand(t *testing.T) { // On macOS (test environment), useSystemd will be false, so node/npm use short paths. // We explicitly set it to test both modes. - workDir := "/home/debros/deployments/alice/myapp" + workDir := "/home/orama/deployments/alice/myapp" tests := []struct { name string @@ -227,9 +227,9 @@ func TestMapRestartPolicy(t *testing.T) { func TestParseSystemctlShow(t *testing.T) { tests := []struct { - name string - input string - want map[string]string + name string + input string + want map[string]string }{ { name: "typical output", diff --git a/pkg/discovery/discovery.go b/pkg/discovery/discovery.go index 4eb4fa4..94be9ae 100644 --- a/pkg/discovery/discovery.go +++ b/pkg/discovery/discovery.go @@ -18,7 +18,7 @@ import ( ) // Protocol ID for peer exchange -const PeerExchangeProtocol = "/debros/peer-exchange/1.0.0" +const PeerExchangeProtocol = "/orama/peer-exchange/1.0.0" // libp2pPort is the standard port used for libp2p peer connections. // Filtering on this port prevents cross-connecting with IPFS (4101) or IPFS Cluster (9096/9098). diff --git a/pkg/environments/production/config.go b/pkg/environments/production/config.go index 7c8b1dc..7c601ea 100644 --- a/pkg/environments/production/config.go +++ b/pkg/environments/production/config.go @@ -307,14 +307,14 @@ func ensureSecretFilePermissions(secretPath string) error { return fmt.Errorf("failed to set permissions on %s: %w", secretPath, err) } - if usr, err := user.Lookup("debros"); err == nil { + if usr, err := user.Lookup("orama"); err == nil { uid, err := strconv.Atoi(usr.Uid) if err != nil { - return fmt.Errorf("failed to parse debros UID: %w", err) + return fmt.Errorf("failed to parse orama UID: %w", err) } gid, err := strconv.Atoi(usr.Gid) if err != nil { - return fmt.Errorf("failed to parse debros GID: %w", err) + return fmt.Errorf("failed to parse orama GID: %w", err) } if err := os.Chown(secretPath, uid, gid); err != nil { return fmt.Errorf("failed to change ownership of %s: %w", secretPath, err) @@ -439,8 +439,8 @@ func (sg *SecretGenerator) SaveConfig(filename string, content string) error { } // Fix ownership - if err := exec.Command("chown", "debros:debros", configPath).Run(); err != nil { - fmt.Printf("Warning: failed to chown %s to debros:debros: %v\n", configPath, err) + if err := exec.Command("chown", "orama:orama", configPath).Run(); err != nil { + fmt.Printf("Warning: failed to chown %s to orama:orama: %v\n", configPath, err) } return nil diff --git a/pkg/environments/production/installers.go b/pkg/environments/production/installers.go index 3fbc295..032c3e7 100644 --- a/pkg/environments/production/installers.go +++ b/pkg/environments/production/installers.go @@ -27,7 +27,7 @@ type BinaryInstaller struct { // NewBinaryInstaller creates a new binary installer func NewBinaryInstaller(arch string, logWriter io.Writer) *BinaryInstaller { - oramaHome := "/home/debros" + oramaHome := "/home/orama" return &BinaryInstaller{ arch: arch, logWriter: logWriter, @@ -72,7 +72,7 @@ func (bi *BinaryInstaller) ResolveBinaryPath(binary string, extraPaths ...string return installers.ResolveBinaryPath(binary, extraPaths...) } -// InstallDeBrosBinaries builds DeBros binaries from source +// InstallDeBrosBinaries builds Orama binaries from source func (bi *BinaryInstaller) InstallDeBrosBinaries(oramaHome string) error { return bi.gateway.InstallDeBrosBinaries(oramaHome) } diff --git a/pkg/environments/production/installers/anyone_relay.go b/pkg/environments/production/installers/anyone_relay.go index 02688b1..f1e6acb 100644 --- a/pkg/environments/production/installers/anyone_relay.go +++ b/pkg/environments/production/installers/anyone_relay.go @@ -194,7 +194,7 @@ func (ari *AnyoneRelayInstaller) Install() error { os.Remove(installScript) // Stop and disable the default 'anon' systemd service that the apt package - // auto-enables. We use our own 'debros-anyone-relay' service instead. + // auto-enables. We use our own 'orama-anyone-relay' service instead. exec.Command("systemctl", "stop", "anon").Run() exec.Command("systemctl", "disable", "anon").Run() diff --git a/pkg/environments/production/installers/caddy.go b/pkg/environments/production/installers/caddy.go index 504e071..ac9f5e0 100644 --- a/pkg/environments/production/installers/caddy.go +++ b/pkg/environments/production/installers/caddy.go @@ -77,7 +77,7 @@ func (ci *CaddyInstaller) Install() error { if _, err := exec.LookPath("xcaddy"); err != nil { fmt.Fprintf(ci.logWriter, " Installing xcaddy...\n") cmd := exec.Command("go", "install", xcaddyRepo) - cmd.Env = append(os.Environ(), "PATH="+goPath, "GOBIN=/usr/local/bin") + cmd.Env = append(os.Environ(), "PATH="+goPath, "GOBIN=/usr/local/bin", "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to install xcaddy: %w\n%s", err, string(output)) } @@ -105,7 +105,7 @@ func (ci *CaddyInstaller) Install() error { // Run go mod tidy tidyCmd := exec.Command("go", "mod", "tidy") tidyCmd.Dir = moduleDir - tidyCmd.Env = append(os.Environ(), "PATH="+goPath) + tidyCmd.Env = append(os.Environ(), "PATH="+goPath, "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := tidyCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to run go mod tidy: %w\n%s", err, string(output)) } @@ -122,7 +122,7 @@ func (ci *CaddyInstaller) Install() error { "--with", "github.com/DeBrosOfficial/caddy-dns-orama="+moduleDir, "--output", filepath.Join(buildDir, "caddy")) buildCmd.Dir = buildDir - buildCmd.Env = append(os.Environ(), "PATH="+goPath) + buildCmd.Env = append(os.Environ(), "PATH="+goPath, "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := buildCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to build Caddy: %w\n%s", err, string(output)) } diff --git a/pkg/environments/production/installers/coredns.go b/pkg/environments/production/installers/coredns.go index f92a2c7..96291ce 100644 --- a/pkg/environments/production/installers/coredns.go +++ b/pkg/environments/production/installers/coredns.go @@ -171,21 +171,21 @@ func (ci *CoreDNSInstaller) Install() error { getCmd := exec.Command("go", "get", "github.com/miekg/dns@latest") getCmd.Dir = buildDir - getCmd.Env = append(os.Environ(), "PATH="+goPath) + getCmd.Env = append(os.Environ(), "PATH="+goPath, "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := getCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to get miekg/dns: %w\n%s", err, string(output)) } getCmd = exec.Command("go", "get", "go.uber.org/zap@latest") getCmd.Dir = buildDir - getCmd.Env = append(os.Environ(), "PATH="+goPath) + getCmd.Env = append(os.Environ(), "PATH="+goPath, "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := getCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to get zap: %w\n%s", err, string(output)) } tidyCmd := exec.Command("go", "mod", "tidy") tidyCmd.Dir = buildDir - tidyCmd.Env = append(os.Environ(), "PATH="+goPath) + tidyCmd.Env = append(os.Environ(), "PATH="+goPath, "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := tidyCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to run go mod tidy: %w\n%s", err, string(output)) } @@ -194,7 +194,7 @@ func (ci *CoreDNSInstaller) Install() error { fmt.Fprintf(ci.logWriter, " Generating plugin code...\n") genCmd := exec.Command("go", "generate") genCmd.Dir = buildDir - genCmd.Env = append(os.Environ(), "PATH="+goPath) + genCmd.Env = append(os.Environ(), "PATH="+goPath, "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := genCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to generate: %w\n%s", err, string(output)) } @@ -203,7 +203,7 @@ func (ci *CoreDNSInstaller) Install() error { fmt.Fprintf(ci.logWriter, " Building CoreDNS binary...\n") buildCmd := exec.Command("go", "build", "-o", "coredns") buildCmd.Dir = buildDir - buildCmd.Env = append(os.Environ(), "PATH="+goPath, "CGO_ENABLED=0") + buildCmd.Env = append(os.Environ(), "PATH="+goPath, "CGO_ENABLED=0", "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := buildCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to build CoreDNS: %w\n%s", err, string(output)) } diff --git a/pkg/environments/production/installers/gateway.go b/pkg/environments/production/installers/gateway.go index e2e0d34..2c9c2a6 100644 --- a/pkg/environments/production/installers/gateway.go +++ b/pkg/environments/production/installers/gateway.go @@ -9,7 +9,7 @@ import ( "strings" ) -// GatewayInstaller handles DeBros binary installation (including gateway) +// GatewayInstaller handles Orama binary installation (including gateway) type GatewayInstaller struct { *BaseInstaller } @@ -27,7 +27,7 @@ func (gi *GatewayInstaller) IsInstalled() bool { return false // Always build to ensure latest version } -// Install clones and builds DeBros binaries +// Install clones and builds Orama binaries func (gi *GatewayInstaller) Install() error { // This is a placeholder - actual installation is handled by InstallDeBrosBinaries return nil @@ -39,10 +39,10 @@ func (gi *GatewayInstaller) Configure() error { return nil } -// InstallDeBrosBinaries builds DeBros binaries from source at /home/debros/src. +// InstallDeBrosBinaries builds Orama binaries from source at /home/orama/src. // Source must already be present (uploaded via SCP archive). func (gi *GatewayInstaller) InstallDeBrosBinaries(oramaHome string) error { - fmt.Fprintf(gi.logWriter, " Building DeBros binaries...\n") + fmt.Fprintf(gi.logWriter, " Building Orama binaries...\n") srcDir := filepath.Join(oramaHome, "src") binDir := filepath.Join(oramaHome, "bin") @@ -64,7 +64,7 @@ func (gi *GatewayInstaller) InstallDeBrosBinaries(oramaHome string) error { fmt.Fprintf(gi.logWriter, " Building binaries...\n") cmd := exec.Command("make", "build") cmd.Dir = srcDir - cmd.Env = append(os.Environ(), "HOME="+oramaHome, "PATH="+os.Getenv("PATH")+":/usr/local/go/bin") + cmd.Env = append(os.Environ(), "HOME="+oramaHome, "PATH="+os.Getenv("PATH")+":/usr/local/go/bin", "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to build: %v\n%s", err, string(output)) } @@ -117,7 +117,7 @@ func (gi *GatewayInstaller) InstallDeBrosBinaries(oramaHome string) error { if err := exec.Command("chmod", "-R", "755", binDir).Run(); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ Warning: failed to chmod bin directory: %v\n", err) } - if err := exec.Command("chown", "-R", "debros:debros", binDir).Run(); err != nil { + if err := exec.Command("chown", "-R", "orama:orama", binDir).Run(); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ Warning: failed to chown bin directory: %v\n", err) } @@ -132,26 +132,29 @@ func (gi *GatewayInstaller) InstallDeBrosBinaries(oramaHome string) error { } } - fmt.Fprintf(gi.logWriter, " ✓ DeBros binaries installed\n") + fmt.Fprintf(gi.logWriter, " ✓ Orama binaries installed\n") return nil } // InstallGo downloads and installs Go toolchain func (gi *GatewayInstaller) InstallGo() error { - requiredVersion := "1.22.5" + requiredVersion := "1.24.6" if goPath, err := exec.LookPath("go"); err == nil { // Check version - upgrade if too old out, _ := exec.Command(goPath, "version").Output() - if strings.Contains(string(out), "go"+requiredVersion) || strings.Contains(string(out), "go1.23") || strings.Contains(string(out), "go1.24") { + if strings.Contains(string(out), "go"+requiredVersion) { fmt.Fprintf(gi.logWriter, " ✓ Go already installed (%s)\n", strings.TrimSpace(string(out))) return nil } - fmt.Fprintf(gi.logWriter, " Upgrading Go (current: %s, need >= %s)...\n", strings.TrimSpace(string(out)), requiredVersion) + fmt.Fprintf(gi.logWriter, " Upgrading Go (current: %s, need %s)...\n", strings.TrimSpace(string(out)), requiredVersion) os.RemoveAll("/usr/local/go") } else { fmt.Fprintf(gi.logWriter, " Installing Go...\n") } + // Always remove old Go installation to avoid mixing versions + os.RemoveAll("/usr/local/go") + goTarball := fmt.Sprintf("go%s.linux-%s.tar.gz", requiredVersion, gi.arch) goURL := fmt.Sprintf("https://go.dev/dl/%s", goTarball) @@ -214,12 +217,12 @@ func (gi *GatewayInstaller) InstallAnyoneClient() error { fmt.Fprintf(gi.logWriter, " Initializing NPM cache...\n") // Create nested cache directories with proper permissions - debrosHome := "/home/debros" + oramaHome := "/home/orama" npmCacheDirs := []string{ - filepath.Join(debrosHome, ".npm"), - filepath.Join(debrosHome, ".npm", "_cacache"), - filepath.Join(debrosHome, ".npm", "_cacache", "tmp"), - filepath.Join(debrosHome, ".npm", "_logs"), + filepath.Join(oramaHome, ".npm"), + filepath.Join(oramaHome, ".npm", "_cacache"), + filepath.Join(oramaHome, ".npm", "_cacache", "tmp"), + filepath.Join(oramaHome, ".npm", "_logs"), } for _, dir := range npmCacheDirs { @@ -227,8 +230,8 @@ func (gi *GatewayInstaller) InstallAnyoneClient() error { fmt.Fprintf(gi.logWriter, " ⚠️ Failed to create %s: %v\n", dir, err) continue } - // Fix ownership to debros user (sequential to avoid race conditions) - if err := exec.Command("chown", "debros:debros", dir).Run(); err != nil { + // Fix ownership to orama user (sequential to avoid race conditions) + if err := exec.Command("chown", "orama:orama", dir).Run(); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ Warning: failed to chown %s: %v\n", dir, err) } if err := exec.Command("chmod", "700", dir).Run(); err != nil { @@ -236,14 +239,14 @@ func (gi *GatewayInstaller) InstallAnyoneClient() error { } } - // Recursively fix ownership of entire .npm directory to ensure all nested files are owned by debros - if err := exec.Command("chown", "-R", "debros:debros", filepath.Join(debrosHome, ".npm")).Run(); err != nil { + // Recursively fix ownership of entire .npm directory to ensure all nested files are owned by orama + if err := exec.Command("chown", "-R", "orama:orama", filepath.Join(oramaHome, ".npm")).Run(); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ Warning: failed to chown .npm directory: %v\n", err) } - // Run npm cache verify as debros user with proper environment - cacheInitCmd := exec.Command("sudo", "-u", "debros", "npm", "cache", "verify", "--silent") - cacheInitCmd.Env = append(os.Environ(), "HOME="+debrosHome) + // Run npm cache verify as orama user with proper environment + cacheInitCmd := exec.Command("sudo", "-u", "orama", "npm", "cache", "verify", "--silent") + cacheInitCmd.Env = append(os.Environ(), "HOME="+oramaHome) if err := cacheInitCmd.Run(); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ NPM cache verify warning: %v (continuing anyway)\n", err) } @@ -255,11 +258,11 @@ func (gi *GatewayInstaller) InstallAnyoneClient() error { } // Create terms-agreement file to bypass interactive prompt when running as a service - termsFile := filepath.Join(debrosHome, "terms-agreement") + termsFile := filepath.Join(oramaHome, "terms-agreement") if err := os.WriteFile(termsFile, []byte("agreed"), 0644); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ Warning: failed to create terms-agreement: %v\n", err) } else { - if err := exec.Command("chown", "debros:debros", termsFile).Run(); err != nil { + if err := exec.Command("chown", "orama:orama", termsFile).Run(); err != nil { fmt.Fprintf(gi.logWriter, " ⚠️ Warning: failed to chown terms-agreement: %v\n", err) } } diff --git a/pkg/environments/production/installers/ipfs.go b/pkg/environments/production/installers/ipfs.go index 0a0439e..1520e3c 100644 --- a/pkg/environments/production/installers/ipfs.go +++ b/pkg/environments/production/installers/ipfs.go @@ -217,7 +217,7 @@ func (ii *IPFSInstaller) InitializeRepo(ipfsRepoPath string, swarmKeyPath string } // Fix ownership (best-effort, don't fail if it doesn't work) - if err := exec.Command("chown", "-R", "debros:debros", ipfsRepoPath).Run(); err != nil { + if err := exec.Command("chown", "-R", "orama:orama", ipfsRepoPath).Run(); err != nil { fmt.Fprintf(ii.logWriter, " ⚠️ Warning: failed to chown IPFS repo: %v\n", err) } diff --git a/pkg/environments/production/installers/ipfs_cluster.go b/pkg/environments/production/installers/ipfs_cluster.go index fc7d381..3dfaef9 100644 --- a/pkg/environments/production/installers/ipfs_cluster.go +++ b/pkg/environments/production/installers/ipfs_cluster.go @@ -43,7 +43,7 @@ func (ici *IPFSClusterInstaller) Install() error { } cmd := exec.Command("go", "install", "github.com/ipfs-cluster/ipfs-cluster/cmd/ipfs-cluster-service@latest") - cmd.Env = append(os.Environ(), "GOBIN=/usr/local/bin") + cmd.Env = append(os.Environ(), "GOBIN=/usr/local/bin", "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if err := cmd.Run(); err != nil { return fmt.Errorf("failed to install IPFS Cluster: %w", err) } @@ -77,7 +77,7 @@ func (ici *IPFSClusterInstaller) InitializeConfig(clusterPath, clusterSecret str } // Fix ownership before running init (best-effort) - if err := exec.Command("chown", "-R", "debros:debros", clusterPath).Run(); err != nil { + if err := exec.Command("chown", "-R", "orama:orama", clusterPath).Run(); err != nil { fmt.Fprintf(ici.logWriter, " ⚠️ Warning: failed to chown cluster path before init: %v\n", err) } @@ -120,7 +120,7 @@ func (ici *IPFSClusterInstaller) InitializeConfig(clusterPath, clusterSecret str } // Fix ownership again after updates (best-effort) - if err := exec.Command("chown", "-R", "debros:debros", clusterPath).Run(); err != nil { + if err := exec.Command("chown", "-R", "orama:orama", clusterPath).Run(); err != nil { fmt.Fprintf(ici.logWriter, " ⚠️ Warning: failed to chown cluster path after updates: %v\n", err) } diff --git a/pkg/environments/production/installers/olric.go b/pkg/environments/production/installers/olric.go index 2bbb7ff..409b9c9 100644 --- a/pkg/environments/production/installers/olric.go +++ b/pkg/environments/production/installers/olric.go @@ -42,7 +42,7 @@ func (oi *OlricInstaller) Install() error { } cmd := exec.Command("go", "install", fmt.Sprintf("github.com/olric-data/olric/cmd/olric-server@%s", oi.version)) - cmd.Env = append(os.Environ(), "GOBIN=/usr/local/bin") + cmd.Env = append(os.Environ(), "GOBIN=/usr/local/bin", "GOPROXY=https://proxy.golang.org|direct", "GONOSUMDB=*") if err := cmd.Run(); err != nil { return fmt.Errorf("failed to install Olric: %w", err) } diff --git a/pkg/environments/production/installers/rqlite.go b/pkg/environments/production/installers/rqlite.go index 6ff788e..82747c4 100644 --- a/pkg/environments/production/installers/rqlite.go +++ b/pkg/environments/production/installers/rqlite.go @@ -79,7 +79,7 @@ func (ri *RQLiteInstaller) InitializeDataDir(dataDir string) error { return fmt.Errorf("failed to create RQLite data directory: %w", err) } - if err := exec.Command("chown", "-R", "debros:debros", dataDir).Run(); err != nil { + if err := exec.Command("chown", "-R", "orama:orama", dataDir).Run(); err != nil { fmt.Fprintf(ri.logWriter, " ⚠️ Warning: failed to chown RQLite data dir: %v\n", err) } return nil diff --git a/pkg/environments/production/orchestrator.go b/pkg/environments/production/orchestrator.go index 374e178..96ea0c3 100644 --- a/pkg/environments/production/orchestrator.go +++ b/pkg/environments/production/orchestrator.go @@ -30,13 +30,13 @@ type AnyoneRelayConfig struct { type ProductionSetup struct { osInfo *OSInfo arch string - oramaHome string - oramaDir string + oramaHome string + oramaDir string logWriter io.Writer forceReconfigure bool skipOptionalDeps bool skipResourceChecks bool - isNameserver bool // Whether this node is a nameserver (runs CoreDNS + Caddy) + isNameserver bool // Whether this node is a nameserver (runs CoreDNS + Caddy) isAnyoneClient bool // Whether this node runs Anyone as client-only (SOCKS5 proxy) anyoneRelayConfig *AnyoneRelayConfig // Configuration for Anyone relay mode privChecker *PrivilegeChecker @@ -73,12 +73,12 @@ func ReadBranchPreference(oramaDir string) string { func SaveBranchPreference(oramaDir, branch string) error { branchFile := filepath.Join(oramaDir, ".branch") if err := os.MkdirAll(oramaDir, 0755); err != nil { - return fmt.Errorf("failed to create debros directory: %w", err) + return fmt.Errorf("failed to create orama directory: %w", err) } if err := os.WriteFile(branchFile, []byte(branch), 0644); err != nil { return fmt.Errorf("failed to save branch preference: %w", err) } - exec.Command("chown", "debros:debros", branchFile).Run() + exec.Command("chown", "orama:orama", branchFile).Run() return nil } @@ -88,8 +88,8 @@ func NewProductionSetup(oramaHome string, logWriter io.Writer, forceReconfigure arch, _ := (&ArchitectureDetector{}).Detect() return &ProductionSetup{ - oramaHome: oramaHome, - oramaDir: oramaDir, + oramaHome: oramaHome, + oramaDir: oramaDir, logWriter: logWriter, forceReconfigure: forceReconfigure, arch: arch, @@ -100,7 +100,7 @@ func NewProductionSetup(oramaHome string, logWriter io.Writer, forceReconfigure resourceChecker: NewResourceChecker(), portChecker: NewPortChecker(), fsProvisioner: NewFilesystemProvisioner(oramaHome), - userProvisioner: NewUserProvisioner("debros", oramaHome, "/bin/bash"), + userProvisioner: NewUserProvisioner("orama", oramaHome, "/bin/bash"), stateDetector: NewStateDetector(oramaDir), configGenerator: NewConfigGenerator(oramaDir), secretGenerator: NewSecretGenerator(oramaDir), @@ -231,14 +231,14 @@ func (ps *ProductionSetup) Phase1CheckPrerequisites() error { func (ps *ProductionSetup) Phase2ProvisionEnvironment() error { ps.logf("Phase 2: Provisioning environment...") - // Create debros user + // Create orama user if !ps.userProvisioner.UserExists() { if err := ps.userProvisioner.CreateUser(); err != nil { - return fmt.Errorf("failed to create debros user: %w", err) + return fmt.Errorf("failed to create orama user: %w", err) } - ps.logf(" ✓ Created 'debros' user") + ps.logf(" ✓ Created 'orama' user") } else { - ps.logf(" ✓ 'debros' user already exists") + ps.logf(" ✓ 'orama' user already exists") } // Set up sudoers access if invoked via sudo @@ -251,21 +251,21 @@ func (ps *ProductionSetup) Phase2ProvisionEnvironment() error { } } - // Set up deployment sudoers (allows debros user to manage orama-deploy-* services) + // Set up deployment sudoers (allows orama user to manage orama-deploy-* services) if err := ps.userProvisioner.SetupDeploymentSudoers(); err != nil { ps.logf(" ⚠️ Failed to setup deployment sudoers: %v", err) } else { ps.logf(" ✓ Deployment sudoers configured") } - // Set up namespace sudoers (allows debros user to manage debros-namespace-* services) + // Set up namespace sudoers (allows orama user to manage orama-namespace-* services) if err := ps.userProvisioner.SetupNamespaceSudoers(); err != nil { ps.logf(" ⚠️ Failed to setup namespace sudoers: %v", err) } else { ps.logf(" ✓ Namespace sudoers configured") } - // Set up WireGuard sudoers (allows debros user to manage WG peers) + // Set up WireGuard sudoers (allows orama user to manage WG peers) if err := ps.userProvisioner.SetupWireGuardSudoers(); err != nil { ps.logf(" ⚠️ Failed to setup wireguard sudoers: %v", err) } else { @@ -287,7 +287,7 @@ func (ps *ProductionSetup) Phase2ProvisionEnvironment() error { return nil } -// Phase2bInstallBinaries installs external binaries and DeBros components +// Phase2bInstallBinaries installs external binaries and Orama components func (ps *ProductionSetup) Phase2bInstallBinaries() error { ps.logf("Phase 2b: Installing binaries...") @@ -305,9 +305,9 @@ func (ps *ProductionSetup) Phase2bInstallBinaries() error { ps.logf(" ⚠️ Olric install warning: %v", err) } - // Install DeBros binaries (source must be at /home/debros/src via SCP) + // Install Orama binaries (source must be at /home/orama/src via SCP) if err := ps.binaryInstaller.InstallDeBrosBinaries(ps.oramaHome); err != nil { - return fmt.Errorf("failed to install DeBros binaries: %w", err) + return fmt.Errorf("failed to install Orama binaries: %w", err) } // Install CoreDNS only for nameserver nodes @@ -471,7 +471,7 @@ func (ps *ProductionSetup) Phase2cInitializeServices(peerAddresses []string, vps } // Ensure all directories and files created during service initialization have correct ownership - // This is critical because directories/files created as root need to be owned by debros user + // This is critical because directories/files created as root need to be owned by orama user if err := ps.fsProvisioner.FixOwnership(); err != nil { return fmt.Errorf("failed to fix ownership after service initialization: %w", err) } @@ -564,7 +564,7 @@ func (ps *ProductionSetup) Phase4GenerateConfigs(peerAddresses []string, vpsIP s if err := os.WriteFile(olricConfigPath, []byte(olricConfig), 0644); err != nil { return fmt.Errorf("failed to save olric config: %w", err) } - exec.Command("chown", "debros:debros", olricConfigPath).Run() + exec.Command("chown", "orama:orama", olricConfigPath).Run() ps.logf(" ✓ Olric config generated") // Configure CoreDNS (if baseDomain is provided - this is the zone name) @@ -633,44 +633,44 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error { // IPFS service (unified - no bootstrap/node distinction) ipfsUnit := ps.serviceGenerator.GenerateIPFSService(ipfsBinary) - if err := ps.serviceController.WriteServiceUnit("debros-ipfs.service", ipfsUnit); err != nil { + if err := ps.serviceController.WriteServiceUnit("orama-ipfs.service", ipfsUnit); err != nil { return fmt.Errorf("failed to write IPFS service: %w", err) } - ps.logf(" ✓ IPFS service created: debros-ipfs.service") + ps.logf(" ✓ IPFS service created: orama-ipfs.service") // IPFS Cluster service clusterUnit := ps.serviceGenerator.GenerateIPFSClusterService(clusterBinary) - if err := ps.serviceController.WriteServiceUnit("debros-ipfs-cluster.service", clusterUnit); err != nil { + if err := ps.serviceController.WriteServiceUnit("orama-ipfs-cluster.service", clusterUnit); err != nil { return fmt.Errorf("failed to write IPFS Cluster service: %w", err) } - ps.logf(" ✓ IPFS Cluster service created: debros-ipfs-cluster.service") + ps.logf(" ✓ IPFS Cluster service created: orama-ipfs-cluster.service") // RQLite is managed internally by each node - no separate systemd service needed // Olric service olricUnit := ps.serviceGenerator.GenerateOlricService(olricBinary) - if err := ps.serviceController.WriteServiceUnit("debros-olric.service", olricUnit); err != nil { + if err := ps.serviceController.WriteServiceUnit("orama-olric.service", olricUnit); err != nil { return fmt.Errorf("failed to write Olric service: %w", err) } ps.logf(" ✓ Olric service created") // Node service (unified - includes embedded gateway) nodeUnit := ps.serviceGenerator.GenerateNodeService() - if err := ps.serviceController.WriteServiceUnit("debros-node.service", nodeUnit); err != nil { + if err := ps.serviceController.WriteServiceUnit("orama-node.service", nodeUnit); err != nil { return fmt.Errorf("failed to write Node service: %w", err) } - ps.logf(" ✓ Node service created: debros-node.service (with embedded gateway)") + ps.logf(" ✓ Node service created: orama-node.service (with embedded gateway)") // Anyone Relay service (only created when --anyone-relay flag is used) if ps.IsAnyoneRelay() { anyoneUnit := ps.serviceGenerator.GenerateAnyoneRelayService() - if err := ps.serviceController.WriteServiceUnit("debros-anyone-relay.service", anyoneUnit); err != nil { + if err := ps.serviceController.WriteServiceUnit("orama-anyone-relay.service", anyoneUnit); err != nil { return fmt.Errorf("failed to write Anyone Relay service: %w", err) } ps.logf(" ✓ Anyone Relay service created (operator mode, ORPort: %d)", ps.anyoneRelayConfig.ORPort) } else if ps.IsAnyoneClient() { anyoneUnit := ps.serviceGenerator.GenerateAnyoneRelayService() - if err := ps.serviceController.WriteServiceUnit("debros-anyone-relay.service", anyoneUnit); err != nil { + if err := ps.serviceController.WriteServiceUnit("orama-anyone-relay.service", anyoneUnit); err != nil { return fmt.Errorf("failed to write Anyone client service: %w", err) } ps.logf(" ✓ Anyone client service created (SocksPort 9050)") @@ -712,13 +712,13 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error { ps.logf(" ✓ Systemd daemon reloaded") // Enable services (unified names - no bootstrap/node distinction) - // Note: debros-gateway.service is no longer needed - each node has an embedded gateway - // Note: debros-rqlite.service is NOT created - RQLite is managed by each node internally - services := []string{"debros-ipfs.service", "debros-ipfs-cluster.service", "debros-olric.service", "debros-node.service"} + // Note: orama-gateway.service is no longer needed - each node has an embedded gateway + // Note: orama-rqlite.service is NOT created - RQLite is managed by each node internally + services := []string{"orama-ipfs.service", "orama-ipfs-cluster.service", "orama-olric.service", "orama-node.service"} // Add Anyone service if configured (relay or client) if ps.IsAnyoneRelay() || ps.IsAnyoneClient() { - services = append(services, "debros-anyone-relay.service") + services = append(services, "orama-anyone-relay.service") } // Add CoreDNS only for nameserver nodes @@ -744,7 +744,7 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error { ps.logf(" Starting services...") // Start infrastructure first (IPFS, Olric, Anyone) - RQLite is managed internally by each node - infraServices := []string{"debros-ipfs.service", "debros-olric.service"} + infraServices := []string{"orama-ipfs.service", "orama-olric.service"} // Add Anyone service if configured (relay or client) if ps.IsAnyoneRelay() { @@ -754,12 +754,12 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error { } if ps.portChecker.IsPortInUse(orPort) { ps.logf(" ℹ️ ORPort %d is already in use (existing anon relay running)", orPort) - ps.logf(" ℹ️ Skipping debros-anyone-relay startup - using existing service") + ps.logf(" ℹ️ Skipping orama-anyone-relay startup - using existing service") } else { - infraServices = append(infraServices, "debros-anyone-relay.service") + infraServices = append(infraServices, "orama-anyone-relay.service") } } else if ps.IsAnyoneClient() { - infraServices = append(infraServices, "debros-anyone-relay.service") + infraServices = append(infraServices, "orama-anyone-relay.service") } for _, svc := range infraServices { @@ -774,17 +774,17 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error { time.Sleep(2 * time.Second) // Start IPFS Cluster - if err := ps.serviceController.RestartService("debros-ipfs-cluster.service"); err != nil { - ps.logf(" ⚠️ Failed to start debros-ipfs-cluster.service: %v", err) + if err := ps.serviceController.RestartService("orama-ipfs-cluster.service"); err != nil { + ps.logf(" ⚠️ Failed to start orama-ipfs-cluster.service: %v", err) } else { - ps.logf(" - debros-ipfs-cluster.service started") + ps.logf(" - orama-ipfs-cluster.service started") } // Start node service (gateway is embedded in node, no separate service needed) - if err := ps.serviceController.RestartService("debros-node.service"); err != nil { - ps.logf(" ⚠️ Failed to start debros-node.service: %v", err) + if err := ps.serviceController.RestartService("orama-node.service"); err != nil { + ps.logf(" ⚠️ Failed to start orama-node.service: %v", err) } else { - ps.logf(" - debros-node.service started (with embedded gateway)") + ps.logf(" - orama-node.service started (with embedded gateway)") } // Start CoreDNS (nameserver nodes only) @@ -798,7 +798,7 @@ func (ps *ProductionSetup) Phase5CreateSystemdServices(enableHTTPS bool) error { } } // Start Caddy on ALL nodes (any node may host namespaces and need TLS) - // Caddy depends on debros-node.service (gateway on :6001), so start after node + // Caddy depends on orama-node.service (gateway on :6001), so start after node if _, err := os.Stat("/usr/bin/caddy"); err == nil { if err := ps.serviceController.RestartService("caddy.service"); err != nil { ps.logf(" ⚠️ Failed to start caddy.service: %v", err) @@ -955,8 +955,8 @@ func (ps *ProductionSetup) LogSetupComplete(peerID string) { ps.logf(strings.Repeat("=", 70)) ps.logf("\nNode Peer ID: %s", peerID) ps.logf("\nService Management:") - ps.logf(" systemctl status debros-ipfs") - ps.logf(" journalctl -u debros-node -f") + ps.logf(" systemctl status orama-ipfs") + ps.logf(" journalctl -u orama-node -f") ps.logf(" tail -f %s/logs/node.log", ps.oramaDir) ps.logf("\nLog Files:") ps.logf(" %s/logs/ipfs.log", ps.oramaDir) @@ -969,7 +969,7 @@ func (ps *ProductionSetup) LogSetupComplete(peerID string) { if ps.IsAnyoneRelay() { ps.logf(" /var/log/anon/notices.log (Anyone Relay)") ps.logf("\nStart All Services:") - ps.logf(" systemctl start debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-node") + ps.logf(" systemctl start orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-node") ps.logf("\nAnyone Relay Operator:") ps.logf(" ORPort: %d", ps.anyoneRelayConfig.ORPort) ps.logf(" Wallet: %s", ps.anyoneRelayConfig.Wallet) @@ -978,7 +978,7 @@ func (ps *ProductionSetup) LogSetupComplete(peerID string) { ps.logf(" IMPORTANT: You need 100 $ANYONE tokens in your wallet to receive rewards") } else { ps.logf("\nStart All Services:") - ps.logf(" systemctl start debros-ipfs debros-ipfs-cluster debros-olric debros-node") + ps.logf(" systemctl start orama-ipfs orama-ipfs-cluster orama-olric orama-node") } ps.logf("\nVerify Installation:") diff --git a/pkg/environments/production/provisioner.go b/pkg/environments/production/provisioner.go index 7c5dc7d..6b54ed9 100644 --- a/pkg/environments/production/provisioner.go +++ b/pkg/environments/production/provisioner.go @@ -12,7 +12,7 @@ import ( type FilesystemProvisioner struct { oramaHome string oramaDir string - logWriter interface{} // Can be io.Writer for logging + logWriter interface{} // Can be io.Writer for logging } // NewFilesystemProvisioner creates a new provisioner @@ -81,30 +81,30 @@ func (fp *FilesystemProvisioner) EnsureDirectoryStructure() error { return nil } -// FixOwnership changes ownership of .orama directory to debros user +// FixOwnership changes ownership of .orama directory to orama user func (fp *FilesystemProvisioner) FixOwnership() error { // Fix entire .orama directory recursively (includes all data, configs, logs, etc.) - cmd := exec.Command("chown", "-R", "debros:debros", fp.oramaDir) + cmd := exec.Command("chown", "-R", "orama:orama", fp.oramaDir) if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", fp.oramaDir, err, string(output)) } // Also fix home directory ownership - cmd = exec.Command("chown", "debros:debros", fp.oramaHome) + cmd = exec.Command("chown", "orama:orama", fp.oramaHome) if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", fp.oramaHome, err, string(output)) } // Fix bin directory binDir := filepath.Join(fp.oramaHome, "bin") - cmd = exec.Command("chown", "-R", "debros:debros", binDir) + cmd = exec.Command("chown", "-R", "orama:orama", binDir) if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", binDir, err, string(output)) } // Fix npm cache directory npmDir := filepath.Join(fp.oramaHome, ".npm") - cmd = exec.Command("chown", "-R", "debros:debros", npmDir) + cmd = exec.Command("chown", "-R", "orama:orama", npmDir) if output, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to set ownership for %s: %w\nOutput: %s", npmDir, err, string(output)) } @@ -157,8 +157,8 @@ func (up *UserProvisioner) SetupSudoersAccess(invokerUser string) error { return nil // Skip if no invoker } - sudoersRule := fmt.Sprintf("%s ALL=(debros) NOPASSWD: ALL\n", invokerUser) - sudoersFile := "/etc/sudoers.d/debros-access" + sudoersRule := fmt.Sprintf("%s ALL=(orama) NOPASSWD: ALL\n", invokerUser) + sudoersFile := "/etc/sudoers.d/orama-access" // Check if rule already exists if existing, err := os.ReadFile(sudoersFile); err == nil { @@ -182,31 +182,31 @@ func (up *UserProvisioner) SetupSudoersAccess(invokerUser string) error { return nil } -// SetupDeploymentSudoers configures the debros user with permissions needed for +// SetupDeploymentSudoers configures the orama user with permissions needed for // managing user deployments via systemd services. func (up *UserProvisioner) SetupDeploymentSudoers() error { - sudoersFile := "/etc/sudoers.d/debros-deployments" + sudoersFile := "/etc/sudoers.d/orama-deployments" // Check if already configured if _, err := os.Stat(sudoersFile); err == nil { return nil // Already configured } - sudoersContent := `# DeBros Network - Deployment Management Permissions -# Allows debros user to manage systemd services for user deployments + sudoersContent := `# Orama Network - Deployment Management Permissions +# Allows orama user to manage systemd services for user deployments # Systemd service management for orama-deploy-* services -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl daemon-reload -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl start orama-deploy-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop orama-deploy-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart orama-deploy-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable orama-deploy-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl disable orama-deploy-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl status orama-deploy-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl daemon-reload +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl start orama-deploy-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop orama-deploy-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart orama-deploy-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable orama-deploy-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl disable orama-deploy-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl status orama-deploy-* # Service file management (tee to write, rm to remove) -debros ALL=(ALL) NOPASSWD: /usr/bin/tee /etc/systemd/system/orama-deploy-*.service -debros ALL=(ALL) NOPASSWD: /bin/rm -f /etc/systemd/system/orama-deploy-*.service +orama ALL=(ALL) NOPASSWD: /usr/bin/tee /etc/systemd/system/orama-deploy-*.service +orama ALL=(ALL) NOPASSWD: /bin/rm -f /etc/systemd/system/orama-deploy-*.service ` // Write sudoers rule @@ -224,36 +224,36 @@ debros ALL=(ALL) NOPASSWD: /bin/rm -f /etc/systemd/system/orama-deploy-*.service return nil } -// SetupNamespaceSudoers configures the debros user with permissions needed for +// SetupNamespaceSudoers configures the orama user with permissions needed for // managing namespace cluster services via systemd. func (up *UserProvisioner) SetupNamespaceSudoers() error { - sudoersFile := "/etc/sudoers.d/debros-namespaces" + sudoersFile := "/etc/sudoers.d/orama-namespaces" // Check if already configured if _, err := os.Stat(sudoersFile); err == nil { return nil // Already configured } - sudoersContent := `# DeBros Network - Namespace Cluster Management Permissions -# Allows debros user to manage systemd services for namespace clusters + sudoersContent := `# Orama Network - Namespace Cluster Management Permissions +# Allows orama user to manage systemd services for namespace clusters -# Systemd service management for debros-namespace-* services -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl daemon-reload -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl start debros-namespace-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop debros-namespace-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart debros-namespace-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable debros-namespace-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl disable debros-namespace-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl status debros-namespace-* -debros ALL=(ALL) NOPASSWD: /usr/bin/systemctl is-active debros-namespace-* +# Systemd service management for orama-namespace-* services +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl daemon-reload +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl start orama-namespace-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop orama-namespace-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart orama-namespace-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable orama-namespace-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl disable orama-namespace-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl status orama-namespace-* +orama ALL=(ALL) NOPASSWD: /usr/bin/systemctl is-active orama-namespace-* # Service file management (tee to write, rm to remove) -debros ALL=(ALL) NOPASSWD: /usr/bin/tee /etc/systemd/system/debros-namespace-*.service -debros ALL=(ALL) NOPASSWD: /bin/rm -f /etc/systemd/system/debros-namespace-*.service +orama ALL=(ALL) NOPASSWD: /usr/bin/tee /etc/systemd/system/orama-namespace-*.service +orama ALL=(ALL) NOPASSWD: /bin/rm -f /etc/systemd/system/orama-namespace-*.service # Environment file management for namespace services -debros ALL=(ALL) NOPASSWD: /usr/bin/tee /home/debros/.orama/namespace/*/env/* -debros ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /home/debros/.orama/namespace/*/env +orama ALL=(ALL) NOPASSWD: /usr/bin/tee /home/orama/.orama/namespace/*/env/* +orama ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /home/orama/.orama/namespace/*/env ` // Write sudoers rule @@ -271,17 +271,17 @@ debros ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /home/debros/.orama/namespace/*/env return nil } -// SetupWireGuardSudoers configures the debros user with permissions to manage WireGuard +// SetupWireGuardSudoers configures the orama user with permissions to manage WireGuard func (up *UserProvisioner) SetupWireGuardSudoers() error { - sudoersFile := "/etc/sudoers.d/debros-wireguard" + sudoersFile := "/etc/sudoers.d/orama-wireguard" - sudoersContent := `# DeBros Network - WireGuard Management Permissions -# Allows debros user to manage WireGuard peers + sudoersContent := `# Orama Network - WireGuard Management Permissions +# Allows orama user to manage WireGuard peers -debros ALL=(ALL) NOPASSWD: /usr/bin/wg set wg0 * -debros ALL=(ALL) NOPASSWD: /usr/bin/wg show wg0 -debros ALL=(ALL) NOPASSWD: /usr/bin/wg showconf wg0 -debros ALL=(ALL) NOPASSWD: /usr/bin/tee /etc/wireguard/wg0.conf +orama ALL=(ALL) NOPASSWD: /usr/bin/wg set wg0 * +orama ALL=(ALL) NOPASSWD: /usr/bin/wg show wg0 +orama ALL=(ALL) NOPASSWD: /usr/bin/wg showconf wg0 +orama ALL=(ALL) NOPASSWD: /usr/bin/tee /etc/wireguard/wg0.conf ` // Write sudoers rule (always overwrite to ensure latest) diff --git a/pkg/environments/production/services.go b/pkg/environments/production/services.go index 27b3fca..5de197f 100644 --- a/pkg/environments/production/services.go +++ b/pkg/environments/production/services.go @@ -34,8 +34,8 @@ Wants=network-online.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama Environment=HOME=%[1]s Environment=IPFS_PATH=%[2]s ExecStartPre=/bin/bash -c 'if [ -f %[3]s/secrets/swarm.key ] && [ ! -f %[2]s/swarm.key ]; then cp %[3]s/secrets/swarm.key %[2]s/swarm.key && chmod 600 %[2]s/swarm.key; fi' @@ -44,7 +44,7 @@ Restart=always RestartSec=5 StandardOutput=append:%[4]s StandardError=append:%[4]s -SyslogIdentifier=debros-ipfs +SyslogIdentifier=orama-ipfs NoNewPrivileges=yes PrivateTmp=yes @@ -80,14 +80,14 @@ func (ssg *SystemdServiceGenerator) GenerateIPFSClusterService(clusterBinary str return fmt.Sprintf(`[Unit] Description=IPFS Cluster Service -After=debros-ipfs.service -Wants=debros-ipfs.service -Requires=debros-ipfs.service +After=orama-ipfs.service +Wants=orama-ipfs.service +Requires=orama-ipfs.service [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory=%[1]s Environment=HOME=%[1]s Environment=IPFS_CLUSTER_PATH=%[2]s @@ -99,7 +99,7 @@ Restart=always RestartSec=5 StandardOutput=append:%[3]s StandardError=append:%[3]s -SyslogIdentifier=debros-ipfs-cluster +SyslogIdentifier=orama-ipfs-cluster NoNewPrivileges=yes PrivateTmp=yes @@ -150,15 +150,15 @@ Wants=network-online.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama Environment=HOME=%[1]s ExecStart=%[5]s %[2]s Restart=always RestartSec=5 StandardOutput=append:%[3]s StandardError=append:%[3]s -SyslogIdentifier=debros-rqlite +SyslogIdentifier=orama-rqlite NoNewPrivileges=yes PrivateTmp=yes @@ -191,8 +191,8 @@ Wants=network-online.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama Environment=HOME=%[1]s Environment=OLRIC_SERVER_CONFIG=%[2]s ExecStart=%[5]s @@ -222,7 +222,7 @@ WantedBy=multi-user.target `, ssg.oramaHome, olricConfigPath, logFile, ssg.oramaDir, olricBinary) } -// GenerateNodeService generates the DeBros Node systemd unit +// GenerateNodeService generates the Orama Node systemd unit func (ssg *SystemdServiceGenerator) GenerateNodeService() string { configFile := "node.yaml" logFile := filepath.Join(ssg.oramaDir, "logs", "node.log") @@ -230,15 +230,15 @@ func (ssg *SystemdServiceGenerator) GenerateNodeService() string { // Use absolute paths directly as they will be resolved by systemd at runtime return fmt.Sprintf(`[Unit] -Description=DeBros Network Node -After=debros-ipfs-cluster.service debros-olric.service wg-quick@wg0.service -Wants=debros-ipfs-cluster.service debros-olric.service +Description=Orama Network Node +After=orama-ipfs-cluster.service orama-olric.service wg-quick@wg0.service +Wants=orama-ipfs-cluster.service orama-olric.service Requires=wg-quick@wg0.service [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory=%[1]s Environment=HOME=%[1]s ExecStart=%[1]s/bin/orama-node --config %[2]s/configs/%[3]s @@ -246,7 +246,7 @@ Restart=always RestartSec=5 StandardOutput=append:%[4]s StandardError=append:%[4]s -SyslogIdentifier=debros-node +SyslogIdentifier=orama-node NoNewPrivileges=yes PrivateTmp=yes @@ -269,18 +269,18 @@ WantedBy=multi-user.target `, ssg.oramaHome, ssg.oramaDir, configFile, logFile) } -// GenerateGatewayService generates the DeBros Gateway systemd unit +// GenerateGatewayService generates the Orama Gateway systemd unit func (ssg *SystemdServiceGenerator) GenerateGatewayService() string { logFile := filepath.Join(ssg.oramaDir, "logs", "gateway.log") return fmt.Sprintf(`[Unit] -Description=DeBros Gateway -After=debros-node.service debros-olric.service -Wants=debros-node.service debros-olric.service +Description=Orama Gateway +After=orama-node.service orama-olric.service +Wants=orama-node.service orama-olric.service [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory=%[1]s Environment=HOME=%[1]s ExecStart=%[1]s/bin/gateway --config %[2]s/data/gateway.yaml @@ -288,7 +288,7 @@ Restart=always RestartSec=5 StandardOutput=append:%[3]s StandardError=append:%[3]s -SyslogIdentifier=debros-gateway +SyslogIdentifier=orama-gateway AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE @@ -325,8 +325,8 @@ Wants=network-online.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama Environment=HOME=%[1]s Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/lib/node_modules/.bin WorkingDirectory=%[1]s @@ -400,8 +400,8 @@ func (ssg *SystemdServiceGenerator) GenerateCoreDNSService() string { return `[Unit] Description=CoreDNS DNS Server with RQLite backend Documentation=https://coredns.io -After=network-online.target debros-node.service -Wants=network-online.target debros-node.service +After=network-online.target orama-node.service +Wants=network-online.target orama-node.service [Service] Type=simple @@ -429,9 +429,9 @@ func (ssg *SystemdServiceGenerator) GenerateCaddyService() string { return `[Unit] Description=Caddy HTTP/2 Server Documentation=https://caddyserver.com/docs/ -After=network-online.target debros-node.service coredns.service +After=network-online.target orama-node.service coredns.service Wants=network-online.target -Wants=debros-node.service +Wants=orama-node.service [Service] Type=simple diff --git a/pkg/environments/production/services_test.go b/pkg/environments/production/services_test.go index 70d24ef..70cc372 100644 --- a/pkg/environments/production/services_test.go +++ b/pkg/environments/production/services_test.go @@ -47,8 +47,8 @@ func TestGenerateRQLiteService(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ssg := &SystemdServiceGenerator{ - oramaHome: "/home/debros", - oramaDir: "/home/debros/.orama", + oramaHome: "/home/orama", + oramaDir: "/home/orama/.orama", } unit := ssg.GenerateRQLiteService("/usr/local/bin/rqlited", 5001, 7001, tt.joinAddr, tt.advertiseIP) @@ -81,8 +81,8 @@ func TestGenerateRQLiteService(t *testing.T) { // TestGenerateRQLiteServiceArgs verifies the ExecStart command arguments func TestGenerateRQLiteServiceArgs(t *testing.T) { ssg := &SystemdServiceGenerator{ - oramaHome: "/home/debros", - oramaDir: "/home/debros/.orama", + oramaHome: "/home/orama", + oramaDir: "/home/orama/.orama", } unit := ssg.GenerateRQLiteService("/usr/local/bin/rqlited", 5001, 7001, "10.0.0.1:7001", "10.0.0.2") diff --git a/pkg/environments/production/wireguard.go b/pkg/environments/production/wireguard.go index 5097066..fb2a646 100644 --- a/pkg/environments/production/wireguard.go +++ b/pkg/environments/production/wireguard.go @@ -145,7 +145,7 @@ func (wp *WireGuardProvisioner) WriteConfig() error { } } - // Fallback to sudo tee (for non-root, e.g. debros user) + // Fallback to sudo tee (for non-root, e.g. orama user) cmd := exec.Command("sudo", "tee", confPath) cmd.Stdin = strings.NewReader(content) if output, err := cmd.CombinedOutput(); err != nil { diff --git a/pkg/environments/templates/render.go b/pkg/environments/templates/render.go index a30ef0e..4253c26 100644 --- a/pkg/environments/templates/render.go +++ b/pkg/environments/templates/render.go @@ -17,8 +17,8 @@ type NodeConfigData struct { P2PPort int DataDir string RQLiteHTTPPort int - RQLiteRaftPort int // External Raft port for advertisement (7001 for SNI) - RQLiteRaftInternalPort int // Internal Raft port for local binding (7002 when SNI enabled) + RQLiteRaftPort int // External Raft port for advertisement (7001 for SNI) + RQLiteRaftInternalPort int // Internal Raft port for local binding (7002 when SNI enabled) RQLiteJoinAddress string // Optional: join address for joining existing cluster BootstrapPeers []string // List of peer multiaddrs to connect to ClusterAPIPort int @@ -58,13 +58,13 @@ type GatewayConfigData struct { // OlricConfigData holds parameters for olric.yaml rendering type OlricConfigData struct { - ServerBindAddr string // HTTP API bind address (127.0.0.1 for security) - HTTPPort int - MemberlistBindAddr string // Memberlist bind address (WG IP for clustering) - MemberlistPort int - MemberlistEnvironment string // "local", "lan", or "wan" + ServerBindAddr string // HTTP API bind address (127.0.0.1 for security) + HTTPPort int + MemberlistBindAddr string // Memberlist bind address (WG IP for clustering) + MemberlistPort int + MemberlistEnvironment string // "local", "lan", or "wan" MemberlistAdvertiseAddr string // Advertise address (WG IP) so other nodes can reach us - Peers []string // Seed peers for memberlist (host:port) + Peers []string // Seed peers for memberlist (host:port) } // SystemdIPFSData holds parameters for systemd IPFS service rendering @@ -72,33 +72,33 @@ type SystemdIPFSData struct { HomeDir string IPFSRepoPath string SecretsDir string - OramaDir string + OramaDir string } // SystemdIPFSClusterData holds parameters for systemd IPFS Cluster service rendering type SystemdIPFSClusterData struct { HomeDir string ClusterPath string - OramaDir string + OramaDir string } // SystemdOlricData holds parameters for systemd Olric service rendering type SystemdOlricData struct { HomeDir string ConfigPath string - OramaDir string + OramaDir string } // SystemdNodeData holds parameters for systemd Node service rendering type SystemdNodeData struct { HomeDir string ConfigFile string - OramaDir string + OramaDir string } // SystemdGatewayData holds parameters for systemd Gateway service rendering type SystemdGatewayData struct { - HomeDir string + HomeDir string OramaDir string } @@ -132,12 +132,12 @@ func RenderOlricService(data SystemdOlricData) (string, error) { return renderTemplate("systemd_olric.service", data) } -// RenderNodeService renders the DeBros Node systemd service template +// RenderNodeService renders the Orama Node systemd service template func RenderNodeService(data SystemdNodeData) (string, error) { return renderTemplate("systemd_node.service", data) } -// RenderGatewayService renders the DeBros Gateway systemd service template +// RenderGatewayService renders the Orama Gateway systemd service template func RenderGatewayService(data SystemdGatewayData) (string, error) { return renderTemplate("systemd_gateway.service", data) } diff --git a/pkg/environments/templates/render_test.go b/pkg/environments/templates/render_test.go index 3123f64..e82c832 100644 --- a/pkg/environments/templates/render_test.go +++ b/pkg/environments/templates/render_test.go @@ -10,7 +10,7 @@ func TestRenderNodeConfig(t *testing.T) { data := NodeConfigData{ NodeID: "node2", P2PPort: 4002, - DataDir: "/home/debros/.orama/node2", + DataDir: "/home/orama/.orama/node2", RQLiteHTTPPort: 5002, RQLiteRaftPort: 7002, RQLiteJoinAddress: "localhost:5001", diff --git a/pkg/environments/templates/systemd_gateway.service b/pkg/environments/templates/systemd_gateway.service index 89d3cca..ee62d54 100644 --- a/pkg/environments/templates/systemd_gateway.service +++ b/pkg/environments/templates/systemd_gateway.service @@ -1,12 +1,12 @@ [Unit] -Description=DeBros Gateway -After=debros-node.service -Wants=debros-node.service +Description=Orama Gateway +After=orama-node.service +Wants=orama-node.service [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory={{.HomeDir}} Environment=HOME={{.HomeDir}} ExecStart={{.HomeDir}}/bin/gateway --config {{.OramaDir}}/data/gateway.yaml @@ -14,7 +14,7 @@ Restart=always RestartSec=5 StandardOutput=journal StandardError=journal -SyslogIdentifier=debros-gateway +SyslogIdentifier=orama-gateway AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE diff --git a/pkg/environments/templates/systemd_ipfs.service b/pkg/environments/templates/systemd_ipfs.service index d858523..ab61bbc 100644 --- a/pkg/environments/templates/systemd_ipfs.service +++ b/pkg/environments/templates/systemd_ipfs.service @@ -5,8 +5,8 @@ Wants=network-online.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama Environment=HOME={{.HomeDir}} Environment=IPFS_PATH={{.IPFSRepoPath}} ExecStartPre=/bin/bash -c 'if [ -f {{.SecretsDir}}/swarm.key ] && [ ! -f {{.IPFSRepoPath}}/swarm.key ]; then cp {{.SecretsDir}}/swarm.key {{.IPFSRepoPath}}/swarm.key && chmod 600 {{.IPFSRepoPath}}/swarm.key; fi' diff --git a/pkg/environments/templates/systemd_ipfs_cluster.service b/pkg/environments/templates/systemd_ipfs_cluster.service index b6bc365..5701ea9 100644 --- a/pkg/environments/templates/systemd_ipfs_cluster.service +++ b/pkg/environments/templates/systemd_ipfs_cluster.service @@ -1,13 +1,13 @@ [Unit] Description=IPFS Cluster Service ({{.NodeType}}) -After=debros-ipfs-{{.NodeType}}.service -Wants=debros-ipfs-{{.NodeType}}.service -Requires=debros-ipfs-{{.NodeType}}.service +After=orama-ipfs-{{.NodeType}}.service +Wants=orama-ipfs-{{.NodeType}}.service +Requires=orama-ipfs-{{.NodeType}}.service [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory={{.HomeDir}} Environment=HOME={{.HomeDir}} Environment=CLUSTER_PATH={{.ClusterPath}} diff --git a/pkg/environments/templates/systemd_node.service b/pkg/environments/templates/systemd_node.service index d30b77e..b20f8f5 100644 --- a/pkg/environments/templates/systemd_node.service +++ b/pkg/environments/templates/systemd_node.service @@ -1,13 +1,13 @@ [Unit] -Description=DeBros Network Node ({{.NodeType}}) -After=debros-ipfs-cluster-{{.NodeType}}.service -Wants=debros-ipfs-cluster-{{.NodeType}}.service -Requires=debros-ipfs-cluster-{{.NodeType}}.service +Description=Orama Network Node ({{.NodeType}}) +After=orama-ipfs-cluster-{{.NodeType}}.service +Wants=orama-ipfs-cluster-{{.NodeType}}.service +Requires=orama-ipfs-cluster-{{.NodeType}}.service [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama WorkingDirectory={{.HomeDir}} Environment=HOME={{.HomeDir}} ExecStart={{.HomeDir}}/bin/orama-node --config {{.OramaDir}}/configs/{{.ConfigFile}} @@ -15,7 +15,7 @@ Restart=always RestartSec=5 StandardOutput=journal StandardError=journal -SyslogIdentifier=debros-node-{{.NodeType}} +SyslogIdentifier=orama-node-{{.NodeType}} NoNewPrivileges=yes PrivateTmp=yes diff --git a/pkg/environments/templates/systemd_olric.service b/pkg/environments/templates/systemd_olric.service index f10268e..df12456 100644 --- a/pkg/environments/templates/systemd_olric.service +++ b/pkg/environments/templates/systemd_olric.service @@ -5,8 +5,8 @@ Wants=network-online.target [Service] Type=simple -User=debros -Group=debros +User=orama +Group=orama Environment=HOME={{.HomeDir}} Environment=OLRIC_SERVER_CONFIG={{.ConfigPath}} ExecStart=/usr/local/bin/olric-server diff --git a/pkg/gateway/anon_proxy_handler.go b/pkg/gateway/anon_proxy_handler.go index e6fe987..6683c45 100644 --- a/pkg/gateway/anon_proxy_handler.go +++ b/pkg/gateway/anon_proxy_handler.go @@ -127,7 +127,7 @@ func (g *Gateway) anonProxyHandler(w http.ResponseWriter, r *http.Request) { // Set default User-Agent if not provided if proxyReq.Header.Get("User-Agent") == "" { - proxyReq.Header.Set("User-Agent", "DeBros-Gateway/1.0") + proxyReq.Header.Set("User-Agent", "Orama-Gateway/1.0") } // Log the proxy request diff --git a/pkg/gateway/auth/jwt.go b/pkg/gateway/auth/jwt.go index b5da8c6..7891c3b 100644 --- a/pkg/gateway/auth/jwt.go +++ b/pkg/gateway/auth/jwt.go @@ -157,7 +157,7 @@ func (s *Service) ParseAndVerifyJWT(token string) (*JWTClaims, error) { return nil, errors.New("invalid claims json") } // Validate issuer - if claims.Iss != "debros-gateway" { + if claims.Iss != "orama-gateway" { return nil, errors.New("invalid issuer") } // Validate registered claims @@ -199,7 +199,7 @@ func (s *Service) generateEdDSAJWT(ns, subject string, ttl time.Duration) (strin now := time.Now().UTC() exp := now.Add(ttl) payload := map[string]any{ - "iss": "debros-gateway", + "iss": "orama-gateway", "sub": subject, "aud": "gateway", "iat": now.Unix(), @@ -229,7 +229,7 @@ func (s *Service) generateRSAJWT(ns, subject string, ttl time.Duration) (string, now := time.Now().UTC() exp := now.Add(ttl) payload := map[string]any{ - "iss": "debros-gateway", + "iss": "orama-gateway", "sub": subject, "aud": "gateway", "iat": now.Unix(), diff --git a/pkg/gateway/auth/service_test.go b/pkg/gateway/auth/service_test.go index 55b418f..197451f 100644 --- a/pkg/gateway/auth/service_test.go +++ b/pkg/gateway/auth/service_test.go @@ -138,8 +138,8 @@ func TestJWTFlow(t *testing.T) { t.Errorf("expected namespace %s, got %s", ns, claims.Namespace) } - if claims.Iss != "debros-gateway" { - t.Errorf("expected issuer debros-gateway, got %s", claims.Iss) + if claims.Iss != "orama-gateway" { + t.Errorf("expected issuer orama-gateway, got %s", claims.Iss) } } @@ -257,7 +257,7 @@ func TestAlgorithmConfusion_Rejected(t *testing.T) { header := map[string]string{"alg": "none", "typ": "JWT"} hb, _ := json.Marshal(header) payload := map[string]any{ - "iss": "debros-gateway", "sub": "attacker", "aud": "gateway", + "iss": "orama-gateway", "sub": "attacker", "aud": "gateway", "iat": time.Now().Unix(), "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "namespace": "test-ns", } @@ -275,7 +275,7 @@ func TestAlgorithmConfusion_Rejected(t *testing.T) { header := map[string]string{"alg": "HS256", "typ": "JWT", "kid": s.keyID} hb, _ := json.Marshal(header) payload := map[string]any{ - "iss": "debros-gateway", "sub": "attacker", "aud": "gateway", + "iss": "orama-gateway", "sub": "attacker", "aud": "gateway", "iat": time.Now().Unix(), "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "namespace": "test-ns", } @@ -295,7 +295,7 @@ func TestAlgorithmConfusion_Rejected(t *testing.T) { header := map[string]string{"alg": "RS256", "typ": "JWT", "kid": s.edKeyID} hb, _ := json.Marshal(header) payload := map[string]any{ - "iss": "debros-gateway", "sub": "attacker", "aud": "gateway", + "iss": "orama-gateway", "sub": "attacker", "aud": "gateway", "iat": time.Now().Unix(), "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "namespace": "test-ns", } @@ -321,7 +321,7 @@ func TestAlgorithmConfusion_Rejected(t *testing.T) { header := map[string]string{"alg": "RS256", "typ": "JWT", "kid": "unknown-kid-123"} hb, _ := json.Marshal(header) payload := map[string]any{ - "iss": "debros-gateway", "sub": "attacker", "aud": "gateway", + "iss": "orama-gateway", "sub": "attacker", "aud": "gateway", "iat": time.Now().Unix(), "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "namespace": "test-ns", } @@ -341,7 +341,7 @@ func TestAlgorithmConfusion_Rejected(t *testing.T) { header := map[string]string{"alg": "EdDSA", "typ": "JWT"} hb, _ := json.Marshal(header) payload := map[string]any{ - "iss": "debros-gateway", "sub": "attacker", "aud": "gateway", + "iss": "orama-gateway", "sub": "attacker", "aud": "gateway", "iat": time.Now().Unix(), "nbf": time.Now().Unix(), "exp": time.Now().Add(time.Hour).Unix(), "namespace": "test-ns", } diff --git a/pkg/gateway/handlers/join/handler.go b/pkg/gateway/handlers/join/handler.go index a4ca6dd..fb7272b 100644 --- a/pkg/gateway/handlers/join/handler.go +++ b/pkg/gateway/handlers/join/handler.go @@ -65,7 +65,7 @@ type PeerInfo struct { type Handler struct { logger *zap.Logger rqliteClient rqlite.Client - oramaDir string // e.g., /home/debros/.orama + oramaDir string // e.g., /home/orama/.orama } // NewHandler creates a new join handler diff --git a/pkg/gateway/https.go b/pkg/gateway/https.go index 7ea2440..0eefa8c 100644 --- a/pkg/gateway/https.go +++ b/pkg/gateway/https.go @@ -59,7 +59,7 @@ func NewHTTPSGateway(logger *logging.ColoredLogger, cfg *config.HTTPGatewayConfi // Use Let's Encrypt STAGING (consistent with SNI gateway) cacheDir := cfg.HTTPS.CacheDir if cacheDir == "" { - cacheDir = "/home/debros/.orama/tls-cache" + cacheDir = "/home/orama/.orama/tls-cache" } // Use Let's Encrypt STAGING - provides higher rate limits for testing/development diff --git a/pkg/gateway/jwt_test.go b/pkg/gateway/jwt_test.go index 53b6278..c3afba0 100644 --- a/pkg/gateway/jwt_test.go +++ b/pkg/gateway/jwt_test.go @@ -32,7 +32,7 @@ func TestJWTGenerateAndParse(t *testing.T) { if err != nil { t.Fatalf("verify err: %v", err) } - if claims.Namespace != "ns1" || claims.Sub != "subj" || claims.Aud != "gateway" || claims.Iss != "debros-gateway" { + if claims.Namespace != "ns1" || claims.Sub != "subj" || claims.Aud != "gateway" || claims.Iss != "orama-gateway" { t.Fatalf("unexpected claims: %+v", claims) } } diff --git a/pkg/gateway/middleware_test.go b/pkg/gateway/middleware_test.go index 575127f..bef792b 100644 --- a/pkg/gateway/middleware_test.go +++ b/pkg/gateway/middleware_test.go @@ -28,7 +28,7 @@ func TestExtractAPIKey(t *testing.T) { } } -// TestDomainRoutingMiddleware_NonDebrosNetwork tests that non-debros domains pass through +// TestDomainRoutingMiddleware_NonDebrosNetwork tests that non-orama domains pass through func TestDomainRoutingMiddleware_NonDebrosNetwork(t *testing.T) { nextCalled := false next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -46,7 +46,7 @@ func TestDomainRoutingMiddleware_NonDebrosNetwork(t *testing.T) { middleware.ServeHTTP(rr, req) if !nextCalled { - t.Error("Expected next handler to be called for non-debros domain") + t.Error("Expected next handler to be called for non-orama domain") } if rr.Code != http.StatusOK { @@ -379,10 +379,10 @@ func TestSecurityHeadersMiddleware(t *testing.T) { expected := map[string]string{ "X-Content-Type-Options": "nosniff", - "X-Frame-Options": "DENY", - "X-Xss-Protection": "0", - "Referrer-Policy": "strict-origin-when-cross-origin", - "Permissions-Policy": "camera=(), microphone=(), geolocation=()", + "X-Frame-Options": "DENY", + "X-Xss-Protection": "0", + "Referrer-Policy": "strict-origin-when-cross-origin", + "Permissions-Policy": "camera=(), microphone=(), geolocation=()", } for header, want := range expected { got := rr.Header().Get(header) diff --git a/pkg/inspector/checks/anyone.go b/pkg/inspector/checks/anyone.go index d782627..dbc2199 100644 --- a/pkg/inspector/checks/anyone.go +++ b/pkg/inspector/checks/anyone.go @@ -42,7 +42,7 @@ func checkAnyonePerNode(nd *inspector.NodeData) []inspector.CheckResult { if a.RelayActive { r = append(r, inspector.Pass("anyone.relay_active", "Anyone relay service active", anyoneSub, node, - "debros-anyone-relay is active", inspector.High)) + "orama-anyone-relay is active", inspector.High)) } // --- Client-mode checks --- @@ -133,7 +133,7 @@ func checkAnyonePerNode(nd *inspector.NodeData) []inspector.CheckResult { // --- Legacy client checks (if also running client service) --- if a.ClientActive { r = append(r, inspector.Pass("anyone.client_active", "Anyone client service active", anyoneSub, node, - "debros-anyone-client is active", inspector.High)) + "orama-anyone-client is active", inspector.High)) if a.SocksListening { r = append(r, inspector.Pass("anyone.socks_listening", "SOCKS5 port 9050 listening", anyoneSub, node, diff --git a/pkg/inspector/checks/anyone_test.go b/pkg/inspector/checks/anyone_test.go index 55aff74..2d6e07d 100644 --- a/pkg/inspector/checks/anyone_test.go +++ b/pkg/inspector/checks/anyone_test.go @@ -55,7 +55,7 @@ func TestCheckAnyone_HealthyRelay(t *testing.T) { func TestCheckAnyone_HealthyClient(t *testing.T) { nd := makeNodeData("1.1.1.1", "nameserver") nd.Anyone = &inspector.AnyoneData{ - RelayActive: true, // service is debros-anyone-relay for both modes + RelayActive: true, // service is orama-anyone-relay for both modes Mode: "client", SocksListening: true, ControlListening: true, diff --git a/pkg/inspector/checks/ipfs.go b/pkg/inspector/checks/ipfs.go index 538b1ac..bf44f6f 100644 --- a/pkg/inspector/checks/ipfs.go +++ b/pkg/inspector/checks/ipfs.go @@ -36,20 +36,20 @@ func checkIPFSPerNode(nd *inspector.NodeData, data *inspector.ClusterData) []ins // 3.1 IPFS daemon running if ipfs.DaemonActive { r = append(r, inspector.Pass("ipfs.daemon_active", "IPFS daemon active", ipfsSub, node, - "debros-ipfs is active", inspector.Critical)) + "orama-ipfs is active", inspector.Critical)) } else { r = append(r, inspector.Fail("ipfs.daemon_active", "IPFS daemon active", ipfsSub, node, - "debros-ipfs is not active", inspector.Critical)) + "orama-ipfs is not active", inspector.Critical)) return r } // 3.2 IPFS Cluster running if ipfs.ClusterActive { r = append(r, inspector.Pass("ipfs.cluster_active", "IPFS Cluster active", ipfsSub, node, - "debros-ipfs-cluster is active", inspector.Critical)) + "orama-ipfs-cluster is active", inspector.Critical)) } else { r = append(r, inspector.Fail("ipfs.cluster_active", "IPFS Cluster active", ipfsSub, node, - "debros-ipfs-cluster is not active", inspector.Critical)) + "orama-ipfs-cluster is not active", inspector.Critical)) } // 3.6 Swarm peer count diff --git a/pkg/inspector/checks/olric.go b/pkg/inspector/checks/olric.go index 08eb6a0..5dbfd4c 100644 --- a/pkg/inspector/checks/olric.go +++ b/pkg/inspector/checks/olric.go @@ -36,10 +36,10 @@ func checkOlricPerNode(nd *inspector.NodeData) []inspector.CheckResult { // 2.1 Service active if ol.ServiceActive { r = append(r, inspector.Pass("olric.service_active", "Olric service active", olricSub, node, - "debros-olric is active", inspector.Critical)) + "orama-olric is active", inspector.Critical)) } else { r = append(r, inspector.Fail("olric.service_active", "Olric service active", olricSub, node, - "debros-olric is not active", inspector.Critical)) + "orama-olric is not active", inspector.Critical)) return r } diff --git a/pkg/inspector/checks/system.go b/pkg/inspector/checks/system.go index 4f6a5fa..262c580 100644 --- a/pkg/inspector/checks/system.go +++ b/pkg/inspector/checks/system.go @@ -34,7 +34,7 @@ func checkSystemPerNode(nd *inspector.NodeData) []inspector.CheckResult { node := nd.Node.Name() // 6.1 Core services active - coreServices := []string{"debros-node", "debros-olric", "debros-ipfs", "debros-ipfs-cluster"} + coreServices := []string{"orama-node", "orama-olric", "orama-ipfs", "orama-ipfs-cluster"} for _, svc := range coreServices { status, ok := sys.Services[svc] if !ok { @@ -51,7 +51,7 @@ func checkSystemPerNode(nd *inspector.NodeData) []inspector.CheckResult { } // 6.2 Anyone relay/client services (only check if installed, don't fail if absent) - for _, svc := range []string{"debros-anyone-relay", "debros-anyone-client"} { + for _, svc := range []string{"orama-anyone-relay", "orama-anyone-client"} { status, ok := sys.Services[svc] if !ok || status == "inactive" { continue // not installed or intentionally stopped @@ -94,21 +94,21 @@ func checkSystemPerNode(nd *inspector.NodeData) []inspector.CheckResult { } } - // 6.6 Failed systemd units (only debros-related units count as failures) - var debrosUnits, externalUnits []string + // 6.6 Failed systemd units (only orama-related units count as failures) + var oramaUnits, externalUnits []string for _, u := range sys.FailedUnits { - if strings.HasPrefix(u, "debros-") || u == "wg-quick@wg0.service" || u == "caddy.service" || u == "coredns.service" { - debrosUnits = append(debrosUnits, u) + if strings.HasPrefix(u, "orama-") || u == "wg-quick@wg0.service" || u == "caddy.service" || u == "coredns.service" { + oramaUnits = append(oramaUnits, u) } else { externalUnits = append(externalUnits, u) } } - if len(debrosUnits) > 0 { - r = append(r, inspector.Fail("system.no_failed_units", "No failed debros systemd units", systemSub, node, - fmt.Sprintf("failed: %s", strings.Join(debrosUnits, ", ")), inspector.High)) + if len(oramaUnits) > 0 { + r = append(r, inspector.Fail("system.no_failed_units", "No failed orama systemd units", systemSub, node, + fmt.Sprintf("failed: %s", strings.Join(oramaUnits, ", ")), inspector.High)) } else { - r = append(r, inspector.Pass("system.no_failed_units", "No failed debros systemd units", systemSub, node, - "no failed debros units", inspector.High)) + r = append(r, inspector.Pass("system.no_failed_units", "No failed orama systemd units", systemSub, node, + "no failed orama units", inspector.High)) } if len(externalUnits) > 0 { r = append(r, inspector.Warn("system.external_failed_units", "External systemd units healthy", systemSub, node, @@ -217,15 +217,15 @@ func checkSystemPerNode(nd *inspector.NodeData) []inspector.CheckResult { // 6.23 Process user if sys.ProcessUser != "" && sys.ProcessUser != "unknown" { - if sys.ProcessUser == "debros" { - r = append(r, inspector.Pass("system.process_user", "debros-node runs as correct user", systemSub, node, - "user=debros", inspector.High)) + if sys.ProcessUser == "orama" { + r = append(r, inspector.Pass("system.process_user", "orama-node runs as correct user", systemSub, node, + "user=orama", inspector.High)) } else if sys.ProcessUser == "root" { - r = append(r, inspector.Warn("system.process_user", "debros-node runs as correct user", systemSub, node, - "user=root (should be debros)", inspector.High)) + r = append(r, inspector.Warn("system.process_user", "orama-node runs as correct user", systemSub, node, + "user=root (should be orama)", inspector.High)) } else { - r = append(r, inspector.Warn("system.process_user", "debros-node runs as correct user", systemSub, node, - fmt.Sprintf("user=%s (expected debros)", sys.ProcessUser), inspector.Medium)) + r = append(r, inspector.Warn("system.process_user", "orama-node runs as correct user", systemSub, node, + fmt.Sprintf("user=%s (expected orama)", sys.ProcessUser), inspector.Medium)) } } diff --git a/pkg/inspector/checks/system_test.go b/pkg/inspector/checks/system_test.go index ae06954..9efea65 100644 --- a/pkg/inspector/checks/system_test.go +++ b/pkg/inspector/checks/system_test.go @@ -10,11 +10,11 @@ func TestCheckSystem_HealthyNode(t *testing.T) { nd := makeNodeData("1.1.1.1", "node") nd.System = &inspector.SystemData{ Services: map[string]string{ - "debros-node": "active", - "debros-olric": "active", - "debros-ipfs": "active", - "debros-ipfs-cluster": "active", - "wg-quick@wg0": "active", + "orama-node": "active", + "orama-olric": "active", + "orama-ipfs": "active", + "orama-ipfs-cluster": "active", + "wg-quick@wg0": "active", }, FailedUnits: nil, MemTotalMB: 8192, @@ -31,17 +31,17 @@ func TestCheckSystem_HealthyNode(t *testing.T) { InodePct: 10, ListeningPorts: []int{5001, 3322, 6001, 4501}, UFWActive: true, - ProcessUser: "debros", + ProcessUser: "orama", PanicCount: 0, } data := makeCluster(map[string]*inspector.NodeData{"1.1.1.1": nd}) results := CheckSystem(data) - expectStatus(t, results, "system.svc_debros_node", inspector.StatusPass) - expectStatus(t, results, "system.svc_debros_olric", inspector.StatusPass) - expectStatus(t, results, "system.svc_debros_ipfs", inspector.StatusPass) - expectStatus(t, results, "system.svc_debros_ipfs_cluster", inspector.StatusPass) + expectStatus(t, results, "system.svc_orama_node", inspector.StatusPass) + expectStatus(t, results, "system.svc_orama_olric", inspector.StatusPass) + expectStatus(t, results, "system.svc_orama_ipfs", inspector.StatusPass) + expectStatus(t, results, "system.svc_orama_ipfs_cluster", inspector.StatusPass) expectStatus(t, results, "system.svc_wg", inspector.StatusPass) expectStatus(t, results, "system.no_failed_units", inspector.StatusPass) expectStatus(t, results, "system.memory", inspector.StatusPass) @@ -63,30 +63,30 @@ func TestCheckSystem_ServiceInactive(t *testing.T) { nd := makeNodeData("1.1.1.1", "node") nd.System = &inspector.SystemData{ Services: map[string]string{ - "debros-node": "active", - "debros-olric": "inactive", - "debros-ipfs": "active", - "debros-ipfs-cluster": "failed", + "orama-node": "active", + "orama-olric": "inactive", + "orama-ipfs": "active", + "orama-ipfs-cluster": "failed", }, } data := makeCluster(map[string]*inspector.NodeData{"1.1.1.1": nd}) results := CheckSystem(data) - expectStatus(t, results, "system.svc_debros_node", inspector.StatusPass) - expectStatus(t, results, "system.svc_debros_olric", inspector.StatusFail) - expectStatus(t, results, "system.svc_debros_ipfs_cluster", inspector.StatusFail) + expectStatus(t, results, "system.svc_orama_node", inspector.StatusPass) + expectStatus(t, results, "system.svc_orama_olric", inspector.StatusFail) + expectStatus(t, results, "system.svc_orama_ipfs_cluster", inspector.StatusFail) } func TestCheckSystem_NameserverServices(t *testing.T) { nd := makeNodeData("5.5.5.5", "nameserver-ns1") nd.System = &inspector.SystemData{ Services: map[string]string{ - "debros-node": "active", - "debros-olric": "active", - "debros-ipfs": "active", - "debros-ipfs-cluster": "active", - "coredns": "active", - "caddy": "active", + "orama-node": "active", + "orama-olric": "active", + "orama-ipfs": "active", + "orama-ipfs-cluster": "active", + "coredns": "active", + "caddy": "active", }, } data := makeCluster(map[string]*inspector.NodeData{"5.5.5.5": nd}) @@ -99,10 +99,10 @@ func TestCheckSystem_NameserverServicesNotCheckedOnRegularNode(t *testing.T) { nd := makeNodeData("1.1.1.1", "node") nd.System = &inspector.SystemData{ Services: map[string]string{ - "debros-node": "active", - "debros-olric": "active", - "debros-ipfs": "active", - "debros-ipfs-cluster": "active", + "orama-node": "active", + "orama-olric": "active", + "orama-ipfs": "active", + "orama-ipfs-cluster": "active", }, } data := makeCluster(map[string]*inspector.NodeData{"1.1.1.1": nd}) @@ -116,7 +116,7 @@ func TestCheckSystem_FailedUnits_Debros(t *testing.T) { nd := makeNodeData("1.1.1.1", "node") nd.System = &inspector.SystemData{ Services: map[string]string{}, - FailedUnits: []string{"debros-node.service"}, + FailedUnits: []string{"orama-node.service"}, } data := makeCluster(map[string]*inspector.NodeData{"1.1.1.1": nd}) results := CheckSystem(data) @@ -142,9 +142,9 @@ func TestCheckSystem_Memory(t *testing.T) { total int status inspector.Status }{ - {"healthy", 4000, 8000, inspector.StatusPass}, // 50% - {"elevated", 7000, 8000, inspector.StatusWarn}, // 87.5% - {"critical", 7500, 8000, inspector.StatusFail}, // 93.75% + {"healthy", 4000, 8000, inspector.StatusPass}, // 50% + {"elevated", 7000, 8000, inspector.StatusWarn}, // 87.5% + {"critical", 7500, 8000, inspector.StatusFail}, // 93.75% } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -248,7 +248,7 @@ func TestCheckSystem_ProcessUser(t *testing.T) { user string status inspector.Status }{ - {"correct", "debros", inspector.StatusPass}, + {"correct", "orama", inspector.StatusPass}, {"root", "root", inspector.StatusWarn}, {"other", "ubuntu", inspector.StatusWarn}, } diff --git a/pkg/inspector/collector.go b/pkg/inspector/collector.go index dcdc663..a42f2f2 100644 --- a/pkg/inspector/collector.go +++ b/pkg/inspector/collector.go @@ -46,53 +46,53 @@ type NamespaceData struct { // RQLiteData holds parsed RQLite status from a single node. type RQLiteData struct { Responsive bool - StatusRaw string // raw JSON from /status - NodesRaw string // raw JSON from /nodes?nonvoters - ReadyzRaw string // raw response from /readyz - DebugRaw string // raw JSON from /debug/vars - Status *RQLiteStatus // parsed /status + StatusRaw string // raw JSON from /status + NodesRaw string // raw JSON from /nodes?nonvoters + ReadyzRaw string // raw response from /readyz + DebugRaw string // raw JSON from /debug/vars + Status *RQLiteStatus // parsed /status Nodes map[string]*RQLiteNode // parsed /nodes - Readyz *RQLiteReadyz // parsed /readyz - DebugVars *RQLiteDebugVars // parsed /debug/vars - StrongRead bool // SELECT 1 with level=strong succeeded + Readyz *RQLiteReadyz // parsed /readyz + DebugVars *RQLiteDebugVars // parsed /debug/vars + StrongRead bool // SELECT 1 with level=strong succeeded } // RQLiteDebugVars holds metrics from /debug/vars. type RQLiteDebugVars struct { - QueryErrors uint64 - ExecuteErrors uint64 - RemoteExecErrors uint64 - LeaderNotFound uint64 - SnapshotErrors uint64 - ClientRetries uint64 - ClientTimeouts uint64 + QueryErrors uint64 + ExecuteErrors uint64 + RemoteExecErrors uint64 + LeaderNotFound uint64 + SnapshotErrors uint64 + ClientRetries uint64 + ClientTimeouts uint64 } // RQLiteStatus holds parsed fields from /status. type RQLiteStatus struct { - RaftState string // Leader, Follower, Candidate, Shutdown - LeaderNodeID string // store.leader.node_id - LeaderAddr string // store.leader.addr - NodeID string // store.node_id - Term uint64 // store.raft.term (current_term) - AppliedIndex uint64 // store.raft.applied_index - CommitIndex uint64 // store.raft.commit_index - FsmPending uint64 // store.raft.fsm_pending - LastContact string // store.raft.last_contact (followers only) - LastLogIndex uint64 // store.raft.last_log_index - LastLogTerm uint64 // store.raft.last_log_term - NumPeers int // store.raft.num_peers (string in JSON) - LastSnapshot uint64 // store.raft.last_snapshot_index - Voter bool // store.raft.voter - DBSize int64 // store.sqlite3.db_size - DBSizeFriendly string // store.sqlite3.db_size_friendly - DBAppliedIndex uint64 // store.db_applied_index - FsmIndex uint64 // store.fsm_index - Uptime string // http.uptime - Version string // build.version - GoVersion string // runtime.GOARCH + runtime.version - Goroutines int // runtime.num_goroutine - HeapAlloc uint64 // runtime.memory.heap_alloc (bytes) + RaftState string // Leader, Follower, Candidate, Shutdown + LeaderNodeID string // store.leader.node_id + LeaderAddr string // store.leader.addr + NodeID string // store.node_id + Term uint64 // store.raft.term (current_term) + AppliedIndex uint64 // store.raft.applied_index + CommitIndex uint64 // store.raft.commit_index + FsmPending uint64 // store.raft.fsm_pending + LastContact string // store.raft.last_contact (followers only) + LastLogIndex uint64 // store.raft.last_log_index + LastLogTerm uint64 // store.raft.last_log_term + NumPeers int // store.raft.num_peers (string in JSON) + LastSnapshot uint64 // store.raft.last_snapshot_index + Voter bool // store.raft.voter + DBSize int64 // store.sqlite3.db_size + DBSizeFriendly string // store.sqlite3.db_size_friendly + DBAppliedIndex uint64 // store.db_applied_index + FsmIndex uint64 // store.fsm_index + Uptime string // http.uptime + Version string // build.version + GoVersion string // runtime.GOARCH + runtime.version + Goroutines int // runtime.num_goroutine + HeapAlloc uint64 // runtime.memory.heap_alloc (bytes) } // RQLiteNode holds parsed fields from /nodes response per node. @@ -107,11 +107,11 @@ type RQLiteNode struct { // RQLiteReadyz holds parsed readiness state. type RQLiteReadyz struct { - Ready bool - Store string // "ready" or error - Leader string // "ready" or error - Node string // "ready" or error - RawBody string + Ready bool + Store string // "ready" or error + Leader string // "ready" or error + Node string // "ready" or error + RawBody string } // OlricData holds parsed Olric status from a single node. @@ -130,17 +130,17 @@ type OlricData struct { // IPFSData holds parsed IPFS status from a single node. type IPFSData struct { - DaemonActive bool - ClusterActive bool - SwarmPeerCount int + DaemonActive bool + ClusterActive bool + SwarmPeerCount int ClusterPeerCount int - RepoSizeBytes int64 - RepoMaxBytes int64 - KuboVersion string - ClusterVersion string - ClusterErrors int // peers reporting errors - HasSwarmKey bool - BootstrapEmpty bool // true if bootstrap list is empty (private swarm) + RepoSizeBytes int64 + RepoMaxBytes int64 + KuboVersion string + ClusterVersion string + ClusterErrors int // peers reporting errors + HasSwarmKey bool + BootstrapEmpty bool // true if bootstrap list is empty (private swarm) } // DNSData holds parsed DNS/CoreDNS status from a nameserver node. @@ -154,29 +154,29 @@ type DNSData struct { CoreDNSRestarts int LogErrors int // error count in recent CoreDNS logs // Resolution tests (dig results) - SOAResolves bool - NSResolves bool - NSRecordCount int + SOAResolves bool + NSResolves bool + NSRecordCount int WildcardResolves bool - BaseAResolves bool + BaseAResolves bool // TLS - BaseTLSDaysLeft int // -1 = failed to check - WildTLSDaysLeft int // -1 = failed to check + BaseTLSDaysLeft int // -1 = failed to check + WildTLSDaysLeft int // -1 = failed to check // Corefile - CorefileExists bool + CorefileExists bool } // WireGuardData holds parsed WireGuard status from a node. type WireGuardData struct { - InterfaceUp bool + InterfaceUp bool ServiceActive bool - WgIP string - PeerCount int - Peers []WGPeer - MTU int - ListenPort int - ConfigExists bool - ConfigPerms string // e.g. "600" + WgIP string + PeerCount int + Peers []WGPeer + MTU int + ListenPort int + ConfigExists bool + ConfigPerms string // e.g. "600" } // WGPeer holds parsed data for a single WireGuard peer. @@ -192,26 +192,26 @@ type WGPeer struct { // SystemData holds parsed system-level data from a node. type SystemData struct { - Services map[string]string // service name → status - FailedUnits []string // systemd units in failed state - MemTotalMB int - MemUsedMB int - MemFreeMB int - DiskTotalGB string - DiskUsedGB string - DiskAvailGB string - DiskUsePct int - UptimeRaw string - LoadAvg string - CPUCount int - OOMKills int - SwapUsedMB int - SwapTotalMB int - InodePct int // inode usage percentage - ListeningPorts []int // ports from ss -tlnp - UFWActive bool - ProcessUser string // user running debros-node (e.g. "debros") - PanicCount int // panic/fatal in recent logs + Services map[string]string // service name → status + FailedUnits []string // systemd units in failed state + MemTotalMB int + MemUsedMB int + MemFreeMB int + DiskTotalGB string + DiskUsedGB string + DiskAvailGB string + DiskUsePct int + UptimeRaw string + LoadAvg string + CPUCount int + OOMKills int + SwapUsedMB int + SwapTotalMB int + InodePct int // inode usage percentage + ListeningPorts []int // ports from ss -tlnp + UFWActive bool + ProcessUser string // user running orama-node (e.g. "orama") + PanicCount int // panic/fatal in recent logs } // NetworkData holds parsed network-level data from a node. @@ -227,17 +227,17 @@ type NetworkData struct { // AnyoneData holds parsed Anyone relay/client status from a node. type AnyoneData struct { - RelayActive bool // debros-anyone-relay systemd service active - ClientActive bool // debros-anyone-client systemd service active - Mode string // "relay" or "client" (from anonrc ORPort presence) - ORPortListening bool // port 9001 bound locally - SocksListening bool // port 9050 bound locally (client SOCKS5) - ControlListening bool // port 9051 bound locally (control port) - Bootstrapped bool // relay has bootstrapped to 100% - BootstrapPct int // bootstrap percentage (0-100) - Fingerprint string // relay fingerprint - Nickname string // relay nickname - UptimeStr string // uptime from control port + RelayActive bool // orama-anyone-relay systemd service active + ClientActive bool // orama-anyone-client systemd service active + Mode string // "relay" or "client" (from anonrc ORPort presence) + ORPortListening bool // port 9001 bound locally + SocksListening bool // port 9050 bound locally (client SOCKS5) + ControlListening bool // port 9051 bound locally (control port) + Bootstrapped bool // relay has bootstrapped to 100% + BootstrapPct int // bootstrap percentage (0-100) + Fingerprint string // relay fingerprint + Nickname string // relay nickname + UptimeStr string // uptime from control port ORPortReachable map[string]bool // host IP → whether we can TCP connect to their 9001 from this node } @@ -567,17 +567,17 @@ func collectOlric(ctx context.Context, node Node) *OlricData { cmd := ` SEP="===INSPECTOR_SEP===" echo "$SEP" -systemctl is-active debros-olric 2>/dev/null +systemctl is-active orama-olric 2>/dev/null echo "$SEP" ss -tlnp 2>/dev/null | grep ':3322 ' | head -1 echo "$SEP" -journalctl -u debros-olric --no-pager -n 200 --since "1 hour ago" 2>/dev/null | grep -ciE '(error|ERR)' || echo 0 +journalctl -u orama-olric --no-pager -n 200 --since "1 hour ago" 2>/dev/null | grep -ciE '(error|ERR)' || echo 0 echo "$SEP" -journalctl -u debros-olric --no-pager -n 200 --since "1 hour ago" 2>/dev/null | grep -ciE '(suspect|marking.*(failed|dead))' || echo 0 +journalctl -u orama-olric --no-pager -n 200 --since "1 hour ago" 2>/dev/null | grep -ciE '(suspect|marking.*(failed|dead))' || echo 0 echo "$SEP" -journalctl -u debros-olric --no-pager -n 200 --since "1 hour ago" 2>/dev/null | grep -ciE '(memberlist.*(join|leave))' || echo 0 +journalctl -u orama-olric --no-pager -n 200 --since "1 hour ago" 2>/dev/null | grep -ciE '(memberlist.*(join|leave))' || echo 0 echo "$SEP" -systemctl show debros-olric --property=NRestarts 2>/dev/null | cut -d= -f2 +systemctl show orama-olric --property=NRestarts 2>/dev/null | cut -d= -f2 echo "$SEP" ps -C olric-server -o rss= 2>/dev/null | head -1 || echo 0 ` @@ -611,9 +611,9 @@ func collectIPFS(ctx context.Context, node Node) *IPFSData { cmd := ` SEP="===INSPECTOR_SEP===" echo "$SEP" -systemctl is-active debros-ipfs 2>/dev/null +systemctl is-active orama-ipfs 2>/dev/null echo "$SEP" -systemctl is-active debros-ipfs-cluster 2>/dev/null +systemctl is-active orama-ipfs-cluster 2>/dev/null echo "$SEP" curl -sf -X POST 'http://localhost:4501/api/v0/swarm/peers' 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('Peers') or []))" 2>/dev/null || echo -1 echo "$SEP" @@ -625,7 +625,7 @@ curl -sf -X POST 'http://localhost:4501/api/v0/version' 2>/dev/null | python3 -c echo "$SEP" curl -sf 'http://localhost:9094/id' 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin).get('version',''))" 2>/dev/null || echo unknown echo "$SEP" -sudo test -f /home/debros/.orama/data/ipfs/repo/swarm.key && echo yes || echo no +sudo test -f /home/orama/.orama/data/ipfs/repo/swarm.key && echo yes || echo no echo "$SEP" curl -sf -X POST 'http://localhost:4501/api/v0/bootstrap/list' 2>/dev/null | python3 -c "import sys,json; peers=json.load(sys.stdin).get('Peers',[]); print(len(peers))" 2>/dev/null || echo -1 ` @@ -887,8 +887,8 @@ func collectSystem(ctx context.Context, node Node) *SystemData { } services := []string{ - "debros-node", "debros-ipfs", "debros-ipfs-cluster", - "debros-olric", "debros-anyone-relay", "debros-anyone-client", + "orama-node", "orama-ipfs", "orama-ipfs-cluster", + "orama-olric", "orama-anyone-relay", "orama-anyone-client", "coredns", "caddy", "wg-quick@wg0", } @@ -918,9 +918,9 @@ func collectSystem(ctx context.Context, node Node) *SystemData { cmd += ` && echo "$SEP"` cmd += ` && sudo ufw status 2>/dev/null | head -1` cmd += ` && echo "$SEP"` - cmd += ` && ps -C debros-node -o user= 2>/dev/null | head -1 || echo unknown` + cmd += ` && ps -C orama-node -o user= 2>/dev/null | head -1 || echo unknown` cmd += ` && echo "$SEP"` - cmd += ` && journalctl -u debros-node --no-pager -n 500 --since "1 hour ago" 2>/dev/null | grep -ciE '(panic|fatal)' || echo 0` + cmd += ` && journalctl -u orama-node --no-pager -n 500 --since "1 hour ago" 2>/dev/null | grep -ciE '(panic|fatal)' || echo 0` res := RunSSH(ctx, node, cmd) if !res.OK() && res.Stdout == "" { @@ -1152,9 +1152,9 @@ func collectAnyone(ctx context.Context, node Node) *AnyoneData { cmd := ` SEP="===INSPECTOR_SEP===" echo "$SEP" -systemctl is-active debros-anyone-relay 2>/dev/null || echo inactive +systemctl is-active orama-anyone-relay 2>/dev/null || echo inactive echo "$SEP" -systemctl is-active debros-anyone-client 2>/dev/null || echo inactive +systemctl is-active orama-anyone-client 2>/dev/null || echo inactive echo "$SEP" ss -tlnp 2>/dev/null | grep -q ':9001 ' && echo yes || echo no echo "$SEP" @@ -1289,11 +1289,11 @@ func collectAnyoneReachability(ctx context.Context, data *ClusterData) { } func collectNamespaces(ctx context.Context, node Node) []NamespaceData { - // Detect namespace services: debros-namespace-gateway@.service + // Detect namespace services: orama-namespace-gateway@.service cmd := ` SEP="===INSPECTOR_SEP===" echo "$SEP" -systemctl list-units --type=service --all --no-pager --no-legend 'debros-namespace-gateway@*.service' 2>/dev/null | awk '{print $1}' | sed 's/debros-namespace-gateway@//;s/\.service//' +systemctl list-units --type=service --all --no-pager --no-legend 'orama-namespace-gateway@*.service' 2>/dev/null | awk '{print $1}' | sed 's/orama-namespace-gateway@//;s/\.service//' echo "$SEP" ` res := RunSSH(ctx, node, cmd) @@ -1327,7 +1327,7 @@ echo "$SEP" nsCmd += fmt.Sprintf(` echo "NS_START:%s" # Get gateway port from systemd or default discovery -GWPORT=$(ss -tlnp 2>/dev/null | grep 'debros-namespace-gateway@%s' | grep -oP ':\K[0-9]+' | head -1) +GWPORT=$(ss -tlnp 2>/dev/null | grep 'orama-namespace-gateway@%s' | grep -oP ':\K[0-9]+' | head -1) echo "GW_PORT:${GWPORT:-0}" # Try common namespace port ranges (10000-10099) for BASE in $(seq 10000 5 10099); do diff --git a/pkg/installer/discovery/peer_discovery.go b/pkg/installer/discovery/peer_discovery.go index df074c5..4b0d16e 100644 --- a/pkg/installer/discovery/peer_discovery.go +++ b/pkg/installer/discovery/peer_discovery.go @@ -21,7 +21,7 @@ type DiscoveryResult struct { // DiscoverPeerFromDomain queries an existing node to get its peer ID and IPFS info // Tries HTTPS first, then falls back to HTTP -// Respects DEBROS_TRUSTED_TLS_DOMAINS and DEBROS_CA_CERT_PATH environment variables for certificate verification +// Respects ORAMA_TRUSTED_TLS_DOMAINS and ORAMA_CA_CERT_PATH environment variables for certificate verification func DiscoverPeerFromDomain(domain string) (*DiscoveryResult, error) { // Use centralized TLS configuration that respects CA certificates and trusted domains client := tlsutil.NewHTTPClientForDomain(10*time.Second, domain) diff --git a/pkg/ipfs/cluster.go b/pkg/ipfs/cluster.go index 17089a9..ea75509 100644 --- a/pkg/ipfs/cluster.go +++ b/pkg/ipfs/cluster.go @@ -113,7 +113,7 @@ func (cm *ClusterConfigManager) EnsureConfig() error { cfg.Cluster.Peername = nodeName cfg.Cluster.Secret = cm.secret cfg.Cluster.ListenMultiaddress = []string{fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", clusterListenPort)} - cfg.Consensus.CRDT.ClusterName = "debros-cluster" + cfg.Consensus.CRDT.ClusterName = "orama-cluster" cfg.Consensus.CRDT.TrustedPeers = []string{"*"} cfg.API.RestAPI.HTTPListenMultiaddress = fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", restAPIPort) cfg.API.IPFSProxy.ListenMultiaddress = fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", proxyPort) diff --git a/pkg/rqlite/instance_spawner.go b/pkg/rqlite/instance_spawner.go index afb8f85..5739cbd 100644 --- a/pkg/rqlite/instance_spawner.go +++ b/pkg/rqlite/instance_spawner.go @@ -86,9 +86,9 @@ func (is *InstanceSpawner) SpawnInstance(ctx context.Context, cfg InstanceConfig // Raft tuning — match the global node's tuning for consistency args = append(args, "-raft-election-timeout", "5s", - "-raft-heartbeat-timeout", "2s", + "-raft-timeout", "2s", "-raft-apply-timeout", "30s", - "-raft-leader-lease-timeout", "5s", + "-raft-leader-lease-timeout", "2s", ) // Add join addresses if not the leader (must be before data directory) diff --git a/pkg/rqlite/process.go b/pkg/rqlite/process.go index 8df7bed..1078c03 100644 --- a/pkg/rqlite/process.go +++ b/pkg/rqlite/process.go @@ -128,11 +128,11 @@ func (r *RQLiteManager) launchProcess(ctx context.Context, rqliteDataDir string) } raftLeaderLease := r.config.RaftLeaderLeaseTimeout if raftLeaderLease == 0 { - raftLeaderLease = 5 * time.Second + raftLeaderLease = 2 * time.Second } args = append(args, "-raft-election-timeout", raftElection.String(), - "-raft-heartbeat-timeout", raftHeartbeat.String(), + "-raft-timeout", raftHeartbeat.String(), "-raft-apply-timeout", raftApply.String(), "-raft-leader-lease-timeout", raftLeaderLease.String(), ) diff --git a/pkg/rqlite/util.go b/pkg/rqlite/util.go index e24d54f..0d480e3 100644 --- a/pkg/rqlite/util.go +++ b/pkg/rqlite/util.go @@ -17,7 +17,7 @@ func (r *RQLiteManager) rqliteDataDirPath() (string, error) { } func (r *RQLiteManager) resolveMigrationsDir() (string, error) { - productionPath := "/home/debros/src/migrations" + productionPath := "/home/orama/src/migrations" if _, err := os.Stat(productionPath); err == nil { return productionPath, nil } @@ -55,4 +55,3 @@ func (r *RQLiteManager) exponentialBackoff(attempt int, baseDelay time.Duration, } return delay } - diff --git a/pkg/systemd/manager.go b/pkg/systemd/manager.go index 65605ac..3507ae9 100644 --- a/pkg/systemd/manager.go +++ b/pkg/systemd/manager.go @@ -37,7 +37,7 @@ func NewManager(namespaceBase string, logger *zap.Logger) *Manager { // serviceName returns the systemd service name for a namespace and service type func (m *Manager) serviceName(namespace string, serviceType ServiceType) string { - return fmt.Sprintf("debros-namespace-%s@%s.service", serviceType, namespace) + return fmt.Sprintf("orama-namespace-%s@%s.service", serviceType, namespace) } // StartService starts a namespace service @@ -228,7 +228,7 @@ func (m *Manager) StartAllNamespaceServices(namespace string) error { // ListNamespaceServices returns all namespace services currently registered in systemd func (m *Manager) ListNamespaceServices() ([]string, error) { - cmd := exec.Command("sudo", "-n", "systemctl", "list-units", "--all", "--no-legend", "debros-namespace-*@*.service") + cmd := exec.Command("sudo", "-n", "systemctl", "list-units", "--all", "--no-legend", "orama-namespace-*@*.service") output, err := cmd.CombinedOutput() if err != nil { return nil, fmt.Errorf("failed to list namespace services: %w; output: %s", err, string(output)) @@ -343,9 +343,9 @@ func (m *Manager) InstallTemplateUnits(sourceDir string) error { m.logger.Info("Installing systemd template units", zap.String("source", sourceDir)) templates := []string{ - "debros-namespace-rqlite@.service", - "debros-namespace-olric@.service", - "debros-namespace-gateway@.service", + "orama-namespace-rqlite@.service", + "orama-namespace-olric@.service", + "orama-namespace-gateway@.service", } for _, template := range templates { diff --git a/pkg/tlsutil/client.go b/pkg/tlsutil/client.go index 0d16ce1..4b318f0 100644 --- a/pkg/tlsutil/client.go +++ b/pkg/tlsutil/client.go @@ -29,7 +29,7 @@ func init() { trustedDomains = append(trustedDomains, defaultTrustedDomains...) // Add any additional domains from environment - domains := os.Getenv("DEBROS_TRUSTED_TLS_DOMAINS") + domains := os.Getenv("ORAMA_TRUSTED_TLS_DOMAINS") if domains != "" { for _, d := range strings.Split(domains, ",") { d = strings.TrimSpace(d) @@ -40,9 +40,9 @@ func init() { } // Try to load CA certificate - caCertPath := os.Getenv("DEBROS_CA_CERT_PATH") + caCertPath := os.Getenv("ORAMA_CA_CERT_PATH") if caCertPath == "" { - caCertPath = "/etc/debros/ca.crt" + caCertPath = "/etc/orama/ca.crt" } if caCertData, err := os.ReadFile(caCertPath); err == nil { diff --git a/scripts/check-node-health.sh b/scripts/check-node-health.sh index 3bcf8b2..018a49c 100755 --- a/scripts/check-node-health.sh +++ b/scripts/check-node-health.sh @@ -25,7 +25,7 @@ WG_IP=$(ip -4 addr show wg0 2>/dev/null | grep -oP 'inet \K[0-9.]+' || true) # 1. Services echo "── Services ──" -for svc in debros-node debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy; do +for svc in orama-node orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy; do status=$(systemctl is-active "$svc" 2>/dev/null || true) case "$status" in active) mark="✓";; @@ -86,7 +86,7 @@ echo "" # 4. IPFS echo "── IPFS ──" -PEERS=$(sudo -u debros IPFS_PATH=/home/debros/.orama/data/ipfs/repo /usr/local/bin/ipfs swarm peers 2>/dev/null) +PEERS=$(sudo -u orama IPFS_PATH=/home/orama/.orama/data/ipfs/repo /usr/local/bin/ipfs swarm peers 2>/dev/null) if [ -n "$PEERS" ]; then COUNT=$(echo "$PEERS" | wc -l) echo " Connected peers: $COUNT" @@ -119,7 +119,7 @@ echo "" # 6. Olric echo "── Olric ──" -if systemctl is-active debros-olric &>/dev/null; then +if systemctl is-active orama-olric &>/dev/null; then echo " service: active" # Olric doesn't have a simple HTTP health endpoint; just check the process OLRIC_PID=$(pgrep -f olric-server || true) diff --git a/scripts/clean-testnet.sh b/scripts/clean-testnet.sh index 3c6c6b3..838f3dc 100755 --- a/scripts/clean-testnet.sh +++ b/scripts/clean-testnet.sh @@ -29,11 +29,11 @@ set -e export DEBIAN_FRONTEND=noninteractive echo " Stopping services..." -systemctl stop debros-node debros-gateway debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy 2>/dev/null || true -systemctl disable debros-node debros-gateway debros-ipfs debros-ipfs-cluster debros-olric debros-anyone-relay debros-anyone-client coredns caddy 2>/dev/null || true +systemctl stop orama-node orama-gateway orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy 2>/dev/null || true +systemctl disable orama-node orama-gateway orama-ipfs orama-ipfs-cluster orama-olric orama-anyone-relay orama-anyone-client coredns caddy 2>/dev/null || true echo " Removing systemd service files..." -rm -f /etc/systemd/system/debros-*.service +rm -f /etc/systemd/system/orama-*.service rm -f /etc/systemd/system/coredns.service rm -f /etc/systemd/system/caddy.service rm -f /etc/systemd/system/orama-deploy-*.service @@ -50,18 +50,18 @@ ufw --force reset ufw allow 22/tcp ufw --force enable -echo " Killing debros processes..." -pkill -u debros 2>/dev/null || true +echo " Killing orama processes..." +pkill -u orama 2>/dev/null || true sleep 1 -echo " Removing debros user and data..." -userdel -r debros 2>/dev/null || true -rm -rf /home/debros +echo " Removing orama user and data..." +userdel -r orama 2>/dev/null || true +rm -rf /home/orama echo " Removing sudoers files..." -rm -f /etc/sudoers.d/debros-access -rm -f /etc/sudoers.d/debros-deployments -rm -f /etc/sudoers.d/debros-wireguard +rm -f /etc/sudoers.d/orama-access +rm -f /etc/sudoers.d/orama-deployments +rm -f /etc/sudoers.d/orama-wireguard echo " Removing CoreDNS and Caddy configs..." rm -rf /etc/coredns diff --git a/scripts/extract-deploy.sh b/scripts/extract-deploy.sh index b9401c6..bf6af0a 100755 --- a/scripts/extract-deploy.sh +++ b/scripts/extract-deploy.sh @@ -1,81 +1,46 @@ #!/bin/bash -# Extracts /tmp/network-source.tar.gz on a VPS and places everything correctly. +# Extracts /tmp/network-source.tar.gz on a VPS and places the CLI binary. # Run as root on the target VPS. # # What it does: -# 1. Extracts source to /home/debros/src/ +# 1. Extracts source to /home/orama/src/ # 2. Installs CLI to /usr/local/bin/orama -# 3. If bin-linux/ is in the archive (pre-built), copies binaries to their locations: -# - orama-node, gateway, identity, rqlite-mcp, olric-server → /home/debros/bin/ -# - coredns → /usr/local/bin/coredns -# - caddy → /usr/bin/caddy +# All other binaries are built from source during `orama install`. # -# Usage: sudo bash /home/debros/src/scripts/extract-deploy.sh -# (or pipe via SSH: ssh root@host 'bash -s' < scripts/extract-deploy.sh) +# Usage: sudo bash /home/orama/src/scripts/extract-deploy.sh set -e ARCHIVE="/tmp/network-source.tar.gz" -SRC_DIR="/home/debros/src" -BIN_DIR="/home/debros/bin" +SRC_DIR="/home/orama/src" +BIN_DIR="/home/orama/bin" if [ ! -f "$ARCHIVE" ]; then echo "Error: $ARCHIVE not found" exit 1 fi -# Ensure debros user exists (orama install also creates it, but we need it now for chown) -if ! id -u debros &>/dev/null; then - echo "Creating 'debros' user..." - useradd -m -s /bin/bash debros +# Ensure orama user exists +if ! id -u orama &>/dev/null; then + echo "Creating 'orama' user..." + useradd -m -s /bin/bash orama fi echo "Extracting source..." rm -rf "$SRC_DIR" mkdir -p "$SRC_DIR" "$BIN_DIR" tar xzf "$ARCHIVE" -C "$SRC_DIR" -id -u debros &>/dev/null && chown -R debros:debros "$SRC_DIR" || true +chown -R orama:orama "$SRC_DIR" || true -# Install CLI +# Install CLI binary if [ -f "$SRC_DIR/bin-linux/orama" ]; then cp "$SRC_DIR/bin-linux/orama" /usr/local/bin/orama chmod +x /usr/local/bin/orama echo " ✓ CLI installed: /usr/local/bin/orama" -fi - -# Place pre-built binaries if present -if [ -d "$SRC_DIR/bin-linux" ]; then - echo "Installing pre-built binaries..." - - for bin in orama-node gateway identity rqlite-mcp olric-server orama; do - if [ -f "$SRC_DIR/bin-linux/$bin" ]; then - # Atomic rename: copy to temp, then move (works even if binary is running) - cp "$SRC_DIR/bin-linux/$bin" "$BIN_DIR/$bin.tmp" - chmod +x "$BIN_DIR/$bin.tmp" - mv -f "$BIN_DIR/$bin.tmp" "$BIN_DIR/$bin" - echo " ✓ $bin → $BIN_DIR/$bin" - fi - done - - if [ -f "$SRC_DIR/bin-linux/coredns" ]; then - cp "$SRC_DIR/bin-linux/coredns" /usr/local/bin/coredns.tmp - chmod +x /usr/local/bin/coredns.tmp - mv -f /usr/local/bin/coredns.tmp /usr/local/bin/coredns - echo " ✓ coredns → /usr/local/bin/coredns" - fi - - if [ -f "$SRC_DIR/bin-linux/caddy" ]; then - cp "$SRC_DIR/bin-linux/caddy" /usr/bin/caddy.tmp - chmod +x /usr/bin/caddy.tmp - mv -f /usr/bin/caddy.tmp /usr/bin/caddy - echo " ✓ caddy → /usr/bin/caddy" - fi - - id -u debros &>/dev/null && chown -R debros:debros "$BIN_DIR" || true - echo "All binaries installed." else - echo "No pre-built binaries in archive (bin-linux/ not found)." - echo "Install CLI manually: sudo mv /tmp/orama /usr/local/bin/orama" + echo " ⚠️ CLI binary not found in archive (bin-linux/orama)" fi -echo "Done. Ready for: sudo orama install --no-pull --pre-built ..." +chown -R orama:orama "$BIN_DIR" || true + +echo "Done. Ready for: sudo orama install --vps-ip ..." diff --git a/scripts/generate-source-archive.sh b/scripts/generate-source-archive.sh index d06c34e..7f379b8 100755 --- a/scripts/generate-source-archive.sh +++ b/scripts/generate-source-archive.sh @@ -2,10 +2,13 @@ # Generates a tarball of the current codebase for deployment # Output: /tmp/network-source.tar.gz # -# If bin-linux/ exists (from make build-linux-all), it is included in the archive. -# On the VPS, use scripts/extract-deploy.sh to extract source + place binaries. +# Includes bin-linux/orama (CLI binary cross-compiled via make build-linux). +# All other binaries are built from source on the VPS during install. # -# Usage: ./scripts/generate-source-archive.sh +# Usage: +# make build-linux +# ./scripts/generate-source-archive.sh +# ./bin/orama install --vps-ip --nameserver --domain ... set -e @@ -18,15 +21,14 @@ cd "$PROJECT_ROOT" # Remove root-level binaries before archiving (they'll be rebuilt on VPS) rm -f gateway cli node orama-cli-linux 2>/dev/null -# Check if pre-built binaries exist -if [ -d "bin-linux" ] && [ "$(ls -A bin-linux 2>/dev/null)" ]; then - echo "Generating source archive (with pre-built binaries)..." - EXCLUDE_BIN="" -else - echo "Generating source archive (source only, no bin-linux/)..." - EXCLUDE_BIN="--exclude=bin-linux/" +# Verify CLI binary exists +if [ ! -f "bin-linux/orama" ]; then + echo "Error: bin-linux/orama not found. Run 'make build-linux' first." + exit 1 fi +echo "Generating source archive (with CLI binary)..." + tar czf "$OUTPUT" \ --exclude='.git' \ --exclude='node_modules' \ @@ -39,12 +41,8 @@ tar czf "$OUTPUT" \ --exclude='testdata/' \ --exclude='examples/' \ --exclude='*.tar.gz' \ - $EXCLUDE_BIN \ . echo "Archive created: $OUTPUT" echo "Size: $(du -h $OUTPUT | cut -f1)" - -if [ -d "bin-linux" ] && [ "$(ls -A bin-linux 2>/dev/null)" ]; then - echo "Includes pre-built binaries: $(ls bin-linux/ | tr '\n' ' ')" -fi +echo "Includes CLI binary: bin-linux/orama" diff --git a/scripts/patches/fix-anyone-relay.sh b/scripts/patches/fix-anyone-relay.sh index af84418..6dfd276 100755 --- a/scripts/patches/fix-anyone-relay.sh +++ b/scripts/patches/fix-anyone-relay.sh @@ -5,7 +5,7 @@ # After orama upgrade, the firewall reset drops the ORPort 9001 rule because # preferences.yaml didn't have anyone_relay=true. This patch: # 1. Opens port 9001/tcp in UFW -# 2. Re-enables debros-anyone-relay (survives reboot) +# 2. Re-enables orama-anyone-relay (survives reboot) # 3. Saves anyone_relay preference so future upgrades preserve the rule # # Usage: @@ -51,10 +51,10 @@ fix_node() { local cmd cmd=$(cat <<'REMOTE' set -e -PREFS="/home/debros/.orama/preferences.yaml" +PREFS="/home/orama/.orama/preferences.yaml" # Only patch nodes that have the Anyone relay service installed -if [ ! -f /etc/systemd/system/debros-anyone-relay.service ]; then +if [ ! -f /etc/systemd/system/orama-anyone-relay.service ]; then echo "SKIP_NO_RELAY" exit 0 fi @@ -63,11 +63,11 @@ fi sudo ufw allow 9001/tcp >/dev/null 2>&1 # 2. Enable the service so it survives reboot -sudo systemctl enable debros-anyone-relay >/dev/null 2>&1 +sudo systemctl enable orama-anyone-relay >/dev/null 2>&1 # 3. Restart the service if not running -if ! systemctl is-active --quiet debros-anyone-relay; then - sudo systemctl start debros-anyone-relay >/dev/null 2>&1 +if ! systemctl is-active --quiet orama-anyone-relay; then + sudo systemctl start orama-anyone-relay >/dev/null 2>&1 fi # 4. Save anyone_relay preference if missing diff --git a/scripts/patches/fix-logrotate.sh b/scripts/patches/fix-logrotate.sh index 0e4561e..6848314 100755 --- a/scripts/patches/fix-logrotate.sh +++ b/scripts/patches/fix-logrotate.sh @@ -4,7 +4,7 @@ # # The `anon` apt package ships /etc/logrotate.d/anon with: # postrotate: invoke-rc.d anon reload -# But we use debros-anyone-relay, not the anon service. So the relay +# But we use orama-anyone-relay, not the anon service. So the relay # never gets SIGHUP after rotation, keeps writing to the old fd, and # the new notices.log stays empty (causing false "bootstrap=0%" in inspector). # diff --git a/scripts/recover-rqlite.sh b/scripts/recover-rqlite.sh index 15b3be3..7264d96 100644 --- a/scripts/recover-rqlite.sh +++ b/scripts/recover-rqlite.sh @@ -3,7 +3,7 @@ # Recover RQLite cluster from split-brain. # # Strategy: -# 1. Stop debros-node on ALL nodes simultaneously +# 1. Stop orama-node on ALL nodes simultaneously # 2. Keep raft/ data ONLY on the node with the highest commit index (leader candidate) # 3. Delete raft/ on all other nodes (they'll join fresh via -join) # 4. Start the leader candidate first, wait for it to become Leader @@ -121,7 +121,7 @@ node_ssh() { # ── Confirmation ───────────────────────────────────────────────────────────── echo "⚠️ THIS WILL:" -echo " 1. Stop debros-node on ALL ${#HOSTS[@]} nodes" +echo " 1. Stop orama-node on ALL ${#HOSTS[@]} nodes" echo " 2. DELETE raft/ data on ${#HOSTS[@]}-1 nodes (backup to /tmp/rqlite-raft-backup/)" echo " 3. Keep raft/ data ONLY on ${HOSTS[$LEADER_IDX]} (leader candidate)" echo " 4. Restart all nodes to reform the cluster" @@ -133,17 +133,17 @@ if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then fi echo "" -RAFT_DIR="/home/debros/.orama/data/rqlite/raft" +RAFT_DIR="/home/orama/.orama/data/rqlite/raft" BACKUP_DIR="/tmp/rqlite-raft-backup" -# ── Phase 1: Stop debros-node on ALL nodes ─────────────────────────────────── -echo "== Phase 1: Stopping debros-node on all ${#HOSTS[@]} nodes ==" +# ── Phase 1: Stop orama-node on ALL nodes ─────────────────────────────────── +echo "== Phase 1: Stopping orama-node on all ${#HOSTS[@]} nodes ==" failed=() for i in "${!HOSTS[@]}"; do h="${HOSTS[$i]}" p="${PASSES[$i]}" echo -n " Stopping $h ... " - if node_ssh "$i" "printf '%s\n' '$p' | sudo -S systemctl stop debros-node 2>&1 && echo STOPPED"; then + if node_ssh "$i" "printf '%s\n' '$p' | sudo -S systemctl stop orama-node 2>&1 && echo STOPPED"; then echo "" else echo "FAILED" @@ -202,7 +202,7 @@ echo "Leader node ${HOSTS[$LEADER_IDX]} raft/ data preserved." echo "" echo "== Phase 3: Starting leader node (${HOSTS[$LEADER_IDX]}) ==" lp="${PASSES[$LEADER_IDX]}" -node_ssh "$LEADER_IDX" "printf '%s\n' '$lp' | sudo -S systemctl start debros-node" || die "Failed to start leader node" +node_ssh "$LEADER_IDX" "printf '%s\n' '$lp' | sudo -S systemctl start orama-node" || die "Failed to start leader node" echo " Waiting for leader to become Leader..." max_wait=120 @@ -236,7 +236,7 @@ for i in "${!HOSTS[@]}"; do h="${HOSTS[$i]}" p="${PASSES[$i]}" echo -n " Starting $h ... " - if node_ssh "$i" "printf '%s\n' '$p' | sudo -S systemctl start debros-node && echo STARTED"; then + if node_ssh "$i" "printf '%s\n' '$p' | sudo -S systemctl start orama-node && echo STARTED"; then true else echo "FAILED" @@ -286,4 +286,4 @@ echo "" echo "Next steps:" echo " 1. Run 'scripts/inspect.sh --devnet' to verify full cluster health" echo " 2. If some nodes show Candidate state, give them more time (up to 5 min)" -echo " 3. If nodes fail to join, check /home/debros/.orama/logs/rqlite-node.log on the node" +echo " 3. If nodes fail to join, check /home/orama/.orama/logs/rqlite-node.log on the node" diff --git a/scripts/redeploy.sh b/scripts/redeploy.sh index ca34fc5..1add12e 100755 --- a/scripts/redeploy.sh +++ b/scripts/redeploy.sh @@ -4,7 +4,7 @@ # Reads node credentials from scripts/remote-nodes.conf. # # Flow: -# 1) make build-linux-all +# 1) make build-linux # 2) scripts/generate-source-archive.sh -> /tmp/network-source.tar.gz # 3) scp archive + extract-deploy.sh + conf to hub node # 4) from hub: sshpass scp to all other nodes + sudo bash /tmp/extract-deploy.sh @@ -107,9 +107,9 @@ echo "Hub: $HUB_HOST (idx=$HUB_IDX, key=${HUB_KEY:-none})" # ── Build ──────────────────────────────────────────────────────────────────── if [[ "$NO_BUILD" -eq 0 ]]; then - echo "== build-linux-all ==" - (cd "$ROOT_DIR" && make build-linux-all) || { - echo "WARN: make build-linux-all failed; continuing if existing bin-linux is acceptable." + echo "== build-linux ==" + (cd "$ROOT_DIR" && make build-linux) || { + echo "WARN: make build-linux failed; continuing if existing bin-linux is acceptable." } else echo "== skipping build (--no-build) ==" @@ -289,7 +289,7 @@ upgrade_one() { # 2. Stop all services echo " [2/4] stopping services..." if ! sshpass -p "$p" ssh -n -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ - "$h" "printf '%s\n' '$p' | sudo -S systemctl stop 'debros-*'" 2>&1; then + "$h" "printf '%s\n' '$p' | sudo -S systemctl stop 'orama-*'" 2>&1; then echo " !! stop failed on $h" failed_nodes+=("$h") return 1 @@ -327,7 +327,7 @@ upgrade_hub() { # 2. Stop all services echo " [2/4] stopping services..." - if ! (printf '%s\n' "$hub_pass" | sudo -S systemctl stop 'debros-*') 2>&1; then + if ! (printf '%s\n' "$hub_pass" | sudo -S systemctl stop 'orama-*') 2>&1; then echo " !! stop failed on hub ($hub_host)" failed_nodes+=("$hub_host (hub)") return 1 diff --git a/scripts/release.sh b/scripts/release.sh index 68b9e01..79984d3 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,6 +1,6 @@ #!/bin/bash -# DeBros Network Interactive Release Script +# Orama Network Interactive Release Script # Handles the complete release workflow for both stable and nightly releases set -e diff --git a/systemd/debros-namespace-gateway@.service b/systemd/debros-namespace-gateway@.service deleted file mode 100644 index a8a31b6..0000000 --- a/systemd/debros-namespace-gateway@.service +++ /dev/null @@ -1,42 +0,0 @@ -[Unit] -Description=DeBros Namespace Gateway (%i) -Documentation=https://github.com/DeBrosOfficial/network -After=network.target debros-namespace-rqlite@%i.service debros-namespace-olric@%i.service -Requires=debros-namespace-rqlite@%i.service debros-namespace-olric@%i.service -PartOf=debros-node.service - -[Service] -Type=simple -User=debros -Group=debros -WorkingDirectory=/home/debros - -EnvironmentFile=/home/debros/.orama/data/namespaces/%i/gateway.env - -# Use shell to properly expand NODE_ID from env file -ExecStart=/bin/sh -c 'exec /home/debros/bin/gateway --config ${GATEWAY_CONFIG}' - -TimeoutStopSec=30s -KillMode=mixed -KillSignal=SIGTERM - -Restart=on-failure -RestartSec=5s - -StandardOutput=journal -StandardError=journal -SyslogIdentifier=debros-gateway-%i - -# Security hardening -NoNewPrivileges=yes -ProtectSystem=strict -ProtectHome=read-only -ProtectKernelTunables=yes -ProtectKernelModules=yes -ReadWritePaths=/home/debros/.orama/data/namespaces - -LimitNOFILE=65536 -MemoryMax=1G - -[Install] -WantedBy=multi-user.target diff --git a/systemd/orama-namespace-gateway@.service b/systemd/orama-namespace-gateway@.service new file mode 100644 index 0000000..3eea274 --- /dev/null +++ b/systemd/orama-namespace-gateway@.service @@ -0,0 +1,42 @@ +[Unit] +Description=Orama Namespace Gateway (%i) +Documentation=https://github.com/DeBrosOfficial/network +After=network.target orama-namespace-rqlite@%i.service orama-namespace-olric@%i.service +Requires=orama-namespace-rqlite@%i.service orama-namespace-olric@%i.service +PartOf=orama-node.service + +[Service] +Type=simple +User=orama +Group=orama +WorkingDirectory=/home/orama + +EnvironmentFile=/home/orama/.orama/data/namespaces/%i/gateway.env + +# Use shell to properly expand NODE_ID from env file +ExecStart=/bin/sh -c 'exec /home/orama/bin/gateway --config ${GATEWAY_CONFIG}' + +TimeoutStopSec=30s +KillMode=mixed +KillSignal=SIGTERM + +Restart=on-failure +RestartSec=5s + +StandardOutput=journal +StandardError=journal +SyslogIdentifier=orama-gateway-%i + +# Security hardening +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=read-only +ProtectKernelTunables=yes +ProtectKernelModules=yes +ReadWritePaths=/home/orama/.orama/data/namespaces + +LimitNOFILE=65536 +MemoryMax=1G + +[Install] +WantedBy=multi-user.target diff --git a/systemd/debros-namespace-olric@.service b/systemd/orama-namespace-olric@.service similarity index 54% rename from systemd/debros-namespace-olric@.service rename to systemd/orama-namespace-olric@.service index f0f3270..8869da3 100644 --- a/systemd/debros-namespace-olric@.service +++ b/systemd/orama-namespace-olric@.service @@ -1,20 +1,20 @@ [Unit] -Description=DeBros Namespace Olric Cache (%i) +Description=Orama Namespace Olric Cache (%i) Documentation=https://github.com/DeBrosOfficial/network -After=network.target debros-namespace-rqlite@%i.service -Requires=debros-namespace-rqlite@%i.service -PartOf=debros-node.service +After=network.target orama-namespace-rqlite@%i.service +Requires=orama-namespace-rqlite@%i.service +PartOf=orama-node.service [Service] Type=simple -User=debros -Group=debros -WorkingDirectory=/home/debros +User=orama +Group=orama +WorkingDirectory=/home/orama # Olric reads config from environment variable (set in env file) -EnvironmentFile=/home/debros/.orama/data/namespaces/%i/olric.env +EnvironmentFile=/home/orama/.orama/data/namespaces/%i/olric.env -ExecStart=/home/debros/bin/olric-server +ExecStart=/home/orama/bin/olric-server TimeoutStopSec=30s KillMode=mixed @@ -25,7 +25,7 @@ RestartSec=5s StandardOutput=journal StandardError=journal -SyslogIdentifier=debros-olric-%i +SyslogIdentifier=orama-olric-%i # Security hardening NoNewPrivileges=yes @@ -33,7 +33,7 @@ ProtectSystem=strict ProtectHome=read-only ProtectKernelTunables=yes ProtectKernelModules=yes -ReadWritePaths=/home/debros/.orama/data/namespaces +ReadWritePaths=/home/orama/.orama/data/namespaces LimitNOFILE=65536 MemoryMax=2G diff --git a/systemd/debros-namespace-rqlite@.service b/systemd/orama-namespace-rqlite@.service similarity index 72% rename from systemd/debros-namespace-rqlite@.service rename to systemd/orama-namespace-rqlite@.service index 082fed2..0777c4e 100644 --- a/systemd/debros-namespace-rqlite@.service +++ b/systemd/orama-namespace-rqlite@.service @@ -1,18 +1,18 @@ [Unit] -Description=DeBros Namespace RQLite (%i) +Description=Orama Namespace RQLite (%i) Documentation=https://github.com/DeBrosOfficial/network After=network.target -PartOf=debros-node.service +PartOf=orama-node.service StopWhenUnneeded=false [Service] Type=simple -User=debros -Group=debros -WorkingDirectory=/home/debros +User=orama +Group=orama +WorkingDirectory=/home/orama # Environment file contains namespace-specific config -EnvironmentFile=/home/debros/.orama/data/namespaces/%i/rqlite.env +EnvironmentFile=/home/orama/.orama/data/namespaces/%i/rqlite.env # Start rqlited with args from environment (using shell to properly expand JOIN_ARGS) ExecStart=/bin/sh -c 'exec /usr/local/bin/rqlited \ @@ -21,7 +21,7 @@ ExecStart=/bin/sh -c 'exec /usr/local/bin/rqlited \ -http-adv-addr ${HTTP_ADV_ADDR} \ -raft-adv-addr ${RAFT_ADV_ADDR} \ ${JOIN_ARGS} \ - /home/debros/.orama/data/namespaces/%i/rqlite/${NODE_ID}' + /home/orama/.orama/data/namespaces/%i/rqlite/${NODE_ID}' # Graceful shutdown TimeoutStopSec=30s @@ -35,7 +35,7 @@ RestartSec=5s # Logging StandardOutput=journal StandardError=journal -SyslogIdentifier=debros-rqlite-%i +SyslogIdentifier=orama-rqlite-%i # Security hardening NoNewPrivileges=yes @@ -43,7 +43,7 @@ ProtectSystem=strict ProtectHome=read-only ProtectKernelTunables=yes ProtectKernelModules=yes -ReadWritePaths=/home/debros/.orama/data/namespaces +ReadWritePaths=/home/orama/.orama/data/namespaces # Resource limits LimitNOFILE=65536 diff --git a/testdata/apps/nextjs-app/pages/index.js b/testdata/apps/nextjs-app/pages/index.js index e627d16..1a4f258 100644 --- a/testdata/apps/nextjs-app/pages/index.js +++ b/testdata/apps/nextjs-app/pages/index.js @@ -23,7 +23,7 @@ export async function getServerSideProps() { export default function Home({ notes, error, fetchedAt, goApiUrl }) { return (
-

DeBros Notes (SSR)

+

Orama Notes (SSR)

Next.js SSR + Go API + SQLite

diff --git a/testdata/apps/react-app/index.html b/testdata/apps/react-app/index.html index 787660b..e02e8fb 100644 --- a/testdata/apps/react-app/index.html +++ b/testdata/apps/react-app/index.html @@ -3,7 +3,7 @@ - DeBros Notes + Orama Notes
diff --git a/testdata/apps/react-app/src/App.jsx b/testdata/apps/react-app/src/App.jsx index a425759..182282e 100644 --- a/testdata/apps/react-app/src/App.jsx +++ b/testdata/apps/react-app/src/App.jsx @@ -38,7 +38,7 @@ export default function App() { return (
-

DeBros Notes

+

Orama Notes

React Static + Node.js Proxy + Go API + SQLite