3 Nsscash (a pun on cache) is a simple file-based cache for NSS similar to
4 nsscache [1]. The goal is to distribute users/groups/etc. to multiple systems
5 without having to rely on a (single) stable server. Traditional systems like
6 LDAP or NIS require a stable server or users/groups cannot be resolved. By
7 distributing the data to all systems, temporary outages of the server cause no
8 issues on the clients. In addition the local storage is much faster than
9 remote network access. To update the local caches polling via HTTP is
10 performed, for example every minute, only downloading new data if anything has
13 Nsscash consists of two parts: `nsscash`, written in Go, which downloads files
14 via HTTP or HTTPS, parses them, creates indices and writes the result to a
15 local file. The second part is the NSS module (`libnss_cash.so.2`), written in
16 C, which provides integration via `/etc/nsswitch.conf`. It's specifically
17 designed to be very simple and uses the data prepared by `nsscash` for
18 lookups. To support quick lookups, in O(log n), the files utilize indices.
20 Nsscash is very careful when deploying the changes:
21 - All files are updated using the standard "write to temporary file", "sync",
22 "rename" steps which is atomic on UNIX file systems.
23 - All errors cause an immediate abort ("fail fast") with a proper error
24 message and a non-zero exit status. This prevents hiding possibly important
25 errors. In addition all files are fetched first and then deployed to try to
26 prevent inconsistent state if only one file can be downloaded. The state
27 file (containing last file modification and content hash) is only updated
28 when all operations were successful.
29 - To prevent unexpected permissions, `nsscash` does not create new files. The
30 user must create them first and `nsscash` will then re-use the permissions
31 (without the write bits to discourage manual modifications) and owner/group
32 when updating the file (see examples below).
33 - To prevent misconfigurations, empty files (no users/groups) are not
34 permitted and will not be written to disk. This is designed to prevent the
35 accidental loss of all users/groups on a system.
37 The passwd/group files have the following size restrictions:
38 - maximum number of entries: '2^64-1' (uint64_t)
39 - maximum passwd entry size: 65543 bytes (including newline)
40 - maximum group entry size: 65535 bytes (including newline, only one member)
41 - maximum members per group: depends on the user name length,
42 with 9 bytes per user: 5460 users
43 - `nsscash` checks for these restrictions and aborts with an error if they are
46 nsscash is licensed under AGPL version 3 or later.
48 [1] https://github.com/google/nsscache
54 - github.com/pkg/errors
55 - github.com/BurntSushi/toml
56 - C compiler, for `libnss_cash.so.2`
58 Tested on Debian Stretch and Buster, but should work on any GNU/Linux system.
59 With adapations to the NSS module it should work on any UNIX-like system which
65 Install `libnss_cash.so.2` somewhere in your library search path (see
66 `/etc/ld.so.conf`), e.g. `/usr/lib/x86_64-linux-gnu/`.
68 Update `/etc/nsswitch.conf` to include the cash module; `passwd` and `group`
69 are currently supported. For example:
75 Create the cache files with the proper permissions (`nsscash fetch` won't
76 create new files to prevent using incorrect permissions):
78 touch /etc/passwd.nsscash
79 touch /etc/group.nsscash
80 chmod 0644 /etc/passwd.nsscash
81 chmod 0644 /etc/group.nsscash
83 Configure the `nsscash` configuration file `nsscash.toml`, see below.
87 nsscash fetch /path/to/config/nsscash.toml
89 This will fetch the configured files and update the local caches. The files
90 are atomically overwritten (via temporary file, sync, and rename).
92 Verify the users/groups are available, e.g. with `getent`. If everything
93 works, remember to reboot the host as changes to `nsswitch.conf` don't affect
96 Now configure `nsscash` to run regularly, for example via cron or a systemd
99 To monitor `nsscash` for errors one can use the last modification time of the
100 state file (see below). It's written on each successful run and not modified
105 Nsscash is configured through a simple configuration file written in TOML. A
106 typical configuration looks like this:
108 statepath = "/var/lib/nsscash/state.json"
112 url = "https://example.org/passwd"
113 path = "/etc/passwd.nsscash"
117 url = "https://example.org/group"
118 path = "/etc/group.nsscash"
120 # Optional, but useful to deploy files which are not supported by the
121 # nsscash NSS module, but by libc's "files" NSS module. nsscash takes care
122 # of the atomic replacement and updates; an "netgroup: files" entry in
123 # "/etc/nsswitch.conf" makes the netgroups available.
126 url = "https://example.org/netgroup"
127 path = "/etc/netgroup"
129 The following global keys are available:
131 - `statepath`: Path to a JSON file which stores the last modification time and
132 hash of each file; automatically updated by `nsscash`. Used to fetch data
133 only when something has changed to reduce the required traffic, via
134 `If-Modified-Since`. When the hash of a file has changed the download is
137 Each `file` block describes a single file to download/write. The following
140 - `type`: Type of this file; can be either `passwd` (for files in
141 `/etc/passwd` format), `group` (for files in `/etc/group` format), or
142 `plain` (arbitrary format). Only `passwd` and `group` files are supported by
143 the nsscash NSS module. But, as explained above, `plain` can be used to
144 distribute arbitrary files. The type is required as the `.nsscash` files are
145 pre processed for faster lookups and simpler code which requires a known
148 - `url`: URL to fetch the file from; HTTP and HTTPS are supported
150 - `path`: Path to store the retrieved file
155 Written by Simon Ruderich <simon@ruderich.org>.
160 This program is licensed under AGPL version 3 or later.
162 Copyright (C) 2019 Simon Ruderich
164 This program is free software: you can redistribute it and/or modify
165 it under the terms of the GNU Affero General Public License as published by
166 the Free Software Foundation, either version 3 of the License, or
167 (at your option) any later version.
169 This program is distributed in the hope that it will be useful,
170 but WITHOUT ANY WARRANTY; without even the implied warranty of
171 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
172 GNU Affero General Public License for more details.
174 You should have received a copy of the GNU Affero General Public License
175 along with this program. If not, see <https://www.gnu.org/licenses/>.