├── .github └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── default.nix ├── flake.lock ├── flake.nix ├── index-debuginfo.cc ├── mirror-nixos-branch.pl ├── nix-index-https.patch ├── renovate.json └── shell.nix /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | merge_group: 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | nix-build: 15 | runs-on: "${{ matrix.os }}" 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | os: 20 | - ubuntu-latest 21 | # not supported by the flake atm 22 | #- ubuntu-22.04-arm 23 | #- macos-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: cachix/install-nix-action@v31 27 | - uses: cachix/cachix-action@v16 28 | with: 29 | name: nixos-infra-dev 30 | authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" 31 | - run: nix run --inputs-from . nixpkgs#nix-fast-build -- --skip-cached --no-nom 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Building 2 | 3 | $ nix-build 4 | 5 | ## Running 6 | 7 | $ ./result/bin/mirror-nixos-branch nixos-16.03-small https://hydra.nixos.org/job/nixos/release-16.03-small/tested/latest-finished 8 | 9 | $ ./result/bin/mirror-nixos-branch nixos-unstable-small https://hydra.nixos.org/job/nixos/unstable-small/tested/latest-finished 10 | 11 | $ ./result/bin/generate-programs-index /data/releases/nixos-files.sqlite ./programs.sqlite http://nix-cache.s3.amazonaws.com/ /data/releases/nixos/unstable-small/nixos-16.09pre89017.9db1990-tmp/store-paths /data/releases/nixos/unstable-small/nixos-16.09pre89017.9db1990-tmp/unpack/nixos-16.09pre89017.9db1990/nixpkgs -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") { 2 | src = builtins.fetchGit ./.; 3 | }).defaultNix 4 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1748124805, 6 | "narHash": "sha256-8A7HjmnvCpDjmETrZY1QwzKunR63LiP7lHu1eA5q6JI=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "db1aed32009f408e4048c1dd0beaf714dd34ed93", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "nixos-25.05-small", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Script for generating Nixpkgs/NixOS channels"; 3 | 4 | inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small"; 5 | 6 | outputs = 7 | { self, nixpkgs }: 8 | { 9 | overlays.default = final: prev: { 10 | nixos-channel-native-programs = final.stdenv.mkDerivation { 11 | name = "nixos-channel-native-programs"; 12 | 13 | strictDeps = true; 14 | 15 | nativeBuildInputs = with final.buildPackages; [ 16 | pkg-config 17 | ]; 18 | 19 | buildInputs = with final; [ 20 | nixVersions.nix_2_28 21 | nlohmann_json 22 | boost 23 | ]; 24 | 25 | buildCommand = '' 26 | mkdir -p $out/bin 27 | 28 | $CXX \ 29 | -Os -g -Wall \ 30 | -std=c++14 \ 31 | $(pkg-config --libs --cflags nix-store) \ 32 | $(pkg-config --libs --cflags nix-main) \ 33 | -I . \ 34 | ${./index-debuginfo.cc} \ 35 | -o $out/bin/index-debuginfo 36 | ''; 37 | }; 38 | 39 | nixos-channel-scripts = final.stdenv.mkDerivation { 40 | name = "nixos-channel-scripts"; 41 | 42 | strictDeps = true; 43 | 44 | nativeBuildInputs = with final.buildPackages; [ 45 | makeWrapper 46 | ]; 47 | 48 | buildInputs = with final.perlPackages; [ 49 | final.perl 50 | FileSlurp 51 | LWP 52 | LWPProtocolHttps 53 | ListMoreUtils 54 | DBDSQLite 55 | NetAmazonS3 56 | ]; 57 | 58 | buildCommand = '' 59 | mkdir -p $out/bin 60 | 61 | cp ${./mirror-nixos-branch.pl} $out/bin/mirror-nixos-branch 62 | wrapProgram $out/bin/mirror-nixos-branch \ 63 | --set PERL5LIB $PERL5LIB \ 64 | --set XZ_OPT "-T0" \ 65 | --prefix PATH : ${ 66 | final.lib.makeBinPath ( 67 | with final; 68 | [ 69 | wget 70 | git 71 | nix 72 | gnutar 73 | xz 74 | rsync 75 | openssh 76 | nix-index 77 | nixos-channel-native-programs 78 | ] 79 | ) 80 | } 81 | 82 | patchShebangs $out/bin 83 | ''; 84 | }; 85 | 86 | }; 87 | 88 | packages.x86_64-linux.default = 89 | (import nixpkgs { 90 | system = "x86_64-linux"; 91 | overlays = [ self.overlays.default ]; 92 | }).nixos-channel-scripts; 93 | 94 | checks.x86_64-linux.default = self.packages.x86_64-linux.default; 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /index-debuginfo.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | // cache.nixos.org/debuginfo/ 15 | // => redirect to NAR 16 | 17 | using namespace nix; 18 | 19 | void mainWrapped(int argc, char * * argv) 20 | { 21 | initNix(); 22 | 23 | if (argc != 3) throw Error("usage: index-debuginfo DEBUG-DB BINARY-CACHE-URI"); 24 | 25 | Path debugDbPath = argv[1]; 26 | std::string binaryCacheUri = argv[2]; 27 | 28 | if (hasSuffix(binaryCacheUri, "/")) binaryCacheUri.pop_back(); 29 | auto binaryCache = openStore(binaryCacheUri).cast(); 30 | 31 | ThreadPool threadPool(25); 32 | 33 | auto doFile = [&](std::string build_id, std::string url, std::string filename) { 34 | checkInterrupt(); 35 | 36 | nlohmann::json json; 37 | json["archive"] = url; 38 | json["member"] = filename; 39 | 40 | std::string key = "debuginfo/" + build_id; 41 | 42 | // FIXME: or should we overwrite? The previous link may point 43 | // to a GC'ed file, so overwriting might be useful... 44 | if (binaryCache->fileExists(key)) return; 45 | 46 | printError("redirecting ‘%s’ to ‘%s’", key, filename); 47 | 48 | binaryCache->upsertFile(key, json.dump(), "application/json"); 49 | }; 50 | 51 | auto db = SQLite(debugDbPath); 52 | 53 | auto stmt = SQLiteStmt(db, "select build_id, url, filename from DebugInfo;"); 54 | auto query = stmt.use(); 55 | 56 | while (query.next()) { 57 | threadPool.enqueue(std::bind(doFile, query.getStr(0), query.getStr(1), query.getStr(2))); 58 | } 59 | 60 | threadPool.process(); 61 | } 62 | 63 | int main(int argc, char * * argv) 64 | { 65 | return handleExceptions(argv[0], [&]() { 66 | mainWrapped(argc, argv); 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /mirror-nixos-branch.pl: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | use Data::Dumper; 6 | use Digest::SHA; 7 | use Fcntl qw(:flock); 8 | use File::Basename; 9 | use File::Path; 10 | use File::Slurp; 11 | use File::stat; 12 | use JSON::PP; 13 | use LWP::UserAgent; 14 | use List::MoreUtils qw(uniq); 15 | use Net::Amazon::S3; 16 | use POSIX qw(strftime); 17 | 18 | # Runs the given command, printing the (unescaped) command. 19 | # This command continues on failure. 20 | sub runAllowFailure { 21 | print STDERR " \$ ", join(" ", @_), "\n"; 22 | system(@_); 23 | } 24 | 25 | # Runs the given command, printing the (unescaped) command. 26 | # This command dies on failure. 27 | sub run { 28 | my $context = caller(0); 29 | my $code = runAllowFailure(@_); 30 | unless ($code == 0) { 31 | my $exit = $code >> 8; 32 | my $errno = $code - ($exit << 8); 33 | die "Command failed with code ($exit) errno ($errno).\n"; 34 | } 35 | 36 | return $code; 37 | } 38 | 39 | my $channelName = $ARGV[0]; 40 | my $releaseUrl = $ARGV[1]; 41 | 42 | die "Usage: $0 CHANNEL-NAME RELEASE-URL\n" unless defined $channelName && defined $releaseUrl; 43 | 44 | $channelName =~ /^([a-z]+)-(.*)$/ or die; 45 | my $channelDirRel = $channelName eq "nixpkgs-unstable" ? "nixpkgs" : "$1/$2"; 46 | 47 | 48 | # Configuration. 49 | my $TMPDIR = $ENV{'TMPDIR'} // "/tmp"; 50 | my $filesCache = "${TMPDIR}/nixos-files.sqlite"; 51 | my $bucketReleasesName = "nix-releases"; 52 | my $bucketChannelsName = "nix-channels"; 53 | my $dryRun = $ENV{'DRY_RUN'} // 0; 54 | 55 | $ENV{'GIT_DIR'} = "/home/hydra-mirror/nixpkgs-channels"; 56 | 57 | my $bucketReleases; 58 | my $bucketChannels; 59 | 60 | unless ($dryRun) { 61 | # S3 setup. 62 | my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die "No AWS_ACCESS_KEY_ID given."; 63 | my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die "No AWS_SECRET_ACCESS_KEY given."; 64 | 65 | my $s3 = Net::Amazon::S3->new( 66 | { aws_access_key_id => $aws_access_key_id, 67 | aws_secret_access_key => $aws_secret_access_key, 68 | retry => 1, 69 | host => "s3-eu-west-1.amazonaws.com", 70 | }); 71 | 72 | $bucketReleases = $s3->bucket($bucketReleasesName) or die; 73 | 74 | my $s3_us = Net::Amazon::S3->new( 75 | { aws_access_key_id => $aws_access_key_id, 76 | aws_secret_access_key => $aws_secret_access_key, 77 | retry => 1, 78 | }); 79 | 80 | $bucketChannels = $s3_us->bucket($bucketChannelsName) or die; 81 | } else { 82 | print STDERR "WARNING: Running in dry-run.\n"; 83 | } 84 | 85 | sub fetch { 86 | my ($url, $type) = @_; 87 | 88 | my $ua = LWP::UserAgent->new; 89 | $ua->default_header('Accept', $type) if defined $type; 90 | 91 | my $response = $ua->get($url); 92 | die "could not download $url: ", $response->status_line, "\n" unless $response->is_success; 93 | 94 | return $response->decoded_content; 95 | } 96 | 97 | my $releaseInfo = decode_json(fetch($releaseUrl, 'application/json')); 98 | 99 | my $releaseId = $releaseInfo->{id} or die; 100 | my $releaseName = $releaseInfo->{nixname} or die; 101 | $releaseName =~ /-([0-9].+)/ or die; 102 | my $releaseVersion = $1; 103 | my $evalId = $releaseInfo->{jobsetevals}->[0] or die; 104 | my $evalUrl = "https://hydra.nixos.org/eval/$evalId"; 105 | my $evalInfo = decode_json(fetch($evalUrl, 'application/json')); 106 | my $releasePrefix = "$channelDirRel/$releaseName"; 107 | 108 | my $rev = $evalInfo->{jobsetevalinputs}->{nixpkgs}->{revision} or die; 109 | 110 | print STDERR "\nRelease information:\n"; 111 | print STDERR " - release is: $releaseName (build $releaseId)\n - eval is: $evalId\n - prefix is: $releasePrefix\n - Git commit is: $rev\n\n"; 112 | 113 | if ($bucketChannels) { 114 | # Guard against the channel going back in time. 115 | my $curRelease = ""; 116 | 117 | if (defined(my $object = $bucketChannels->get_key($channelName))) { 118 | $curRelease = $object->{'x-amz-website-redirect-location'} // ""; 119 | } 120 | 121 | if (!defined $ENV{'FORCE'}) { 122 | print STDERR "previous release is $curRelease\n"; 123 | $! = 0; # Clear errno to avoid reporting non-fork/exec-related issues 124 | my $d = `NIX_PATH= nix-instantiate --eval -E "builtins.compareVersions (builtins.parseDrvName \\"$curRelease\\").version (builtins.parseDrvName \\"$releaseName\\").version"`; 125 | if ($? != 0) { 126 | warn "Could not execute nix-instantiate: exit $?; errno $!\n"; 127 | exit 1; 128 | } 129 | chomp $d; 130 | if ($d == 1) { 131 | warn("channel would go back in time from $curRelease to $releaseName, bailing out\n"); 132 | exit; 133 | } 134 | exit if $d == 0; 135 | } 136 | } 137 | 138 | if ($bucketReleases && $bucketReleases->head_key("$releasePrefix")) { 139 | print STDERR "release already exists\n"; 140 | } else { 141 | my $tmpDir = "$TMPDIR/release-$channelName/$releaseName"; 142 | File::Path::make_path($tmpDir); 143 | 144 | write_file("$tmpDir/src-url", $evalUrl); 145 | write_file("$tmpDir/git-revision", $rev); 146 | write_file("$tmpDir/binary-cache-url", "https://cache.nixos.org"); 147 | 148 | if (! -e "$tmpDir/store-paths.xz") { 149 | my $storePaths = decode_json(fetch("$evalUrl/store-paths", 'application/json')); 150 | write_file("$tmpDir/store-paths", join("\n", uniq(@{$storePaths})) . "\n"); 151 | } 152 | 153 | sub downloadFile { 154 | my ($jobName, $dstName, $productType) = @_; 155 | 156 | my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json')); 157 | 158 | my $products = (); 159 | # Key the products by subtype. 160 | foreach my $key (keys $buildInfo->{buildproducts}->%*) { 161 | my $subType = $buildInfo->{buildproducts}->{$key}->{subtype}; 162 | if ($products->{$subType}) { 163 | die "Job $jobName has multiple products of the same subtype $subType.\nThis is a bad assumption from this script"; 164 | } 165 | $products->{$subType} = $buildInfo->{buildproducts}->{$key}; 166 | } 167 | my $size = keys %{$products}; 168 | 169 | if ($size > 1 && !$productType) { 170 | my $types = join(", ", keys %{$products}); 171 | die "Job $jobName has $size build products. Select the right product by subtype [$types]"; 172 | } 173 | 174 | my $product; 175 | if (!$productType) { 176 | # Take the only element 177 | my ($key) = keys %{$products}; 178 | $product = $products->{$key}; 179 | } else { 180 | # Take the selected element 181 | $product = $products->{$productType}; 182 | } 183 | 184 | unless ($product) { 185 | die "No product could be selected for $jobName, with type $productType"; 186 | } 187 | 188 | my $srcFile = $product->{path} or die "job '$jobName' lacks a store path"; 189 | $dstName //= basename($srcFile); 190 | my $dstFile = "$tmpDir/" . $dstName; 191 | 192 | my $sha256_expected = $product->{sha256hash} or die; 193 | 194 | if (! -e $dstFile) { 195 | print STDERR "downloading $srcFile to $dstFile...\n"; 196 | write_file("$dstFile.sha256", "$sha256_expected $dstName"); 197 | runAllowFailure("NIX_REMOTE=s3://nix-cache nix --experimental-features nix-command store cat '$srcFile' > '$dstFile.tmp'") == 0 198 | or die "unable to fetch $srcFile\n"; 199 | rename("$dstFile.tmp", $dstFile) or die; 200 | } 201 | 202 | if (-e "$dstFile.sha256") { 203 | my $sha256_actual = `nix --experimental-features nix-command hash file --base16 --type sha256 '$dstFile'`; 204 | chomp $sha256_actual; 205 | if ($sha256_expected ne $sha256_actual) { 206 | print STDERR "file $dstFile is corrupt $sha256_expected $sha256_actual\n"; 207 | exit 1; 208 | } 209 | } 210 | } 211 | 212 | if ($channelName =~ /nixos/) { 213 | downloadFile("nixos.channel", "nixexprs.tar.xz"); 214 | downloadFile("nixpkgs.tarball", "packages.json.br", "json-br"); 215 | downloadFile("nixos.options", "options.json.br", "json-br"); 216 | 217 | # Minimal installer ISOs were dropped from the small channel 218 | if ($channelName !~ /-small/ || 219 | $channelName =~ /nixos-2([0123]\...|4\.05)-small/) { 220 | downloadFile("nixos.iso_minimal.aarch64-linux"); 221 | downloadFile("nixos.iso_minimal.x86_64-linux"); 222 | } 223 | 224 | # All of these jobs are not present in small channels 225 | if ($channelName !~ /-small/) { 226 | # These jobs were combined into a single job 227 | if ($channelName =~ /nixos-2[01234]/) { 228 | if ($channelName =~ /nixos-2[0123]/) { 229 | downloadFile("nixos.iso_plasma5.aarch64-linux"); 230 | downloadFile("nixos.iso_plasma5.x86_64-linux"); 231 | } else { 232 | downloadFile("nixos.iso_plasma6.aarch64-linux"); 233 | downloadFile("nixos.iso_plasma6.x86_64-linux"); 234 | } 235 | 236 | downloadFile("nixos.iso_gnome.aarch64-linux"); 237 | downloadFile("nixos.iso_gnome.x86_64-linux"); 238 | } else { 239 | downloadFile("nixos.iso_graphical.aarch64-linux"); 240 | downloadFile("nixos.iso_graphical.x86_64-linux"); 241 | } 242 | 243 | if ($channelName =~ /nixos-2[0123]/) { # i686 dropped for > 23.11 244 | downloadFile("nixos.iso_minimal.i686-linux"); 245 | } 246 | 247 | if ($channelName =~ /nixos-2([0123]\...|4\.05)/) { 248 | downloadFile("nixos.ova.x86_64-linux"); 249 | } 250 | } 251 | 252 | } else { 253 | downloadFile("tarball", "nixexprs.tar.xz", "source-dist"); 254 | downloadFile("tarball", "packages.json.br", "json-br"); 255 | } 256 | 257 | # Generate the programs.sqlite database and put it in 258 | # nixexprs.tar.xz. Also maintain the debug info repository at 259 | # https://cache.nixos.org/debuginfo. 260 | if ($channelName =~ /nixos/ && -e "$tmpDir/store-paths") { 261 | File::Path::make_path("$tmpDir/unpack"); 262 | run("tar", "xfJ", "$tmpDir/nixexprs.tar.xz", "-C", "$tmpDir/unpack"); 263 | my $exprDir = glob("$tmpDir/unpack/*"); 264 | run("nix-channel-index", "-o", "$exprDir/programs.sqlite", "-d", "$exprDir/debug.sqlite", "-f", "$exprDir/nixpkgs", "-s", "aarch64-linux", "-s", "x86_64-linux"); 265 | run("index-debuginfo", "$exprDir/debug.sqlite", "s3://nix-cache"); 266 | run("rm", "-f", "$tmpDir/nixexprs.tar.xz", "$exprDir/debug.sqlite"); 267 | unlink("$tmpDir/nixexprs.tar.xz.sha256"); 268 | run("tar", "cfJ", "$tmpDir/nixexprs.tar.xz", "-C", "$tmpDir/unpack", basename($exprDir)); 269 | run("rm", "-rf", "$tmpDir/unpack"); 270 | } 271 | 272 | if (-e "$tmpDir/store-paths") { 273 | run("xz", "$tmpDir/store-paths"); 274 | } 275 | 276 | my $now = strftime("%F %T", localtime); 277 | my $title = "$channelName release $releaseName"; 278 | my $githubLink = "https://github.com/NixOS/nixpkgs/commits/$rev"; 279 | 280 | my $html = ""; 281 | $html .= "$title"; 282 | $html .= "

$title

"; 283 | $html .= "

Released on $now from Git commit $rev "; 284 | $html .= "via Hydra evaluation $evalId.

"; 285 | $html .= ""; 286 | 287 | if ($bucketReleases) { 288 | # Upload the release to S3. 289 | for my $fn (sort glob("$tmpDir/*")) { 290 | my $basename = basename $fn; 291 | my $key = "$releasePrefix/" . $basename; 292 | 293 | unless (defined $bucketReleases->head_key($key)) { 294 | print STDERR "mirroring $fn to s3://$bucketReleasesName/$key...\n"; 295 | 296 | # Default headers 297 | my $configuration = (); 298 | $configuration->{content_type} = "application/octet-stream"; 299 | 300 | if ($fn =~ /.sha256|src-url|binary-cache-url|git-revision/) { 301 | # Text files 302 | $configuration->{content_type} = "text/plain"; 303 | } elsif ($fn =~ /.json.br$/) { 304 | # JSON encoded as brotli 305 | $configuration->{content_type} = "application/json"; 306 | $configuration->{content_encoding} = "br"; 307 | } 308 | 309 | $bucketReleases->add_key_filename( 310 | $key, $fn, $configuration 311 | ) or die $bucketReleases->err . ": " . $bucketReleases->errstr; 312 | } 313 | 314 | next if $basename =~ /.sha256$/; 315 | 316 | my $size = stat($fn)->size; 317 | my $sha256 = Digest::SHA::sha256_hex(read_file($fn)); 318 | $html .= ""; 319 | $html .= ""; 320 | $html .= ""; 321 | $html .= ""; 322 | $html .= ""; 323 | } 324 | 325 | $html .= "
File nameSizeSHA-256 hash
$basename$size$sha256
"; 326 | 327 | $bucketReleases->add_key($releasePrefix, $html, 328 | { content_type => "text/html" }) 329 | or die $bucketReleases->err . ": " . $bucketReleases->errstr; 330 | } 331 | 332 | File::Path::remove_tree($tmpDir); 333 | } 334 | 335 | if ($dryRun) { 336 | print STDERR "WARNING: dry-run finished...\n"; 337 | exit(0); 338 | } 339 | 340 | # Update the nixos-* branch in the nixpkgs repo. 341 | run("git remote update origin >&2"); 342 | run("git push origin $rev:refs/heads/$channelName >&2"); 343 | 344 | # maxage=600: Serve from cache for 5 minutes. 345 | # stale-while-revaliadate=1800: Serve from cache while updating in the background for 30 minutes. 346 | # https://web.dev/stale-while-revalidate/ 347 | # https://developer.fastly.com/learning/concepts/cache-freshness/ 348 | my $cache_control = "maxage=600,stale-while-revalidate=1800,public"; 349 | 350 | sub redirect { 351 | my ($from, $to) = @_; 352 | $to = "https://releases.nixos.org/" . $to; 353 | print STDERR "redirect $from -> $to\n"; 354 | $bucketChannels->add_key($from, "", { "x-amz-website-redirect-location" => $to, "cache-control" => $cache_control }) 355 | or die $bucketChannels->err . ": " . $bucketChannels->errstr; 356 | } 357 | 358 | # Update channels on channels.nixos.org. 359 | redirect($channelName, $releasePrefix); 360 | redirect("$channelName/nixexprs.tar.xz", "$releasePrefix/nixexprs.tar.xz?rev=$rev"); 361 | redirect("$channelName/git-revision", "$releasePrefix/git-revision"); 362 | redirect("$channelName/packages.json.br", "$releasePrefix/packages.json.br"); 363 | redirect("$channelName/store-paths.xz", "$releasePrefix/store-paths.xz"); 364 | 365 | # Create redirects relevant only to NixOS channels. 366 | # FIXME: create only redirects to files that exist. 367 | if ($channelName =~ /nixos/) { 368 | # Options listing 369 | redirect("$channelName/options.json.br", "$releasePrefix/options.json.br"); 370 | 371 | # Redirects for latest images. 372 | for my $arch ("x86_64-linux", "i686-linux", "aarch64-linux") { 373 | # i686 dropped for > 23.11 374 | next if $arch eq "i686-linux" && $channelName !~ /nixos-2[0123]/; 375 | 376 | for my $artifact ("nixos-graphical", 377 | "nixos-plasma5", 378 | "nixos-plasma6", 379 | "nixos-gnome", 380 | "nixos-minimal", 381 | ) 382 | { 383 | redirect("$channelName/latest-$artifact-$arch.iso", "$releasePrefix/$artifact-$releaseVersion-$arch.iso"); 384 | redirect("$channelName/latest-$artifact-$arch.iso.sha256", "$releasePrefix/$artifact-$releaseVersion-$arch.iso.sha256"); 385 | } 386 | 387 | redirect("$channelName/latest-nixos-$arch.ova", "$releasePrefix/nixos-$releaseVersion-$arch.ova"); 388 | redirect("$channelName/latest-nixos-$arch.ova.sha256", "$releasePrefix/nixos-$releaseVersion-$arch.ova.sha256"); 389 | } 390 | } 391 | -------------------------------------------------------------------------------- /nix-index-https.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/lib.rs b/src/lib.rs 2 | index 4393e4b..4a84fc0 100644 3 | --- a/src/lib.rs 4 | +++ b/src/lib.rs 5 | @@ -23,4 +23,4 @@ pub mod workset; 6 | /// The URL of the binary cache that we use to fetch file listings and references. 7 | /// 8 | /// Hardcoded for now, but may be made a configurable option in the future. 9 | -pub const CACHE_URL: &str = "http://cache.nixos.org"; 10 | +pub const CACHE_URL: &str = "https://cache.nixos.org"; 11 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended", 5 | ":dependencyDashboard" 6 | ], 7 | "nix": { 8 | "enabled": true 9 | }, 10 | "lockFileMaintenance": { 11 | "enabled": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") { 2 | src = builtins.fetchGit ./.; 3 | }).shellNix 4 | --------------------------------------------------------------------------------