peertube data in s3 storage

This commit is contained in:
Taeer Bar-Yam 2024-04-03 08:40:19 -04:00
parent 48084fa688
commit af6e76134a
4 changed files with 136 additions and 7 deletions

View file

@ -66,15 +66,21 @@ You can then access the apps on your local machine (using the magic of port forw
- [ ] get garage replication running (multiple machines) - [ ] get garage replication running (multiple machines)
- [ ] some way of declaratively defining users? - [ ] some way of declaratively defining users?
- [ ] shared users between fediverse services - [ ] shared users between fediverse services
- [ ] s3 cache server (SEE: https://docs.joinpeertube.org/maintain/remote-storage)
- [ ] is "s3" the right term, given that it's not an open protocol?
# questions # questions
- what is meant to be shared between instances? - what is meant to be shared between instances?
- this is relevant to the security model. If garage is being shared between instances, we have to be careful having configurations depend on each other. - this is relevant to the security model. If garage is being shared between instances, we have to be careful having configurations depend on each other.
- we want to be able to migrate user's data. s3 migration is not supported by peertube. what do? (SEE: https://docs.joinpeertube.org/maintain/remote-storage)
# resources # resources
- Tutorial for setting up better logging: https://krisztianfekete.org/self-hosting-mastodon-on-nixos-a-proof-of-concept/ - Tutorial for setting up better logging: https://krisztianfekete.org/self-hosting-mastodon-on-nixos-a-proof-of-concept/
- Setting up development environment: https://docs.joinmastodon.org/dev/setup/ - Setting up development environment: https://docs.joinmastodon.org/dev/setup/
- Tutorial for PeerTube that doesn't use `createLocally`: https://nixos.wiki/wiki/PeerTube - Tutorial for PeerTube that doesn't use `createLocally`: https://nixos.wiki/wiki/PeerTube
- garage settings for specific apps: https://garagehq.deuxfleurs.fr/documentation/connect/apps/

View file

@ -19,7 +19,7 @@
peertube = nixpkgs.lib.nixosSystem { peertube = nixpkgs.lib.nixosSystem {
inherit system; inherit system;
modules = [ ./common.nix ./peertube.nix ]; modules = [ ./common.nix ./peertube.nix ./garage.nix ];
}; };
pixelfed = nixpkgs.lib.nixosSystem { pixelfed = nixpkgs.lib.nixosSystem {

View file

@ -2,8 +2,8 @@ let
# generate one using openssl (somehow) # generate one using openssl (somehow)
# XXX: when importing, garage tells you importing is only meant for keys previously generated by garage. is it okay to generate them using openssl? # XXX: when importing, garage tells you importing is only meant for keys previously generated by garage. is it okay to generate them using openssl?
snakeoil_key = { snakeoil_key = {
id = "GK3515373e4c851ebaad366558"; id = "GK22a15201acacbd51cd43e327";
secret = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; secret = "82b2b4cbef27bf8917b350d5b10a87c92fa9c8b13a415aeeea49726cf335d74e";
}; };
in in
# TODO: expand to a multi-machine setup # TODO: expand to a multi-machine setup
@ -11,7 +11,7 @@ in
# add in options to ensure creation of buckets and keys # add in options to ensure creation of buckets and keys
options = options =
let let
inherit (lib) types mkOption; inherit (lib) types mkOption mkEnableOption;
in { in {
services.garage = { services.garage = {
ensureBuckets = mkOption { ensureBuckets = mkOption {
@ -21,11 +21,31 @@ in
type = types.bool; type = types.bool;
default = false; default = false;
}; };
corsRules = {
enable = mkEnableOption "CORS Rules";
allowedHeaders = mkOption {
type = types.listOf types.str;
default = [];
};
allowedMethods = mkOption {
type = types.listOf types.str;
default = [];
};
allowedOrigins = mkOption {
type = types.listOf types.str;
default = [];
};
};
aliases = mkOption {
type = types.listOf types.str;
default = [];
};
}; };
}); });
}; };
ensureKeys = mkOption { ensureKeys = mkOption {
type = types.attrsOf (types.submodule { type = types.attrsOf (types.submodule {
# TODO: these should be managed as secrets, not in the nix store
options = { options = {
id = mkOption { id = mkOption {
type = types.string; type = types.string;
@ -75,7 +95,7 @@ in
} }
]; ];
}; };
environment.systemPackages = [ pkgs.minio-client ]; environment.systemPackages = [ pkgs.minio-client pkgs.awscli ];
networking.firewall.allowedTCPPorts = [ 3901 3902 ]; networking.firewall.allowedTCPPorts = [ 3901 3902 ];
services.garage = { services.garage = {
@ -100,7 +120,7 @@ in
systemd.services.ensure-garage = { systemd.services.ensure-garage = {
after = [ "garage.service" ]; after = [ "garage.service" ];
wantedBy = [ "garage.service" ]; wantedBy = [ "garage.service" ];
path = [ config.services.garage.package pkgs.perl ]; path = [ config.services.garage.package pkgs.perl pkgs.awscli ];
script = '' script = ''
set -xeuo pipefail set -xeuo pipefail
# give garage time to start up # give garage time to start up
@ -114,13 +134,36 @@ in
LAYOUT_VER=$(garage layout show | perl -ne '/Current cluster layout version: (\d*)/ && print $1') LAYOUT_VER=$(garage layout show | perl -ne '/Current cluster layout version: (\d*)/ && print $1')
garage layout apply --version $((LAYOUT_VER + 1)) garage layout apply --version $((LAYOUT_VER + 1))
# XXX: this is a hack because we want to write to the buckets here but we're not guaranteed any access keys
garage key import --yes -n tmp ${snakeoil_key.id} ${snakeoil_key.secret}
export AWS_ACCESS_KEY_ID=${snakeoil_key.id};
export AWS_SECRET_ACCESS_KEY=${snakeoil_key.secret};
${ ${
lib.concatStringsSep "\n" (lib.mapAttrsToList (bucket: { website }: '' lib.concatStringsSep "\n" (lib.mapAttrsToList (bucket: { website, aliases, corsRules }: ''
garage bucket create ${bucket} garage bucket create ${bucket}
# XXX: should this --deny the website if `website` is false? # XXX: should this --deny the website if `website` is false?
${lib.optionalString website '' ${lib.optionalString website ''
garage bucket website --allow ${bucket} garage bucket website --allow ${bucket}
''} ''}
${lib.concatStringsSep "\n" (map (alias: ''
garage bucket alias ${bucket} ${alias}
'') aliases)}
${lib.optionalString corsRules.enable ''
export CORS=${lib.concatStrings [
"'"
''{"CORSRules":[{''
''"AllowedHeaders":${builtins.toJSON corsRules.allowedHeaders},''
''"AllowedMethods":${builtins.toJSON corsRules.allowedMethods},''
''"AllowedOrigins":${builtins.toJSON corsRules.allowedOrigins}''
''}]}''
"'"
]}
garage bucket allow --read --write --owner ${bucket} --key tmp
aws --endpoint http://s3.garage.localhost:3900 s3api put-bucket-cors --bucket ${bucket} --cors-configuration $CORS
garage bucket deny --read --write --owner ${bucket} --key tmp
''}
'') config.services.garage.ensureBuckets) '') config.services.garage.ensureBuckets)
} }
${ ${

View file

@ -1,6 +1,86 @@
let
snakeoil_key = {
id = "GK1f9feea9960f6f95ff404c9b";
secret = "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
};
in
{ config, lib, pkgs, ... }: { { config, lib, pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 80 9000 ]; networking.firewall.allowedTCPPorts = [ 80 9000 ];
services.garage = {
ensureBuckets = {
peertube-videos = {
website = true;
corsRules = {
enable = true;
allowedHeaders = [ "*" ];
allowedMethods = [ "GET" ];
allowedOrigins = [ "*" ];
};
};
peertube-playlists = {
website = true;
corsRules = {
enable = true;
allowedHeaders = [ "*" ];
allowedMethods = [ "GET" ];
allowedOrigins = [ "*" ];
};
};
};
ensureKeys = {
peertube = {
inherit (snakeoil_key) id secret;
ensureAccess = {
peertube-videos = {
read = true;
write = true;
owner = true;
};
peertube-playlists = {
read = true;
write = true;
owner = true;
};
};
};
};
};
services.peertube = {
settings = {
object_storage = {
enabled = true;
endpoint = "http://s3.garage.localhost:3900";
region = "garage";
# not supported by garage
# SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube
proxy.proxyify_private_files = false;
web_videos = {
bucket_name = "peertube-videos";
prefix = "";
base_url = "http://peertube-videos.web.garage.localhost:3902";
};
videos = {
bucket_name = "peertube-videos";
prefix = "";
base_url = "http://peertube-videos.web.garage.localhost:3902";
};
streaming_playlists = {
bucket_name = "peertube-playlists";
prefix = "";
base_url = "http://peertube-playlists.web.garage.localhost:3902";
};
};
};
serviceEnvironmentFile = "/etc/peertube-env";
};
environment.etc.peertube-env.text = ''
AWS_ACCESS_KEY_ID=${snakeoil_key.id}
AWS_SECRET_ACCESS_KEY=${snakeoil_key.secret}
'';
# these configurations only apply when producing a VM (e.g. nixos-rebuild build-vm) # these configurations only apply when producing a VM (e.g. nixos-rebuild build-vm)
virtualisation.vmVariant = { config, ... }: { virtualisation.vmVariant = { config, ... }: {
services.peertube = { services.peertube = {