Inventaire
Inventaire is a libre/free webapp to make inventories and lists of books, and facilitates book sharing. By aggregating individuals' and collectives' book inventories from around the world, Inventaire is kind of a huge, distributed community library.
Try the service in a VM
-
Install Nix
- Arch Linux
-
- Bash
-
$ pacman --sync --refresh --noconfirm curl git jq nix
- Debian
-
- Bash
-
$ apt install --yes curl git jq nix
- Ubuntu
-
- Bash
-
$ apt install --yes curl git jq nix
-
Download a configuration file
# default.nix { ngipkgs ? import (fetchTarball "https://github.com/ngi-nix/ngipkgs/tarball/main") { }, }: ngipkgs.demo-vm ( { config, lib, pkgs, ... }: let # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is only done like this here to allow easy testing & debugging. # Use some secrets management mechanism to track values like this outside of Nix, so they can't leak into the store couchdbUser = "inventaire"; couchdbPassword = "ThisIsNotSecurelyManagedAndImFullyAwareOfThis"; couchdbPort = 5984; elasticPort = 9200; inventairePort = 3006; inventaireServiceDeps = [ "couchdb.service" # If using ElasticSearch instead, change this to: "elasticsearch.service" "opensearch.service" ]; in { # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is just done like this here to allow easy testing & debugging. # Use some secrets management mechanism to get a string of a path at runtime here. environment.etc."inventaire-config-overrides.cjs".text = '' // This is not securely managed, and I'm fully aware of this. module.exports = { db: { username: "${couchdbUser}", password: "${couchdbPassword}", }, } ''; services.couchdb = { enable = true; port = couchdbPort; extraConfigFiles = [ # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is only done like this here to allow easy testing & debugging. # Point it at a path that secrets management will produce at runtime instead. ((pkgs.formats.ini { }).generate "couchdb-admin-setup.ini" { admins = { "${couchdbUser}" = "${couchdbPassword}"; }; }) ]; }; # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is only done like this here to allow easy testing & debugging. # Manually complete the CouchDB setup instead. systemd.services."couchdb-setup" = { description = "Setup of CouchDB"; wantedBy = [ "couchdb.service" "inventaire.service" ]; after = [ "couchdb.service" ]; before = [ "inventaire.service" ]; path = with pkgs; [ bash coreutils curl netcat ]; serviceConfig.Type = "oneshot"; script = '' set -e echo "Waiting for CouchDB to open its port..." timeout 30 bash -c 'until nc -z localhost ${toString config.services.couchdb.port}; do sleep 1; done' echo "CouchDB port open." echo "Creating _user table in CouchDB (if necessary)..." set +x # in case it already exists curl -X PUT \ 'http://${couchdbUser}:${couchdbPassword}@localhost:${toString config.services.couchdb.port}/_users' set -e echo "_user table created." echo "CouchDB should now be configured for Inventaire usage." ''; }; # We're using OpenSearch instead of ElasticSearch here because the latter's packaging in Nixpkgs would require us to opt into unfreely-licensed packages. # If unfree packages are not an issue to you, or you just want specifically ElasticSearch, then you may use `services.elasticsearch` here instead. services.opensearch = { enable = true; settings."http.port" = elasticPort; }; services.inventaire = { enable = true; inProductionMode = false; # production mode expects to be running behind nginx, breaks some asset serving openFirewall = true; settings = { hostname = "0.0.0.0"; port = inventairePort; # CouchDB db = { hostname = "localhost"; port = couchdbPort; }; # LevelDB leveldb = { directory = "${config.services.inventaire.stateDir}/db/leveldb"; }; # ElasticSearch / OpenSearch elasticsearch = { origin = "http://localhost:${toString elasticPort}"; }; # OpenStreetMap, so no access token is necessary mapTiles = { provider = "openstreetmap"; }; # Storage of downloaded files mediaStorage = { local = { directory = "${config.services.inventaire.stateDir}/storage"; }; }; }; # When using proper secrets management, set a path produced at runtime by your secrets management here instead. extraDevelopmentSettingsFile = "/etc/inventaire-config-overrides.cjs"; }; # We connect to local instances of these, so we might as well ensure they get launched first systemd.services."inventaire".wants = inventaireServiceDeps; systemd.services."inventaire".after = inventaireServiceDeps; } )
-
Enable binary substituters
- Bash
-
$ export NIX_CONFIG='substituters = https://cache.nixos.org/ https://ngi.cachix.org/ trusted-public-keys = cache.nixos.org-1:6nchdd59x431o0gwypbmraurkbj16zpmqfgspcdshjy= ngi.cachix.org-1:n+cal72roc3qqulxihpv+tw5t42whxmmhpragkrsrow='
-
Build and run a virtual machine
- Arch Linux, Debian Sid and Ubuntu 25.04
-
- Bash
-
$ nix-build ./default.nix && ./result
- Debian 12 and Ubuntu 24.04/24.10
-
- Bash
-
$ rev=$(nix-instantiate --eval --attr sources.nixpkgs.rev https://github.com/ngi-nix/ngipkgs/archive/master.tar.gz | jq --raw-output)
$ nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/$rev.tar.gz --packages nix --run "nix-build ./default.nix && ./result"
-
Usage Instructions
A (very insecure!) example of setting up Inventaire and its dependencies on the local machine.
Options
services.inventaire
- services.inventaire.enable
-
Whether to enable Inventaire server.
- Type:
boolean
- Default:
false
- services.inventaire.extraDevelopmentSettingsFile
-
Path to a .cjs file that exists at runtime with any additional setting.
Notes:
- The passed path (if any) will be set up as
config/local-development.cjs
, to override the built-in defaults and values from the mainsettings
attribute - These settings are not world-readable (assuming you're passing a path that isn't generated by Nix), and thus suitable for secrets
Links for settings (make sure to look at the version that's actually packaged):
- Type:
null or absolute path
- Default:
null
- The passed path (if any) will be set up as
- services.inventaire.extraProductionSettingsFile
-
Path to a .cjs file that exists at runtime with any additional setting.
Notes:
- The passed path (if any) will be set up as
config/local-production.cjs
, to override the built-in defaults and values from the mainsettings
attribute - These settings are not world-readable (assuming you're passing a path that isn't generated by Nix), and thus suitable for secrets
Links for settings (make sure to look at the version that's actually packaged):
- Type:
null or absolute path
- Default:
null
- The passed path (if any) will be set up as
- services.inventaire.inProductionMode
-
Whether to run in development or production mode.
Will affect which default settings get loaded, and which of the extra settings files options will be relevant.
- Type:
boolean
- Default:
false
- services.inventaire.openFirewall
-
Whether to open the
port
specified insettings
in the firewall.- Type:
boolean
- Default:
false
- services.inventaire.package
-
The inventaire package to use.
- Type:
package
- Default:
pkgs.inventaire
- Notes:
- Missing update script An update script is required for automatically tracking the latest release.
- services.inventaire.settings
-
Settings that you wish to set for the service.
Notes:
- The settings here will be set up as
config/local.cjs
, to override the built-in defaults - These settings are world-readable, and thus not suitable for secrets
Links for settings (make sure to look at the version that's actually packaged):
- Type:
JSON value
- Default:
{ hostname = "localhost"; leveldb = { directory = "/var/lib/inventaire/db/leveldb"; }; mediaStorage = { local = { directory = "/var/lib/inventaire/storage"; }; }; port = 3006; }
- The settings here will be set up as
- services.inventaire.stateDir
-
Directory in which Inventaire will run & put its data into.
- Type:
absolute path
- Default:
"/var/lib/inventaire"
Examples
Enable Inventaire
{ config, lib, pkgs, ... }: let # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is only done like this here to allow easy testing & debugging. # Use some secrets management mechanism to track values like this outside of Nix, so they can't leak into the store couchdbUser = "inventaire"; couchdbPassword = "ThisIsNotSecurelyManagedAndImFullyAwareOfThis"; couchdbPort = 5984; elasticPort = 9200; inventairePort = 3006; inventaireServiceDeps = [ "couchdb.service" # If using ElasticSearch instead, change this to: "elasticsearch.service" "opensearch.service" ]; in { # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is just done like this here to allow easy testing & debugging. # Use some secrets management mechanism to get a string of a path at runtime here. environment.etc."inventaire-config-overrides.cjs".text = '' // This is not securely managed, and I'm fully aware of this. module.exports = { db: { username: "${couchdbUser}", password: "${couchdbPassword}", }, } ''; services.couchdb = { enable = true; port = couchdbPort; extraConfigFiles = [ # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is only done like this here to allow easy testing & debugging. # Point it at a path that secrets management will produce at runtime instead. ((pkgs.formats.ini { }).generate "couchdb-admin-setup.ini" { admins = { "${couchdbUser}" = "${couchdbPassword}"; }; }) ]; }; # !!! THIS IS INSECURE, DO NOT DO THIS IN PRODUCTION !!! # This is only done like this here to allow easy testing & debugging. # Manually complete the CouchDB setup instead. systemd.services."couchdb-setup" = { description = "Setup of CouchDB"; wantedBy = [ "couchdb.service" "inventaire.service" ]; after = [ "couchdb.service" ]; before = [ "inventaire.service" ]; path = with pkgs; [ bash coreutils curl netcat ]; serviceConfig.Type = "oneshot"; script = '' set -e echo "Waiting for CouchDB to open its port..." timeout 30 bash -c 'until nc -z localhost ${toString config.services.couchdb.port}; do sleep 1; done' echo "CouchDB port open." echo "Creating _user table in CouchDB (if necessary)..." set +x # in case it already exists curl -X PUT \ 'http://${couchdbUser}:${couchdbPassword}@localhost:${toString config.services.couchdb.port}/_users' set -e echo "_user table created." echo "CouchDB should now be configured for Inventaire usage." ''; }; # We're using OpenSearch instead of ElasticSearch here because the latter's packaging in Nixpkgs would require us to opt into unfreely-licensed packages. # If unfree packages are not an issue to you, or you just want specifically ElasticSearch, then you may use `services.elasticsearch` here instead. services.opensearch = { enable = true; settings."http.port" = elasticPort; }; services.inventaire = { enable = true; inProductionMode = false; # production mode expects to be running behind nginx, breaks some asset serving openFirewall = true; settings = { hostname = "0.0.0.0"; port = inventairePort; # CouchDB db = { hostname = "localhost"; port = couchdbPort; }; # LevelDB leveldb = { directory = "${config.services.inventaire.stateDir}/db/leveldb"; }; # ElasticSearch / OpenSearch elasticsearch = { origin = "http://localhost:${toString elasticPort}"; }; # OpenStreetMap, so no access token is necessary mapTiles = { provider = "openstreetmap"; }; # Storage of downloaded files mediaStorage = { local = { directory = "${config.services.inventaire.stateDir}/storage"; }; }; }; # When using proper secrets management, set a path produced at runtime by your secrets management here instead. extraDevelopmentSettingsFile = "/etc/inventaire-config-overrides.cjs"; }; # We connect to local instances of these, so we might as well ensure they get launched first systemd.services."inventaire".wants = inventaireServiceDeps; systemd.services."inventaire".after = inventaireServiceDeps; }
This project is funded by NLnet through these subgrants: