Shared infrastructure

The surfaces every product depends on

Topology at a glance

flowchart LR subgraph EXT[External SaaS] CF[Cloudflare
twistedyeti@gmail.com
19 zones] AWS[AWS SES
outbound smarthost] GH[GitHub
teaganwins-dev] ANT[Anthropic Team] TS[Tailscale] BW[Bitwarden
SPS LLC org] end subgraph DO[DigitalOcean droplet] MC[Mailcow
mail.sandpointstudios.ltd
167.71.174.187] end subgraph VS[vigil-server] TUN[cloudflared
multi-tenant tunnel
21+ hostnames] HP[Homepage
intranet] VST[Vigil Steward
:8003 / 297 routes] OL[Ollama LLM] GT[GlitchTip] GR[Grafana] NWZ[NWZ helpdesk] end subgraph EDGE[Cloudflare edge] PAGES[Pages projects
onboarding-site, etc.] ACC[CF Access
Google IdP] end USR((SPS user)) --> ACC ACC --> TUN ACC --> PAGES TUN --> HP TUN --> VST TUN --> NWZ TUN --> GT TUN --> GR MC -. SMTP relay .-> AWS ANT -. seats .-> USR GH -. repos .-> VS BW -. creds .-> USR USR -. tailnet .-> TS TS -. private mesh .-> VS

Mailcow on DigitalOcean

Email for every SPS-owned domain (sandpointstudios.ltd, onecutshop.app, wyrdlyre.app, rightbower.app, agogedev.com, dev.finishops.com, casaops.{mx,app}) runs on a single Mailcow instance hosted on a DigitalOcean droplet at mail.sandpointstudios.ltd (167.71.174.187). Outbound mail relays through Amazon SES on port 2587 as a deliverability smarthost.

Common pitfall. SMTP submission on port 587 requires server.starttls() before server.login(), or you get 535 5.7.8. Or use port 465 with SMTP_SSL. Bot scripts have silently broken on this before.

The help@sandpointstudios.ltd mailbox is the centralized contributor intake — every product's outbound system email defaults to this address, with the relevant help@<product-domain> as the override for product-specific channels.

Apex domains NOT on Mailcow: finishops.com and sshomefinishes.com stay on Microsoft 365 (Dusty's existing setup; not migrated).

vigil-server

The primary production AI server. ASUS TUF X570-PLUS, Ubuntu 24.04, on the team Tailnet as vigil-server (100.98.48.21) and on the LAN at 192.168.0.21. Hosts the heaviest workloads in the portfolio: Vigil Steward, the NWZ helpdesk stack, Homer, the intranet (Homepage), Ollama, Grafana/Prometheus, code-server containers, the centralized cloudflared tunnel, and more.

Containers + ports (representative subset)

ServiceContainerPortPublic hostname
Vigil Steward APIvigil-steward-api8003via Tailscale only
Homer (intranet)homepage3030intranet.sandpointstudios.ltd
NWZnwz-*variesnwz.sandpointstudios.ltd
cloudflaredcloudflaredtunnel routes 21+ hosts
code-server (6 contributors)code-{lewis,bert,arthur,phoenix,dusty,raghav}127.0.0.1:8502-8507code-<name>.sandpointstudios.ltd via CF Access
Ollamaollama11434Tailscale only
Grafanagrafana3000Tailscale only
GlitchTipglitchtipglitchtip.sandpointstudios.ltd
TimeKeeptimekeeptime.sandpointstudios.ltd
STR-opsstrops-{backend,frontend}8015 / 8081strops.sandpointstudios.ltd

The multi-tenant cloudflared tunnel

A single cloudflared container on vigil-server fronts 21+ public hostnames despite its historical name being vigil-ledger. New public hostnames are added by appending an ingress rule — not by spinning up a new tunnel. This is the path every CF-Access-gated service uses to surface from vigil-server's private network to the Cloudflare edge.

When you add a new self-hosted service: ingress rule in the existing tunnel config + DNS CNAME via flarectl + CF Access app (if it should be gated). Three writes, no new infra.

Cloudflare account

All 19 zones live in a single Cloudflare account under twistedyeti@gmail.com (account ID e61960da9bb822bb27cac40b7284c76b). Includes sandpointstudios.ltd, sandpointstudios.net, teaganwins.net, onecutshop.app, wyrdlyre.app, rightbower.app, sshomefinishes.com, stierpainting.com, and more.

A second CF account exists. teaganwins@gmail.com is a secondary account where some orphan domains (haulhard.com, casaops.{mx,app}) landed by accident. CF can't merge accounts, but Move-Domain transfers individual zones in ~30s.

The vigil-ops-primary API token at the primary account has broad scopes — DNS Write, Pages Write, Workers Write, Routes Write, Single Redirects Write, Page Rules Write, Tunnel R/W, R2/KV/D1 Write, Access policy R/W, SSL/Certs Write, and the ability to mint/patch other tokens. This drives flarectl, wrangler, and direct API calls in agent contexts.

Cloudflare Access — Google IdP

Every self-hosted service that needs identity-gated access uses Cloudflare Access with Google as the upstream IdP. Policies allow @sandpointstudios.ltd emails by domain, plus explicit allowlists for externals (Bert's bakerbert7@gmail.com, Dusty's dstier@sshomefinishes.com, Lewis's lewis.ellwanger@gmail.com).

This is what makes "sign in once with your SPS Google account, get the intranet + onboarding site + code-server + NWZ + Agoge + TimeKeep all at once" actually work. Contributors only have to authenticate one provider.

Bitwarden — SPS LLC organization

The Sand Point Studios LLC Bitwarden organization is the primary credential store for everything an agent or contributor might need to reach. The SPS Service collection holds 77+ migrated agent-reachable creds: Mailcow mailboxes, Cloudflare/AWS/GitHub/Anthropic API keys, NWZ secrets, DB passwords.

BW is laptop-local. The bw unlock path uses the BW_MASTER_PASSWORD env var which is set only on Teagan's laptop (Windows user env) and on vigil-server's shell env. SSHing somewhere else and trying to use BW silently fails. Unlock locally; SSH for the remote action.

GitHub — teaganwins-dev

The primary GitHub identity for the SPS portfolio is teaganwins-dev (personal account, not an organization). Repos are private by default; contributor access is granted per-repo as a write collaborator. Contributors authenticate via personal access tokens stored as GITHUB_TOKEN environment variables inside their code-server containers, with a credential helper bridging the token to HTTPS git operations.

Anthropic Team plan

Five seats on the SPS Team plan (Lewis Premium, Bert + Arthur + Phoenix + Dusty Standard, plus Raghav inbound 2026-06-08). Each contributor's Claude Code instance — both on their laptop and in their code-server container — should authenticate against their SPS-email-bound Anthropic account so usage rolls up against the Team plan, not against Teagan's personal API key.

The migration is incomplete. A few contributor containers had a personal ANTHROPIC_API_KEY hard-coded in .bashrc as a holdover from the pre-Team-plan setup. Those were neutralized 2026-05-17 for Lewis and Bert. Check this before onboarding any new contributor — if echo $ANTHROPIC_API_KEY returns anything inside their container, comment it out.

Vigil TeamCode (VTC)

A metering proxy at code.sandpointstudios.ltd fronts a fleet of code-server containers, one per contributor. Each container has the SPS toolchain pre-installed and a /shared/dev-context/ bind mount that surfaces the team's conventions, decisions log, and active-projects index inside every contributor's workspace.

Document map

Cross-references for "where does X live?"

SurfaceWhere
Conventions, decisions log, active projects~/dev-context/ (synced to /shared/dev-context/ in code-server containers)
Memory cards (per-session learnings)~/.claude/projects/.../memory/
Onboarding guide for contributorsonboarding.sandpointstudios.ltd
Intranet launcher (live tools/dashboards)intranet.sandpointstudios.ltd
This architecture KBarchitecture.sandpointstudios.ltd
Email infrastructure deep-dive~/dev-context/email-platform.md
Bitwarden migration notes~/dev-context/bw-service-account-migration.md