How to Set Up Invidious Locally for Development: Complete Crystal & PostgreSQL Guide
To set up Invidious locally for development, install Crystal and PostgreSQL using the provided dependency script, copy and customize config/config.example.yml to config/config.yml, initialize the PostgreSQL database with the SQL schemas in config/sql/, then compile and run src/invidious.cr or use Docker Compose for an isolated environment.
Invidious is an open-source Crystal-based web application that provides an alternative front-end to YouTube. The codebase uses the Kemal micro-framework for HTTP routing and relies on PostgreSQL for persistent storage of user data, subscriptions, and video metadata. This guide covers the complete workflow to build and run the application from source as implemented in the iv-org/invidious repository.
Prerequisites and Architecture Overview
Invidious requires a POSIX-compatible environment with Crystal (~1.7 or newer) and PostgreSQL (12+). The application architecture consists of three layers defined in src/invidious.cr:
- Web layer: Uses Kemal (imported at lines 20–22) to handle HTTP routes and static assets
- Service layer: Maintains
YoutubeConnectionPoolandCompanionConnectionPoolfor external HTTP calls (defined at lines 89–97) - Background jobs: Periodic workers refresh channels and statistics (registered at lines 162–176)
Install System Dependencies
The repository includes a distribution-aware script that automates the installation of Crystal, PostgreSQL, and required C libraries.
Using the Automated Script
Run the installer from the repository root:
chmod +x scripts/install-dependencies.sh
./scripts/install-dependencies.sh
The script detects your distribution (Debian/Ubuntu, Fedora, Arch, etc.) and installs the appropriate packages. For Debian-based systems, the install_apt function installs crystal, libssl-dev, libxml2-dev, libyaml-dev, libgmp-dev, libevent-dev, libpcre3-dev, and libsqlite3-dev (see scripts/install-dependencies.sh lines 60–78).
Manual Installation
If you prefer manual setup, install Crystal directly:
curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash
sudo apt-get install crystal
Then install PostgreSQL and development libraries: libssl-dev, libxml2-dev, libyaml-dev, libgmp-dev, libevent-dev, libpcre3-dev, libsqlite3-dev, and librsvg2-bin (required for CAPTCHA generation).
Configure Invidious
Configuration is loaded at runtime via CONFIG = Config.load (lines 60–61 in src/invidious.cr).
Create the Configuration File
Copy the example configuration and edit the database connection:
cp config/config.example.yml config/config.yml
Edit the db: section to match your PostgreSQL credentials:
db:
user: kemal
password: kemal
host: localhost
port: 5432
dbname: invidious
Generate the HMAC Key
Invidious requires a random hmac_key for session security. Generate one using OpenSSL:
export HMAC=$(openssl rand -hex 16)
sed -i "s/^hmac_key: .*/hmac_key: \"${HMAC}\"/" config/config.yml
Set Up the PostgreSQL Database
The application uses the PG_DB constant (lines 63–69) to connect to PostgreSQL using the database_url constructed from your configuration.
Create Database and User
Create a PostgreSQL role matching your config credentials:
sudo -u postgres createuser -P kemal
# Enter the password specified in config.yml
sudo -u postgres createdb -O kemal invidious
Apply Database Schemas
The SQL schema files reside in config/sql/. Apply them in sequence:
psql -U kemal -d invidious -f config/sql/users.sql
psql -U kemal -d invidious -f config/sql/channels.sql
psql -U kemal -d invidious -f config/sql/videos.sql
psql -U kemal -d invidious -f config/sql/nonces.sql
psql -U kemal -d invidious -f config/sql/session_ids.sql
psql -U kemal -d invidious -f config/sql/annotations.sql
psql -U kemal -d invidious -f config/sql/playlists.sql
psql -U kemal -d invidious -f config/sql/playlist_videos.sql
Build and Run the Server
The entry point is src/invidious.cr, which initializes the Kemal web server and registers routes under the Invidious::Routing module (lines 200–206).
Compile from Source
Build the binary with the Crystal compiler:
crystal build src/invidious.cr -o invidious --release
For development builds (faster compilation, less optimization):
crystal build src/invidious.cr -o invidious
Start the Development Server
Run the compiled binary:
./invidious
The server starts on http://localhost:3000 by default. Command-line flags are parsed in src/invidious.cr (lines 99–134):
-cor--channel-threads: Number of threads for refreshing channels-for--feed-threads: Number of threads for refreshing feeds-oor--output: Output log file path
Example with custom thread counts:
./invidious -c 4 -f 2
Docker Development Environment
For an isolated setup, use the provided Docker Compose configuration. The docker-compose.yml includes an INVIDIOUS_CONFIG block (lines 22–38) that injects configuration without requiring a local config.yml file.
Quick Start with Docker
docker-compose up --build
Access the application at http://127.0.0.1:3000. The Compose file builds the Invidious binary from source and links it to a PostgreSQL container.
Run Detached with Logs
docker-compose up -d
docker-compose logs -f
Development Workflow
The repository includes a Makefile with common development tasks.
Hot Reload with Make Watch
Use the watch target to automatically rebuild when source files change:
make watch
Run the Test Suite
Execute the Crystal specification files located in spec/:
crystal spec
Or use the Makefile target:
make test
Project Structure Reference
Key directories for development:
src/invidious/routes/: HTTP endpoint definitions (mounted viaInvidious::Routing)src/invidious/jobs/: Background workers for channel refresh, feed updates, and PubSubHub subscriptionsconfig/sql/: Database migrations and schema definitionsassets/: Static CSS, JavaScript, and images served by Kemal
Adding a New Route
To add a development route, create a file in src/invidious/routes/ and register it in the routing module:
# src/invidious/routes/custom.cr
module Invidious::Routes::Custom
get "/dev/test" do |env|
env.response.content_type = "application/json"
{"status": "development endpoint active"}.to_json
end
end
# Register in src/invidious/routing.cr
Invidious::Routing.register(Invidious::Routes::Custom)
Summary
- Automated setup: Use
scripts/install-dependencies.shto install Crystal, PostgreSQL, and system libraries for your distro - Configuration: Copy
config/config.example.ymltoconfig/config.yml, set database credentials, and generate a securehmac_key - Database: Create the
invidiousdatabase and user, then apply all SQL schemas fromconfig/sql/ - Compilation: Build with
crystal build src/invidious.cr -o invidiousand run with./invidiouson port 3000 - Development tools: Use
make watchfor hot reloading,crystal specfor testing, anddocker-compose up --buildfor containerized development
Frequently Asked Questions
What version of Crystal is required to build Invidious?
Invidious requires Crystal version 1.7 or newer. The scripts/install-dependencies.sh script automatically detects and installs the appropriate Crystal version for Debian, Ubuntu, Fedora, Arch Linux, and other supported distributions.
Why does Invidious need librsvg2-bin installed?
The librsvg2-bin package is required for CAPTCHA generation functionality within Invidious. The application uses this library to render SVG-based challenge images that appear during certain user interactions, such as registration or when YouTube rate-limiting triggers security checks.
Can I use SQLite instead of PostgreSQL for local development?
No, Invidious strictly requires PostgreSQL. The database layer uses PG_DB (defined in src/invidious.cr lines 63–69) with PostgreSQL-specific connection pools and queries. The SQL schema files in config/sql/ use PostgreSQL-specific syntax and data types incompatible with SQLite.
How do I customize the port or bind address for development?
Edit config/config.yml and modify the host and port settings under the default section, or set the INVIDIOUS_CONFIG environment variable as a YAML block when using Docker. For command-line overrides, you must modify the configuration file directly, as Invidious does not expose port binding as a CLI flag (see src/invidious.cr lines 99–134 for available flags).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →