Tulpa Studio
Scheda operativa per tulpa-studio
Tulpa Studio
Stato operativo
VPS e router produzione gia' preparati, ma il dominio e' gestito dal cliente. Cutover in attesa di coordinamento esterno.
Runtime e deploy
| Voce | Valore |
|---|---|
| Repo | /opt/obelica/repos/tulpa-studio |
| Container | tulpa-studio |
| Stack | Next.js |
| Porta interna | 3000 |
| Env file | /opt/obelica/secrets/apps/tulpa-studio.env |
| Deploy | next-docker |
DNS e TLS
Dominio produzione: tulpastudio.com, www.tulpastudio.com.
Router Traefik include staging e produzione. Finche' il DNS resta su terzi/Vercel, Traefik puo' registrare errori ACME attesi per tulpastudio.com.
Record importanti da preservare nella zona target: Google Workspace, Amazon SES, Lovable, Canva e record commercial, secondo runbook DNS DigitalOcean.
Database, storage e backup
Database su DigitalOcean Managed PostgreSQL. Storage migrato verso DigitalOcean Spaces secondo documentazione storage. Backup Obelica copre repo/config; database e Spaces seguono policy dedicate.
Verifiche
Staging VPS disponibile su tulpa-studio.vps.obelica.com.
Router Traefik — modifica 2026-07-03
I domini production sono stati RIMOSSI dal router Traefik: il DNS punta ancora
all'hosting precedente e la challenge ACME falliva in loop ogni ora (rischio
rate-limit Let's Encrypt, 22 errori/24h sui log Traefik). Il compose contiene
un commento AL CUTOVER accanto alla rule con le righe esatte da riattivare
(Host production + label tls.domains). Al cutover: riattivare le label,
docker compose up -d, verificare emissione certificato.
Punti aperti
- attendere che il cliente cambi DNS/nameserver;
- verificare certificato Let's Encrypt dopo il cutover;
- aggiornare questa scheda con esito finale.
- al cutover: riattivare i domini production nel router Traefik (commento AL CUTOVER nel compose).
Upload media / Storage Spaces (risolto 2026-07-19)
Gli upload dell'area admin (media library) usano DigitalOcean Spaces via
presigned URL (src/lib/storage/server → createUploadTarget, client
src/lib/storage/client-upload). Il client chiede un target di upload alla
route, riceve un uploadUrl presigned (ACL public-read) e fa il PUT
direttamente su Spaces.
Bug risolto: in produzione SPACES_ACCESS_KEY_ID e SPACES_SECRET_ACCESS_KEY
erano vuote ("") — le chiavi c'erano ma i valori no. Con
STORAGE_PROVIDER=spaces, createUploadTarget chiamava
requireEnv('SPACES_ACCESS_KEY_ID') e lanciava
Missing required environment variable: SPACES_ACCESS_KEY_ID, quindi la
generazione del target falliva e l'upload non partiva. Nessuno l'aveva ancora
notato (nessun errore nei log: feature non usata di recente).
Fix (env-only, nessun rebuild): popolate le due credenziali riusando quelle
del bucket condiviso obelica-assets-prod (già in uso da wash-dog), backup
dell'env salvato accanto al file, container ricreato
(docker compose up -d --force-recreate --no-build).
Verifica: route upload-target raggiungibile (401 senza auth = modulo storage
ok, nessun problema di bundling del presigner); flusso presigned reale testato
con le credenziali → PUT 200 + GET pubblica 200 image/png sul prefisso
dell'app.
Nota: stesso identico problema che aveva sonja-trekking (vedi sua scheda).
Tutte le app condividono il bucket obelica-assets-prod, namespacato con
SPACES_APP_PREFIX.
Addendum tulpa: la route /api/cms/media/upload usa ancora @vercel/blob/client come fallback quando il provider non e spaces; con STORAGE_PROVIDER=spaces quel path resta inattivo. Il token BLOB_READ_WRITE_TOKEN residuo e quindi morto. Eventuali media storici in DB potrebbero puntare a URL blob.vercel-storage.com (vedi script migrate).