blob: 2a594c0ea8be099325532059b96d5de56aba91c8 (
plain) (
tree)
|
|
{
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.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;
};
};
};
};
}
|