summary refs log tree commit diff
path: root/pkgs/servers/invidious/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/servers/invidious/default.nix')
-rw-r--r--pkgs/servers/invidious/default.nix112
1 files changed, 112 insertions, 0 deletions
diff --git a/pkgs/servers/invidious/default.nix b/pkgs/servers/invidious/default.nix
new file mode 100644
index 00000000000..adcd694bad9
--- /dev/null
+++ b/pkgs/servers/invidious/default.nix
@@ -0,0 +1,112 @@
+{ lib, stdenv, crystal, fetchFromGitHub, librsvg, pkg-config, libxml2, openssl, shards, sqlite, lsquic, videojs, nixosTests }:
+let
+  # All versions, revisions, and checksums are stored in ./versions.json.
+  # The update process is the following:
+  #   * pick the latest commit
+  #   * update .invidious.rev, .invidious.version, and .invidious.sha256
+  #   * prefetch the videojs dependencies with scripts/fetch-player-dependencies.cr
+  #     and update .videojs.sha256 (they are normally fetched during build
+  #     but nix's sandboxing does not allow that)
+  #   * if shard.lock changed
+  #     * recreate shards.nix by running crystal2nix
+  #     * update lsquic and boringssl if necessarry, lsquic.cr depends on
+  #       the same version of lsquic and lsquic requires the boringssl
+  #       commit mentioned in its README
+  versions = builtins.fromJSON (builtins.readFile ./versions.json);
+in
+crystal.buildCrystalPackage rec {
+  pname = "invidious";
+  inherit (versions.invidious) version;
+
+  src = fetchFromGitHub {
+    owner = "iv-org";
+    repo = pname;
+    inherit (versions.invidious) rev sha256;
+  };
+
+  postPatch =
+    let
+      # Replacing by the value (templates) of the variables ensures that building
+      # fails if upstream changes the way the metadata is formatted.
+      branchTemplate = ''{{ "#{`git branch | sed -n '/* /s///p'`.strip}" }}'';
+      commitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit`.strip}" }}'';
+      versionTemplate = ''{{ "#{`git log -1 --format=%ci | awk '{print $1}' | sed s/-/./g`.strip}" }}'';
+      # This always uses the latest commit which invalidates the cache even if
+      # the assets were not changed
+      assetCommitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit -- assets`.strip}" }}'';
+    in
+    ''
+      for d in ${videojs}/*; do ln -s "$d" assets/videojs; done
+
+      # Use the version metadata from the derivation instead of using git at
+      # build-time
+      substituteInPlace src/invidious.cr \
+          --replace ${lib.escapeShellArg branchTemplate} '"master"' \
+          --replace ${lib.escapeShellArg commitTemplate} '"${lib.substring 0 7 versions.invidious.rev}"' \
+          --replace ${lib.escapeShellArg versionTemplate} '"${lib.replaceChars ["-"] ["."] (lib.substring 9 10 version)}"' \
+          --replace ${lib.escapeShellArg assetCommitTemplate} '"${lib.substring 0 7 versions.invidious.rev}"'
+
+      # Patch the assets and locales paths to be absolute
+      substituteInPlace src/invidious.cr \
+          --replace 'public_folder "assets"' 'public_folder "${placeholder "out"}/share/invidious/assets"'
+      substituteInPlace src/invidious/helpers/i18n.cr \
+          --replace 'File.read("locales/' 'File.read("${placeholder "out"}/share/invidious/locales/'
+
+      # Reference sql initialisation/migration scripts by absolute path
+      substituteInPlace src/invidious/database/base.cr \
+            --replace 'config/sql' '${placeholder "out"}/share/invidious/config/sql'
+
+      substituteInPlace src/invidious/user/captcha.cr \
+          --replace 'Process.run(%(rsvg-convert' 'Process.run(%(${lib.getBin librsvg}/bin/rsvg-convert'
+    '';
+
+  nativeBuildInputs = [ pkg-config shards ];
+  buildInputs = [ libxml2 openssl sqlite ];
+
+  format = "crystal";
+  shardsFile = ./shards.nix;
+  crystalBinaries.invidious = {
+    src = "src/invidious.cr";
+    options = [ "--release" "--progress" "--verbose" "--no-debug" "-Dskip_videojs_download" ];
+  };
+
+  postConfigure = ''
+    # lib includes nix store paths which can’t be patched, so the links have to
+    # be dereferenced first.
+    cp -rL lib lib2
+    rm -r lib
+    mv lib2 lib
+    chmod +w -R lib
+    cp ${lsquic}/lib/liblsquic.a lib/lsquic/src/lsquic/ext
+  '';
+
+  postInstall = ''
+    mkdir -p $out/share/invidious/config
+
+    # Copy static parts
+    cp -r assets locales $out/share/invidious
+    cp -r config/sql $out/share/invidious/config
+  '';
+
+  # Invidious tries to open config/config.yml and connect to the database, even
+  # when running --help. This specifies a minimal configuration in an
+  # environment variable. Even though the database is bogus, --help still
+  # works.
+  installCheckPhase = ''
+    INVIDIOUS_CONFIG="database_url: sqlite3:///dev/null" $out/bin/invidious --help
+  '';
+
+  passthru = {
+    inherit lsquic;
+    tests = { inherit (nixosTests) invidious; };
+    updateScript = ./update.sh;
+  };
+
+  meta = with lib; {
+    description = "An open source alternative front-end to YouTube";
+    homepage = "https://invidious.io/";
+    license = licenses.agpl3;
+    maintainers = with maintainers; [ infinisil sbruder ];
+    broken = stdenv.isDarwin && stdenv.isAarch64;
+  };
+}