--- /dev/null
+{
+ description = "A free software to take back control of your videos";
+ inputs.myuids = {
+ url = "https://git.immae.eu/perso/Immae/Config/Nix.git";
+ type = "git";
+ dir = "flakes/myuids";
+ };
+ inputs.flake-utils.url = "github:numtide/flake-utils";
+ inputs.nixpkgs.url = "github:NixOS/nixpkgs";
+ inputs.peertube = {
+ url = "github:Chocobozzz/PeerTube/v3.0.1";
+ flake = false;
+ };
+
+ outputs = { self, myuids, nixpkgs, peertube, flake-utils }: flake-utils.lib.eachSystem ["x86_64-linux"] (system:
+ let
+ version = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.peertube.locked.rev;
+ pkgs = import nixpkgs { inherit system; overlays = [
+ (self: super: { nodejs = self.nodejs-12_x; })
+ ]; };
+ inherit (pkgs) callPackage stdenv jq youtube-dl fetchurl nodePackages yarn2nix-moretea;
+
+ patchedSource = stdenv.mkDerivation {
+ pname = "peertube";
+ inherit version;
+ src = peertube;
+ phases = [ "unpackPhase" "patchPhase" "installPhase" ];
+ patches = [ ./fix_yarn_lock.patch ];
+ installPhase = ''
+ mkdir $out
+ cp -a . $out/
+ '';
+ };
+ yarnModulesConfig = {
+ bcrypt = {
+ buildInputs = [ nodePackages.node-pre-gyp ];
+ postInstall = let
+ bcrypt_version = "5.0.0";
+ bcrypt_lib = fetchurl {
+ url = "https://github.com/kelektiv/node.bcrypt.js/releases/download/v${bcrypt_version}/bcrypt_lib-v${bcrypt_version}-napi-v3-linux-x64-glibc.tar.gz";
+ sha256 = "0j3p2px1xb17sw3gpm8l4apljajxxfflal1yy552mhpzhi21wccn";
+ };
+ in
+ ''
+ if [ "${bcrypt_version}" != "$(cat package.json | ${jq}/bin/jq -r .version)" ]; then
+ echo "Mismatching version please update bcrypt in derivation"
+ false
+ fi
+ mkdir -p lib/binding && tar -C lib/binding -xf ${bcrypt_lib}
+ patchShebangs ../node-pre-gyp
+ npm run install
+ '';
+ };
+ utf-8-validate = {
+ buildInputs = [ nodePackages.node-gyp-build ];
+ };
+ youtube-dl = {
+ postInstall = ''
+ mkdir bin
+ ln -s ${youtube-dl}/bin/youtube-dl bin/youtube-dl
+ cat > bin/details <<EOF
+ {"version":"${youtube-dl.version}","path":null,"exec":"youtube-dl"}
+ EOF
+ '';
+ };
+ };
+ mkYarnModules' = args: (yarn2nix-moretea.mkYarnModules args).overrideAttrs(old: {
+ # This hack permits to workaround the fact that the yarn.lock
+ # file doesn't respect the semver requirements
+ buildPhase = builtins.replaceStrings [" ./package.json"] [" /dev/null; cp deps/*/package.json ."] old.buildPhase;
+ });
+
+ server = callPackage ./server.nix {
+ inherit version yarnModulesConfig mkYarnModules';
+ sources = patchedSource;
+ };
+ client = callPackage ./client.nix {
+ inherit server version yarnModulesConfig mkYarnModules';
+ sources = patchedSource;
+ };
+
+ in rec {
+ packages.peertube = stdenv.mkDerivation rec {
+ inherit version;
+ pname = "peertube";
+ src = patchedSource;
+ buildPhase = ''
+ ln -s ${server.modules}/node_modules .
+ rm -rf dist && cp -a ${server.dist}/dist dist
+ rm -rf client/dist && cp -a ${client.dist}/dist client/
+ '';
+ installPhase = ''
+ mkdir $out
+ cp -a * $out
+ ln -s /tmp $out/.cache
+ '';
+
+ meta = {
+ description = "A free software to take back control of your videos";
+
+ longDescription = ''
+ PeerTube aspires to be a decentralized and free/libre alternative to video
+ broadcasting services.
+ PeerTube is not meant to become a huge platform that would centralize
+ videos from all around the world. Rather, it is a network of
+ inter-connected small videos hosters.
+ Anyone with a modicum of technical skills can host a PeerTube server, aka
+ an instance. Each instance hosts its users and their videos. In this way,
+ every instance is created, moderated and maintained independently by
+ various administrators.
+ You can still watch from your account videos hosted by other instances
+ though if the administrator of your instance had previously connected it
+ with other instances.
+ '';
+
+ license = stdenv.lib.licenses.agpl3Plus;
+
+ homepage = "https://joinpeertube.org/";
+
+ platforms = stdenv.lib.platforms.unix;
+ };
+ };
+ defaultPackage = packages.peertube;
+ legacyPackages.peertube = packages.peertube;
+ checks = {
+ build = defaultPackage;
+ } // pkgs.lib.optionalAttrs (builtins.elem system pkgs.lib.systems.doubles.linux) {
+ test =
+ let testing = import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; };
+ in testing.makeTest {
+ nodes = {
+ client = { pkgs, ... }: {};
+
+ server = { pkgs, ... }: {
+ imports = [ self.nixosModule ];
+ config.networking.firewall.allowedTCPPorts = [ 8888 ];
+ config.services.redis.enable = true;
+ config.services.postgresql = {
+ enable = true;
+ initialScript = pkgs.writeText "peertube.sql" ''
+ CREATE ROLE "peertube" WITH LOGIN PASSWORD 'peertube';
+ CREATE DATABASE "peertube_prod" WITH OWNER "peertube"
+ TEMPLATE template0
+ LC_COLLATE = "C"
+ LC_CTYPE = "C";
+ \c peertube_prod
+ CREATE EXTENSION unaccent;
+ CREATE EXTENSION pg_trgm;
+ '';
+ };
+ config.services.peertube.enable = true;
+ config.services.peertube.configFile = pkgs.writeText "peertube.conf" ''
+ listen:
+ hostname: '0.0.0.0'
+ port: 8888
+ webserver:
+ https: false
+ hostname: 'localhost.tld'
+ port: 8888
+ database:
+ hostname: 'localhost'
+ port: 5432
+ suffix: '_prod'
+ username: 'peertube'
+ password: 'peertube'
+ pool:
+ max: 5
+ redis:
+ socket: 'localhost'
+ auth: null
+ db: 0
+ storage:
+ tmp: '/var/lib/peertube/storage/tmp/'
+ avatars: '/var/lib/peertube/storage/avatars/'
+ videos: '/var/lib/peertube/storage/videos/'
+ streaming_playlists: '/var/lib/peertube/storage/streaming-playlists/'
+ redundancy: '/var/lib/peertube/storage/videos/'
+ logs: '/var/lib/peertube/storage/logs/'
+ previews: '/var/lib/peertube/storage/previews/'
+ thumbnails: '/var/lib/peertube/storage/thumbnails/'
+ torrents: '/var/lib/peertube/storage/torrents/'
+ captions: '/var/lib/peertube/storage/captions/'
+ cache: '/var/lib/peertube/storage/cache/'
+ plugins: '/var/lib/peertube/storage/plugins/'
+ client_overrides: '/var/lib/peertube/storage/client-overrides/'
+ '';
+ };
+ };
+ testScript = ''
+ start_all()
+ server.wait_for_unit("peertube.service")
+ server.wait_for_open_port(8888)
+ client.succeed("curl http://server:8888")
+ client.succeed("curl http://server:8888/client/fr-FR/index.html")
+ '';
+ };
+ };
+ }
+ ) // {
+ nixosModule = { lib, pkgs, config, ... }:
+ let
+ name = "peertube";
+ cfg = config.services.peertube;
+ in
+ {
+ options.services.peertube = {
+ enable = lib.mkEnableOption "Enable Peertube’s service";
+ user = lib.mkOption {
+ type = lib.types.str;
+ default = name;
+ description = "User account under which Peertube runs";
+ };
+ group = lib.mkOption {
+ type = lib.types.str;
+ default = name;
+ description = "Group under which Peertube runs";
+ };
+ dataDir = lib.mkOption {
+ type = lib.types.path;
+ default = "/var/lib/${name}";
+ description = ''
+ The directory where Peertube stores its data.
+ '';
+ };
+ configFile = lib.mkOption {
+ type = lib.types.path;
+ description = ''
+ The configuration file path for Peertube.
+ '';
+ };
+ package = lib.mkOption {
+ type = lib.types.package;
+ default = self.defaultPackage."${pkgs.system}";
+ description = ''
+ Peertube package to use.
+ '';
+ };
+ # Output variables
+ systemdStateDirectory = lib.mkOption {
+ type = lib.types.str;
+ # Use ReadWritePaths= instead if varDir is outside of /var/lib
+ default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
+ lib.strings.removePrefix "/var/lib/" cfg.dataDir;
+ description = ''
+ Adjusted Peertube data directory for systemd
+ '';
+ readOnly = true;
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ users.users = lib.optionalAttrs (cfg.user == name) {
+ "${name}" = {
+ uid = myuids.lib.uids.peertube;
+ group = cfg.group;
+ description = "Peertube user";
+ home = cfg.dataDir;
+ useDefaultShell = true;
+ };
+ };
+ users.groups = lib.optionalAttrs (cfg.group == name) {
+ "${name}" = {
+ gid = myuids.lib.gids.peertube;
+ };
+ };
+
+ systemd.services.peertube = {
+ description = "Peertube";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" "postgresql.service" ];
+ wants = [ "postgresql.service" ];
+
+ environment.NODE_CONFIG_DIR = "${cfg.dataDir}/config";
+ environment.NODE_ENV = "production";
+ environment.HOME = cfg.package;
+
+ path = [ pkgs.nodejs pkgs.bashInteractive pkgs.ffmpeg pkgs.openssl ];
+
+ script = ''
+ install -m 0750 -d ${cfg.dataDir}/config
+ ln -sf ${cfg.configFile} ${cfg.dataDir}/config/production.yaml
+ ln -sf ${cfg.package}/config/default.yaml ${cfg.dataDir}/config/default.yaml
+ exec npm run start
+ '';
+
+ serviceConfig = {
+ User = cfg.user;
+ Group = cfg.group;
+ WorkingDirectory = cfg.package;
+ StateDirectory = cfg.systemdStateDirectory;
+ StateDirectoryMode = 0750;
+ PrivateTmp = true;
+ ProtectHome = true;
+ ProtectControlGroups = true;
+ Restart = "always";
+ Type = "simple";
+ TimeoutSec = 60;
+ };
+
+ unitConfig.RequiresMountsFor = cfg.dataDir;
+ };
+ };
+ };
+
+ };
+}