88 lines
3.3 KiB
Markdown
88 lines
3.3 KiB
Markdown
|
X-Date: 2023-10-26T00:50:00Z
|
||
|
X-Note-Id: 333c449a-d74b-4691-b769-45036424e79f
|
||
|
Subject: I now host my own videos (with PeerTube)
|
||
|
X-Slug: i_now_host_my_own_videos
|
||
|
|
||
|
Today I've launched a separate server that contains my own PeerTube instance: [videos.knazarov.com](https://videos.knazarov.com).
|
||
|
All videos that I produce will be mirrored there, because I care about giving people an alternative to centralized platforms.
|
||
|
|
||
|
If you're curious how this is set up, here's [a link to the configuration repo](https://git.sr.ht/~knazarov/nixos/tree/master/item/nodes/videos/configuration.nix).
|
||
|
The most interesting part that's not mentioned in the [official wiki article](https://nixos.wiki/wiki/PeerTube) on NixOS is the
|
||
|
security. The way the article does this will keep the world-readable plain-text passwords in the configuration on the
|
||
|
filesystem. My approach is to use SOPS and use a principle of minimal access permissions, and as such I've figured out how
|
||
|
to store the passwords encrypted and expose them to only the required users.
|
||
|
|
||
|
For example, take the postgres init script. In this init script, you are setting up a peertube user. This is how
|
||
|
the authors did it:
|
||
|
|
||
|
```
|
||
|
postgresql = {
|
||
|
enable = true;
|
||
|
enableTCPIP = true;
|
||
|
authentication = ''
|
||
|
hostnossl peertube_local peertube_test 127.0.0.1/32 md5
|
||
|
'';
|
||
|
initialScript = pkgs.writeText "postgresql_init.sql" ''
|
||
|
CREATE ROLE peertube_test LOGIN PASSWORD 'test123';
|
||
|
CREATE DATABASE peertube_local TEMPLATE template0 ENCODING UTF8;
|
||
|
GRANT ALL PRIVILEGES ON DATABASE peertube_local TO peertube_test;
|
||
|
\connect peertube_local
|
||
|
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||
|
CREATE EXTENSION IF NOT EXISTS unaccent;
|
||
|
'';
|
||
|
};
|
||
|
```
|
||
|
|
||
|
Notice that the password is in plain text here. This would put the password to `/nix/store/` which is world-readable.
|
||
|
Since the postgres recipe doesn't have a separate configuration parameter for users/passwords, I've stuffed the whole initialScript into SOPS secret, like this:
|
||
|
|
||
|
```
|
||
|
services.postgresql = {
|
||
|
enable = true;
|
||
|
enableTCPIP = true;
|
||
|
authentication = ''
|
||
|
hostnossl peertube_local peertube_test 127.0.0.1/32 md5
|
||
|
'';
|
||
|
initialScript = config.sops.secrets.postgresql_init.path;
|
||
|
};
|
||
|
|
||
|
sops.secrets = {
|
||
|
postgresql_init = {
|
||
|
mode = "0440";
|
||
|
group = config.users.groups.postgres.name;
|
||
|
};
|
||
|
};
|
||
|
```
|
||
|
|
||
|
And then put the whole init script into the SOPS-managed secret file.
|
||
|
|
||
|
Another nice thing that I did is plugging LetsEncrypt SSL certificate generation right into this config. The
|
||
|
wiki doesn't bother with doing this, but you can actually combine:
|
||
|
|
||
|
```
|
||
|
services.peertube = {
|
||
|
enable = true;
|
||
|
localDomain = "videos.knazarov.com";
|
||
|
configureNginx = true;
|
||
|
...
|
||
|
};
|
||
|
services.nginx = {
|
||
|
enable = true;
|
||
|
virtualHosts = {
|
||
|
"videos.knazarov.com" = {
|
||
|
enableACME = true;
|
||
|
forceSSL = true;
|
||
|
locations."/" = { proxyPass = "http://127.0.0.1:9000"; };
|
||
|
};
|
||
|
};
|
||
|
...
|
||
|
};
|
||
|
```
|
||
|
|
||
|
Initially I thought that specifying `virtualHosts` with `enableACME` would conflict with the autogenerated configuration
|
||
|
that `services.peertube` is creating, but it didn't!
|
||
|
|
||
|
With this config, I can now reproduce this server again from scratch in one single command.
|
||
|
|
||
|
What's left to do is to set up fail2ban to get a bit more security and also configure backups.
|