13 # All versions, revisions, and checksums are stored in ./versions.json.
14 # The update process is the following:
15 # * pick the latest tag
16 # * update .invidious.version, .invidious.date, .invidious.commit and .invidious.hash
17 # * prefetch the videojs dependencies with scripts/fetch-player-dependencies.cr
18 # and update .videojs.hash (they are normally fetched during build
19 # but nix's sandboxing does not allow that)
20 # * if shard.lock changed
21 # * recreate shards.nix by running crystal2nix
22 , versions ? lib.importJSON ./versions.json
25 # normally video.js is downloaded at build time
26 videojs = callPackage ./videojs.nix { inherit versions; };
28 crystal.buildCrystalPackage rec {
30 inherit (versions.invidious) version;
32 src = fetchFromGitHub {
35 fetchSubmodules = true;
36 rev = versions.invidious.rev or "v${version}";
37 inherit (versions.invidious) hash;
42 # Replacing by the value (templates) of the variables ensures that building
43 # fails if upstream changes the way the metadata is formatted.
44 branchTemplate = ''{{ "#{`git branch | sed -n '/* /s///p'`.strip}" }}'';
45 commitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit`.strip}" }}'';
46 versionTemplate = ''{{ "#{`git log -1 --format=%ci | awk '{print $1}' | sed s/-/./g`.strip}" }}'';
47 # This always uses the latest commit which invalidates the cache even if
48 # the assets were not changed
49 assetCommitTemplate = ''{{ "#{`git rev-list HEAD --max-count=1 --abbrev-commit -- assets`.strip}" }}'';
51 inherit (versions.invidious) commit date;
54 for d in ${videojs}/*; do ln -s "$d" assets/videojs; done
56 # Use the version metadata from the derivation instead of using git at
58 substituteInPlace src/invidious.cr \
59 --replace-fail ${lib.escapeShellArg branchTemplate} '"master"' \
60 --replace-fail ${lib.escapeShellArg commitTemplate} '"${commit}"' \
61 --replace-fail ${lib.escapeShellArg versionTemplate} '"${date}"' \
62 --replace-fail ${lib.escapeShellArg assetCommitTemplate} '"${commit}"'
64 # Patch the assets and locales paths to be absolute
65 substituteInPlace src/invidious.cr \
66 --replace-fail 'public_folder "assets"' 'public_folder "${placeholder "out"}/share/invidious/assets"'
67 substituteInPlace src/invidious/helpers/i18n.cr \
68 --replace-fail 'File.read("locales/' 'File.read("${placeholder "out"}/share/invidious/locales/'
70 # Reference sql initialisation/migration scripts by absolute path
71 substituteInPlace src/invidious/database/base.cr \
72 --replace-fail 'config/sql' '${placeholder "out"}/share/invidious/config/sql'
74 substituteInPlace src/invidious/user/captcha.cr \
75 --replace-fail 'Process.run(%(rsvg-convert' 'Process.run(%(${lib.getBin librsvg}/bin/rsvg-convert'
78 nativeBuildInputs = [ pkg-config shards ];
79 buildInputs = [ libxml2 openssl sqlite ];
82 shardsFile = ./shards.nix;
83 crystalBinaries.invidious = {
84 src = "src/invidious.cr";
90 "-Dskip_videojs_download"
95 mkdir -p $out/share/invidious/config
98 cp -r assets locales $out/share/invidious
99 cp -r config/sql $out/share/invidious/config
102 # Invidious tries to open and validate config/config.yml, even when
103 # running --help. This specifies a minimal configuration in an
104 # environment variable. Even though the database and hmac_key are
105 # bogus, --help still works.
106 installCheckPhase = ''
107 export INVIDIOUS_CONFIG="$(cat <<EOF
108 database_url: sqlite3:///dev/null
109 hmac_key: "this-is-required"
112 $out/bin/invidious --help
113 $out/bin/invidious --version
117 tests = { inherit (nixosTests) invidious; };
118 updateScript = ./update.sh;
122 description = "Open source alternative front-end to YouTube";
123 mainProgram = "invidious";
124 homepage = "https://invidious.io/";
125 license = licenses.agpl3Plus;
126 maintainers = with maintainers; [