SpacesOps

# SpacesOps on StartOS > **Upstream repo:** > > Everything not listed in this document should behave the same as upstream > SpacesOps. If a feature, setting, or behavior is not mentioned here, the > upstream documentation is accurate and fully applicable. SpacesOps is a web platform for confirming [Spaces](https://spacesprotocol.org) ownership and selling subspace names. It talks to the Spaces `spaced` daemon over JSON-RPC, signs operator events on Nostr, and optionally integrates pricing and subname-purchase backends. On StartOS it **requires the Spaces service** and auto-connects to it — see [Installation and First-Run Flow](#installation-and-first-run-flow). --- ## Table of Contents - [Image and Container Runtime](#image-and-container-runtime) - [Volume and Data Layout](#volume-and-data-layout) - [Installation and First-Run Flow](#installation-and-first-run-flow) - [The Spaces Dependency (auto-wiring)](#the-spaces-dependency-auto-wiring) - [Configuration Management](#configuration-management) - [Network Access and Interfaces](#network-access-and-interfaces) - [Actions](#actions) - [Backups and Restore](#backups-and-restore) - [Health Checks](#health-checks) - [Limitations and Differences](#limitations-and-differences) - [What Is Unchanged from Upstream](#what-is-unchanged-from-upstream) - [Quick Reference for AI Consumers](#quick-reference-for-ai-consumers) --- ## Image and Container Runtime | Field | Value | | --- | --- | | Image | `docker.io/spacesops/spacesops:v1.0.3` | | Base | `node:20-alpine` | | Architectures | `x86_64` (linux/amd64), `aarch64` (linux/arm64) | | Entrypoint | The image's `/app/docker-entrypoint.sh` is **kept**. StartOS runs `/app/docker-entrypoint.sh node server.js` as the daemon. | | Runs as | `root`, working directory `/app` | The image bundles Node 20 and the app's `node_modules` (including `nostr-tools` and `bitcoinjs-lib`). The entrypoint creates `/data{,/spaces,/signed}`, symlinks `/app/data` → `/data`, and loads defaults from `/app/setup-spacesops-env.sh` for any environment variable StartOS leaves unset, then exec's `node server.js`. ## Volume and Data Layout | Path | Volume | Purpose | | --- | --- | --- | | `/data` | `main` | SpacesOps data directory. SQLite databases (`local.db`, `sessions.db`, `prices.db`, per-tenant DBs), signed artifacts, and StartOS `store.json`. | | `/data/local.db` | `main` | Primary SQLite database (`PLATFORM_DB_PATH`). DB migrations auto-run on startup. | | `/data/store.json` | `main` | StartOS-managed settings: the generated Nostr operator keypair, the generated session secret, and optional Configure-Platform values. | | `/spaces-data` | _Spaces `main`_ | The **Spaces** service's volume, mounted **read-only**. Used only at startup to read the spaced RPC credentials — see below. | ## Installation and First-Run Flow On first install, StartOS: 1. Generates a **Nostr operator keypair** (`operatorSecretHex` / `operatorPublicHex` in `store.json`). SpacesOps requires this keypair at startup; the **Show Operator Credentials** action surfaces it (npub / nsec / hex), and **Import Operator Key** replaces it with one you supply. 2. Generates a strong **session secret** (`sessionSecret`), replacing the weak hardcoded default the upstream image ships with. 3. Reads the **spaced RPC credentials from the Spaces service** and connects to it (see next section). The service will not finish starting until those credentials are available. There is no upstream setup wizard to complete — the operator keypair and session secret are provisioned automatically. ## The Spaces Dependency (auto-wiring) SpacesOps **requires the Spaces service** (`spaces`, version `>=0.0.9:3`). **Install and sync Spaces first.** SpacesOps does not ask you for spaced RPC credentials. Instead, at startup it: 1. Mounts the Spaces `main` volume read-only at `/spaces-data`. 2. Reads `spacedAuth.{username,password}` from the Spaces `store.json`. 3. Connects to spaced at `http://spaces.startos:7225` with those credentials, exporting `SPACED_RPC_URL`, `SPACED_RPC_USER`, `SPACED_RPC_PASSWORD`, and `SPACED_WALLETLOAD_NAME=default`. If Spaces is not installed yet, or its credentials have not been seeded, the service **restarts until they appear** — this is expected. (Dependency declarations do not gate startup; SpacesOps handles readiness itself.) ## Configuration Management | StartOS-Managed | Upstream-Managed | | --- | --- | | `PLATFORM_HOST` / `PLATFORM_PORT` (forced to `0.0.0.0:7264` so the proxy can reach the app) | Everything inside the SpacesOps web UI / admin area | | `PLATFORM_DB_PATH` (`/data/local.db`) | Tenant management, space-ownership flows | | `OPERATOR_SECRET_HEX` / `OPERATOR_PUBLIC_HEX` (generated or imported) | | | `PLATFORM_SESSION_SECRET` (generated) | | | `SPACED_RPC_*` (auto-wired from Spaces) | | | `PLATFORM_CALLBACK_HOST` (defaults to `spacesops.startos`; override via **Configure Platform**) | | | Optional: `OPERATOR_RELAY`, `PLATFORM_MODE`, `COINGECKO_*`, `SUBS_*` (via **Configure Platform**) | | ## Network Access and Interfaces | Interface | Port | Protocol | Exposure | Notes | | --- | --- | --- | --- | --- | | Web UI | 7264 | HTTP | LAN / `.local` / Tor / clearnet (via StartOS) | The SpacesOps web platform + admin area. The app provides its own auth; the admin area uses a **fixed built-in credential** (see warning below). | ## Actions | ID | Name | Visibility | Availability | Inputs | Purpose | | --- | --- | --- | --- | --- | --- | | `show-operator-credentials` | Show Operator Credentials | Enabled | Any | — | Displays the Nostr operator keypair: npub (QR), hex public key, and the masked nsec / hex secret. | | `import-operator-key` | Import Operator Key | Enabled | Any | 64-char hex secret key | Replaces the operator keypair. Derives the public key automatically. **Warns** that it changes the operator identity; the service restarts to apply it. | | `show-admin-credentials` | Show Admin Credentials | Enabled | Any | — | Displays the **fixed** built-in admin login (`admin` / `Whatever!`) with a security warning. | | `configure-platform` | Configure Platform | Enabled | Any | relay, mode, CoinGecko, SUBS, callback host | Sets the Nostr relay, theme mode, pricing, SUBS backend, and `PLATFORM_CALLBACK_HOST`. Saving restarts the service. | ## Backups and Restore `sdk.Backups.ofVolumes('main')` — the entire `/data` volume is backed up, including all SQLite databases, signed artifacts, and `store.json` (operator keypair, session secret, and Configure-Platform settings). On restore, the same idempotent init runs and reuses the existing keypair and secret. The Spaces volume is **not** part of this package's backup. ## Health Checks | ID | Display | Grace period | Behaviour | | --- | --- | --- | --- | | `spacesops` (daemon `ready`) | Web Interface | 60 s | TCP listen on `0.0.0.0:7264` | ## Limitations and Differences 1. **Requires the Spaces service.** SpacesOps auto-connects to `spaces.startos:7225` by reading the Spaces RPC credentials from the mounted Spaces volume. Install and sync Spaces before (or alongside) SpacesOps; the service restarts until those credentials are available. 2. **The admin password is fixed and well-known.** Admin Basic Auth is hardcoded in the v1.0.3 image as `admin` / `Whatever!` with **no environment override**. It cannot be changed without rebuilding the image. **Keep this service private (Tor-only) and never expose its admin routes to the public internet** — the admin area can run SQL and manage tenants. See **Show Admin Credentials**. 3. **`PLATFORM_HOST` is forced to `0.0.0.0` and `PLATFORM_PORT` to `7264`** so the StartOS reverse proxy can reach the app (it otherwise binds `127.0.0.1:3000`). 4. **Subname-purchase and pricing are off by default.** They activate only when you fill in the relevant fields in **Configure Platform** (`COINGECKO_*` for pricing, `SUBS_*` for subname purchase + cert-callback flows). Payment callback URLs use `PLATFORM_CALLBACK_HOST`, which defaults to `spacesops.startos` and can be overridden in **Configure Platform**. 5. **The SUBS backend is not auto-wired to the Spaces subs daemon in v1.** The Spaces service's subs daemon listens on 7777 with a different API/auth than the SUBS endpoint (port 7244) SpacesOps expects, so SUBS must be configured manually if used. StartOS always sets `NODE_EXTRA_CA_CERTS` to the StartOS root CA (fetched via `sdk.getSslCertificate` for the SUBS `*.startos` hostname when configured, otherwise `spaces.startos`) so outbound HTTPS to same-host StartOS services succeeds and the v1.0.3 image entrypoint does not crash on its broken `_SCRIPT_DIR` default. ## What Is Unchanged from Upstream - All SpacesOps web UI, admin, and REST API routes behave as upstream documents. - SQLite schema and migrations are managed by the app and run on startup. - `nostr-tools` / `bitcoinjs-lib` cryptography ships in the image and is used exactly as upstream. - Any environment variable not set by StartOS falls back to the image's `setup-spacesops-env.sh` defaults. ## Quick Reference for AI Consumers ```yaml package_id: spacesops upstream_version: 1.0.3 image: docker.io/spacesops/spacesops:v1.0.3 architectures: [x86_64, aarch64] volumes: main: /data mounted_dependencies: spaces: /spaces-data # read-only; used to read spaced RPC creds at startup ports: ui: 7264 dependencies: - spaces # kind: running, versionRange '>=0.0.9:3', healthChecks [spaced, sync] startos_managed_env_vars: - PLATFORM_HOST # forced 0.0.0.0 - PLATFORM_PORT # forced 7264 - PLATFORM_DB_PATH # /data/local.db - PLATFORM_MODE # store.platformMode ?? prod - PLATFORM_SESSION_SECRET # generated - OPERATOR_SECRET_HEX # generated or imported - OPERATOR_PUBLIC_HEX # derived - OPERATOR_RELAY # store.operatorRelay ?? wss://relay.primal.net - SPACED_RPC_URL # http://spaces.startos:7225 - SPACED_RPC_USER # from Spaces store.json - SPACED_RPC_PASSWORD # from Spaces store.json - SPACED_WALLETLOAD_NAME # default - PLATFORM_CALLBACK_HOST # store.platformCallbackHost ?? spacesops.startos optional_env_vars: # only set when configured via configure-platform - COINGECKO_API_KEY - COINGECKO_TOKEN_COINS - SUBS_URI_VALUE - SUBS_RPC_USER - SUBS_RPC_PASSWORD - NODE_EXTRA_CA_CERTS # /data/.startos/startos-root-ca.crt (always set) admin_credentials: username: admin password: Whatever! # FIXED, baked into image, cannot be changed note: keep service private; admin area can run SQL and manage tenants actions: - show-operator-credentials - import-operator-key - show-admin-credentials - configure-platform ```