{"id":16911019,"url":"https://github.com/thoughtpolice/eris","last_synced_at":"2025-03-17T07:30:53.529Z","repository":{"id":44532026,"uuid":"151705384","full_name":"thoughtpolice/eris","owner":"thoughtpolice","description":"Serve your /nix/store directory over the internet :sparkles:","archived":false,"fork":false,"pushed_at":"2022-02-09T17:34:33.000Z","size":127,"stargazers_count":88,"open_issues_count":7,"forks_count":4,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-02-27T19:35:16.209Z","etag":null,"topics":["http","nix","perl"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thoughtpolice.png","metadata":{"files":{"readme":"readme.org","changelog":"changelog.org","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":".github/SECURITY.md","support":null},"funding":{"github":["thoughtpolice"]}},"created_at":"2018-10-05T10:33:11.000Z","updated_at":"2025-02-22T20:21:37.000Z","dependencies_parsed_at":"2022-08-20T07:51:09.064Z","dependency_job_id":null,"html_url":"https://github.com/thoughtpolice/eris","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtpolice%2Feris","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtpolice%2Feris/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtpolice%2Feris/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtpolice%2Feris/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thoughtpolice","download_url":"https://codeload.github.com/thoughtpolice/eris/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243848106,"owners_count":20357491,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","nix","perl"],"created_at":"2024-10-13T19:04:12.695Z","updated_at":"2025-03-17T07:30:53.209Z","avatar_url":"https://github.com/thoughtpolice.png","language":"Perl","readme":"* Eris - a binary cache for Nix ✨\n\n[[https://img.shields.io/badge/version-0.1pre-blue.svg]] [[https://img.shields.io/badge/license-GPL%20(%3E%3D%203)-orange.svg]] [[https://github.com/thoughtpolice/eris/workflows/Continuous%20Integration/badge.svg]]\n\nEris is an HTTP server and web application that can act as a \"binary cache\" for\n[[https://nixos.org/nix/][Nix]] -- it serves your ~/nix/store~ directory over an HTTP server to other\nclients on the network. This means they can download files from your\n~/nix/store~ very easily.\n\nThere are several ways to host a Nix cache, including S3, [[https://nixos.org/hydra/][Hydra]], the lightweight\n(but inflexible, slow) [[https://github.com/edolstra/nix-serve][nix-serve]], as well as the newer (unknown) [[https://github.com/serokell/nix-cache][nix-cache]]. But\nEris tries to strike a balance between usability and power. It does one thing\nand only one thing: *serve a Nix cache*. It's for when you want to serve your\ncache temporarily -- or long term, for many remote, possibly authenticated users\n-- without the complexity of setting up something like [[https://nixos.org/hydra/][Hydra]].\n\nEris is written in Perl and built using *[[https://mojolicious.org][Mojolicious]]*.\n\n* Features\n\n- Easier to use and install than the competition.\n  - It actually has documentation, so you know how to use it.\n  - You can run it from the command line.\n  - Or run it on [[https://nixos.org][NixOS]].\n  - Or non-NixOS, via ~systemd~.\n- Powerful, flexible, Perl-like configuration language.\n  - It's like JSON, with more sigils, and comments.\n  - Comments are a useful feature in a configuration language.\n- Comes with documentation, including a ~man~ page!\n  - You're also reading a bunch of documentation right now.\n  - It's very useful to write documentation for your software projects.\n  - The source code is also well commented.\n- Supports HTTP authentication for Nix 2.0, via ~netrc~\n  - Lock away your treasure, so nobody can access it.\n  - Or run it on the internet for everyone to use.\n- Support for signed caches\n  - Or unsigned ones, if you're feeling daring.\n  - It can also read existing secret keys from a file. Reading files is\n    *serious business*!\n\n* Table of Contents :TOC_4_gh:\n- [[#eris---a-binary-cache-for-nix-][Eris - a binary cache for Nix ✨]]\n- [[#features][Features]]\n- [[#installation][Installation]]\n- [[#usage][Usage]]\n  - [[#quick-start-running-eris-standalone][Quick start: running ~eris~ standalone]]\n  - [[#quick-start-nixos-system-environment][Quick start: NixOS system environment]]\n- [[#configuration][Configuration]]\n    - [[#basic-configuration][Basic configuration]]\n    - [[#listening-ports-and-addresses][Listening ports and addresses]]\n    - [[#signing-support][Signing support]]\n      - [[#no-signature-mode]['No signature'-mode]]\n      - [[#using-pre-generated-keys][Using pre-generated keys]]\n    - [[#support-for-private-users-via-http-authentication][Support for private users via HTTP authentication]]\n    - [[#tls-support][TLS support]]\n    - [[#nixos-specific-notes][NixOS-specific notes]]\n  - [[#checking-mojolicious-server-status][Checking Mojolicious server status]]\n  - [[#full-configuration-file-reference][Full configuration file reference]]\n- [[#deployment][Deployment]]\n  - [[#running-eris-standalone][Running Eris standalone]]\n  - [[#running-eris-as-a-nixos-service][Running Eris as a NixOS service]]\n  - [[#running-eris-as-a-service-on-any-linux-distribution][Running Eris as a service on any Linux distribution]]\n- [[#http-api][HTTP API]]\n  - [[#basic-nix-http-api][Basic Nix HTTP API]]\n  - [[#eris-http-api-v1][Eris HTTP API (v1)]]\n- [[#demo-build-a-private-cache-with-cloudflare-and-packetnet][Demo: build a private cache with CloudFlare and Packet.net]]\n- [[#faq][FAQ]]\n  - [[#why-write-this][Why write this?]]\n  - [[#whats-with-the-name][What's with the name?]]\n  - [[#does-eris-handle-cache-uploads][Does Eris handle cache /uploads/?]]\n  - [[#what-about-alternative-systems-like-cachix][What about alternative systems like Cachix?]]\n  - [[#austin-you-wrote-this-in-perl][Austin, you wrote this in /Perl/?]]\n- [[#hacking][Hacking]]\n  - [[#running-eris-in-place][Running Eris in-place]]\n  - [[#running-the-tests][Running the tests]]\n  - [[#protip-running-eris-behind-ngrok][Protip: Running Eris behind Ngrok]]\n- [[#todos][TODOs]]\n  - [[#dynamic-routes][Dynamic routes]]\n  - [[#lets-encrypt-integration][Let's Encrypt integration]]\n- [[#authors][Authors]]\n- [[#license][License]]\n\n* Installation\n\nEris requires you to have the [[https://nixos.org/nix/][Nix package manager]] *version 2.0 or later*\ninstalled. It may be installed on any standard Intel/AMD Linux system\n(regardless of the distribution choice), as well as other hardware platforms\nsuch as AArch64 where Nix is available. It might work on macOS. See the [[http://nixos.org/nix/][Nix]]\nwebsite for more information.\n\nProvided you have installed Nix, no further work is necessary to get Eris to\nserve your Nix store as a binary cache. Read on.\n\n*NixOS Users*: There is an Eris module for NixOS that makes setup near-automatic\nusing ~configuration.nix~, as you expect.\n\nEris currently *is not available in upstream Nixpkgs*. Therefore, you must\ninstall it from this repository, which is where the package and NixOS module are\nboth located.\n\n#+BEGIN_SRC bash\n$ git clone https://github.com/thoughtpolice/eris.git \u0026\u0026 cd eris/\n$ nix-env -i $(nix-build --no-link -Q release.nix -A eris)\n...\ninstalling 'eris-X.YpreN_XXXXXXX'\n$ nix-env -q | grep eris\neris-X.YpreN_XXXXXXX\n$\n#+END_SRC\n\nYou're done, and there should now be an ~eris~ binary available in your user\nenvironment and on your ~$PATH~ now (from under ~$HOME/.nix-profile/bin~).\n\nThe above command installs ~eris~ with a fixed version of the Nix package set,\nensuring that it's correctly built against a known set of tested dependencies.\n(This is specified in ~release.nix~ and ~nix/nixpkgs.json~.)\n\n* Usage\n\n** Quick start: running ~eris~ standalone\n\nNow that ~eris~ is installed, you can quickly run it out of the box with\nno further configuration:\n\n#+BEGIN_SRC bash\n$ eris -f\n[Thu Oct  4 14:29:48 2018] [info] Listening at \"http://*:8080\"\nServer available at http://127.0.0.1:8080\n[Thu Oct  4 14:29:48 2018] [info] Manager 50265 started\n[Thu Oct  4 14:29:48 2018] [info] Worker 51617 started\n[Thu Oct  4 14:29:48 2018] [info] Worker 51618 started\n[Thu Oct  4 14:29:48 2018] [info] Worker 51619 started\n...\n#+END_SRC\n\nCongratulations! Your ~/nix/store~ is now being served on\n~https://localhost:8080~. *Be careful if you have secrets in your Nix store!*\nThis won't bind to public IPs by default, only ~localhost~, but you should still\nbe aware of that. You can hit ~Ctrl-C~ at any time to stop this server.\n\nIf you're not using NixOS, you can skip to the [[Configuration]] section.\n\n** Quick start: NixOS system environment\n\nBecause Eris currently isn't available in [[https://github.com/nixos/nixpkgs][upstream nixpkgs]], if you wish to use\nand manage Eris as a NixOS module, you must clone this repository, and manually\nadd the eris ~module.nix~ file to your ~configuration.nix~.\n\nLet's assume your configuration is located at ~/etc/nixos/configuration.nix~,\nand you've cloned Eris into ~/etc/nixos/eris/~. Then you can import the Eris\nmodule into your configuration like so:\n\n#+BEGIN_SRC nix\n{ config, pkgs, lib, ... }:\n\n{\n  imports = [\n    ./eris/module.nix\n  ];\n\n  # ...\n}\n\n#+END_SRC\n\nNow you have ~services.eris-git~ available. You can enable Eris on ~localhost~\njust like the above manual command by setting the option:\n\n#+BEGIN_SRC nix\n{ config, pkgs, lib, ... }:\n\n{\n  services.eris-git.enable = true;\n}\n\n#+END_SRC\n\nIf you don't want to clone a git repository first, you can also use *Import From\nDerivation* (IFD) in order to have Nix clone the repository and import the\nmodule at evaluation time. First, clone a copy of ~eris.git~ and get the\nrevision and hash you need:\n\n#+BEGIN_SRC bash\n$ nix run nixpkgs.nix-prefetch-git -c nix-prefetch-git \\\n    https://github.com/thoughtpolice/eris.git\n...\ngit revision is 22973527727a3747349f2d6f234f20fd459f05c3\npath is /nix/store/61411d70dydyqp220n1kd323gipq6skn-eris\ngit human-readable version is -- none --\nCommit date is 2018-10-03 13:45:42 +0100\nhash is 0qaw9kjj26xm3lq339z4bzr8vy3d997yxcapc9z9217ahzpgqhws\n{\n  \"url\": \"https://github.com/thoughtpolice/eris\",\n  \"rev\": \"22973527727a3747349f2d6f234f20fd459f05c3\",\n  \"date\": \"2018-10-03T13:45:42+01:00\",\n  \"sha256\": \"0qaw9kjj26xm3lq339z4bzr8vy3d997yxcapc9z9217ahzpgqhws\",\n  \"fetchSubmodules\": false\n}\n#+END_SRC\n\nThen, import this using IFD in your ~configuration.nix~:\n\n#+BEGIN_SRC nix\n{ config, pkgs, lib, ... }:\n\nlet\n  eris = pkgs.fetchFromGitHub {\n    owner  = \"thoughtpolice\";\n    repo   = \"eris\";\n    rev    = \"22973527727a3747349f2d6f234f20fd459f05c3\";\n    sha256 = \"0qaw9kjj26xm3lq339z4bzr8vy3d997yxcapc9z9217ahzpgqhws\";\n  };\nin\n{\n  imports = [\n    \"${eris}/module.nix\"\n  ];\n\n  # ...\n  services.eris-git.enable = true;\n}\n#+END_SRC\n\n*Note*: IFD is not available in restricted build environments (such as Hydra CI)\nservers, so this method is not adviseable if you wish to continuously integrate\nyour NixOS configuration files. This method works fine however for simple\nsystems or workstations.\n\n* Configuration\n\nEris is configured using [[https://mojolicious.org/perldoc/Mojolicious/Plugin/Config][Mojolicious::Plugin::Config]], which uses a Perl-like\nconfiguration format that can contain live code for flexibility in deployment.\n\n*** Basic configuration\n\nBy default, Eris starts up by reading a file named ~eris.conf~, *in the CWD\nwhere you execute it*.\n\nThis file is not JSON, but a Perl-based configuration file that can use general\nPerl code for configuration. The general form looks like this:\n\n#+BEGIN_SRC perl\n{\n  option1 =\u003e 'value',    # strings\n  option2 =\u003e 1,          # integers\n  option3 =\u003e [ 1, 2 ],   # arrays\n  option4 =\u003e {           # hashes (\"objects\")\n    param1 =\u003e 'value1',\n    param2 =\u003e 'value2',\n  },\n  option5 =\u003e $ENV{VALUE} || \"default\", # read '$VALUE' from the environment\n}\n#+END_SRC\n\nComments start with ~#~, and trailing commas are allowed in all positions, just\nas regular Perl code allows.\n\nThe last example of ~option5~ shows how to use the Perl-based nature to your\nadvantage, by instead reading a value out of the environment at startup time,\nwith a default option provided. By utilizing this, you can get a lot of\nflexibility out of the configuration file format with pretty minimal fuss.\n\n*** Listening ports and addresses\n\nListening ports and addresses for the HTTP server are configured through the\n~listen~ option in ~eris.conf~. This parameter takes a list of strings,\nspecified as URLs, which specify the connection information, somewhat like an\nODBC/JDBC connection string. The configuration is best expressed by some\nexamples:\n\n#+BEGIN_SRC perl\n{\n  listen =\u003e [\n    'http://*:3000',         # listen on all IPv4 interfaces, on port 3000\n    'http://[::]:3000',      # same, but on all IPv4 and IPv6 interfaces\n    'http://[::1]:3000',     # IPv6 only\n\n    'http://*:3000?reuse=1', # enable SO_REUSEPORT\n    'https://*:4000',        # listen on HTTPS, as well. uses built-in testing certs\n\n    # specify a custom certificate and keyfile\n    'https://*:3000?cert=/x/server.crt\u0026key=/y/server.key',\n\n    # listen on a (percent-encoded) unix socket path, e.g. for frontend proxies\n    # this listens in /tmp/eris.sock\n    'http+unix://%2Ftmp%2Feris.sock',\n  ]\n}\n#+END_SRC\n\n*** Signing support\n\nPackages are signed \"on the fly\" when served by the cache. You can configure\nsigning in one of three modes:\n\n    1. No signing (the default mode).\n\n    2. Hard-coded keys, generated/procured ahead of time.\n\nThese three behaviors are controlled using the ~signing~ option in ~eris.conf~.\n\n**** 'No signature'-mode\n\nThe default mode is to not use signatures at all, which can be specified using\nthe ~none~ setting:\n\n#+BEGIN_SRC perl\n{\n  signing =\u003e 'none',\n}\n#+END_SRC\n\n**** Using pre-generated keys\n\nPre-generated keys are also easy; rather than a freeform string, you simply use\nan options hash to specify the hostname, and the files containing the\npublic and private keys.\n\nAssuming you generate a set of keys using ~nix-store --generate-binary-cache-key\ncache.example.com-1 /etc/nix/cache.sk /etc/nix/cache.pk~, you can configure Eris\nwith:\n\n#+BEGIN_SRC perl\n{\n  signing =\u003e {\n    host    =\u003e 'cache.example.com-1',\n    private =\u003e '/etc/nix/cache.sk',\n  },\n}\n#+END_SRC\n\nThe host attribute can be omitted when the private key is in the form of ~host:key~.\n\n*** Support for private users via HTTP authentication\n\nYou can add support for basic HTTP authentication via the ~users~ field in\n~eris.conf~, which contains a list of ~user:password~ strings.\n\n#+BEGIN_SRC perl\n{\n  users =\u003e [\n    'austin:rules',\n    'david:rocks'\n  ],\n}\n#+END_SRC\n\nGiven the above configuration, you can test the endpoint with ~curl~:\n\n#+BEGIN_SRC bash\n# this works\ncurl -u austin:rules http://eris/nix-cache-info\n\n# this fails\ncurl -u david:rules http://eris/nix-cache-info\n\n# and so does this\ncurl http://eris/nix-cache-info\n#+END_SRC\n\nOnce this configuration is in place, clients can authenticate with the server\nusing a standard cURL ~.netrc~ configuration file. This file takes the following\nform:\n\n#+BEGIN_SRC\nmachine \u003chostname\u003e\nlogin \u003cusername\u003e\npassword \u003cpassword\u003e\n...\n#+END_SRC\n\nEntries may be repeated to provide multiple logins for different caches.\n\nNow, you can use the option ~--option netrc-file /path/to/netrc~ with any of\nyour ~nix~ commands in order to authenticate properly, e.g.\n\n#+BEGIN_SRC bash\nnix --option netrc-file /path/to/netrc copy --from http://.../ /nix/store/...\n#+END_SRC\n\n*NOTE*: The path must be absolute.\n\nCheck out [[https://ec.haxx.se/usingcurl-netrc.html][the cURL manual page for ~.netrc~ files]], and the [[https://nixos.org/nix/manual/#name-11][nix.conf manual]]\n(particularly the ~netrc-file~ option) for more information.\n\n*** TLS support\n\nTLS support is controlled by the ~listen~ parameter in ~eris.conf~, as shown\nearlier. In particular, simply specifying an HTTPS URI in the ~listen~\nconfiguration will use a built-in set of testing certificates, distributed with\nMojolicious:\n\n#+BEGIN_SRC perl\n{\n  listen =\u003e ['https://*:443'],\n}\n#+END_SRC\n\nBut you almost _definitely do not want to do this_, since there's no way for\nclients to securely verify the certificate. Provided you do have a signed, valid\ncertificate, specifying the key and certificate is done with the ~\u0026cert=~ and\n~\u0026key=~ URL parameters:\n\n#+BEGIN_SRC perl\n{\n  listen =\u003e [ 'https://*:443?cert=/etc/eris/ssl.crt\u0026key=/etc/eris/ssl.key' ],\n}\n#+END_SRC\n\n*** NixOS-specific notes\n\nThere are a few NixOS-specific things to note, enforced primarily by the NixOS\nmodule and systemd, which users might want to be aware of:\n\n    1. *Eris has no visible /tmp dir*. Do not try to include or write files\n       here; they will never be visible by any other service, due to\n       ~PrivateTemp=true~ being specified for systemd.\n\n    2. *Eris has no assigned user*. The module uses systemd's ~DynamicUser=true~\n       directive, so UIDs are assigned dynamically to the service. (This could\n       be changed in the future but requires some upstream NixOS coordination\n       for reserving UIDs.)\n\n    3. *Eris is part of the ~adm~ group*. The intention is that members of the\n       ~adm~ group will be able to do things like rotate signing keys, located\n       under ~/etc/eris~; these actions don't require full admin privileges, but\n       ~eris~ will want to read the results.\n\n    3. *Eris can only read ~/etc/eris~ and almost nothing else. It cannot write\n       there*. We use an array of systemd's filesystem namespace features to\n       essentially allow the path ~/etc/eris~ to be bind-mounted inside the\n       service.\n\n       This means that even though ~eris~ is part of the ~adm~ group, it cannot\n       read almost anything else in ~/etc~ anyway.\n\n       Due to this combination of features, if you would like to keep your keys,\n       etc in a safe, read-only place, it's suggested to put them in ~/etc/eris~\n       and mark them as read-only files with strict visibility permission.\n\n** Checking Mojolicious server status\n\nEris uses the [[https://metacpan.org/pod/Mojolicious::Plugin::Status][Mojolicious::Plugin::Status]] module in order to provide some basic\ninformation about the running machine. The server status can be found by viewing\n~http://localhost:8080/mojo-status~, which will show you the server uptime,\ncurrently connected clients, and more, formatted as a nice, live HTML page.\n\nYou must enable the status plugin by setting the configuration value ~status =\u003e\n1~ in ~eris.conf~\n\n** Full configuration file reference\n\nCheck out [[https://github.com/thoughtpolice/eris/blob/master/conf/eris.conf.example][./conf/eris.conf.example]] in this repository for the full\nconfiguration file reference, along with some examples.\n\n* Deployment\n\nThere are several options for running the cache server, but the following three\noutline the most typical scenarios.\n\n** Running Eris standalone\n\nAs you saw above, you can easily install Eris into the Nix environment of your\nuser account, making it trivial and easy to quickly export your Nix store. (You\ncan even run it directly from the source code repository, too. See [[Hacking]] for\nmore.)\n\nIn the original example above, we executed the standalone ~eris~ program in\n/foreground mode/, using the ~-f~ flag. By default, ~eris~ executes in daemon\nmode: it forks a process, writes a ~.pid~ file, and then detaches from the host\nshell.\n\nThis means if you simply log into a machine and run ~eris~, it will immediately\nfork and start running. When you log out, it will stay running. That's all you\nhave to do! In order to stop the running daemon, just execute ~eris -s~, which\nwill kill the prior worker processes, using the ~.pid~ file.\n\nAnd, of course, if you'd like to keep it running while in foreground mode, be\nsure to run it behind something like ~tmux~ or ~screen~!\n\n** Running Eris as a NixOS service\n\nEris comes with a NixOS-compatible service module, allowing you to quickly and\neasily serve your Nix store on any machine you're running. We saw how to do this\nearlier, but to recap, after importing, just add the following lines to your\nconfiguration:\n\n#+BEGIN_SRC nix\n{ config, pkgs, lib, ... }:\n\n{\n  # ...\n  services.eris-git.enable = true;\n}\n#+END_SRC\n\nLike above, this defaults to only serving the HTTP cache on ~localhost~ for\nsecurity reasons, so you'll need to tweak the configuration to expose it on your\nLAN/WAN address.\n\nCheck ~module.nix~ for information on the configuration options.\n\n** Running Eris as a service on any Linux distribution\n\nEris can also be deployed on non-NixOS machines, which is often convenient for\nusers and many deployment situations where NixOS isn't available.\n\nThe easiest way to do this is to first log in as the ~root~ user on your Linux\nmachine with Nix installed. For Nix-on-Linux, the root user controls the\ndefault set of system profiles and channels, so we'll want to install it\nthere.\n\n#+BEGIN_SRC bash\n$ whoami\nroot\n$ nix run nixpkgs.git -c git clone https://github.com/thoughtpolice/eris.git\n$ cd eris/\n$ nix-env -i $(nix-build --no-link -Q release.nix -A eris)\n#+END_SRC\n\n~eris~ is now installed for the ~root~ user. This installs the ~eris~ outputs\ninto the default profile, which includes an ~eris.service~ file for systemd.\nBy installing it into the root user, we can give it a stable path.\n\nNow, you can link this file into the default systemd search path, enable it,\nand start it.\n\n#+BEGIN_SRC bash\n$ systemctl link /nix/var/nix/profiles/system/sw/lib/systemd/system/eris.service\n$ systemctl enable eris\n$ systemctl start eris\n#+END_SRC\n\nWhenever you want to upgrade ~eris~, just install a new version of the package\ninto the ~root~ users account (e.g. by running ~git pull~ and re-performing the\ninstallation.) ~systemd~ will still follow the same stable symbolic link name to\nthe updated filesystem paths.\n\nLikewise, there is also a stable path to the ~eris~ binary installed in the\ndefault profile, located at:\n\n#+BEGIN_SRC bash\n/nix/var/nix/profiles/system/sw/bin/eris\n#+END_SRC\n\nNote that, because this ~eris.service~ file is inside ~/nix/store~, it is\nread-only. You are advised to carefully examine the service file and see if it\nmeets your needs. If it doesn't, which is possible, simply copying it to\n~/etc/system/systemd/~ on your system and following the same commands above will\ngive you a version you can edit.\n\n* HTTP API\n\nThere are only a couple HTTP endpoints that Nix actually relies on in order to\ndownload files from an HTTP server. But Eris exposes a few more, too.\n\n** Basic Nix HTTP API\n\nThere are three primary endpoints a Nix-compliant HTTP cache must implement:\n\n 1. ~/nix-cache-info~ -- information about the cache server, including where\n    the Nix store is located.\n\n 2. ~/:hash.narinfo~ -- the narinfo endpoint. A ~GET~ request against this\n    server endpoint will give back information about the resulting object named\n    ~:hash~ in the store, including its path, if it exists. If the object cannot\n    be found in the store, a 404 error code is returned.\n\n 3. ~/nar/:hash.nar~ -- the download endpoint. A ~GET~ request against\n    this endpoint will download the ~.nar~ file for the given store object,\n    identified by ~:hash~.\n\n** Eris HTTP API (v1)\n\nThe prior endpoints give you enough to query Nix packages from the store, but\nEris also exposes a few extra endpoints, which are probably more useful for\nend-users, or scripting tools.\n\n - ~/v1/public-key~ -- the Ed25519 public key, which all served objects will be\n   signed by, This would be useful in scripting environments to identify what\n   key the server will sign with. If a server is not configured to sign\n   downloaded objects, a 404 error code is returned.\n\n - ~/v1/version~ -- the version of ~Eris~, in traditional Nix format, including\n   pre-release/git information if applicable. This endpoint is always available\n   and will never return a non-200 error code, outside of \"catastrophic\"\n   situations (network/disk/ghosts attacking you).\n\n* Demo: build a private cache with [[https://www.cloudflare.com][CloudFlare]] and [[https://www.packet.net][Packet.net]]\n\nA demonstration of a full-fledged deployment on top of [[https://www.packet.net][Packet.net]] using\n[[https://www.cloudflare.com][CloudFlare]] as a frontend firewall, cache, and DNS service is provided. Thanks to\nthe [[https://www.cloudflare.com/bandwidth-alliance/][Bandwidth Alliance]], egress between Packet and CloudFlare is free, so the\nonly costs you pay for the cache server are for the physical hardware.\n\nSee [[./demo/readme.org][the ~./demo/~ directory]] for more information.\n\n* FAQ\n\n** Why write this?\n\nA few reasons:\n\n1. I wanted something more configurable than [[https://github.com/edolstra/nix-serve][nix-serve]], which is a bit\n   barebones and doesn't include necessary features like authentication.\n2. I wanted something /less heavyweight/ and obscure than [[https://nixos.org/hydra/][Hydra]], which I've\n   had many painful experiences with.\n3. It was a good reason to learn to use [[https://mojolicious.org][Mojolicious]], which is awesome.\n\n** What's with the name?\n\nEris is the daughter of [[https://en.wikipedia.org/wiki/Eris_(mythology)][Nyx]] in Greek mythology.\n\n** Does Eris handle cache /uploads/?\n\nNo. It's assumed you will use some mechanism such as ~nix copy --to ssh://...~\nin order to securely copy store objects to the remote server that runs Eris.\nThey will then become available in the cache.\n\n** What about alternative systems like Cachix?\n\n[[https://cachix.org][Cachix]] is a new service for the NixOS community that offers simple, easy-to-use\nhosting for Nix binary caches. You might be wondering if you should use Cachix\nor Eris for your project.\n\nHere's my simple guideline as the author of Eris: *you probably want to use\nCachix if at all possible*. If you're doing open source work it's also freely\navailable, which is especially attractive, but paid, closed-source caches should\nbe available soon.\n\nThe reasons for this are a bit obvious but it's essentially worth repeating\nhere: you probably don't want to run and maintain your own binary cache server.\nNixOS is wonderful but even then, it is a constant maintenance overhead of\ntuning, deployment, upgrades, and security.\n\nOn top of that, Eris doesn't really care about or involve itself in the /other/\nhalf required of a full caching system: uploads, as previously mentioned. Cachix\ndoes 'first-class' authenticated uploads, i.e. it is a feature. Using SSH is\nfine, and keeps Eris simple, but involves secondary authorization/policy\nmanagement at your own expense. (It's possible this might change one day, but\nit's unlikely any time in the near-future.)\n\n** Austin, you wrote this in /Perl/?\n\nA lot of people know me (Austin Seipp, the primary author) as a Haskell\nprogrammer. But even outside of that, Perl doesn't ever seem vogue these days\nfor new projects (a truly damning image, coming from an industry that's mostly\nfashion-driven), which might leave some to wonder. So this is a quick way of\nsaying: I know you're thinking \"Why would you choose Perl\", and the answer may\nsurprise you.\n\nThe short of it is: because I like Perl, and it was a chance to learn how to use\nMojolicious (which I can now say I like quite a lot). That is basically all it\ncomes down to. From this point of view I consider Eris a complete success: it\nhas been relatively painfree to develop (thanks to Mojo) and I believe its\nfuture evolution will work out well, and remain clean, and easy to understand,\nover time.\n\n* Hacking\n\nIf you want to work on the source code, here are a few tips and tricks.\n\n** Running Eris in-place\n\nThe easiest way to get started with Eris is to just run it right out of this\nrepository by executing the ~eris.pl~ script:\n\n#+BEGIN_SRC bash\n$ git clone https://github.com/thoughtpolice/eris.git\n$ cd eris\n$ MOJO_MODE=development ./eris.pl -f\n#+END_SRC\n\nThis uses ~nix-shell~'s support for shebang lines in order to immediately run\nthe underlying Perl script with no fuss. You can just hack on ~eris.pl~ in place\nand restart as you like.\n\n~MOJO_MODE=development~ sets up development mode for the HTTP Route handlers,\nwhich makes debugging errors and faults much easier.\n\nIf you want to test the whole build process and run the resulting executable\nfrom the Nix derivation, you can do that with ~nix-build~:\n\n#+BEGIN_SRC bash\nexport MOJO_MODE=development\n$(nix-build -Q --no-out-link release.nix -A eris)/bin/eris -f\n#+END_SRC\n\n** Running the tests\n\nRunning the tests can be done using ~nix build~ quite easily:\n\n#+BEGIN_SRC bash\n$ nix build -f release.nix test\n#+END_SRC\n\nThis actually runs the complete set of tests that exist under the ~./t/~\ndirectory. Each file contains its own NixOS-based test which is collected\ninto a full attrset, based on the filename (~test.nix~ is very short, so feel\nfree to read it yourself).\n\n** Protip: Running Eris behind Ngrok\n\n[[https://ngrok.io][ngrok]] is an online service that exposes public URLs for local webservers and is\nuseful for testing integration. It comes with a free tier. However, it can also\nbe used to quickly expose Eris to remote machines. The free tier only allows 40\nconnections per minute, however, so it's only useful for light testing.\n\nThe ~ngrok~ binary is available in Nixpkgs; you can install and authenticate\nwith the http://ngrok.io service as follows, then launch an HTTP tunnel:\n\n#+BEGIN_SRC bash\n$ nix-env -iA nixpkgs.ngrok\n$ ngrok authtoken ...\n$ ngrok http 8080\n#+END_SRC\n\nNow, you're free to use the randomly generated ~ngrok.io~ domain as a temporary\nbinary cache.\n\nNote that if you do this, you probably want to enable Hypnotoad's ~proxy~\nsetting so that the server will correctly recognize ~X-Forwarded-For~ headers\nand user IPs properly. Add something like this to your ~eris.conf~:\n\n#+BEGIN_SRC perl\n{\n  proxy =\u003e 1,\n}\n#+END_SRC\n\n* TODOs\n\nThese are basically in the order I wish to tackle them.\n\n** Dynamic routes\n\nIt would be interesting to explore 'dynamic routes' for caches, e.g. different\ncaches located at different HTTP endpoints with different authentication\nmechanisms, or backends.\n\n** Let's Encrypt integration\n\nFor those of us out there who trust nobody, it would be nice if the Hypnotoad\nserver could auto-start itself with a set of TLS certificates.\n\n* Authors\n\nSee [[https://raw.githubusercontent.com/thoughtpolice/eris/master/AUTHORS.txt][AUTHORS.txt]] for the list of contributors to the project.\n\n* License\n\n*GPLv3 or later*. See [[https://raw.githubusercontent.com/thoughtpolice/eris/master/COPYING][COPYING]] for precise terms of copyright and redistribution.\n","funding_links":["https://github.com/sponsors/thoughtpolice"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtpolice%2Feris","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthoughtpolice%2Feris","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtpolice%2Feris/lists"}