A Working Invidious Tutorial

Why?
Invidious is a lovely self-hosted video player that I just learned about. I found about 20 ways to unsuccessfully get it running and then finally found one way that works. I figured I would document that working method for others.
What?
Basically
- Docker
- Docker Compose
- This docker-compose.yml
services:
invidious:
image: quay.io/invidious/invidious:latest
# image: quay.io/invidious/invidious:latest-arm64 # ARM64/AArch64 devices
restart: unless-stopped
ports:
- "3000:3000"
environment:
# Please read the following file for a comprehensive list of all available
# configuration options and their associated syntax:
# https://github.com/iv-org/invidious/blob/master/config/config.example.yml
INVIDIOUS_CONFIG: |
db:
dbname: invidious
user: kemal
password: kemal
host: invidious-db
port: 5432
check_tables: true
signature_server: inv_sig_helper:12999
visitor_data: "ChangeMe"
po_token: "ChangeMe"
# external_port:
# domain:
# https_only: false
# statistics_enabled: false
hmac_key: "ChangeMe"
healthcheck:
test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending || exit 1
interval: 30s
timeout: 5s
retries: 2
# logging:
# options:
# max-size: "1G"
# max-file: "4"
depends_on:
- invidious-db
inv_sig_helper:
image: quay.io/invidious/inv-sig-helper:latest
init: true
command: ["--tcp", "0.0.0.0:12999"]
environment:
- RUST_LOG=info
restart: unless-stopped
cap_drop:
- ALL
read_only: true
security_opt:
- no-new-privileges:true
invidious-db:
image: docker.io/library/postgres:14
restart: unless-stopped
volumes:
- postgresdata:/var/lib/postgresql/data
- ./config/sql:/config/sql
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
environment:
POSTGRES_DB: invidious
POSTGRES_USER: kemal
POSTGRES_PASSWORD: kemal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
volumes:
postgresdata:
How?
- Save that docker-compose.yml somewhere
- Run this docker command in order to get the values for visitor_data: and po_token:
$ docker run quay.io/invidious/youtube-trusted-session-generator
[snip]
[INFO] internally launching GUI (X11 environment)
[INFO] starting Xvfb
[INFO] launching chromium instance
visitor_data: CgtWa1FpUXloTk[redacted]jIKCgJVUxIEGgAgVA%3D%3D
po_token: MnQgJPDJBUaJxCAc5Z-Z0TywPP6MRI8Xhk1vdbvse[redacted]cG6nBM7umn62tLgDrgf_VlAyf5L_itpSxsWIzoYhjSpjRvF_GJZruAnQF6zeKSv19fe7Z8x85n780lO4dG0E9Q3yLdc4fbxXAfe_sg==
- Update the visitor_data: and po_token: values from that output in your docker-compose.yml
- Run this command order to get a value for hmac_key:
$ pwgen 20 1
yohcooghfoobar1ohTh6
- Update the hmac_key: value from that output in your docker-compose.yml
- Run docker compose up
$ docker compose up
[+] Running 1/1
✔ Container invidious-invidious-1 Created 0.0s
Attaching to inv_sig_helper-1, invidious-1, invidious-db-1
inv_sig_helper-1 | [2025-06-25T19:13:55Z INFO inv_sig_helper_rust] Fetching player
invidious-db-1 |
invidious-db-1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
invidious-db-1 |
invidious-db-1 | 2025-06-25 19:13:55.538 UTC [1] LOG: starting PostgreSQL 14.18 (Debian 14.18-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
invidious-db-1 | 2025-06-25 19:13:55.538 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
invidious-db-1 | 2025-06-25 19:13:55.538 UTC [1] LOG: listening on IPv6 address "::", port 5432
invidious-db-1 | 2025-06-25 19:13:55.540 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
invidious-db-1 | 2025-06-25 19:13:55.542 UTC [27] LOG: database system was shut down at 2025-06-25 17:52:12 UTC
invidious-db-1 | 2025-06-25 19:13:55.547 UTC [1] LOG: database system is ready to accept connections
invidious-1 | 2025-06-25 19:13:55 UTC [info] SigHelper: Using helper at 'inv_sig_helper:12999'
inv_sig_helper-1 | [2025-06-25T19:13:56Z INFO inv_sig_helper_rust::player] Fetching player JS URL: https://www.youtube.com/s/player/5dcb2c1f/player_ias.vflset/en_US/base.js
inv_sig_helper-1 | [2025-06-25T19:13:56Z INFO inv_sig_helper_rust::player] Prepending n function code with global array variable 'I'
inv_sig_helper-1 | [2025-06-25T19:13:56Z INFO inv_sig_helper_rust::player] Fixing up nsig_func_body
inv_sig_helper-1 | [2025-06-25T19:13:56Z INFO inv_sig_helper_rust] Successfully fetched player
invidious-1 | [production] Invidious is ready to lead at http://0.0.0.0:3000
- Enjoy your Invidious deployment at http://ip-address:3000
Thank You
Thanks for taking the time to read this post. I hope it maybe saved you the few hours it took me to find all the installation methods that do not work. I welcome your feedback.
Postscript
Edit: Some videos fail to load with a "Nil assertion failed (NilAssertionError)" error. Invidious Github Issues says this may be due to videos with age restrictions. I'm not sure. Try another video if that happens.