# host-on-sx live service — the SX web host (lib/host) served by the native # http-listen server via lib/host/serve.sh. Joins the sx-dev project + externalnet # so Caddy can reverse_proxy a subdomain to it (blog.rose-ash.com). Isolated from # the sx_docs server: separate container, separate port. # # Usage: # docker compose -p sx-dev -f docker-compose.dev-sx-host.yml up -d sx_host # docker compose -p sx-dev -f docker-compose.dev-sx-host.yml logs -f sx_host # docker compose -p sx-dev -f docker-compose.dev-sx-host.yml down services: sx_host: image: registry.rose-ash.com:5000/sx_docs:latest container_name: sx-dev-sx_host-1 entrypoint: ["bash", "/app/lib/host/serve.sh"] working_dir: /app environment: SX_PROJECT_DIR: /app SX_SERVER: /app/bin/sx_server HOST_PORT: "8000" # Bind all interfaces so Caddy (on externalnet) can reach it. SX_HTTP_HOST: "0.0.0.0" # Durable persist store root — on a named volume so data survives restarts. SX_PERSIST_DIR: /data/persist # Blog write auth: admin login + session-cookie signing secret. The blog # write routes (POST /new, POST/PUT/DELETE /posts) are guarded by a session # login or Bearer token, so these gate publishing. Not a real site — these # are demo creds; rotate by editing here and recreating the container. SX_ADMIN_USER: admin SX_ADMIN_PASSWORD: "sx-host-camper-van-2026" SX_SESSION_SECRET: "ra-host-sess-7c1f9b3e2a8d4056" # Serving-mode JIT: bytecode-compile hot SX (esp. the Datalog/relations path) # on the epoch serving channel. Validated: host conformance 271/271 under JIT, # 5.4x faster (1m43s -> 19s). Default-OFF gate, opt in here. SX_SERVING_JIT: "1" OCAMLRUNPARAM: "b" # TA-live ACTOR MODEL: A's actor identity + base URL. A is FOLLOWED (B follows it), so A has no # SX_FOLLOW; it delivers its activities to its followers. SX_FED_SECRET signs/verifies fed POSTs. SX_ACTOR: "blog.rose-ash.com" SX_SELF_URL: "http://sx_host:8000" SX_FED_SECRET: "rose-ash-fed-2026-shared-a3f9" volumes: # SX source (hot-reload on container restart) - ./spec:/app/spec:ro - ./lib:/app/lib:ro - ./next:/app/next:ro - ./web:/app/web:ro # Client assets for the blog SPA: the WASM OCaml kernel + sx-platform + the # web-stack modules, served by lib/host/static.sx at /static/**. - ./shared/static:/app/shared/static:ro # OCaml server binary — this worktree's build (has the SX_HTTP_HOST bind fix) - ./hosts/ocaml/_build/default/bin/sx_server.exe:/app/bin/sx_server:ro # Durable persist store (the SX op-log/kv on disk) — survives restarts. # Host dir, chowned to the image's appuser (uid 10001) so the non-root # server can write: sudo mkdir -p /root/sx-host-persist && sudo chown 10001:10001 /root/sx-host-persist - /root/sx-host-persist:/data/persist networks: - externalnet - default restart: unless-stopped # The durable-execution KERNEL (next/kernel/host_kernel.erl) — a persistent next/ service holding # flow_store across requests (RA-live substrate). The host reaches it at http://sx_kernel:8930 over # the shared `default` network. SX_HTTP_HOST=0.0.0.0 so the bind is reachable cross-container. sx_kernel: image: registry.rose-ash.com:5000/sx_docs:latest container_name: sx-dev-sx_kernel-1 entrypoint: ["bash", "/app/next/kernel/serve.sh"] working_dir: /app environment: SX_PROJECT_DIR: /app SX_SERVER: /app/bin/sx_server KERNEL_PORT: "8930" SX_HTTP_HOST: "0.0.0.0" OCAMLRUNPARAM: "b" volumes: - ./spec:/app/spec:ro - ./lib:/app/lib:ro - ./next:/app/next:ro - ./hosts/ocaml/_build/default/bin/sx_server.exe:/app/bin/sx_server:ro networks: - default restart: unless-stopped # A second host instance — a federation PEER (B). Host A federates its emitted activities to B's # /inbox; B's engine fires ITS OWN behaviors on A's state changes ("everything works over fed-sx"). # B has its own durable store + no peers (receives without re-federating). Reached on the default # network only (not exposed via Caddy). sx_host_b: image: registry.rose-ash.com:5000/sx_docs:latest container_name: sx-dev-sx_host_b-1 entrypoint: ["bash", "/app/lib/host/serve.sh"] working_dir: /app environment: SX_PROJECT_DIR: /app SX_SERVER: /app/bin/sx_server HOST_PORT: "8000" SX_HTTP_HOST: "0.0.0.0" SX_PERSIST_DIR: /data/persist SX_ADMIN_USER: admin SX_ADMIN_PASSWORD: "sx-host-b-camper-2026" SX_SESSION_SECRET: "ta-host-b-sess-9d2e1f" SX_SERVING_JIT: "1" OCAMLRUNPARAM: "b" # TA-live ACTOR MODEL: B's identity + base. B FOLLOWS A (SX_FOLLOW = A's base) at boot, so A # delivers its activities to B. Same shared SX_FED_SECRET so signatures verify across A↔B. SX_ACTOR: "sx_host_b" SX_SELF_URL: "http://sx_host_b:8000" SX_FOLLOW: "http://sx_host:8000" SX_FED_SECRET: "rose-ash-fed-2026-shared-a3f9" volumes: - ./spec:/app/spec:ro - ./lib:/app/lib:ro - ./next:/app/next:ro - ./web:/app/web:ro - ./shared/static:/app/shared/static:ro - ./hosts/ocaml/_build/default/bin/sx_server.exe:/app/bin/sx_server:ro - /root/sx-host-b-persist:/data/persist networks: # externalnet too, so a Caddy route (e.g. blog-b.rose-ash.com) can reverse_proxy to B — the # public-domain step is external Caddy + DNS config (not in this repo). default = A↔B fed traffic. - externalnet - default restart: unless-stopped networks: externalnet: external: true