puter: create config.json with allow_nipio_domains to fix 'Invalid Host Header' on LAN
slink: replace $STD with plain redirects on fallible console commands (silent() hard-exits before || true)
slink: add ORIGIN env var via EnvironmentFile for SvelteKit CSRF to allow LAN login
- Set ADMIN_EMAIL/ADMIN_PASSWORD so admin user is created on first boot
- Generate JWT keypair for authentication to work
- Run doctrine:migrations:migrate for DB schema
- Save credentials to ~/slink.creds
- nginx: add exact-match location for /uploads (no trailing slash)
to handle S3 presigned POST URLs from Plane's storage backend
- ct: fix curl -s to curl -fsSL for consistency with other scripts
TubeArchivist uses TA_CACHE_DIR and TA_MEDIA_DIR directly as URL paths.
In Docker these are /cache and /youtube, matching nginx locations.
Our paths (/opt/tubearchivist/cache, /opt/tubearchivist/media) broke
video playback URLs and file downloads.
Create symlinks /cache and /youtube pointing to data dirs, set env vars
to match Docker defaults. Aligns nginx alias paths with official config.
The auth_request subrequest to /api/ping/ through the generic /api
location block doesn't properly forward cookies to the Django backend,
causing 403 for all /cache/ and /media/ requests.
Use a dedicated internal /_auth location that explicitly proxies to
/api/ping/ with Cookie header forwarding.
Beat service starts before manage.py migrate creates the
django_celery_beat tables, causing 'no such table' error.
Add ExecStartPre that waits for migration to complete by
polling the SQLite DB for the crontab table.
ExecStartPre runs Xvfb as a blocking foreground process, preventing
systemd from ever reaching ExecStart (timeout/failure).
Use xvfb-run wrapper to properly manage the virtual display.
Docker copies backend to /app, so APP_DIR=/app maps static/img/ correctly.
Our bare-metal install has backend at /opt/tubearchivist/backend/,
so TA_APP_DIR must point there for fallback thumbnails to resolve.
Fixes missing thumbnails, default-channel-banner.jpg not found error.
Update script migrates existing installs to the corrected path.
Next.js standalone output requires .next/static and public/ to be
copied manually into .next/standalone/ for CSS/JS to be served.
Also source .env before prisma generate in update script.
- Replace Caddy with Nginx (matches upstream Dockerfile)
- Add crypto.randomUUID polyfill in index.html for non-HTTPS access
(browsers only expose crypto.randomUUID in secure contexts)
- Apply polyfill also in update script
- Transmute: replace manual curl with fetch_and_deploy_gh_release prebuild
- Nametag: pass DATABASE_URL to prisma generate (config needs it at load time)
- OTBR: use apt nodejs/npm instead of setup_nodejs (only needed for cmake web build)
- Build from source via git clone + cmake/ninja
- Privileged container for network admin (iptables/ipset/tun)
- Web GUI on port 80, REST API, mDNS service discovery
- Configurable RCP device path in /etc/default/otbr-agent
- Git-based update with shallow fetch + rebuild
Browser uploads fail with ERR_CONNECTION_REFUSED because Museum returns
presigned S3 URLs with localhost:3200 — unreachable from the user's PC.
Changed all three S3 bucket endpoints to use LOCAL_IP:3200.