aboutsummaryrefslogblamecommitdiff
path: root/flakes/peertube/flake.nix
blob: e8153ebd7ab860e49f3ffbbe1ca6f7f90e6cd7f3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14


                                                                      
                           









                                                                                                                  






                                                                                             
                               















































                                                                                                                                                                   
                                                 


                                         
                                                        



                                
                                                                                          











































































                                                                                               






                                                         


                                             
                                            

        
                                          

























                                                                    
                                    

















                                                                           
                                              






















                                                                  

                                                                        

                                           
                                                                                           




























                                                                                          
{
  description = "A free software to take back control of your videos";
  inputs.myuids = {
    url = "path:../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
      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";
        version = peertube.rev;
        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 yarnModulesConfig mkYarnModules';
        sources = patchedSource;
      };
      client = callPackage ./client.nix {
        inherit server yarnModulesConfig mkYarnModules';
        sources = patchedSource;
      };

    in rec {
      packages.peertube = callPackage ./. { inherit server client; src = patchedSource; };
      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")
            '';
          };
      };
    }
  ) // rec {
    overlays = {
      peertube = final: prev: {
        peertube = self.defaultPackage."${final.system}";
      };
    };
    overlay = overlays.peertube;
    nixosModule = { lib, pkgs, config, ... }:
      let
        name = "peertube";
        cfg = config.immaeServices.peertube;
      in
      {
        options.immaeServices.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 = pkgs.peertube;
            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 {
          nixpkgs.overlays = [ self.overlay ];
          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.NPM_CONFIG_LOGS_DIR = "${cfg.dataDir}/npm_logs";
            environment.NPM_CONFIG_CACHE = "${cfg.dataDir}/npm_cache";
            environment.HOME = cfg.package;

            path = [ pkgs.nodejs pkgs.yarn 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;
          };
        };
      };

  };
}