# [`nfsn-utils`][]
Interact with [NearlyFreeSpeech.NET][]'s [API][] from the command line.
[`nfsn-utils`]: https://git.rcrnstn.net/rcrnstn/nfsn-utils
[NearlyFreeSpeech.NET]: https://www.nearlyfreespeech.net
[API]: https://en.wikipedia.org/wiki/API
## Goals
`nfsn-utils` has three main goals:
1. **Be portable** (even to things like [routers][]).
POSIX shell is used as glue for standard utilities. See
[dependencies](#dependencies).
2. **Be modular** where it makes sense.
[`nfsn-send`](#nfsn-send) is a general purpose [NearlyFreeSpeech.NET][]
[API][] wrapper. [`nfsn-dns-update`](#nfsn-dns-update) is a general purpose
[NearlyFreeSpeech.NET][] DNS update utility.
3. **Be opinionated with sane defaults** where it makes sense.
The smaller utilities assume things like that you want to use [standard
email addresses][].
4. **Be easily auditable**.
The scripts are well abstracted and no more than about 100 lines of code.
[routers]: https://openwrt.org
[standard email addresses]: https://www.ietf.org/rfc/rfc2142.txt
## Prerequisites
### API key
As described in the [NearlyFreeSpeech.NET][] [documentation][], one needs to
submit a [free assistance request][] to obtain an API key.
Place the credentials in the environment variables `NFSN_LOGIN` and
`NFSN_API_KEY` or in the file `./.nfsn-api` or `$HOME/.nfsn-api` (location
overridable by the `NFSN_CREDENTIALS_PATH` environment variable). This file
should be a JSON file consisting of an object with the keys `login` and
`api-key`. (The file format and default location is compatible with
[WebService::NFSN][] and [python-nfsn][].)
[documentation]: https://members.nearlyfreespeech.net/wiki/API/Introduction
[free assistance request]: https://members.nearlyfreespeech.net/support/assist?tag=apikey
[WebService::NFSN]: https://metacpan.org/pod/WebService::NFSN#INTERFACE
[python-nfsn]: https://github.com/ktdreyer/python-nfsn#authentication
### Dependencies
- Unix-like environment (in particular, `/dev/urandom`).
- [POSIX utilities][] with `date` supporting `+%s` (such as GNU `date`).
- `sha1sum` (for instance, the one in `coreutils`).
- [curl][].
- [jq][].
- `certbot` (only needed for `nfsn-dns-certbot*`).
[POSIX utilities]: http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html
[curl]: https://curl.haxx.se
[jq]: https://github.com/stedolan/jq
## Included programs
Dependency graph:
![included programs](doc/included-programs.dot.png)
### `nfsn-send`
Wraps the Requests, Responses and Authentication described in the
[NearlyFreeSpeech.NET][] [documentation][].
### `nfsn-dns-update`
Updates several DNS records and outputs what data was actually changed.
### `nfsn-dns-a`
Updates DNS [A][] records, used to map hostnames to an IPv4 address.
[A]: https://en.wikipedia.org/wiki/List_of_DNS_record_types#A
### `nfsn-dns-spf`
Updates DNS [SPF][] records, used for email authorization (specifying who is
allowed to send mail from a domain).
[SPF]: https://en.wikipedia.org/wiki/Sender_Policy_Framework
### `nfsn-dns-dkim`
Updates DNS [DKIM][] records, used for email authentication (using digital
signatures).
[DKIM]: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
### `nfsn-dns-dmarc`
Updates DNS [DMARC][] records, extending [SPF][] and [DKIM][] by specifying
failure policy and reporting.
See also the [dmarc.org FAQ][].
[DMARC]: https://en.wikipedia.org/wiki/DMARC
[dmarc.org FAQ]: https://dmarc.org/wiki/FAQ#Sender_Questions
### `nfsn-dns-certbot*`
`nfsn-dns-certbot` calls [certbot][] (the [Electronic Frontier Foundation][]'s
(EFF) [Let's Encrypt][] client, for getting HTTPS certificates) in [manual
mode][] to make it use `nfsn-utils` to update DNS records in order to fullfill
the [`dns-01` challenge][]. It does this by registering
`nfsn-dns-certbot-{auth,cleanup}` as [hooks][].
By default, the `auth` hook sleeps for 30 seconds to let the DNS records
propagate. This can be overridden with the environment variable
`NFSN_DNS_CERTBOT_AUTH_SLEEP`.
Given that `nfsn-dns-certbot` has successfully run once, running `certbot
renew` will suffice to renew the certificates.
[certbot]: https://certbot.eff.org
[Electronic Frontier Foundation]: https://www.eff.org
[Let's Encrypt]: https://letsencrypt.org
[manual mode]: https://certbot.eff.org/docs/using.html#manual
[`dns-01` challenge]: https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.4
[hooks]: https://certbot.eff.org/docs/using.html#hooks
## License
Licensed under the [ISC License][] unless otherwise noted, see the
[`LICENSE`][] file.
[ISC License]: https://choosealicense.com/licenses/isc
[`LICENSE`]: LICENSE