SpacesOps on StartOS
Upstream repo: https://git.spacesops.com/spacesops/spacesops
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
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.
Table of Contents
- Image and Container Runtime
- Volume and Data Layout
- Installation and First-Run Flow
- The Spaces Dependency (auto-wiring)
- Configuration Management
- Network Access and Interfaces
- Actions
- Backups and Restore
- Health Checks
- Limitations and Differences
- What Is Unchanged from Upstream
- 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:
- Generates a Nostr operator keypair (
operatorSecretHex/operatorPublicHexinstore.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. - Generates a strong session secret (
sessionSecret), replacing the weak hardcoded default the upstream image ships with. - 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:
- Mounts the Spaces
mainvolume read-only at/spaces-data. - Reads
spacedAuth.{username,password}from the Spacesstore.json. - Connects to spaced at
http://spaces.startos:7225with those credentials, exportingSPACED_RPC_URL,SPACED_RPC_USER,SPACED_RPC_PASSWORD, andSPACED_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
- Requires the Spaces service. SpacesOps auto-connects to
spaces.startos:7225by 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. - 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. PLATFORM_HOSTis forced to0.0.0.0andPLATFORM_PORTto7264so the StartOS reverse proxy can reach the app (it otherwise binds127.0.0.1:3000).- 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 usePLATFORM_CALLBACK_HOST, which defaults tospacesops.startosand can be overridden in Configure Platform. - 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_CERTSto the StartOS root CA (fetched viasdk.getSslCertificatefor the SUBS*.startoshostname when configured, otherwisespaces.startos) so outbound HTTPS to same-host StartOS services succeeds and the v1.0.3 image entrypoint does not crash on its broken_SCRIPT_DIRdefault.
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-libcryptography 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.shdefaults.
Quick Reference for AI Consumers
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