2 description = "A free software to take back control of your videos";
4 url = "https://git.immae.eu/perso/Immae/Config/Nix.git";
8 inputs.flake-utils.url = "github:numtide/flake-utils";
9 inputs.nixpkgs.url = "github:NixOS/nixpkgs";
11 url = "github:Chocobozzz/PeerTube/v3.0.1";
15 outputs = { self, myuids, nixpkgs, peertube, flake-utils }: flake-utils.lib.eachSystem ["x86_64-linux"] (system:
17 version = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.peertube.locked.rev;
18 pkgs = import nixpkgs { inherit system; overlays = [
19 (self: super: { nodejs = self.nodejs-12_x; })
21 inherit (pkgs) callPackage stdenv jq youtube-dl fetchurl nodePackages yarn2nix-moretea;
23 patchedSource = stdenv.mkDerivation {
27 phases = [ "unpackPhase" "patchPhase" "installPhase" ];
28 patches = [ ./fix_yarn_lock.patch ];
36 buildInputs = [ nodePackages.node-pre-gyp ];
38 bcrypt_version = "5.0.0";
39 bcrypt_lib = fetchurl {
40 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";
41 sha256 = "0j3p2px1xb17sw3gpm8l4apljajxxfflal1yy552mhpzhi21wccn";
45 if [ "${bcrypt_version}" != "$(cat package.json | ${jq}/bin/jq -r .version)" ]; then
46 echo "Mismatching version please update bcrypt in derivation"
49 mkdir -p lib/binding && tar -C lib/binding -xf ${bcrypt_lib}
50 patchShebangs ../node-pre-gyp
55 buildInputs = [ nodePackages.node-gyp-build ];
60 ln -s ${youtube-dl}/bin/youtube-dl bin/youtube-dl
61 cat > bin/details <<EOF
62 {"version":"${youtube-dl.version}","path":null,"exec":"youtube-dl"}
67 mkYarnModules' = args: (yarn2nix-moretea.mkYarnModules args).overrideAttrs(old: {
68 # This hack permits to workaround the fact that the yarn.lock
69 # file doesn't respect the semver requirements
70 buildPhase = builtins.replaceStrings [" ./package.json"] [" /dev/null; cp deps/*/package.json ."] old.buildPhase;
73 server = callPackage ./server.nix {
74 inherit version yarnModulesConfig mkYarnModules';
75 sources = patchedSource;
77 client = callPackage ./client.nix {
78 inherit server version yarnModulesConfig mkYarnModules';
79 sources = patchedSource;
83 packages.peertube = stdenv.mkDerivation rec {
88 ln -s ${server.modules}/node_modules .
89 rm -rf dist && cp -a ${server.dist}/dist dist
90 rm -rf client/dist && cp -a ${client.dist}/dist client/
95 ln -s /tmp $out/.cache
99 description = "A free software to take back control of your videos";
102 PeerTube aspires to be a decentralized and free/libre alternative to video
103 broadcasting services.
104 PeerTube is not meant to become a huge platform that would centralize
105 videos from all around the world. Rather, it is a network of
106 inter-connected small videos hosters.
107 Anyone with a modicum of technical skills can host a PeerTube server, aka
108 an instance. Each instance hosts its users and their videos. In this way,
109 every instance is created, moderated and maintained independently by
110 various administrators.
111 You can still watch from your account videos hosted by other instances
112 though if the administrator of your instance had previously connected it
113 with other instances.
116 license = stdenv.lib.licenses.agpl3Plus;
118 homepage = "https://joinpeertube.org/";
120 platforms = stdenv.lib.platforms.unix;
123 defaultPackage = packages.peertube;
124 legacyPackages.peertube = packages.peertube;
126 build = defaultPackage;
127 } // pkgs.lib.optionalAttrs (builtins.elem system pkgs.lib.systems.doubles.linux) {
129 let testing = import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; };
130 in testing.makeTest {
132 client = { pkgs, ... }: {};
134 server = { pkgs, ... }: {
135 imports = [ self.nixosModule ];
136 config.networking.firewall.allowedTCPPorts = [ 8888 ];
137 config.services.redis.enable = true;
138 config.services.postgresql = {
140 initialScript = pkgs.writeText "peertube.sql" ''
141 CREATE ROLE "peertube" WITH LOGIN PASSWORD 'peertube';
142 CREATE DATABASE "peertube_prod" WITH OWNER "peertube"
147 CREATE EXTENSION unaccent;
148 CREATE EXTENSION pg_trgm;
151 config.services.peertube.enable = true;
152 config.services.peertube.configFile = pkgs.writeText "peertube.conf" ''
158 hostname: 'localhost.tld'
161 hostname: 'localhost'
173 tmp: '/var/lib/peertube/storage/tmp/'
174 avatars: '/var/lib/peertube/storage/avatars/'
175 videos: '/var/lib/peertube/storage/videos/'
176 streaming_playlists: '/var/lib/peertube/storage/streaming-playlists/'
177 redundancy: '/var/lib/peertube/storage/videos/'
178 logs: '/var/lib/peertube/storage/logs/'
179 previews: '/var/lib/peertube/storage/previews/'
180 thumbnails: '/var/lib/peertube/storage/thumbnails/'
181 torrents: '/var/lib/peertube/storage/torrents/'
182 captions: '/var/lib/peertube/storage/captions/'
183 cache: '/var/lib/peertube/storage/cache/'
184 plugins: '/var/lib/peertube/storage/plugins/'
185 client_overrides: '/var/lib/peertube/storage/client-overrides/'
191 server.wait_for_unit("peertube.service")
192 server.wait_for_open_port(8888)
193 client.succeed("curl http://server:8888")
194 client.succeed("curl http://server:8888/client/fr-FR/index.html")
200 nixosModule = { lib, pkgs, config, ... }:
203 cfg = config.services.peertube;
206 options.services.peertube = {
207 enable = lib.mkEnableOption "Enable Peertube’s service";
208 user = lib.mkOption {
209 type = lib.types.str;
211 description = "User account under which Peertube runs";
213 group = lib.mkOption {
214 type = lib.types.str;
216 description = "Group under which Peertube runs";
218 dataDir = lib.mkOption {
219 type = lib.types.path;
220 default = "/var/lib/${name}";
222 The directory where Peertube stores its data.
225 configFile = lib.mkOption {
226 type = lib.types.path;
228 The configuration file path for Peertube.
231 package = lib.mkOption {
232 type = lib.types.package;
233 default = self.defaultPackage."${pkgs.system}";
235 Peertube package to use.
239 systemdStateDirectory = lib.mkOption {
240 type = lib.types.str;
241 # Use ReadWritePaths= instead if varDir is outside of /var/lib
242 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
243 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
245 Adjusted Peertube data directory for systemd
251 config = lib.mkIf cfg.enable {
252 users.users = lib.optionalAttrs (cfg.user == name) {
254 uid = myuids.lib.uids.peertube;
256 description = "Peertube user";
258 useDefaultShell = true;
261 users.groups = lib.optionalAttrs (cfg.group == name) {
263 gid = myuids.lib.gids.peertube;
267 systemd.services.peertube = {
268 description = "Peertube";
269 wantedBy = [ "multi-user.target" ];
270 after = [ "network.target" "postgresql.service" ];
271 wants = [ "postgresql.service" ];
273 environment.NODE_CONFIG_DIR = "${cfg.dataDir}/config";
274 environment.NODE_ENV = "production";
275 environment.HOME = cfg.package;
277 path = [ pkgs.nodejs pkgs.yarn pkgs.bashInteractive pkgs.ffmpeg pkgs.openssl ];
280 install -m 0750 -d ${cfg.dataDir}/config
281 ln -sf ${cfg.configFile} ${cfg.dataDir}/config/production.yaml
282 ln -sf ${cfg.package}/config/default.yaml ${cfg.dataDir}/config/default.yaml
289 WorkingDirectory = cfg.package;
290 StateDirectory = cfg.systemdStateDirectory;
291 StateDirectoryMode = 0750;
294 ProtectControlGroups = true;
300 unitConfig.RequiresMountsFor = cfg.dataDir;