Files
twotalesanimation 7150c3f3d2
Deploy / deploy (push) Successful in 39s
Add /drops/: login-protected, view-only shot previews
- nginx basic auth on /drops/ (page and clips); login file and clips live
  on the server only (docker/auth, docker/drops), never in git or the image
- Fails closed: missing login file returns 500; no-store, noindex
- Page reads manifest.json from the server, shows "taken down" when empty
- Player hides download/cast/PiP, blocks right-click, confidential overlay
- DEPLOY.md step 8: how to share a drop and take it down

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 14:10:02 +02:00

6.9 KiB

Deploying twotalesvfx.com

Same setup as the other apps (vfxreview, xbid):

git push main ──► Gitea Actions runner ──► cd /opt/ttvfx_web && git pull
                                          docker compose up -d --build
                                                    │
                    Cloudflare ──► Nginx Proxy Manager ──► ttvfx-web:80 (nginx, static files)
                                   (npm_default network)

Files involved:

File What it does
Dockerfile Builds the static export with Node 20, then serves out/ from nginx:alpine
docker/nginx.conf nginx config inside the container (routes, 404 page, caching, relative redirects)
docker-compose.yml One service, container name ttvfx-web, joined to the external npm_default network, no host ports
.gitea/workflows/deploy.yml On push to main: pull in /opt/ttvfx_web and rebuild

There is no .env and no database. The site is fully static.


One-time setup on the server

1. SSH in

ssh <you>@178.104.56.62        # git.twotalesvfx.com's IP; use your usual host if different

2. Check how the existing apps are set up, and copy that

ls -la /opt                         # note the owner of /opt/xbid and /opt/vfxreview
git -C /opt/xbid remote -v          # note HOW it authenticates (https+token, ssh, ...)
docker network ls | grep npm_default

npm_default must exist. It's the Nginx Proxy Manager network.

3. Clone into /opt/ttvfx_web

Use the same remote style as /opt/xbid so the runner's git pull can authenticate. For example, if xbid uses an https remote:

sudo git clone https://git.twotalesvfx.com/pinto/ttvfx.git /opt/ttvfx_web

Then match the ownership of the other app folders (replace <owner> with what ls -la /opt showed):

sudo chown -R <owner>:<owner> /opt/ttvfx_web

If xbid's remote URL contains a token or uses SSH, clone this one the same way (e.g. git clone git@git.twotalesvfx.com:pinto/ttvfx.git /opt/ttvfx_web).

4. First build by hand

cd /opt/ttvfx_web
docker compose up -d --build
docker ps --filter name=ttvfx-web          # should be "Up"

The first build takes a minute or two (npm install + Next build). Later builds reuse the cache.

Check that it serves from inside the proxy network:

docker run --rm --network npm_default curlimages/curl -sI http://ttvfx-web/
# -> HTTP/1.1 200 OK

5. Nginx Proxy Manager: add the proxy host

In the NPM web UI → Hosts → Proxy Hosts → Add Proxy Host:

  • Domain names: twotalesvfx.com, www.twotalesvfx.com
  • Scheme: http
  • Forward hostname / IP: ttvfx-web
  • Forward port: 80
  • Tick Block common exploits. Websockets aren't needed.
  • SSL tab: request a new Let's Encrypt certificate, then tick Force SSL and HTTP/2.
    • Cloudflare is proxying the domain. If the HTTP challenge fails, either grey-cloud the two records for a minute while the cert is issued, or use DNS challenge → Cloudflare with an API token. Use whichever you did for review. / xbid..

6. Cloudflare DNS

The apex currently returns 522 (Cloudflare can't reach the origin). Point it at this server:

Type Name Value Proxy
A @ 178.104.56.62 Proxied
A www 178.104.56.62 Proxied

(Confirm the server's IP with curl -4 ifconfig.me on the box.) Leave review, git, xbid etc. alone. Set SSL/TLS → Full (strict), the same as the other subdomains.

7. Turn on auto-deploy

The workflow is already in the repo (.gitea/workflows/deploy.yml). In Gitea, open pinto/ttvfx → Settings → Repository → Enable Actions if it isn't enabled already (it's on for the other repos). The existing runner picks the job up. It uses the same ubuntu-latest label and /opt:/opt mount as xbid.

Test it: push any commit to main and watch Actions in the repo. The job should run git pull and docker compose up -d --build, then the site updates.

8. Private shot previews at /drops/

/drops/ is a view-only screening page for vendors and clients. nginx asks for a login before it serves the page or any clip. The login file and the clips stay on the server only, in docker/auth/ and docker/drops/, and are never committed. The page reads docker/drops/manifest.json to know which clips to show.

Share a drop. On your PC, convert the clips to web MP4 without re-encoding, then copy them up:

ffmpeg -i SHOT.mov -map 0:v -map 0:a? -c copy -movflags +faststart -map_metadata -1 SHOT.mp4
scp SHOT.mp4 manifest.json <you>@178.104.56.62:/opt/ttvfx_web/docker/drops/

manifest.json looks like this (src is the file name in docker/drops/):

{ "title": "DH2 shot previews", "note": "For review only.",
  "files": [{ "name": "DH2_VFX_027_210_REF", "src": "DH2_VFX_027_210_REF.mp4" }] }

Then set a password on the server. Use a new password for each vendor and drop:

cd /opt/ttvfx_web
mkdir -p docker/auth
printf "vendor:$(openssl passwd -apr1)\n" > docker/auth/drops.htpasswd   # prompts for the password
docker compose up -d --force-recreate    # first time only, so the folders get mounted

Send https://twotalesvfx.com/drops/, the username vendor and the password through two different channels (for example, the link by email and the password by WhatsApp).

Take it down. No deploy is needed. Delete the clips and the login, and the page returns "taken down" or 500 straight away:

rm /opt/ttvfx_web/docker/drops/* /opt/ttvfx_web/docker/auth/drops.htpasswd

If the login file is missing, /drops/ returns 500, so it is never left open. Nothing in /drops/ is cached by browsers or Cloudflare.


Day to day

git push            # from your machine. That's it, the runner deploys.

Manual redeploy or logs on the server:

cd /opt/ttvfx_web && git pull && docker compose up -d --build
docker logs -f ttvfx-web

Troubleshooting

Symptom Fix
Action fails on git pull with dubious ownership git config --global --add safe.directory /opt/ttvfx_web (run it however you did for xbid), or fix ownership to match /opt/xbid
Action fails on git pull with authentication The clone's remote URL needs the same credentials as /opt/xbid (git -C /opt/xbid remote -v)
network npm_default declared as external, but could not be found NPM's network has a different name on this box. Check docker network ls and update docker-compose.yml
NPM shows 502 Bad Gateway Container not running (docker ps) or wrong forward host. It must be ttvfx-web, port 80
Cloudflare 522 DNS @/www still point at the wrong IP, or ports 80/443 are firewalled
Old content after deploy Purge Cloudflare cache (Caching → Purge Everything). HTML isn't cached long, but video and images are cached for 7 days