August 02, 2020

#Hosting Your Invidious Instance on a VPS

Invidious is an alternative front-end to YouTube with an emphasis on privacy and low system resource usage. It is wonderful free software that not only does away with the annoyances of Google's bloated, ad-ridden video site, but also adds plenty of QoL features.

This weekend I spent some time setting up my own instance of Invidious to share with friends. Here's a quick rundown on what I did:

#1. Pick a server

I went with the $5/mo Nanode over at Linode. It's packing a grand total 1GB of RAM, a single CPU, and 25GB of storage. More than enough to run our instance, but not enough to actually compile the damn codebase (we'll get to this in a bit).

#2. Get a domain (or not)

I wanted a simple and short domain name for myself and my buddies to be able to use instead of typing an IP address in the address bar every time. Getting a domain isn't terribly important especially if you're hosting this just for your own use.

For the record, I used Namecheap to purchase my domain. I found this guide particularly helpful in setting up my domain with my Linode VPS.

#3. Pick a Linux Distribution for your VPS

Again, not terribly important what you pick. If you plan to use Invidious Updater, know that it only supports Debian, Ubuntu, CentOS, Fedora, and Arch. Originally I attempted to use it on an Alpine Linux installation, but the script promptly failed.

Also, the Invidious docs only provide installation instructions for Arch Linux and Debian/Ubuntu. I went with Arch Linux.

#4. Pick how you're going to install Invidious

The README provides 3 options:

  • Install Invidious manually
  • Use Invidious Updater (linked above)
  • Use Docker

All options are simple and easy to do. I went with 1.

#5. Install it!

Install dependencies:

sudo pacman -Syu base-devel shards crystal librsvg postgresql nano

Create Invidious user:

useradd -m invidious
sudo -i -u invidious
git clone https://github.com/iv-org/invidious
exit

Setup Postgres:

sudo systemctl enable postgresql
sudo systemctl start postgresql
sudo -i -u postgres
psql -c "CREATE USER kemal WITH PASSWORD 'kemal';" # Change 'kemal' here to a stronger password, and update `password` in config/config.yml
createdb -O kemal invidious
psql invidious kemal < /home
exit

I was only able to run the following commands as root. Make sure the postgresql service is running:

psql invidious kemal < /home/invidious/invidious/config/sql/channels.sql
psql invidious kemal < /home/invidious/invidious/config/sql/videos.sql
psql invidious kemal < /home/invidious/invidious/config/sql/channel_videos.sql
psql invidious kemal < /home/invidious/invidious/config/sql/users.sql
psql invidious kemal < /home/invidious/invidious/config/sql/session_ids.sql
psql invidious kemal < /home/invidious/invidious/config/sql/nonces.sql
psql invidious kemal < /home/invidious/invidious/config/sql/annotations.sql
psql invidious kemal < /home/invidious/invidious/config/sql/playlists.sql
psql invidious kemal < /home/invidious/invidious/config/sql/playlist_videos.sql

The next steps to install Invidious involve compiling the project code. On my measly 1GB of RAM, the compilation choked. In order to prepare for this, I used systemd-swap to create a swapfile. There are other ways to create a swapfile or a swap partition on Linux. See: Swap on Arch Linux Wiki. I found using systemd-swap the simplest. This guide by Ricosta Cruz was very helpful.

I did as follows:

sudo pacman -Syu systemd-swap

Then I edited the config file to enable zram_enabled=1 and swapfc_enabled=1:

sudo nano /etc/systemd/swap.conf

Then enable systemd-swap.service:

sudo systemctl enable --now systemd-swap

Finally add the swapfile to /etc/fstab so it'll be used on every boot. Add this: /swapfile none swap defaults 0 0 to the end of the file:

sudo nano /etc/fstab

Finally, you won't run out of RAM to setup Invidious. Let's go back and finally install it:

sudo -i -u invidious
cd invidious
shards update && shards install
crystal build src/invidious.cr --release
./invidious # test compiled binary, stop with ctrl c
exit

It's installed! Now some administrative stuff. Let's setup the systemd service so that Invidious runs in the background:

sudo cp /home/invidious/invidious/invidious.service /etc/systemd/system/invidious.service
sudo systemctl enable invidious.service
sudo systemctl start invidious.service

And lets rotate the logs so that they don't balloon in size:

sudo echo "/home/invidious/invidious/invidious.log {
rotate 4
weekly
notifempty
missingok
compress
minsize 1048576
}" | tee /etc/logrotate.d/invidious.logrotate

sudo chmod 0644 /etc/logrotate.d/invidious.logrotate

You now got a running Invidious instance! Navigate to your VPS's IP address on port 3000 to see it up and running. Type http://<VPS_IP_ADDRESS>:3000 into your browser's address bar, and get to watching some videos!

#6. (Optional) Setting up nginx

When I bought my domain, I intended to use it for more than just Invidious. In my case, I wanted a subdomain to serve as my Invidious URL, while I can use the main domain to host a "hub" of sorts to other services.

So for example:

http://tube.mydomain.com -> Invidious Service
http://mydomain.com -> Homepage

I was able to do this easily using nginx reverse proxies. Here are the steps I took.

Install nginx:

pacman -Syu nginx-mainline

Enable and start nginx service:

sudo systemctl enable nginx.service
sudo systemctl start nginx.service

Configure /etc/nginx/nginx.conf. Add this additional server entry somewhere under http:

http {
  ...

  server {
    server_name tube.mydomain.com;
    location / {
      proxy_pass http://127.0.0.1:3000;
    }
  }
  
  ...
}

Next addition is completely optional if you want your root domain to point to a kind of homepage. This is what I wanted, so I'm putting it here partly to document it for myself. I changed the existing, default http.server entry to point to custom html I had written:

http {
  server {
    server_name mydomain.com

    location / {
      root /sites/mydomain.com
      index index.html index.htm
    }

    ... # the rest remained unchanged from the default
  }
  
  ...
}

#7. (Optional) Enabling HTTPS

I used EFF's Certbot for this. It is painfully easy to use. Note that if you choose to, it will make modifications to your nginx.conf for you.

You must enable an option in Invidious's config if you want assets to only be transferred via HTTPS. More information can be found here.


That's all. Hopefully you found this helpful. If you got any questions, shoot me an email. And always, if you liked this post, hit Like and Subscribe! (haha).