]>
Commit | Line | Data |
---|---|---|
ded643e1 IB |
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 | 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; }) | |
20 | ]; }; | |
21 | inherit (pkgs) callPackage stdenv jq youtube-dl fetchurl nodePackages yarn2nix-moretea; | |
22 | ||
23 | patchedSource = stdenv.mkDerivation { | |
24 | pname = "peertube"; | |
25 | inherit version; | |
26 | src = peertube; | |
27 | phases = [ "unpackPhase" "patchPhase" "installPhase" ]; | |
28 | patches = [ ./fix_yarn_lock.patch ]; | |
29 | installPhase = '' | |
30 | mkdir $out | |
31 | cp -a . $out/ | |
32 | ''; | |
33 | }; | |
34 | yarnModulesConfig = { | |
35 | bcrypt = { | |
36 | buildInputs = [ nodePackages.node-pre-gyp ]; | |
37 | postInstall = let | |
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"; | |
42 | }; | |
43 | in | |
44 | '' | |
45 | if [ "${bcrypt_version}" != "$(cat package.json | ${jq}/bin/jq -r .version)" ]; then | |
46 | echo "Mismatching version please update bcrypt in derivation" | |
47 | false | |
48 | fi | |
49 | mkdir -p lib/binding && tar -C lib/binding -xf ${bcrypt_lib} | |
50 | patchShebangs ../node-pre-gyp | |
51 | npm run install | |
52 | ''; | |
53 | }; | |
54 | utf-8-validate = { | |
55 | buildInputs = [ nodePackages.node-gyp-build ]; | |
56 | }; | |
57 | youtube-dl = { | |
58 | postInstall = '' | |
59 | mkdir bin | |
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"} | |
63 | EOF | |
64 | ''; | |
65 | }; | |
66 | }; | |
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; | |
71 | }); | |
72 | ||
73 | server = callPackage ./server.nix { | |
74 | inherit version yarnModulesConfig mkYarnModules'; | |
75 | sources = patchedSource; | |
76 | }; | |
77 | client = callPackage ./client.nix { | |
78 | inherit server version yarnModulesConfig mkYarnModules'; | |
79 | sources = patchedSource; | |
80 | }; | |
81 | ||
82 | in rec { | |
83 | packages.peertube = stdenv.mkDerivation rec { | |
84 | inherit version; | |
85 | pname = "peertube"; | |
86 | src = patchedSource; | |
87 | buildPhase = '' | |
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/ | |
91 | ''; | |
92 | installPhase = '' | |
93 | mkdir $out | |
94 | cp -a * $out | |
95 | ln -s /tmp $out/.cache | |
96 | ''; | |
97 | ||
98 | meta = { | |
99 | description = "A free software to take back control of your videos"; | |
100 | ||
101 | longDescription = '' | |
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. | |
114 | ''; | |
115 | ||
116 | license = stdenv.lib.licenses.agpl3Plus; | |
117 | ||
118 | homepage = "https://joinpeertube.org/"; | |
119 | ||
120 | platforms = stdenv.lib.platforms.unix; | |
121 | }; | |
122 | }; | |
123 | defaultPackage = packages.peertube; | |
124 | legacyPackages.peertube = packages.peertube; | |
125 | checks = { | |
126 | build = defaultPackage; | |
127 | } // pkgs.lib.optionalAttrs (builtins.elem system pkgs.lib.systems.doubles.linux) { | |
128 | test = | |
129 | let testing = import (nixpkgs + "/nixos/lib/testing-python.nix") { inherit system; }; | |
130 | in testing.makeTest { | |
131 | nodes = { | |
132 | client = { pkgs, ... }: {}; | |
133 | ||
134 | server = { pkgs, ... }: { | |
135 | imports = [ self.nixosModule ]; | |
136 | config.networking.firewall.allowedTCPPorts = [ 8888 ]; | |
137 | config.services.redis.enable = true; | |
138 | config.services.postgresql = { | |
139 | enable = true; | |
140 | initialScript = pkgs.writeText "peertube.sql" '' | |
141 | CREATE ROLE "peertube" WITH LOGIN PASSWORD 'peertube'; | |
142 | CREATE DATABASE "peertube_prod" WITH OWNER "peertube" | |
143 | TEMPLATE template0 | |
144 | LC_COLLATE = "C" | |
145 | LC_CTYPE = "C"; | |
146 | \c peertube_prod | |
147 | CREATE EXTENSION unaccent; | |
148 | CREATE EXTENSION pg_trgm; | |
149 | ''; | |
150 | }; | |
151 | config.services.peertube.enable = true; | |
152 | config.services.peertube.configFile = pkgs.writeText "peertube.conf" '' | |
153 | listen: | |
154 | hostname: '0.0.0.0' | |
155 | port: 8888 | |
156 | webserver: | |
157 | https: false | |
158 | hostname: 'localhost.tld' | |
159 | port: 8888 | |
160 | database: | |
161 | hostname: 'localhost' | |
162 | port: 5432 | |
163 | suffix: '_prod' | |
164 | username: 'peertube' | |
165 | password: 'peertube' | |
166 | pool: | |
167 | max: 5 | |
168 | redis: | |
169 | socket: 'localhost' | |
170 | auth: null | |
171 | db: 0 | |
172 | storage: | |
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/' | |
186 | ''; | |
187 | }; | |
188 | }; | |
189 | testScript = '' | |
190 | start_all() | |
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") | |
195 | ''; | |
196 | }; | |
197 | }; | |
198 | } | |
199 | ) // { | |
200 | nixosModule = { lib, pkgs, config, ... }: | |
201 | let | |
202 | name = "peertube"; | |
203 | cfg = config.services.peertube; | |
204 | in | |
205 | { | |
206 | options.services.peertube = { | |
207 | enable = lib.mkEnableOption "Enable Peertube’s service"; | |
208 | user = lib.mkOption { | |
209 | type = lib.types.str; | |
210 | default = name; | |
211 | description = "User account under which Peertube runs"; | |
212 | }; | |
213 | group = lib.mkOption { | |
214 | type = lib.types.str; | |
215 | default = name; | |
216 | description = "Group under which Peertube runs"; | |
217 | }; | |
218 | dataDir = lib.mkOption { | |
219 | type = lib.types.path; | |
220 | default = "/var/lib/${name}"; | |
221 | description = '' | |
222 | The directory where Peertube stores its data. | |
223 | ''; | |
224 | }; | |
225 | configFile = lib.mkOption { | |
226 | type = lib.types.path; | |
227 | description = '' | |
228 | The configuration file path for Peertube. | |
229 | ''; | |
230 | }; | |
231 | package = lib.mkOption { | |
232 | type = lib.types.package; | |
233 | default = self.defaultPackage."${pkgs.system}"; | |
234 | description = '' | |
235 | Peertube package to use. | |
236 | ''; | |
237 | }; | |
238 | # Output variables | |
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; | |
244 | description = '' | |
245 | Adjusted Peertube data directory for systemd | |
246 | ''; | |
247 | readOnly = true; | |
248 | }; | |
249 | }; | |
250 | ||
251 | config = lib.mkIf cfg.enable { | |
252 | users.users = lib.optionalAttrs (cfg.user == name) { | |
253 | "${name}" = { | |
254 | uid = myuids.lib.uids.peertube; | |
255 | group = cfg.group; | |
256 | description = "Peertube user"; | |
257 | home = cfg.dataDir; | |
258 | useDefaultShell = true; | |
259 | }; | |
260 | }; | |
261 | users.groups = lib.optionalAttrs (cfg.group == name) { | |
262 | "${name}" = { | |
263 | gid = myuids.lib.gids.peertube; | |
264 | }; | |
265 | }; | |
266 | ||
267 | systemd.services.peertube = { | |
268 | description = "Peertube"; | |
269 | wantedBy = [ "multi-user.target" ]; | |
270 | after = [ "network.target" "postgresql.service" ]; | |
271 | wants = [ "postgresql.service" ]; | |
272 | ||
273 | environment.NODE_CONFIG_DIR = "${cfg.dataDir}/config"; | |
274 | environment.NODE_ENV = "production"; | |
275 | environment.HOME = cfg.package; | |
276 | ||
3d11eafc | 277 | path = [ pkgs.nodejs pkgs.yarn pkgs.bashInteractive pkgs.ffmpeg pkgs.openssl ]; |
ded643e1 IB |
278 | |
279 | script = '' | |
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 | |
283 | exec npm run start | |
284 | ''; | |
285 | ||
286 | serviceConfig = { | |
287 | User = cfg.user; | |
288 | Group = cfg.group; | |
289 | WorkingDirectory = cfg.package; | |
290 | StateDirectory = cfg.systemdStateDirectory; | |
291 | StateDirectoryMode = 0750; | |
292 | PrivateTmp = true; | |
293 | ProtectHome = true; | |
294 | ProtectControlGroups = true; | |
295 | Restart = "always"; | |
296 | Type = "simple"; | |
297 | TimeoutSec = 60; | |
298 | }; | |
299 | ||
300 | unitConfig.RequiresMountsFor = cfg.dataDir; | |
301 | }; | |
302 | }; | |
303 | }; | |
304 | ||
305 | }; | |
306 | } |