This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

localinfra: run camo and avatar

Signed-off-by: dawn <dawn@tangled.org>

author
dawn
date (Jul 30, 2026, 7:45 PM +0300) commit 17ce98e7 parent 645aca8a change-id nunvysov
+132 -1
+56
docker-compose.yml
··· 451 451 restart: unless-stopped 452 452 environment: 453 453 BOBBIN_URL: https://bobbin.tngl.boltless.dev 454 + CAMO_URL: https://camo.tngl.boltless.dev 455 + CAMO_SHARED_SECRET: localinfra-camo-secret 456 + AVATAR_URL: https://avatar.tngl.boltless.dev 457 + AVATAR_SHARED_SECRET: localinfra-avatar-secret 454 458 VITE_HANDLE_RESOLVER_URL: https://pds.tngl.boltless.dev 455 459 VITE_PLC_DIRECTORY_URL: https://plc.tngl.boltless.dev 456 460 # host-side port; keeps the oauth loopback redirect consistent 457 461 VITE_DEV_PORT: "5174" 462 + # the bind mount below does not deliver inotify, see vite.config.ts 463 + VITE_WATCH_POLL: "true" 458 464 NODE_EXTRA_CA_CERTS: /caddy-ca/root.crt 459 465 ports: 460 466 - "5174:5174" ··· 477 483 condition: service_started 478 484 networks: [tngl] 479 485 486 + camo: 487 + build: 488 + context: . 489 + dockerfile: localinfra/camo.Dockerfile 490 + restart: unless-stopped 491 + environment: 492 + CAMO_SHARED_SECRET: localinfra-camo-secret 493 + WRANGLER_SEND_METRICS: "false" 494 + volumes: 495 + - ./camo:/src:cached 496 + # shadow generated dirs so the host tree stays untouched 497 + - camo-node-modules:/src/node_modules 498 + - camo-wrangler:/src/.wrangler 499 + - ./localinfra/certs/root.crt:/caddy-ca/root.crt:ro 500 + healthcheck: 501 + test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8787/').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"] 502 + interval: 5s 503 + timeout: 2s 504 + retries: 30 505 + start_period: 30s 506 + networks: [tngl] 507 + 508 + avatar: 509 + build: 510 + context: . 511 + dockerfile: localinfra/avatar.Dockerfile 512 + restart: unless-stopped 513 + environment: 514 + AVATAR_SHARED_SECRET: localinfra-avatar-secret 515 + PLC_DIRECTORY_URL: https://plc.tngl.boltless.dev 516 + WRANGLER_SEND_METRICS: "false" 517 + volumes: 518 + - ./avatar:/src:cached 519 + - avatar-node-modules:/src/node_modules 520 + - avatar-wrangler:/src/.wrangler 521 + - ./localinfra/certs/root.crt:/caddy-ca/root.crt:ro 522 + healthcheck: 523 + test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8787/').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"] 524 + interval: 5s 525 + timeout: 2s 526 + retries: 30 527 + start_period: 30s 528 + networks: [tngl] 529 + 480 530 caddy: 481 531 image: caddy:2-alpine 482 532 restart: unless-stopped ··· 505 555 - zoekt.tngl.boltless.dev 506 556 - pdsls.tngl.boltless.dev 507 557 - bobbin.tngl.boltless.dev 558 + - camo.tngl.boltless.dev 559 + - avatar.tngl.boltless.dev 508 560 509 561 volumes: 510 562 caddy-data: ··· 527 579 bobbin-target: 528 580 web-node-modules: 529 581 web-svelte-kit: 582 + camo-node-modules: 583 + camo-wrangler: 584 + avatar-node-modules: 585 + avatar-wrangler: 530 586 531 587 networks: 532 588 tngl:
+11
localinfra/Caddyfile
··· 79 79 reverse_proxy pdsls:80 80 80 } 81 81 82 + # camo and avatar 83 + camo.tngl.boltless.dev { 84 + tls internal 85 + reverse_proxy camo:8787 86 + } 87 + 88 + avatar.tngl.boltless.dev { 89 + tls internal 90 + reverse_proxy avatar:8787 91 + } 92 + 82 93 # bobbin (read appview / xrpc). permissive CORS so the web/ frontend in the 83 94 # browser can hit it cross-origin (bobbin serves no CORS headers itself). 84 95 bobbin.tngl.boltless.dev {
+27
localinfra/avatar.Dockerfile
··· 1 + # Development only. Not for production use. 2 + FROM node:24-slim 3 + 4 + # slim carries no trust store and workerd reads the system one 5 + RUN apt-get update \ 6 + && apt-get install -y --no-install-recommends ca-certificates \ 7 + && rm -rf /var/lib/apt/lists/* 8 + 9 + COPY <<'EOF' /usr/local/bin/avatar-entrypoint.sh 10 + #!/bin/sh 11 + set -eu 12 + if [ -f /caddy-ca/root.crt ]; then 13 + cp /caddy-ca/root.crt /usr/local/share/ca-certificates/caddy-dev.crt 14 + update-ca-certificates >/dev/null 15 + fi 16 + npm ci --no-audit --no-fund 17 + exec npx wrangler dev --ip 0.0.0.0 --port 8787 \ 18 + --var "AVATAR_SHARED_SECRET:${AVATAR_SHARED_SECRET}" \ 19 + --var "PLC_DIRECTORY_URL:${PLC_DIRECTORY_URL}" 20 + EOF 21 + RUN chmod +x /usr/local/bin/avatar-entrypoint.sh 22 + 23 + WORKDIR /src 24 + 25 + EXPOSE 8787 26 + 27 + ENTRYPOINT ["/usr/local/bin/avatar-entrypoint.sh"]
+26
localinfra/camo.Dockerfile
··· 1 + # Development only. Not for production use. 2 + FROM node:24-slim 3 + 4 + # slim carries no trust store and workerd reads the system one 5 + RUN apt-get update \ 6 + && apt-get install -y --no-install-recommends ca-certificates \ 7 + && rm -rf /var/lib/apt/lists/* 8 + 9 + COPY <<'EOF' /usr/local/bin/camo-entrypoint.sh 10 + #!/bin/sh 11 + set -eu 12 + if [ -f /caddy-ca/root.crt ]; then 13 + cp /caddy-ca/root.crt /usr/local/share/ca-certificates/caddy-dev.crt 14 + update-ca-certificates >/dev/null 15 + fi 16 + npm ci --no-audit --no-fund 17 + exec npx wrangler dev --ip 0.0.0.0 --port 8787 \ 18 + --var "CAMO_SHARED_SECRET:${CAMO_SHARED_SECRET}" 19 + EOF 20 + RUN chmod +x /usr/local/bin/camo-entrypoint.sh 21 + 22 + WORKDIR /src 23 + 24 + EXPOSE 8787 25 + 26 + ENTRYPOINT ["/usr/local/bin/camo-entrypoint.sh"]
+4
localinfra/readme.md
··· 21 21 - pdsls (<https://pdsls.tngl.boltless.dev>) 22 22 - bobbin (<https://bobbin.tngl.boltless.dev>, host `:8090`) 23 23 - hydrant indexer + record/identity resolver feeding bobbin (internal) 24 + - camo (<https://camo.tngl.boltless.dev>) and avatar 25 + (<https://avatar.tngl.boltless.dev>), the workers from `camo/` and `avatar/` 26 + under wrangler. avatar resolves against the local plc, so it serves real 27 + avatars for accounts that have one and a generated placeholder otherwise 24 28 - web/ sveltekit frontend (host `127.0.0.1:5174`, live reloading) 25 29 - caddy reverse proxy 26 30
+8 -1
web/vite.config.ts
··· 13 13 // More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon 14 14 const devHost = process.env.VITE_DEV_HOST ?? "127.0.0.1"; 15 15 const devPort = Number(process.env.VITE_DEV_PORT ?? 5173); 16 + // docker desktop's macos file sharing never forwards inotify to the container, 17 + // so an edit on the host lands on disk but the watcher never fires and hmr goes 18 + // stale. polling is the only way to see those writes, and only the container 19 + // needs it 20 + const watch = 21 + process.env.VITE_WATCH_POLL === "true" ? { usePolling: true, interval: 300 } : undefined; 16 22 const devRedirectUri = `http://127.0.0.1:${devPort}/oauth/callback`; 17 23 const devClientId = `http://localhost?redirect_uri=${encodeURIComponent(devRedirectUri)}&scope=${encodeURIComponent(oauthMetadata.scope)}`; 18 24 export default defineConfig({ ··· 42 48 host: devHost, 43 49 port: devPort, 44 50 strictPort: true, 45 - allowedHosts: [".ts.net"] 51 + allowedHosts: [".ts.net"], 52 + watch 46 53 }, 47 54 test: { 48 55 expect: {