]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - flakes/peertube/flake.nix
Refactor flakes using follows
[perso/Immae/Config/Nix.git] / flakes / peertube / flake.nix
1 {
2 description = "A free software to take back control of your videos";
3 inputs.myuids = {
4 url = "https://git.immae.eu/perso/Immae/Config/Nix.git";
5 type = "git";
6 dir = "flakes/myuids";
7 };
8 inputs.flake-utils.url = "github:numtide/flake-utils";
9 inputs.nixpkgs.url = "github:NixOS/nixpkgs";
10 inputs.peertube = {
11 url = "github:Chocobozzz/PeerTube/v3.0.1";
12 flake = false;
13 };
14
15 outputs = { self, myuids, nixpkgs, peertube, flake-utils }: flake-utils.lib.eachSystem ["x86_64-linux"] (system:
16 let
17 pkgs = import nixpkgs { inherit system; overlays = [
18 (self: super: { nodejs = self.nodejs-12_x; })
19 ]; };
20 inherit (pkgs) callPackage stdenv jq youtube-dl fetchurl nodePackages yarn2nix-moretea;
21
22 patchedSource = stdenv.mkDerivation {
23 pname = "peertube";
24 version = peertube.rev;
25 src = peertube;
26 phases = [ "unpackPhase" "patchPhase" "installPhase" ];
27 patches = [ ./fix_yarn_lock.patch ];
28 installPhase = ''
29 mkdir $out
30 cp -a . $out/
31 '';
32 };
33 yarnModulesConfig = {
34 bcrypt = {
35 buildInputs = [ nodePackages.node-pre-gyp ];
36 postInstall = let
37 bcrypt_version = "5.0.0";
38 bcrypt_lib = fetchurl {
39 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";
40 sha256 = "0j3p2px1xb17sw3gpm8l4apljajxxfflal1yy552mhpzhi21wccn";
41 };
42 in
43 ''
44 if [ "${bcrypt_version}" != "$(cat package.json | ${jq}/bin/jq -r .version)" ]; then
45 echo "Mismatching version please update bcrypt in derivation"
46 false
47 fi
48 mkdir -p lib/binding && tar -C lib/binding -xf ${bcrypt_lib}
49 patchShebangs ../node-pre-gyp
50 npm run install
51 '';
52 };
53 utf-8-validate = {
54 buildInputs = [ nodePackages.node-gyp-build ];
55 };
56 youtube-dl = {
57 postInstall = ''
58 mkdir bin
59 ln -s ${youtube-dl}/bin/youtube-dl bin/youtube-dl
60 cat > bin/details <<EOF
61 {"version":"${youtube-dl.version}","path":null,"exec":"youtube-dl"}
62 EOF
63 '';
64 };
65 };
66 mkYarnModules' = args: (yarn2nix-moretea.mkYarnModules args).overrideAttrs(old: {
67 # This hack permits to workaround the fact that the yarn.lock
68 # file doesn't respect the semver requirements
69 buildPhase = builtins.replaceStrings [" ./package.json"] [" /dev/null; cp deps/*/package.json ."] old.buildPhase;
70 });
71
72 server = callPackage ./server.nix {
73 inherit yarnModulesConfig mkYarnModules';
74 sources = patchedSource;
75 };
76 client = callPackage ./client.nix {
77 inherit server yarnModulesConfig mkYarnModules';
78 sources = patchedSource;
79 };
80
81 in rec {
82 packages.peertube = callPackage ./. { inherit server client; src = patchedSource; };
83 defaultPackage = packages.peertube;
84 legacyPackages.peertube = packages.peertube;
85 checks = {
86 build = defaultPackage;
87 } // pkgs.lib.optionalAttrs (builtins.elem system pkgs.lib.systems.doubles.linux) {
88 test =
89 let testing = import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; };
90 in testing.makeTest {
91 nodes = {
92 client = { pkgs, ... }: {};
93
94 server = { pkgs, ... }: {
95 imports = [ self.nixosModule ];
96 config.networking.firewall.allowedTCPPorts = [ 8888 ];
97 config.services.redis.enable = true;
98 config.services.postgresql = {
99 enable = true;
100 initialScript = pkgs.writeText "peertube.sql" ''
101 CREATE ROLE "peertube" WITH LOGIN PASSWORD 'peertube';
102 CREATE DATABASE "peertube_prod" WITH OWNER "peertube"
103 TEMPLATE template0
104 LC_COLLATE = "C"
105 LC_CTYPE = "C";
106 \c peertube_prod
107 CREATE EXTENSION unaccent;
108 CREATE EXTENSION pg_trgm;
109 '';
110 };
111 config.services.peertube.enable = true;
112 config.services.peertube.configFile = pkgs.writeText "peertube.conf" ''
113 listen:
114 hostname: '0.0.0.0'
115 port: 8888
116 webserver:
117 https: false
118 hostname: 'localhost.tld'
119 port: 8888
120 database:
121 hostname: 'localhost'
122 port: 5432
123 suffix: '_prod'
124 username: 'peertube'
125 password: 'peertube'
126 pool:
127 max: 5
128 redis:
129 socket: 'localhost'
130 auth: null
131 db: 0
132 storage:
133 tmp: '/var/lib/peertube/storage/tmp/'
134 avatars: '/var/lib/peertube/storage/avatars/'
135 videos: '/var/lib/peertube/storage/videos/'
136 streaming_playlists: '/var/lib/peertube/storage/streaming-playlists/'
137 redundancy: '/var/lib/peertube/storage/videos/'
138 logs: '/var/lib/peertube/storage/logs/'
139 previews: '/var/lib/peertube/storage/previews/'
140 thumbnails: '/var/lib/peertube/storage/thumbnails/'
141 torrents: '/var/lib/peertube/storage/torrents/'
142 captions: '/var/lib/peertube/storage/captions/'
143 cache: '/var/lib/peertube/storage/cache/'
144 plugins: '/var/lib/peertube/storage/plugins/'
145 client_overrides: '/var/lib/peertube/storage/client-overrides/'
146 '';
147 };
148 };
149 testScript = ''
150 start_all()
151 server.wait_for_unit("peertube.service")
152 server.wait_for_open_port(8888)
153 client.succeed("curl http://server:8888")
154 client.succeed("curl http://server:8888/client/fr-FR/index.html")
155 '';
156 };
157 };
158 }
159 ) // rec {
160 overlays = {
161 peertube = final: prev: {
162 peertube = self.defaultPackage."${final.system}";
163 };
164 };
165 overlay = overlays.peertube;
166 nixosModule = { lib, pkgs, config, ... }:
167 let
168 name = "peertube";
169 cfg = config.services.peertube;
170 in
171 {
172 options.services.peertube = {
173 enable = lib.mkEnableOption "Enable Peertube’s service";
174 user = lib.mkOption {
175 type = lib.types.str;
176 default = name;
177 description = "User account under which Peertube runs";
178 };
179 group = lib.mkOption {
180 type = lib.types.str;
181 default = name;
182 description = "Group under which Peertube runs";
183 };
184 dataDir = lib.mkOption {
185 type = lib.types.path;
186 default = "/var/lib/${name}";
187 description = ''
188 The directory where Peertube stores its data.
189 '';
190 };
191 configFile = lib.mkOption {
192 type = lib.types.path;
193 description = ''
194 The configuration file path for Peertube.
195 '';
196 };
197 package = lib.mkOption {
198 type = lib.types.package;
199 default = self.defaultPackage."${pkgs.system}";
200 description = ''
201 Peertube package to use.
202 '';
203 };
204 # Output variables
205 systemdStateDirectory = lib.mkOption {
206 type = lib.types.str;
207 # Use ReadWritePaths= instead if varDir is outside of /var/lib
208 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
209 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
210 description = ''
211 Adjusted Peertube data directory for systemd
212 '';
213 readOnly = true;
214 };
215 };
216
217 config = lib.mkIf cfg.enable {
218 users.users = lib.optionalAttrs (cfg.user == name) {
219 "${name}" = {
220 uid = myuids.lib.uids.peertube;
221 group = cfg.group;
222 description = "Peertube user";
223 home = cfg.dataDir;
224 useDefaultShell = true;
225 };
226 };
227 users.groups = lib.optionalAttrs (cfg.group == name) {
228 "${name}" = {
229 gid = myuids.lib.gids.peertube;
230 };
231 };
232
233 systemd.services.peertube = {
234 description = "Peertube";
235 wantedBy = [ "multi-user.target" ];
236 after = [ "network.target" "postgresql.service" ];
237 wants = [ "postgresql.service" ];
238
239 environment.NODE_CONFIG_DIR = "${cfg.dataDir}/config";
240 environment.NODE_ENV = "production";
241 environment.HOME = cfg.package;
242
243 path = [ pkgs.nodejs pkgs.yarn pkgs.bashInteractive pkgs.ffmpeg pkgs.openssl ];
244
245 script = ''
246 install -m 0750 -d ${cfg.dataDir}/config
247 ln -sf ${cfg.configFile} ${cfg.dataDir}/config/production.yaml
248 ln -sf ${cfg.package}/config/default.yaml ${cfg.dataDir}/config/default.yaml
249 exec npm run start
250 '';
251
252 serviceConfig = {
253 User = cfg.user;
254 Group = cfg.group;
255 WorkingDirectory = cfg.package;
256 StateDirectory = cfg.systemdStateDirectory;
257 StateDirectoryMode = 0750;
258 PrivateTmp = true;
259 ProtectHome = true;
260 ProtectControlGroups = true;
261 Restart = "always";
262 Type = "simple";
263 TimeoutSec = 60;
264 };
265
266 unitConfig.RequiresMountsFor = cfg.dataDir;
267 };
268 };
269 };
270
271 };
272 }