···11+# Mill-mode overlay for localinfra.
22+#
33+# The base docker-compose.yml runs a single standalone spindle. This overlay
44+# turns that same spindle into a *mill host* (it places jobs instead of running
55+# them) and adds one *executor* spindle that dials the mill over a websocket and
66+# runs the real microvm/nixery engines. Repos still point at spindle.* exactly
77+# as before — only where the job executes changes.
88+#
99+# standalone (default): docker compose --profile linux up
1010+# mill + executor: docker compose -f docker-compose.yml -f docker-compose.mill.yml --profile linux up
1111+#
1212+# The shared secret is a dev default; override with SPINDLE_MILL_SHARED_SECRET.
1313+1414+services:
1515+ # the existing front door becomes the mill host. it keeps its identity,
1616+ # jetstream subscription and /events + /logs endpoints; its microvm/nixery
1717+ # engines are swapped for the mill placement engine.
1818+ spindle:
1919+ environment:
2020+ SPINDLE_ROLE: mill
2121+ SPINDLE_MILL_SHARED_SECRET: "${SPINDLE_MILL_SHARED_SECRET:-localmill}"
2222+2323+ # a normal spindle that runs the real engines, but takes its work from the
2424+ # mill instead of being pointed at directly. dials out (NAT-friendly), so it
2525+ # needs no caddy alias and no PDS record.
2626+ spindle-executor:
2727+ profiles: ["linux"]
2828+ build:
2929+ context: .
3030+ dockerfile: localinfra/spindle.Dockerfile
3131+ restart: unless-stopped
3232+ environment:
3333+ SPINDLE_ROLE: executor
3434+ SPINDLE_SERVER_HOSTNAME: executor.tngl.boltless.dev
3535+ SPINDLE_SERVER_LISTEN_ADDR: 0.0.0.0:6555
3636+ SPINDLE_SERVER_DB_PATH: /var/lib/spindle/spindle.db
3737+ SPINDLE_SERVER_PLC_URL: https://plc.tngl.boltless.dev
3838+ SPINDLE_SERVER_JETSTREAM_ENDPOINT: wss://jetstream.tngl.boltless.dev/subscribe
3939+ SPINDLE_SERVER_DEV: "true"
4040+ SPINDLE_SERVER_DEV_EXTRA_HOSTS: knot.tngl.boltless.dev,mirror.tngl.boltless.dev
4141+ SPINDLE_SERVER_TAP_DB_PATH: /var/lib/spindle/tap.db
4242+ SPINDLE_SERVER_TAP_RELAY_URL: https://pds.tngl.boltless.dev
4343+ SPINDLE_MICROVM_PIPELINES_IMAGE_DIR: /var/lib/spindle/images
4444+ SPINDLE_MICROVM_PIPELINES_OVERLAY_DIR: /var/lib/spindle/overlays
4545+ # distinct vsock agent port from the base spindle, in case both ever run
4646+ SPINDLE_MICROVM_PIPELINES_AGENT_PORT: "11241"
4747+ SPINDLE_S3_LOG_BUCKET: ""
4848+ SPINDLE_MICROVM_PIPELINES_ENABLE_CGROUPS: "false"
4949+ SPINDLE_NIX_CACHE_READ_URLS: http://ncps:8501
5050+ SPINDLE_NIX_CACHE_TRUSTED_PUBLIC_KEYS: cache.local:F7YqpMzuBdILYd/v+wMZN2YKxCzliXQyFmeezOxw7rU=
5151+ SPINDLE_NIX_CACHE_UPLOAD_URL: http://ncps:8501/upload
5252+ # join the mill instead of being pointed at directly. plain ws to the
5353+ # mill container on the internal network (no caddy / TLS in the loop).
5454+ SPINDLE_MILL_URL: ws://spindle:6555/mill
5555+ SPINDLE_MILL_SHARED_SECRET: "${SPINDLE_MILL_SHARED_SECRET:-localmill}"
5656+ devices:
5757+ - /dev/vsock:/dev/vsock
5858+ - /dev/kvm:/dev/kvm
5959+ - /dev/vhost-vsock:/dev/vhost-vsock
6060+ - /dev/net/tun:/dev/net/tun
6161+ cap_add:
6262+ - NET_ADMIN
6363+ - SYS_ADMIN
6464+ security_opt:
6565+ - label=disable
6666+ - seccomp=unconfined
6767+ volumes:
6868+ - spindle-executor-data:/var/lib/spindle
6969+ - spindle-executor-logs:/var/log/spindle
7070+ - ./out/localinfra-spindle-images:/var/lib/spindle/images:ro
7171+ - init-state:/shared:ro
7272+ - ./localinfra/certs/root.crt:/usr/local/share/ca-certificates/caddy.crt:ro
7373+ healthcheck:
7474+ test: ["CMD", "wget", "-qO-", "http://localhost:6555/"]
7575+ interval: 2s
7676+ timeout: 2s
7777+ retries: 30
7878+ start_period: 5s
7979+ depends_on:
8080+ plc:
8181+ condition: service_started
8282+ jetstream:
8383+ condition: service_started
8484+ init-accounts:
8585+ condition: service_completed_successfully
8686+ ncps:
8787+ condition: service_started
8888+ spindle:
8989+ condition: service_healthy
9090+ networks: [tngl]
9191+9292+volumes:
9393+ spindle-executor-data:
9494+ spindle-executor-logs: