docs(nixery): replace the Nixery mdBook with a simple web page
Nixery's previous landing page was an mdBook that was basically unmaintained and full of incorrect information. It also duplicated some things (like nix-1p) which actually live elsewhere. This commit removes the mdBook completely and reduces it down to a simple TVL-style landing page. The landing page has been checked in in its entirety because Nixery is frequently cloned through josh without the entirety of depot, however the page has been created by building it through depot's //web/tvl/template. See also https://github.com/tazjin/nixery/issues/156 Change-Id: I20e1d58f1e6608377207e80345c169f7d92d3847 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6930 Autosubmit: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
parent
224ec708f7
commit
7c99e9e8e3
15 changed files with 171 additions and 569 deletions
|
@ -24,40 +24,15 @@ let
|
||||||
# Avoid extracting this from git until we have a way to plumb
|
# Avoid extracting this from git until we have a way to plumb
|
||||||
# through revision numbers.
|
# through revision numbers.
|
||||||
nixery-commit-hash = "depot";
|
nixery-commit-hash = "depot";
|
||||||
|
|
||||||
# If Nixery is built outside of depot, it needs to dynamically fetch
|
|
||||||
# the current nix-1p.
|
|
||||||
nix-1p-git = builtins.fetchGit {
|
|
||||||
url = "https://code.tvl.fyi/depot.git:/nix/nix-1p.git";
|
|
||||||
ref = "canon";
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
depot.nix.readTree.drvTargets rec {
|
depot.nix.readTree.drvTargets rec {
|
||||||
# Implementation of the Nix image building logic
|
# Implementation of the Nix image building logic
|
||||||
nixery-prepare-image = import ./prepare-image { inherit pkgs; };
|
nixery-prepare-image = import ./prepare-image { inherit pkgs; };
|
||||||
|
|
||||||
# Use mdBook to build a static asset page which Nixery can then
|
# Include the Nixery website into the Nix store, unless its being
|
||||||
# serve. This is primarily used for the public instance at
|
# overridden to something else. Nixery will serve this as its front
|
||||||
# nixery.dev.
|
# page when visited from a browser.
|
||||||
#
|
nixery-web = ./web;
|
||||||
# If the nixpkgs commit is known, append it to the main docs page.
|
|
||||||
nixery-book = callPackage ./docs {
|
|
||||||
nix-1p = depot.nix.nix-1p or nix-1p-git;
|
|
||||||
|
|
||||||
postamble = lib.optionalString (pkgs ? nixpkgsCommits.unstable) ''
|
|
||||||
### Which revision of `nixpkgs` is used for the builds?
|
|
||||||
|
|
||||||
The current revision of `nixpkgs` is
|
|
||||||
[`${pkgs.nixpkgsCommits.unstable}`][commit] from the
|
|
||||||
`nixos-unstable` channel.
|
|
||||||
|
|
||||||
This instance of Nixery uses the `nixpkgs` channel pinned by TVL
|
|
||||||
in [`//third_party/sources/sources.json`][sources].
|
|
||||||
|
|
||||||
[commit]: https://github.com/NixOS/nixpkgs/commit/${pkgs.nixpkgsCommits.unstable}
|
|
||||||
[sources]: https://code.tvl.fyi/tree/third_party/sources/sources.json
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
nixery-popcount = callPackage ./popcount { };
|
nixery-popcount = callPackage ./popcount { };
|
||||||
|
|
||||||
|
@ -84,7 +59,7 @@ depot.nix.readTree.drvTargets rec {
|
||||||
nativeBuildInputs = [ makeWrapper ];
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
wrapProgram $out/bin/server \
|
wrapProgram $out/bin/server \
|
||||||
--set WEB_DIR "${nixery-book}" \
|
--set WEB_DIR "${nixery-web}" \
|
||||||
--prefix PATH : ${nixery-prepare-image}/bin
|
--prefix PATH : ${nixery-prepare-image}/bin
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|
1
tools/nixery/docs/.gitignore
vendored
1
tools/nixery/docs/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
book
|
|
|
@ -1,8 +0,0 @@
|
||||||
[book]
|
|
||||||
authors = ["Vincent Ambo <tazjin@google.com>"]
|
|
||||||
language = "en"
|
|
||||||
multilingual = false
|
|
||||||
src = "src"
|
|
||||||
|
|
||||||
[output.html]
|
|
||||||
additional-css = ["theme/nixery.css"]
|
|
|
@ -1,22 +0,0 @@
|
||||||
# Copyright 2022 The TVL Contributors
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
# Builds the documentation page using the Rust project's 'mdBook'
|
|
||||||
# tool.
|
|
||||||
#
|
|
||||||
# Some of the documentation is pulled in and included from other
|
|
||||||
# sources.
|
|
||||||
|
|
||||||
{ fetchFromGitHub, mdbook, runCommand, rustPlatform, nix-1p, postamble ? "" }:
|
|
||||||
|
|
||||||
runCommand "nixery-book"
|
|
||||||
{
|
|
||||||
POSTAMBLE = postamble;
|
|
||||||
} ''
|
|
||||||
mkdir -p $out
|
|
||||||
cp -r ${./.}/* .
|
|
||||||
chmod -R a+w src
|
|
||||||
cp ${nix-1p}/README.md src/nix-1p.md
|
|
||||||
echo "''${POSTAMBLE}" >> src/nixery.md
|
|
||||||
${mdbook}/bin/mdbook build -d $out
|
|
||||||
''
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Summary
|
|
||||||
|
|
||||||
- [Nixery](./nixery.md)
|
|
||||||
- [Under the hood](./under-the-hood.md)
|
|
||||||
- [Caching](./caching.md)
|
|
||||||
- [Run your own Nixery](./run-your-own.md)
|
|
||||||
- [Nix](./nix.md)
|
|
||||||
- [Nix, the language](./nix-1p.md)
|
|
|
@ -1,69 +0,0 @@
|
||||||
# Caching in Nixery
|
|
||||||
|
|
||||||
This page gives a quick overview over the caching done by Nixery. All cache data
|
|
||||||
is written to Nixery's storage bucket and is based on deterministic identifiers
|
|
||||||
or content-addressing, meaning that cache entries under the same key *never
|
|
||||||
change*.
|
|
||||||
|
|
||||||
## Manifests
|
|
||||||
|
|
||||||
Manifests of builds are cached at `$BUCKET/manifests/$KEY`. The effect of this
|
|
||||||
cache is that multiple instances of Nixery do not need to rebuild the same
|
|
||||||
manifest from scratch.
|
|
||||||
|
|
||||||
Since the manifest cache is populated only *after* layers are uploaded, Nixery
|
|
||||||
can immediately return the manifest to its clients without needing to check
|
|
||||||
whether layers have been uploaded already.
|
|
||||||
|
|
||||||
`$KEY` is generated by creating a SHA1 hash of the requested content of a
|
|
||||||
manifest plus the package source specification.
|
|
||||||
|
|
||||||
Manifests are *only* cached if the package source specification is *not* a
|
|
||||||
moving target.
|
|
||||||
|
|
||||||
Manifest caching *only* applies in the following cases:
|
|
||||||
|
|
||||||
* package source specification is a specific git commit
|
|
||||||
* package source specification is a specific NixOS/nixpkgs commit
|
|
||||||
|
|
||||||
Manifest caching *never* applies in the following cases:
|
|
||||||
|
|
||||||
* package source specification is a local file path (i.e. `NIXERY_PKGS_PATH`)
|
|
||||||
* package source specification is a NixOS channel (e.g. `NIXERY_CHANNEL=nixos-20.09`)
|
|
||||||
* package source specification is a git branch or tag (e.g. `staging`, `master` or `latest`)
|
|
||||||
|
|
||||||
It is thus always preferable to request images from a fully-pinned package
|
|
||||||
source.
|
|
||||||
|
|
||||||
Manifests can be removed from the manifest cache without negative consequences.
|
|
||||||
|
|
||||||
## Layer tarballs
|
|
||||||
|
|
||||||
Layer tarballs are the files that Nixery clients retrieve from the storage
|
|
||||||
bucket to download an image.
|
|
||||||
|
|
||||||
They are stored content-addressably at `$BUCKET/layers/$SHA256HASH` and layer
|
|
||||||
requests sent to Nixery will redirect directly to this storage location.
|
|
||||||
|
|
||||||
The effect of this cache is that Nixery does not need to upload identical layers
|
|
||||||
repeatedly. When Nixery notices that a layer already exists in GCS it will skip
|
|
||||||
uploading this layer.
|
|
||||||
|
|
||||||
Removing layers from the cache is *potentially problematic* if there are cached
|
|
||||||
manifests or layer builds referencing those layers.
|
|
||||||
|
|
||||||
To clean up layers, a user must ensure that no other cached resources still
|
|
||||||
reference these layers.
|
|
||||||
|
|
||||||
## Layer builds
|
|
||||||
|
|
||||||
Layer builds are cached at `$BUCKET/builds/$HASH`, where `$HASH` is a SHA1 of
|
|
||||||
the Nix store paths included in the layer.
|
|
||||||
|
|
||||||
The content of the cached entries is a JSON-object that contains the SHA256
|
|
||||||
hashes and sizes of the built layer.
|
|
||||||
|
|
||||||
The effect of this cache is that different instances of Nixery will not build,
|
|
||||||
hash and upload layers that have identical contents across different instances.
|
|
||||||
|
|
||||||
Layer builds can be removed from the cache without negative consequences.
|
|
|
@ -1,2 +0,0 @@
|
||||||
This page is a placeholder. During the build process, it is replaced by the
|
|
||||||
actual `nix-1p` guide from https://github.com/tazjin/nix-1p
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Nix
|
|
||||||
|
|
||||||
These sections are designed to give some background information on what Nix is.
|
|
||||||
If you've never heard of Nix before looking at Nixery, this might just be the
|
|
||||||
page for you!
|
|
||||||
|
|
||||||
[Nix][] is a functional package-manager that comes with a number of advantages
|
|
||||||
over traditional package managers, such as side-by-side installs of different
|
|
||||||
package versions, atomic updates, easy customisability, simple binary caching
|
|
||||||
and much more. Feel free to explore the [Nix website][Nix] for an overview of
|
|
||||||
Nix itself.
|
|
||||||
|
|
||||||
Nix uses a custom programming language also called Nix, which is explained here
|
|
||||||
[on its own page][nix-1p].
|
|
||||||
|
|
||||||
In addition to the package manager and language, the Nix project also maintains
|
|
||||||
[NixOS][] - a Linux distribution built entirely on Nix. On NixOS, users can
|
|
||||||
declaratively describe the *entire* configuration of their system and perform
|
|
||||||
updates/rollbacks to other system configurations with ease.
|
|
||||||
|
|
||||||
Most Nix packages are tracked in the [Nix package set][nixpkgs], usually simply
|
|
||||||
referred to as `nixpkgs`. It contains tens of thousands of packages already!
|
|
||||||
|
|
||||||
Nixery (which you are looking at!) provides an easy & simple way to get started
|
|
||||||
with Nix, in fact you don't even need to know that you're using Nix to make use
|
|
||||||
of Nixery.
|
|
||||||
|
|
||||||
[Nix]: https://nixos.org/nix/
|
|
||||||
[nix-1p]: nix-1p.html
|
|
||||||
[NixOS]: https://nixos.org/
|
|
||||||
[nixpkgs]: https://github.com/nixos/nixpkgs
|
|
|
@ -1,72 +0,0 @@
|
||||||
![Nixery](./nixery-logo.png)
|
|
||||||
|
|
||||||
------------
|
|
||||||
|
|
||||||
Welcome to this instance of [Nixery][]. It provides ad-hoc container images that
|
|
||||||
contain packages from the [Nix][] package manager. Images with arbitrary
|
|
||||||
packages can be requested via the image name.
|
|
||||||
|
|
||||||
Nix not only provides the packages to include in the images, but also builds the
|
|
||||||
images themselves by using a special [layering strategy][] that optimises for
|
|
||||||
cache efficiency.
|
|
||||||
|
|
||||||
For general information on why using Nix makes sense for container images, check
|
|
||||||
out [this blog post][layers].
|
|
||||||
|
|
||||||
## Demo
|
|
||||||
|
|
||||||
<script src="https://asciinema.org/a/262583.js" id="asciicast-262583" async data-autoplay="true" data-loop="true"></script>
|
|
||||||
|
|
||||||
## Quick start
|
|
||||||
|
|
||||||
Simply pull an image from this registry, separating each package you want
|
|
||||||
included by a slash:
|
|
||||||
|
|
||||||
docker pull nixery.dev/shell/git/htop
|
|
||||||
|
|
||||||
This gives you an image with `git`, `htop` and an interactively configured
|
|
||||||
shell. You could run it like this:
|
|
||||||
|
|
||||||
docker run -ti nixery.dev/shell/git/htop bash
|
|
||||||
|
|
||||||
Each path segment corresponds either to a key in the Nix package set, or a
|
|
||||||
meta-package that automatically expands to several other packages.
|
|
||||||
|
|
||||||
Meta-packages **must** be the first path component if they are used. Currently
|
|
||||||
there are only two meta-packages:
|
|
||||||
- `shell`, which provides a `bash`-shell with interactive configuration and
|
|
||||||
standard tools like `coreutils`.
|
|
||||||
- `arm64`, which provides ARM64 binaries.
|
|
||||||
|
|
||||||
**Tip:** When pulling from a private Nixery instance, replace `nixery.dev` in
|
|
||||||
the above examples with your registry address.
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
If you have a question that is not answered here, feel free to file an issue on
|
|
||||||
Github so that we can get it included in this section. The volume of questions
|
|
||||||
is quite low, thus by definition your question is already frequently asked.
|
|
||||||
|
|
||||||
### Where is the source code for this?
|
|
||||||
|
|
||||||
Over [on Github][Nixery]. It is licensed under the Apache 2.0 license. Consult
|
|
||||||
the documentation entries in the sidebar for information on how to set up your
|
|
||||||
own instance of Nixery.
|
|
||||||
|
|
||||||
### Should I depend on `nixery.dev` in production?
|
|
||||||
|
|
||||||
While we appreciate the enthusiasm, if you would like to use Nixery in your
|
|
||||||
production project we recommend setting up a private instance. The public Nixery
|
|
||||||
at `nixery.dev` is run on a best-effort basis and we make no guarantees about
|
|
||||||
availability.
|
|
||||||
|
|
||||||
### Who made this?
|
|
||||||
|
|
||||||
Nixery was written by [tazjin][], but many people have contributed to Nix over
|
|
||||||
time, maybe you could become one of them?
|
|
||||||
|
|
||||||
[Nixery]: https://github.com/tazjin/nixery
|
|
||||||
[Nix]: https://nixos.org/nix
|
|
||||||
[layering strategy]: https://storage.googleapis.com/nixdoc/nixery-layers.html
|
|
||||||
[layers]: https://grahamc.com/blog/nix-and-layered-docker-images
|
|
||||||
[tazjin]: https://tazj.in
|
|
|
@ -1,194 +0,0 @@
|
||||||
## Run your own Nixery
|
|
||||||
|
|
||||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
|
|
||||||
|
|
||||||
- [0. Prerequisites](#0-prerequisites)
|
|
||||||
- [1. Choose a package set](#1-choose-a-package-set)
|
|
||||||
- [2. Build Nixery itself](#2-build-nixery-itself)
|
|
||||||
- [3. Prepare configuration](#3-prepare-configuration)
|
|
||||||
- [4. Deploy Nixery](#4-deploy-nixery)
|
|
||||||
- [5. Productionise](#5-productionise)
|
|
||||||
|
|
||||||
<!-- markdown-toc end -->
|
|
||||||
|
|
||||||
|
|
||||||
---------
|
|
||||||
|
|
||||||
⚠ This page is still under construction! ⚠
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
Running your own Nixery is not difficult, but requires some setup. Follow the
|
|
||||||
steps below to get up & running.
|
|
||||||
|
|
||||||
*Note:* Nixery can be run inside of a [GKE][] cluster, providing a local service
|
|
||||||
from which images can be requested. Documentation for how to set this up is
|
|
||||||
forthcoming, please see [nixery#4][].
|
|
||||||
|
|
||||||
## 0. Prerequisites
|
|
||||||
|
|
||||||
To run Nixery, you must have:
|
|
||||||
|
|
||||||
* [Nix][] (to build Nixery itself)
|
|
||||||
* Somewhere to run it (your own server, Google AppEngine, a Kubernetes cluster,
|
|
||||||
whatever!)
|
|
||||||
* *Either* a [Google Cloud Storage][gcs] bucket in which to store & serve layers,
|
|
||||||
*or* a comfortable amount of disk space
|
|
||||||
|
|
||||||
Note that while the main Nixery process is a server written in Go,
|
|
||||||
it invokes a script that itself relies on Nix to be available.
|
|
||||||
You can compile the main Nixery daemon without Nix, but it won't
|
|
||||||
work without Nix.
|
|
||||||
|
|
||||||
(If you are completely new to Nix and don't know how to get
|
|
||||||
started, check the [Nix installation documentation][nixinstall].)
|
|
||||||
|
|
||||||
## 1. Choose a package set
|
|
||||||
|
|
||||||
When running your own Nixery you need to decide which package set you want to
|
|
||||||
serve. By default, Nixery builds packages from a recent NixOS channel which
|
|
||||||
ensures that most packages are cached upstream and no expensive builds need to
|
|
||||||
be performed for trivial things.
|
|
||||||
|
|
||||||
However if you are running a private Nixery, chances are high that you intend to
|
|
||||||
use it with your own packages. There are three options available:
|
|
||||||
|
|
||||||
1. Specify an upstream Nix/NixOS channel[^1], such as `nixos-20.09` or
|
|
||||||
`nixos-unstable`.
|
|
||||||
2. Specify your own git-repository with a custom package set[^2]. This makes it
|
|
||||||
possible to pull different tags, branches or commits by modifying the image
|
|
||||||
tag.
|
|
||||||
3. Specify a local file path containing a Nix package set. Where this comes from
|
|
||||||
or what it contains is up to you.
|
|
||||||
|
|
||||||
## 2. Build Nixery itself
|
|
||||||
|
|
||||||
### 2.1. With a container image
|
|
||||||
|
|
||||||
The easiest way to run Nixery is to build a container image. This
|
|
||||||
section assumes that the container runtime used is Docker, please
|
|
||||||
modify instructions accordingly if you are using something else.
|
|
||||||
|
|
||||||
With a working Nix installation, you can clone and build the Nixery
|
|
||||||
image like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://code.tvl.fyi/depot.git:/tools/nixery.git
|
|
||||||
nix-build -A nixery-image
|
|
||||||
```
|
|
||||||
|
|
||||||
This will create a `result`-symlink which points to a tarball containing the
|
|
||||||
image. In Docker, this tarball can be loaded by using `docker load -i result`.
|
|
||||||
|
|
||||||
### 2.2. Without a container image
|
|
||||||
|
|
||||||
*This method might be more convenient if you intend to work on
|
|
||||||
the code of the Nixery server itself, because you won't have to
|
|
||||||
rebuild (and reload) an image each time to test your changes.*
|
|
||||||
|
|
||||||
You will need to run the two following commands at the root of the repo:
|
|
||||||
|
|
||||||
* `go build` to build the `nixery` binary;
|
|
||||||
* `nix-env --install --file prepare-image/default.nix` to build
|
|
||||||
the required helpers.
|
|
||||||
|
|
||||||
## 3. Prepare configuration
|
|
||||||
|
|
||||||
Nixery is configured via environment variables.
|
|
||||||
|
|
||||||
You must set *all* of these:
|
|
||||||
|
|
||||||
* `NIXERY_STORAGE_BACKEND` (must be set to `gcs` or `filesystem`)
|
|
||||||
* `PORT`: HTTP port on which Nixery should listen
|
|
||||||
* `WEB_DIR`: directory containing static files (see below)
|
|
||||||
|
|
||||||
You must set *one* of these:
|
|
||||||
|
|
||||||
* `NIXERY_CHANNEL`: The name of a [Nix/NixOS channel][nixchannel] to use for building,
|
|
||||||
for instance `nixos-21.05`
|
|
||||||
* `NIXERY_PKGS_REPO`: URL of a git repository containing a package set (uses
|
|
||||||
locally configured SSH/git credentials)
|
|
||||||
* `NIXERY_PKGS_PATH`: A local filesystem path containing a Nix package set to use
|
|
||||||
for building
|
|
||||||
|
|
||||||
If `NIXERY_STORAGE_BACKEND` is set to `filesystem`, then `STORAGE_PATH`
|
|
||||||
must be set to the directory that will hold the registry blobs.
|
|
||||||
That directory must be located on a filesystem that supports extended
|
|
||||||
attributes (which means that on most systems, `/tmp` won't work).
|
|
||||||
|
|
||||||
If `NIXERY_STORAGE_BACKEND` is set to `gcs`, then `GCS_BUCKET`
|
|
||||||
must be set to the [Google Cloud Storage][gcs] bucket that will be
|
|
||||||
used to store & serve image layers.
|
|
||||||
|
|
||||||
You may set *all* of these:
|
|
||||||
|
|
||||||
* `NIX_TIMEOUT`: Number of seconds that any Nix builder is allowed to run
|
|
||||||
(defaults to 60)
|
|
||||||
|
|
||||||
To authenticate to the configured GCS bucket, Nixery uses Google's [Application
|
|
||||||
Default Credentials][ADC]. Depending on your environment this may require
|
|
||||||
additional configuration.
|
|
||||||
|
|
||||||
If the `GOOGLE_APPLICATION_CREDENTIALS` environment is configured, the service
|
|
||||||
account's private key will be used to create [signed URLs for
|
|
||||||
layers][signed-urls].
|
|
||||||
|
|
||||||
## 4. Start Nixery
|
|
||||||
|
|
||||||
Run the image that was built in step 2.1 with all the environment variables
|
|
||||||
mentioned above. Alternatively, set all the environment variables and run
|
|
||||||
the Nixery server that was built in step 2.2.
|
|
||||||
|
|
||||||
Once Nixery is running you can immediately start requesting images from it.
|
|
||||||
|
|
||||||
## 5. Productionise
|
|
||||||
|
|
||||||
(⚠ Here be dragons! ⚠)
|
|
||||||
|
|
||||||
Nixery is still an early project and has not yet been deployed in any production
|
|
||||||
environments and some caveats apply.
|
|
||||||
|
|
||||||
Notably, Nixery currently does not support any authentication methods, so anyone
|
|
||||||
with network access to the registry can retrieve images.
|
|
||||||
|
|
||||||
Running a Nixery inside of a fenced-off environment (such as internal to a
|
|
||||||
Kubernetes cluster) should be fine, but you should consider to do all of the
|
|
||||||
following:
|
|
||||||
|
|
||||||
* Issue a TLS certificate for the hostname you are assigning to Nixery. In fact,
|
|
||||||
Docker will refuse to pull images from registries that do not use TLS (with
|
|
||||||
the exception of `.local` domains).
|
|
||||||
* Configure signed GCS URLs to avoid having to make your bucket world-readable.
|
|
||||||
* Configure request timeouts for Nixery if you have your own web server in front
|
|
||||||
of it. This will be natively supported by Nixery in the future.
|
|
||||||
|
|
||||||
## 6. `WEB_DIR`
|
|
||||||
|
|
||||||
All the URLs accessed by Docker registry clients start with `/v2/`.
|
|
||||||
This means that it is possible to serve a static website from Nixery
|
|
||||||
itself (as long as you don't want to serve anything starting with `/v2`).
|
|
||||||
This is how, for instance, https://nixery.dev shows the website for Nixery,
|
|
||||||
while it is also possible to e.g. `docker pull nixery.dev/shell`.
|
|
||||||
|
|
||||||
When running Nixery, you must set the `WEB_DIR` environment variable.
|
|
||||||
When Nixery receives requests that don't look like registry requests,
|
|
||||||
it tries to serve them using files in the directory indicated by `WEB_DIR`.
|
|
||||||
If the directory doesn't exist, Nixery will run fine but serve 404.
|
|
||||||
|
|
||||||
-------
|
|
||||||
|
|
||||||
[^1]: Nixery will not work with Nix channels older than `nixos-19.03`.
|
|
||||||
|
|
||||||
[^2]: This documentation will be updated with instructions on how to best set up
|
|
||||||
a custom Nix repository. Nixery expects custom package sets to be a superset
|
|
||||||
of `nixpkgs`, as it uses `lib` and other features from `nixpkgs`
|
|
||||||
extensively.
|
|
||||||
|
|
||||||
[GKE]: https://cloud.google.com/kubernetes-engine/
|
|
||||||
[nixery#4]: https://github.com/tazjin/nixery/issues/4
|
|
||||||
[Nix]: https://nixos.org/nix
|
|
||||||
[gcs]: https://cloud.google.com/storage/
|
|
||||||
[signed-urls]: under-the-hood.html#5-image-layers-are-requested
|
|
||||||
[ADC]: https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
|
|
||||||
[nixinstall]: https://nixos.org/manual/nix/stable/installation/installing-binary.html
|
|
||||||
[nixchannel]: https://nixos.wiki/wiki/Nix_channels
|
|
|
@ -1,129 +0,0 @@
|
||||||
# Under the hood
|
|
||||||
|
|
||||||
This page serves as a quick explanation of what happens under-the-hood when an
|
|
||||||
image is requested from Nixery.
|
|
||||||
|
|
||||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
|
|
||||||
|
|
||||||
- [1. The image manifest is requested](#1-the-image-manifest-is-requested)
|
|
||||||
- [2. Nix fetches and prepares image content](#2-nix-fetches-and-prepares-image-content)
|
|
||||||
- [3. Layers are grouped, created, hashed, and persisted](#3-layers-are-grouped-created-hashed-and-persisted)
|
|
||||||
- [4. The manifest is assembled and returned to the client](#4-the-manifest-is-assembled-and-returned-to-the-client)
|
|
||||||
- [5. Image layers are requested](#5-image-layers-are-requested)
|
|
||||||
|
|
||||||
<!-- markdown-toc end -->
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
## 1. The image manifest is requested
|
|
||||||
|
|
||||||
When container registry clients such as Docker pull an image, the first thing
|
|
||||||
they do is ask for the image manifest. This is a JSON document describing which
|
|
||||||
layers are contained in an image, as well as some additional auxiliary
|
|
||||||
information.
|
|
||||||
|
|
||||||
This request is of the form `GET /v2/$imageName/manifests/$imageTag`.
|
|
||||||
|
|
||||||
Nixery receives this request and begins by splitting the image name into its
|
|
||||||
path components and substituting meta-packages (such as `shell`) for their
|
|
||||||
contents.
|
|
||||||
|
|
||||||
For example, requesting `shell/htop/git` results in Nixery expanding the image
|
|
||||||
name to `["bashInteractive", "coreutils", "htop", "git"]`.
|
|
||||||
|
|
||||||
If Nixery is configured with a private Nix repository, it also looks at the
|
|
||||||
image tag and substitutes `latest` with `master`.
|
|
||||||
|
|
||||||
It then invokes Nix with three parameters:
|
|
||||||
|
|
||||||
1. image contents (as above)
|
|
||||||
2. image tag
|
|
||||||
3. configured package set source
|
|
||||||
|
|
||||||
## 2. Nix fetches and prepares image content
|
|
||||||
|
|
||||||
Using the parameters above, Nix imports the package set and begins by mapping
|
|
||||||
the image names to attributes in the package set.
|
|
||||||
|
|
||||||
A special case during this process is packages with uppercase characters in
|
|
||||||
their name, for example anything under `haskellPackages`. The registry protocol
|
|
||||||
does not allow uppercase characters, so the Nix code will translate something
|
|
||||||
like `haskellpackages` (lowercased) to the correct attribute name.
|
|
||||||
|
|
||||||
After identifying all contents, Nix uses the `symlinkJoin` function to
|
|
||||||
create a special layer with the "symlink farm" required to let the
|
|
||||||
image function like a normal disk image.
|
|
||||||
|
|
||||||
Nix then returns information about the image contents as well as the
|
|
||||||
location of the special layer to Nixery.
|
|
||||||
|
|
||||||
## 3. Layers are grouped, created, hashed, and persisted
|
|
||||||
|
|
||||||
With the information received from Nix, Nixery determines the contents
|
|
||||||
of each layer while optimising for the best possible cache efficiency
|
|
||||||
(see the [layering design doc][] for details).
|
|
||||||
|
|
||||||
With the grouped layers, Nixery then begins to create compressed
|
|
||||||
tarballs with all required contents for each layer. As these tarballs
|
|
||||||
are being created, they are simultaneously being hashed (as the image
|
|
||||||
manifest must contain the content-hashes of all layers) and persisted
|
|
||||||
to storage.
|
|
||||||
|
|
||||||
Storage can be either a remote [Google Cloud Storage][gcs] bucket, or
|
|
||||||
a local filesystem path.
|
|
||||||
|
|
||||||
During this step, Nixery checks its build cache (see [Caching][]) to
|
|
||||||
determine whether a layer needs to be built or is already cached from
|
|
||||||
a previous build.
|
|
||||||
|
|
||||||
*Note:* While this step is running (which can take some time in the case of
|
|
||||||
large first-time image builds), the registry client is left hanging waiting for
|
|
||||||
an HTTP response. Unfortunately the registry protocol does not allow for any
|
|
||||||
feedback back to the user at this point, so from the user's perspective things
|
|
||||||
just ... hang, for a moment.
|
|
||||||
|
|
||||||
## 4. The manifest is assembled and returned to the client
|
|
||||||
|
|
||||||
Once armed with the hashes of all required layers, Nixery assembles
|
|
||||||
the OCI Container Image manifest which describes the structure of the
|
|
||||||
built image and names all of its layers by their content hash.
|
|
||||||
|
|
||||||
This manifest is returned to the client.
|
|
||||||
|
|
||||||
## 5. Image layers are requested
|
|
||||||
|
|
||||||
The client now inspects the manifest and determines which of the
|
|
||||||
layers it is currently missing based on their content hashes. Note
|
|
||||||
that different container runtimes will handle this differently, and in
|
|
||||||
the case of certain engine and storage driver combinations (e.g.
|
|
||||||
Docker with OverlayFS) layers might be downloaded again even if they
|
|
||||||
are already present.
|
|
||||||
|
|
||||||
For each of the missing layers, the client now issues a request to
|
|
||||||
Nixery that looks like this:
|
|
||||||
|
|
||||||
`GET /v2/${imageName}/blob/sha256:${layerHash}`
|
|
||||||
|
|
||||||
Nixery receives these requests and handles them based on the
|
|
||||||
configured storage backend.
|
|
||||||
|
|
||||||
If the storage backend is GCS, it *redirects* them to Google Cloud
|
|
||||||
Storage URLs, responding with an `HTTP 303 See Other` status code and
|
|
||||||
the actual download URL of the layer.
|
|
||||||
|
|
||||||
Nixery supports using private buckets which are not generally world-readable, in
|
|
||||||
which case [signed URLs][] are constructed using a private key. These allow the
|
|
||||||
registry client to download each layer without needing to care about how the
|
|
||||||
underlying authentication works.
|
|
||||||
|
|
||||||
If the storage backend is the local filesystem, Nixery will attempt to
|
|
||||||
serve the layer back to the client from disk.
|
|
||||||
|
|
||||||
---------
|
|
||||||
|
|
||||||
That's it. After these five steps the registry client has retrieved all it needs
|
|
||||||
to run the image produced by Nixery.
|
|
||||||
|
|
||||||
[gcs]: https://cloud.google.com/storage/
|
|
||||||
[signed URLs]: https://cloud.google.com/storage/docs/access-control/signed-urls
|
|
||||||
[layering design doc]: https://storage.googleapis.com/nixdoc/nixery-layers.html
|
|
BIN
tools/nixery/docs/theme/favicon.png
vendored
BIN
tools/nixery/docs/theme/favicon.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
3
tools/nixery/docs/theme/nixery.css
vendored
3
tools/nixery/docs/theme/nixery.css
vendored
|
@ -1,3 +0,0 @@
|
||||||
h2, h3 {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
166
tools/nixery/web/index.html
Normal file
166
tools/nixery/web/index.html
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="The Virus Lounge">
|
||||||
|
<link rel="stylesheet" type="text/css" href="https://static.tvl.fyi/latest/tvl.css" media="all">
|
||||||
|
<link rel="icon" type="image/webp" href="/favicon.webp">
|
||||||
|
<title>Nixery</title>
|
||||||
|
</head>
|
||||||
|
<body class="light">
|
||||||
|
<img src="./nixery-logo.png" alt="Nixery">
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Welcome to this instance of Nixery, an ad-hoc container image registry that provides
|
||||||
|
packages from the <a href="https://nixos.org/nix">Nix</a> package manager.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can pull container images from this registry
|
||||||
|
at <code><span class="registry-hostname">nixery.dev</span></code> by appending any
|
||||||
|
packages that you need in the URL, separated by slashes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<p class="cheddar-callout cheddar-tip">
|
||||||
|
<strong>NOTE:</strong> When pulling from a private Nixery instance,
|
||||||
|
replace <code>nixery.dev</code> in the above examples with your registry address.
|
||||||
|
</p>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<h2><a href="#demo" aria-hidden="true" class="anchor" id="demo"></a>Demo</h2>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<p>
|
||||||
|
The interactive demo needs Javascript to run, but you can just read the Usage
|
||||||
|
instructions below instead
|
||||||
|
</p>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<script src="https://asciinema.org/a/262583.js" id="asciicast-262583" async data-autoplay="true" data-loop="true"></script>
|
||||||
|
|
||||||
|
<h2><a href="#usage" aria-hidden="true" class="anchor" id="usage"></a>Usage</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
These usage examples assume that you use Docker, but should not be much different for
|
||||||
|
other OCI-compatible platforms.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Pull an image from this registry, separating each package you want included by a
|
||||||
|
slash:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre style="background-color:#f6f8fa;padding:16px;"><span style="color:#323232;">docker pull <span class="registry-hostname">nixery.dev</span>/shell/git/htop</span></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This gives you an image with <code>git</code>, <code>htop</code> and an interactively
|
||||||
|
configured shell. You could run it like this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre style="background-color:#f6f8fa;padding:16px;"><span style="color:#323232;">docker run -ti <span class="registry-hostname">nixery.dev</span>/shell/git/htop bash</span></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Each path segment corresponds either to a key in the Nix package set, or a
|
||||||
|
meta-package that automatically expands to several other packages.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Meta-packages <strong>must</strong> be the first path component if they are used.
|
||||||
|
Currently there are only two meta-packages:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<code>shell</code>, which provides a <code>bash</code>-shell with interactive
|
||||||
|
configuration and standard tools like <code>coreutils</code></p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>arm64</code>, which provides ARM64 binaries</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2><a href="#faq" aria-hidden="true" class="anchor" id="faq"></a>FAQ</h2>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="#how-does-this-work" aria-hidden="true" class="anchor" id="how-does-this-work"></a>
|
||||||
|
How does this work?
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The short version is that we use the Nix package manager and an optimised
|
||||||
|
<a href="https://tazj.in/blog/nixery-layers">layering strategy</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Check out <a href="https://www.youtube.com/watch?v=pOI9H4oeXqA">the Nixery talk</a>
|
||||||
|
from NixCon 2019 for more information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="#should-i-depend-on-nixerydev-in-production" aria-hidden="true" class="anchor" id="should-i-depend-on-nixerydev-in-production"></a>
|
||||||
|
Should I depend on <code>nixery.dev</code> in production?
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
While we appreciate the enthusiasm, if you would like to use Nixery in your production
|
||||||
|
project we recommend setting up a private instance. The public Nixery
|
||||||
|
at <code>nixery.dev</code> is run on a best-effort basis and we make no guarantees
|
||||||
|
about availability.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="#who-made-this" aria-hidden="true" class="anchor" id="who-made-this"></a>
|
||||||
|
Who made this?
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Nixery was written by <a href="https://tazj.in">tazjin</a>, originally at Google.
|
||||||
|
These days Nixery is maintained by <a href="https://tvl.su">TVL</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Nixery would not be possible without the many people that have contributed to Nix and
|
||||||
|
nixpkgs over time, maybe you could become one of them?
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="#where-is-the-source-code-for-this" aria-hidden="true" class="anchor" id="where-is-the-source-code-for-this"></a>
|
||||||
|
Where is the source code for this?
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Nixery lives in the <a href="https://cs.tvl.fyi/depot/-/tree/tools/nixery">TVL
|
||||||
|
monorepo</a>. All development happens there and follows
|
||||||
|
the <a href="https://cs.tvl.fyi/depot/-/blob/docs/CONTRIBUTING.md">TVL contribution
|
||||||
|
guidelines</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
We <em>mirror</em> the source code <a href="https://github.com/tazjin/nixery">to
|
||||||
|
Github</a> but do not guarantee that anyone will look at PRs or issues there.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<footer>
|
||||||
|
<p class="footer">
|
||||||
|
<a class="uncoloured-link" href="https://at.tvl.fyi/?q=//tools/nixery">code</a>
|
||||||
|
|
|
||||||
|
<a class="uncoloured-link" href="https://cl.tvl.fyi/q/file:%2522%255Etools/nixery/.*%2522">reviews</a>
|
||||||
|
|
|
||||||
|
<a class="uncoloured-link" href="https://b.tvl.fyi/">bugs</a>
|
||||||
|
</p>
|
||||||
|
<p class="lod">ಠ_ಠ</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/* Replace the hostnames above with the one at which this page runs. */
|
||||||
|
let hostname = window.location.hostname;
|
||||||
|
if (hostname != '') {
|
||||||
|
for (span of document.getElementsByClassName("registry-hostname")) {
|
||||||
|
span.textContent = hostname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 190 KiB |
Loading…
Reference in a new issue