Skip to main content

Quickstart

One path, no choices: a fresh Ubuntu or Debian server, the installer, the setup interview, and the owner-claim token. Everything else is a decision you can make later.

Before you start, read Requirements and sizing — the floor is 4 vCPU and 8 GB of RAM, and the reason is transcoding, not web serving.

Compose 2.24 or newer, in production

docker-compose.prod.yml uses the !reset / !override merge tags to close the Postgres, Redis and search port publishes. On an older Compose those tags are silently ignored and your database is published to the internet while the deploy reports success. deploy.sh, rollback.sh and restore.sh each parse docker compose version --short and refuse to run below 2.24. The installer installs a current Compose for you; verify with nmap from another host anyway.

Hardware floor

Do not use a 2 GB droplet. ffmpeg runs inside the api container, so one TargetAll job on a 1080p source is twelve full-source encode passes. Postgres, api, frontend, search, Caddy and one transcode need roughly 4 GB before ClamAV.

Step 1 — run the installer

On the server, as a user who can sudo:

curl -fsSL https://raw.githubusercontent.com/yegamble/vidra/main/install.sh | sh

It detects the platform, installs Docker Engine and the Compose v2 plugin from Docker's own apt repository if they are missing, downloads vidra-core's latest release bundle, verifies it against the release's SHA256SUMS, unpacks it into /opt/vidra, installs the checksum-verified vidra CLI into /usr/local/bin, and then hands the terminal to vidra setup.

Everything it would change sits behind one confirmation, read from /dev/tty because under curl … | sh stdin is the script itself. Pass --yes where there is no terminal to ask on.

You should now see the installer's summary of what it found and what it installed, followed immediately by the first question of the setup interview. Nothing is running yet: the installer starts no containers and opens no ports.

Step 2 — answer vidra setup

The interview writes env/production.env (mode 0600) and renders deploy/Caddyfile.local from the deployment template. It asks for your domain and TLS mode, media storage, which optional components you want, and mints every secret the template leaves blank.

vidra setup --template env/production.env.example   # if you need to re-run it
vidra setup --template env/production.env.example --web # same questions, in a browser

Re-running is safe. The file being written is always read back first and every value it already sets is preserved; a secret is only ever replaced when --rotate names it. The installer never passes --yes to it, so an existing env file is never silently rewritten.

Then bring the stack up:

cd /opt/vidra
vidra deploy

You should now see vidra deploy walk its gated pipeline — pre-deploy dump, pull, the two migrators, up -d --no-build, health probes — and finish with /readyz answering 200. Confirm it yourself:

curl -fsS http://127.0.0.1:8080/readyz

Step 3 — claim the owner account

The first admin is claimed, not registered. While the instance is unclaimed — empty users table, unredeemed token — every signup path answers 403 owner_claim_required. The only way in is a one-time token the api mints at boot and prints to its own log.

./deploy/compose.sh logs api | grep 'FIRST-RUN SETUP REQUIRED'

Use compose.sh, never a bare docker compose logs api — on a deployment host the bare form auto-loads docker-compose.override.yml and addresses a different project than the deploy scripts do. Take the newest line: every api restart mints a fresh token and invalidates the previous one.

Redeem it at https://<your domain>/setup/claim in the browser, or directly:

curl -X POST https://example.com/api/v1/setup/claim-owner \
-H 'Content-Type: application/json' \
-d '{"token":"<the token>","username":"...","email":"...","password":"..."}'

Only the token's hash is stored, so a lost token is re-minted by restarting the api — never recovered.

You should now see your instance's home page at your domain, and be able to sign in as the owner. Verify you actually got admin before you trust it: GET /api/v1/admin/system with your access token must return 200, and /admin in the UI must render.

Next steps

  • Lock the box down. Production deployment covers the firewall, the swapfile, the backup timer and the nmap check that proves your database is not on the internet.
  • Decide your registration policy. REGISTRATION_ENABLED=false is the right default for a private launch; see Moderation and instance settings.
  • Prove your backups work. Run ./deploy/backup.sh once by hand, then restore it into a scratch stack. See Operator CLI.
  • Coming from PeerTube? Migrate from PeerTube.
  • Just want to develop against it? Development setup.