[Blog](https://deploywithox.com/blog) [Guides](https://deploywithox.com/blog#c-guides) # How to self-host PeerTube (video platform) on your own VPS Run PeerTube v8.3.1, a federated video platform, on your own Ubuntu server with ox: Node.js, Postgres, Redis and ffmpeg, from the config that ran. Saurav Sharma Oct 17, 2026 10 min read On this page - [What you need](https://deploywithox.com/blog/self-host-peertube#what-you-need) - [The steps](https://deploywithox.com/blog/self-host-peertube#steps) - [The ox.toml, line by line](https://deploywithox.com/blog/self-host-peertube#config) - [Postgres and Redis](https://deploywithox.com/blog/self-host-peertube#services) - [Updates and backups](https://deploywithox.com/blog/self-host-peertube#updates) - [Frequently asked questions](https://deploywithox.com/blog/self-host-peertube#faq) To self-host PeerTube you need an Ubuntu server, a fork of the PeerTube repo with one `ox.toml` file added, and 35 variables, two of them secrets that ox can generate for you. In our run the first deploy took about 5 minutes, and ox set up Postgres and Redis for it. **How we tested** On Oct 17, 2026, ox deployed PeerTube v8.3.1 from commit [`3324876a`](https://github.com/Chocobozzz/PeerTube/commit/3324876a0b0f846f8b6632470b3d9d53ef74b8b7) on a fresh DigitalOcean server with 8 vCPUs and 16 GB of memory. The run then redeployed it, backed it up and rebooted the server. Then a separate test agent, one that did not write the config, signed in, uploaded a short video, saw it transcoded and published, and saw it after a reload, and checked the app's services and its backup. [PeerTube](https://github.com/Chocobozzz/PeerTube) is a video platform you run yourself, developed by Framasoft. People upload videos to channels, the server turns each upload into HLS streams with ffmpeg, and viewers watch in the browser without an account. Instances can follow each other over ActivityPub. It is a Node.js server written in TypeScript with an Angular front end, under the GNU AGPL v3. Its data lives in Postgres and its job queues run through Redis. ox deployed PeerTube v8.3.1 (commit 3324876a) on Oct 17, 2026 on a fresh DigitalOcean server with 8 vCPUs and 16 GB of memory; the first deploy took 5 minutes and a redeploy took 3 minutes. - **First deploy:** 5 minutes, from adding the project until the app passed the run's first checks. - **Redeploy of the same commit:** 3 minutes, until the app passed the checks again. - **Server:** DigitalOcean, 8 vCPUs and 16 GB of memory (`s-8vcpu-16gb`), with this app alone on it. Every one of the 85 apps we deployed ran on this one size, so it was not picked for this app. - **Memory in use after the reboot:** 865 MB of 15986 MB, for the whole server: Ubuntu, the app, its services, Caddy and the ox agent. On a server with no apps, ox's tests on real servers hold the agent to 40 MB or less and Caddy to 50 MB or less. - **Services ox runs for it:** `postgres`, `redis`. - **Source:** [github.com/Chocobozzz/PeerTube](https://github.com/Chocobozzz/PeerTube) at v8.3.1, commit [`3324876a`](https://github.com/Chocobozzz/PeerTube/commit/3324876a0b0f846f8b6632470b3d9d53ef74b8b7). The PeerTube Browse videos page PeerTube after signing in as root My videos listing the uploaded clip ox verify clip 1017 as public ## What you need - An Ubuntu LTS server. The run used the size shown in the facts, with PeerTube alone on it, and the build, the database, Redis and ffmpeg all ran there. - A GitHub account to fork `Chocobozzz/PeerTube`, and an ox account, which you open by signing in with GitHub. - An SMTP server for PeerTube's mail. The run used a test mail catcher, so no real mail went out, and a real provider was not tested. ## The steps In the ox dashboard press Add a server and run the command it shows, as root, on the new machine. It carries a fresh token and installs the ox agent and Caddy. Fork `Chocobozzz/PeerTube`. Put the code of the tag `v8.3.1`, the release the run deployed, on your fork's default branch, which is the branch ox deploys. Add the `ox.toml` shown below at the repo root and push. The run added no other file. Next write `peertube.env` with the 33 values that are not secrets, which the variables section goes through. With the [ox CLI](https://deploywithox.com/docs/cli) signed in, run: Shell ```bash ox new /PeerTube ox review peertube --generate PEERTUBE_SECRET --generate PT_INITIAL_ROOT_PASSWORD --from-file peertube.env --wait ``` ox lowercases the repo name, so the project is `peertube`. The review saves your values, makes the two secrets and starts the first deploy, and `--wait` prints the run. The browser has the same two steps in the [quickstart](https://deploywithox.com/docs/quickstart). When the deploy is green, read root's password with `ox vars peertube --reveal`, which ox records in its audit log. Open the address ox shows for the project, press Login and sign in as `root`. A welcome window for the administrator opens first, and Remind me later closes it. To publish, press Publish in the side menu, choose a file, give the video a title, set Privacy to Public and press Publish. The test agent uploaded a 5-second clip. PeerTube made a 720p HLS stream from it within seconds, and after a reload the clip was still listed under My videos. The run served PeerTube on its preview address, so a domain of your own was not tested; the [domains page](https://deploywithox.com/docs/operate/domains) covers how ox adds one. PeerTube's production guide says it does not support a change of web server host, so settle on the address you will keep before the instance holds real videos. ## The ox.toml, line by line TOML ```toml # PeerTube on ox, following support/docker/production (the recipe the project # ships): its Dockerfile's apt packages, `npm run install-node-dependencies` # (ox's detected pnpm install), `npm run build` (server, then the Angular # client), and `node dist/server`. Configuration is config/default.yaml, then # config/production.yaml made from the example as support/doc/production.md # says, then the image's PEERTUBE_* environment mapping, which the variables # fill (the image's own production.yaml points storage at ../data and the # database at a "postgres" container, so it is left out). # The image installs openssl, ffmpeg (transcoding, thumbnails), python3 (it # runs yt-dlp for video imports) and build-essential for native modules, # here the C compilers ox check names in its place on Ubuntu 26.04. packages = ["ffmpeg", "python3", "openssl", "gcc", "g++", "make", "libc6-dev", "libcrypt-dev"] # The instance secret and root's first password: PeerTube refuses to start # without the first, and the second is how the first account signs in. required_variables = ["PEERTUBE_SECRET", "PT_INITIAL_ROOT_PASSWORD"] [app] # NODE_ENV is set here, as the image sets it after its build, so the build # never runs with it. Edits made in the admin pages go to # local-production.json in PEERTUBE_LOCAL_CONFIG, which is inside the kept # storage folder so they survive deploys, and node-config reads that folder # after config/. PEERTUBE_WEBSERVER_HTTPS is a JSON boolean, so it follows the # scheme the release is served on. The database is created and migrated as # the server starts (server/server.ts: migrate, then installApplication). start = """ mkdir -p "$OX_DATA_DIR/storage/config" export NODE_ENV=production \ NODE_CONFIG_DIR="$PWD/config:$OX_DATA_DIR/storage/config" \ PEERTUBE_LOCAL_CONFIG="$OX_DATA_DIR/storage/config" \ PEERTUBE_LISTEN_PORT="$PORT" \ PEERTUBE_WEBSERVER_HTTPS=$([ "$PUBLIC_SCHEME" = https ] && echo true || echo false) exec node dist/server """ health = "/api/v1/ping" # PeerTube runs as one process per database: a second copy would run the same # job queues and schedulers beside the first, and the live (RTMP) server binds # the fixed port 1935 once live is turned on in the admin pages. stop_before_start = true [build] commands = [ "cp config/production.yaml.example config/production.yaml", "cp support/docker/production/config/custom-environment-variables.yaml config/", "npm run build", ] [services] # PeerTube creates both extensions as it starts (server/core/initializers/database.ts). postgres = { extensions = ["pg_trgm", "unaccent"] } redis = {} [storage] # Videos, previews, avatars, logs, plugins and the rest: the PEERTUBE_STORAGE_* # variables point each one into this folder under $OX_DATA_DIR, outside the # release, as PeerTube asks of a production instance. keep = ["storage"] [tools] # The image is node:22, and CI runs Node 22. node = "22" ``` - `packages` takes what PeerTube needs from the apt list of its Docker image. ffmpeg makes the HLS streams and thumbnails, and python3 runs yt-dlp for video imports, which were not tested. The image also installs `build-essential` for native Node modules, a name ox refuses on Ubuntu 26.04, so the five compiler packages stand in for it. - `required_variables` names the instance secret and root's first password. PeerTube stops at start when the secret is empty. Without the password, root gets a random one that only PeerTube's log shows. - `start` makes a config folder inside the kept storage and sets `NODE_ENV=production`, here and not in the build, as the Docker image does. `NODE_CONFIG_DIR` lists the release's `config` folder and then the kept one, and `PEERTUBE_LOCAL_CONFIG` names the kept one, so settings saved in PeerTube's admin pages (it writes them to `local-production.json`) survive deploys. The port is ox's `$PORT`, and HTTPS follows the address's scheme. PeerTube migrates its database as it starts, so there is no migrate line. - `health` is PeerTube's ping route, which must answer before ox moves traffic to a new release. - `stop_before_start` is `true` because PeerTube should run as one process per database: a second copy would run the same job queues and schedulers, and with live streaming on it would want the fixed port 1935 too. A deploy stops the running copy first, so the site answers 502 for a short gap each time. - There is no install line. ox sees `pnpm-lock.yaml` and runs the pnpm install with a frozen lockfile, using the pnpm version `package.json` names. - The build `commands` copy `production.yaml.example` to `production.yaml`, as PeerTube's production guide says, and copy the Docker image's `custom-environment-variables.yaml` into `config/`, which maps `PEERTUBE_` variables onto config keys. `npm run build` builds the server and then the Angular client. - `[services]` asks for Postgres with the extensions `pg_trgm` and `unaccent`, which PeerTube checks for at start and creates when they are missing, and for Redis. - `[storage]` keeps the `storage` folder across deploys, so videos, previews, avatars, logs and plugins stay outside the release. - `[tools]` pins Node 22, the major version of PeerTube's Docker image. Shell ```bash PEERTUBE_SECRET PT_INITIAL_ROOT_PASSWORD PEERTUBE_DB_HOSTNAME PEERTUBE_DB_PORT PEERTUBE_DB_NAME PEERTUBE_DB_USERNAME PEERTUBE_DB_PASSWORD PEERTUBE_REDIS_HOSTNAME PEERTUBE_REDIS_PORT PEERTUBE_REDIS_AUTH PEERTUBE_WEBSERVER_HOSTNAME PEERTUBE_WEBSERVER_PORT PEERTUBE_SMTP_HOSTNAME PEERTUBE_SMTP_PORT PEERTUBE_SMTP_TLS PEERTUBE_SMTP_DISABLE_STARTTLS PEERTUBE_STORAGE_TMP PEERTUBE_STORAGE_TMP_PERSISTENT PEERTUBE_STORAGE_BIN PEERTUBE_STORAGE_AVATARS PEERTUBE_STORAGE_WEB_VIDEOS PEERTUBE_STORAGE_STREAMING_PLAYLISTS PEERTUBE_STORAGE_ORIGINAL_VIDEO_FILES PEERTUBE_STORAGE_REDUNDANCY PEERTUBE_STORAGE_LOGS PEERTUBE_STORAGE_PREVIEWS PEERTUBE_STORAGE_THUMBNAILS PEERTUBE_STORAGE_STORYBOARDS PEERTUBE_STORAGE_TORRENTS PEERTUBE_STORAGE_CAPTIONS PEERTUBE_STORAGE_CACHE PEERTUBE_STORAGE_PLUGINS PEERTUBE_STORAGE_WELL_KNOWN PEERTUBE_STORAGE_UPLOADS PEERTUBE_STORAGE_CLIENT_OVERRIDES ``` `PEERTUBE_SECRET` signs login tokens and two-factor codes. `PT_INITIAL_ROOT_PASSWORD` is root's first password. PeerTube's default settings accept 8 to 50 characters, and the one ox generates is 32. The `PEERTUBE_DB_*` and `PEERTUBE_REDIS_*` keys point PeerTube at its services. ox fills in the usual names, such as `DB_HOST`, but not PeerTube's own, so the run wrote references such as `${postgres.host}`, `${postgres.password}`, `${redis.port}` and `${redis.password}`. See [variables](https://deploywithox.com/docs/operate/variables) for how references work. `PEERTUBE_WEBSERVER_HOSTNAME` and `PEERTUBE_WEBSERVER_PORT` were `${PUBLIC_HOST}` and `${PUBLIC_PORT}`, the address ox serves the project on. PeerTube's front end gets its client credentials only from a request whose Host header matches them, so sign-in works only on that address. The four `PEERTUBE_SMTP_*` keys name the mail catcher's host and port, with TLS off and STARTTLS disabled because the catcher speaks plain SMTP. Settings for a real provider were not tested. The 19 `PEERTUBE_STORAGE_*` keys each name one folder, such as web videos, previews, thumbnails and logs. PeerTube's `default.yaml` puts them under `storage/` in the release, and its production check warns about that, so each points into `${OX_DATA_DIR}/storage/`, inside the kept folder. ## Postgres and Redis ox ran one Postgres for the server, with a database and a role for PeerTube, and a Redis for PeerTube alone with its own password. You can read the database from the Services tab, or with `ox explore peertube postgres`. PeerTube runs its job queues, transcoding included, inside the web process, so the project has no worker units. The test agent saw the clip's HLS transcoding job finish in the app's log. ## Updates and backups To move to a newer release, merge its tag into your fork and push, or run `ox deploy peertube --wait`. The run redeployed the same release, and an upgrade was not tested. PeerTube's changelog has IMPORTANT NOTES for some releases, and v8.3.0's asked for a migration script to run after the upgrade, so read them before you move up. Backups need no setup. The run's backups held a Postgres dump and an archive of the `storage` folder, both from Back up now, and the test agent found both not empty. `ox backups peertube` lists them. A large video library and a restore were not tested. The [backups page](https://deploywithox.com/docs/operate/backups) covers keeping copies in an S3 bucket. ## Frequently asked questions ### Do I need Docker to self-host PeerTube? No. PeerTube documents a Docker install and a classic one with Node, Postgres, Redis and ffmpeg on the host. ox follows the Docker image's recipe without running Docker: it builds PeerTube from your fork on the server and runs it as a system service beside Postgres and Redis. ### How do I sign in to a new PeerTube instance? The first account is the administrator `root`. PeerTube makes it on its first start with the password in PT_INITIAL_ROOT_PASSWORD, and without that variable it prints a random one in its log. Sign-up is off by default, so the page has no Create an account link. Making more accounts and sending invites by mail were not tested. ### How much memory does PeerTube use? After the reboot, the facts above show what the run's whole server used, which counts PeerTube, Redis, Postgres, Caddy and the ox agent, before any video was uploaded. Transcoding a long video was not measured. ox works on any server from 1 GB up, and says so when memory is why an app stopped. ### Is PeerTube free to self-host? PeerTube's code is under the GNU Affero General Public License, version 3, which lets you run it yourself at no charge. If you change it and let others use your changed copy over a network, the license asks you to offer them that source. Read the license file for your own case. New to running apps on your own server? [How ox self-hosts your apps](https://deploywithox.com/self-hosting) shows what ox sets up on your server. On this page - [What you need](https://deploywithox.com/blog/self-host-peertube#what-you-need) - [The steps](https://deploywithox.com/blog/self-host-peertube#steps) - [The ox.toml, line by line](https://deploywithox.com/blog/self-host-peertube#config) - [Postgres and Redis](https://deploywithox.com/blog/self-host-peertube#services) - [Updates and backups](https://deploywithox.com/blog/self-host-peertube#updates) - [Frequently asked questions](https://deploywithox.com/blog/self-host-peertube#faq) - [Do I need Docker to self-host PeerTube?](https://deploywithox.com/blog/self-host-peertube#faq-docker) - [How do I sign in to a new PeerTube instance?](https://deploywithox.com/blog/self-host-peertube#faq-admin) - [How much memory does PeerTube use?](https://deploywithox.com/blog/self-host-peertube#faq-memory) - [Is PeerTube free to self-host?](https://deploywithox.com/blog/self-host-peertube#faq-license) Written by Saurav Sharma Builds ox. Writes about running apps on servers you own, without Docker and without a platform bill. [Older post How to self-host PhotoPrism on your own VPS without Docker](https://deploywithox.com/blog/self-host-photoprism) [Newer post How to self-host Paperless-ngx on your own Ubuntu VPS](https://deploywithox.com/blog/self-host-paperless) ## Keep reading - Guides [Self-Hosted Open-Source Apps Deployed with ox: All 85](https://deploywithox.com/blog/self-hosted-open-source-apps-deployed-with-ox) ox deployed 85 open-source apps from pinned commits on fresh servers, with no Docker. The stacks, services, deploy times and a table of every app. Saurav Sharma Oct 17, 2026 16 min read - Guides [How to self-host AFFiNE on your own VPS without Docker](https://deploywithox.com/blog/self-host-affine) Run AFFiNE v0.27.4 on your own Ubuntu server with ox: Postgres with pgvector, Redis, a Rust and Node build, and an admin made from two variables. Saurav Sharma Oct 17, 2026 12 min read - Guides [How to self-host Akaunting on your own VPS without Docker](https://deploywithox.com/blog/self-host-akaunting) Run Akaunting 3.2.4 on your own Ubuntu server with ox: PHP, MariaDB, a scheduler and the first company and admin made on deploy, from the config that ran. Saurav Sharma Oct 17, 2026 10 min read ## Deploy to a server you own ox sets up systemd, Caddy and PostgreSQL on your Ubuntu server and deploys on every push. Free for your first project. [Sign up with GitHub](https://deploywithox.com/login/github) [Read the docs](https://deploywithox.com/docs)