Add standalone docker-compose for all 20 modules
Each module can run as an independent container using its standalone.ts
entrypoint. Reuses the same rspace-online image with CMD override.
Usage:
docker compose -f docker-compose.yml -f docker-compose.standalone.yml \
up -d rtrips-standalone
All services share rspace-db and traefik-public. Module-specific deps
mapped: books/files/swag volumes, OSRM for trips, IMAP for inbox,
R2 for tube, payment network for cart/funds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d25bb3ec5e
commit
3c986f1709
|
|
@ -0,0 +1,327 @@
|
|||
# Standalone module deployments — each module runs as its own container.
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.standalone.yml up -d rbooks-standalone
|
||||
#
|
||||
# All services reuse the same rspace-online image (built by the main compose).
|
||||
# They share the rspace-db database and traefik-public network.
|
||||
# To deploy ALL standalone modules at once:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.standalone.yml up -d
|
||||
#
|
||||
# NOTE: Standalone services override the default CMD to run standalone.ts.
|
||||
# The unified rspace-online container still serves all domains by default.
|
||||
# To switch a domain from unified to standalone, remove its Traefik label
|
||||
# from the main compose and bring up its standalone service here.
|
||||
|
||||
x-standalone-base: &standalone-base
|
||||
image: rspace-online-rspace:latest
|
||||
restart: unless-stopped
|
||||
environment: &base-env
|
||||
NODE_ENV: production
|
||||
PORT: "3000"
|
||||
DATABASE_URL: postgres://rspace:${POSTGRES_PASSWORD:-rspace}@rspace-db:5432/rspace
|
||||
depends_on:
|
||||
rspace-db:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- traefik-public
|
||||
- rspace-internal
|
||||
|
||||
x-traefik-labels: &traefik-enabled
|
||||
traefik.enable: "true"
|
||||
|
||||
services:
|
||||
# ── rBooks ──
|
||||
rbooks-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rbooks-standalone
|
||||
command: ["bun", "run", "modules/books/standalone.ts"]
|
||||
volumes:
|
||||
- rspace-books:/data/books
|
||||
environment:
|
||||
<<: *base-env
|
||||
BOOKS_DIR: /data/books
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rbooks-sa.rule: Host(`rbooks.online`)
|
||||
traefik.http.routers.rbooks-sa.entrypoints: web
|
||||
traefik.http.services.rbooks-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rPubs ──
|
||||
rpubs-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rpubs-standalone
|
||||
command: ["bun", "run", "modules/pubs/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rpubs-sa.rule: Host(`rpubs.online`)
|
||||
traefik.http.routers.rpubs-sa.entrypoints: web
|
||||
traefik.http.services.rpubs-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rCart ──
|
||||
rcart-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rcart-standalone
|
||||
command: ["bun", "run", "modules/cart/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
FLOW_SERVICE_URL: http://payment-flow:3010
|
||||
FLOW_ID: a79144ec-e6a2-4e30-a42a-6d8237a5953d
|
||||
FUNNEL_ID: 0ff6a9ac-1667-4fc7-9a01-b1620810509f
|
||||
X402_PAY_TO: ${X402_PAY_TO:-}
|
||||
X402_NETWORK: ${X402_NETWORK:-eip155:84532}
|
||||
X402_UPLOAD_PRICE: ${X402_UPLOAD_PRICE:-0.01}
|
||||
X402_FACILITATOR_URL: ${X402_FACILITATOR_URL:-https://x402.org/facilitator}
|
||||
networks:
|
||||
- traefik-public
|
||||
- rspace-internal
|
||||
- payment-network
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rcart-sa.rule: Host(`rcart.online`)
|
||||
traefik.http.routers.rcart-sa.entrypoints: web
|
||||
traefik.http.services.rcart-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rProviders ──
|
||||
rproviders-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rproviders-standalone
|
||||
command: ["bun", "run", "modules/providers/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rproviders-sa.rule: Host(`providers.mycofi.earth`)
|
||||
traefik.http.routers.rproviders-sa.entrypoints: web
|
||||
traefik.http.services.rproviders-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rSwag ──
|
||||
rswag-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rswag-standalone
|
||||
command: ["bun", "run", "modules/swag/standalone.ts"]
|
||||
volumes:
|
||||
- rspace-swag:/data/swag-artifacts
|
||||
environment:
|
||||
<<: *base-env
|
||||
SWAG_ARTIFACTS_DIR: /data/swag-artifacts
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rswag-sa.rule: Host(`swag.mycofi.earth`)
|
||||
traefik.http.routers.rswag-sa.entrypoints: web
|
||||
traefik.http.services.rswag-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rChoices ──
|
||||
rchoices-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rchoices-standalone
|
||||
command: ["bun", "run", "modules/choices/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rchoices-sa.rule: Host(`rchoices.online`)
|
||||
traefik.http.routers.rchoices-sa.entrypoints: web
|
||||
traefik.http.services.rchoices-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rFunds ──
|
||||
rfunds-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rfunds-standalone
|
||||
command: ["bun", "run", "modules/funds/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
FLOW_SERVICE_URL: http://payment-flow:3010
|
||||
FLOW_ID: a79144ec-e6a2-4e30-a42a-6d8237a5953d
|
||||
FUNNEL_ID: 0ff6a9ac-1667-4fc7-9a01-b1620810509f
|
||||
networks:
|
||||
- traefik-public
|
||||
- rspace-internal
|
||||
- payment-network
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rfunds-sa.rule: Host(`rfunds.online`)
|
||||
traefik.http.routers.rfunds-sa.entrypoints: web
|
||||
traefik.http.services.rfunds-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rFiles ──
|
||||
rfiles-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rfiles-standalone
|
||||
command: ["bun", "run", "modules/files/standalone.ts"]
|
||||
volumes:
|
||||
- rspace-files:/data/files
|
||||
environment:
|
||||
<<: *base-env
|
||||
FILES_DIR: /data/files
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rfiles-sa.rule: Host(`rfiles.online`)
|
||||
traefik.http.routers.rfiles-sa.entrypoints: web
|
||||
traefik.http.services.rfiles-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rForum ──
|
||||
rforum-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rforum-standalone
|
||||
command: ["bun", "run", "modules/forum/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
HETZNER_API_TOKEN: ${HETZNER_API_TOKEN}
|
||||
CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
|
||||
CLOUDFLARE_ZONE_ID: ${CLOUDFLARE_ZONE_ID}
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rforum-sa.rule: Host(`rforum.online`)
|
||||
traefik.http.routers.rforum-sa.entrypoints: web
|
||||
traefik.http.services.rforum-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rVote ──
|
||||
rvote-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rvote-standalone
|
||||
command: ["bun", "run", "modules/vote/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rvote-sa.rule: Host(`rvote.online`)
|
||||
traefik.http.routers.rvote-sa.entrypoints: web
|
||||
traefik.http.services.rvote-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rNotes ──
|
||||
rnotes-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rnotes-standalone
|
||||
command: ["bun", "run", "modules/notes/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rnotes-sa.rule: Host(`rnotes.online`)
|
||||
traefik.http.routers.rnotes-sa.entrypoints: web
|
||||
traefik.http.services.rnotes-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rMaps ──
|
||||
rmaps-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rmaps-standalone
|
||||
command: ["bun", "run", "modules/maps/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
MAPS_SYNC_URL: wss://sync.rmaps.online
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rmaps-sa.rule: Host(`rmaps.online`)
|
||||
traefik.http.routers.rmaps-sa.entrypoints: web
|
||||
traefik.http.services.rmaps-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rWork ──
|
||||
rwork-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rwork-standalone
|
||||
command: ["bun", "run", "modules/work/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rwork-sa.rule: Host(`rwork.online`)
|
||||
traefik.http.routers.rwork-sa.entrypoints: web
|
||||
traefik.http.services.rwork-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rTrips ──
|
||||
rtrips-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rtrips-standalone
|
||||
command: ["bun", "run", "modules/trips/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
OSRM_URL: http://osrm-backend:5000
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rtrips-sa.rule: Host(`rtrips.online`)
|
||||
traefik.http.routers.rtrips-sa.entrypoints: web
|
||||
traefik.http.services.rtrips-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rCal ──
|
||||
rcal-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rcal-standalone
|
||||
command: ["bun", "run", "modules/cal/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rcal-sa.rule: Host(`rcal.online`)
|
||||
traefik.http.routers.rcal-sa.entrypoints: web
|
||||
traefik.http.services.rcal-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rNetwork ──
|
||||
rnetwork-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rnetwork-standalone
|
||||
command: ["bun", "run", "modules/network/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
TWENTY_API_URL: https://rnetwork.online
|
||||
TWENTY_API_TOKEN: ${TWENTY_API_TOKEN}
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rnetwork-sa.rule: Host(`rnetwork.online`)
|
||||
traefik.http.routers.rnetwork-sa.entrypoints: web
|
||||
traefik.http.services.rnetwork-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rTube ──
|
||||
rtube-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rtube-standalone
|
||||
command: ["bun", "run", "modules/tube/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
R2_ENDPOINT: ${R2_ENDPOINT}
|
||||
R2_BUCKET: ${R2_BUCKET:-rtube-videos}
|
||||
R2_ACCESS_KEY_ID: ${R2_ACCESS_KEY_ID}
|
||||
R2_SECRET_ACCESS_KEY: ${R2_SECRET_ACCESS_KEY}
|
||||
R2_PUBLIC_URL: ${R2_PUBLIC_URL}
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rtube-sa.rule: Host(`rtube.online`)
|
||||
traefik.http.routers.rtube-sa.entrypoints: web
|
||||
traefik.http.services.rtube-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rInbox ──
|
||||
rinbox-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rinbox-standalone
|
||||
command: ["bun", "run", "modules/inbox/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
IMAP_HOST: mail.rmail.online
|
||||
IMAP_PORT: "993"
|
||||
IMAP_TLS_REJECT_UNAUTHORIZED: "false"
|
||||
networks:
|
||||
- traefik-public
|
||||
- rspace-internal
|
||||
- rmail-mailcow
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rinbox-sa.rule: Host(`rinbox.online`)
|
||||
traefik.http.routers.rinbox-sa.entrypoints: web
|
||||
traefik.http.services.rinbox-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rData ──
|
||||
rdata-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rdata-standalone
|
||||
command: ["bun", "run", "modules/data/standalone.ts"]
|
||||
environment:
|
||||
<<: *base-env
|
||||
UMAMI_URL: https://analytics.rspace.online
|
||||
UMAMI_WEBSITE_ID: 292f6ac6-79f8-497b-ba6a-7a51e3b87b9f
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rdata-sa.rule: Host(`rdata.online`)
|
||||
traefik.http.routers.rdata-sa.entrypoints: web
|
||||
traefik.http.services.rdata-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# ── rWallet ──
|
||||
rwallet-standalone:
|
||||
<<: *standalone-base
|
||||
container_name: rwallet-standalone
|
||||
command: ["bun", "run", "modules/wallet/standalone.ts"]
|
||||
labels:
|
||||
<<: *traefik-enabled
|
||||
traefik.http.routers.rwallet-sa.rule: Host(`rwallet.online`)
|
||||
traefik.http.routers.rwallet-sa.entrypoints: web
|
||||
traefik.http.services.rwallet-sa.loadbalancer.server.port: "3000"
|
||||
|
||||
# Volumes and networks inherited from main docker-compose.yml
|
||||
# Use: docker compose -f docker-compose.yml -f docker-compose.standalone.yml up -d <service>
|
||||
Loading…
Reference in New Issue