several documentation improvements

*   prefix docker/nvr commands with sudo (fixes #142).
    I was just going to link to the docker documentation on setting
    up non-root access, but that's kind of a personal preference.
    I included a `<details>` about it instead and made all the commands
    work with sudo.

*   take better advantage of github markdown's code block syntax
    highlighting. Use "console" for shell session stuff, put the
    "nvr" wrapper script in its own block with "bash".

*   add some comments to nvr wrapper script where people need to
    make changes and/or will be confused.

*   add a `<details>` that talks about shutting down and restarting
    the session around `nvr config` (see #151). Still not user-friendly
    but at least it's better documented now.
This commit is contained in:
Scott Lamb 2021-08-23 12:40:14 -07:00
parent a16bda8fb1
commit 30cea5cfcb
5 changed files with 111 additions and 70 deletions

View File

@ -23,7 +23,7 @@ See the [github page](https://github.com/scottlamb/moonfire-nvr) (in case
you're not reading this text there already). You can download the you're not reading this text there already). You can download the
bleeding-edge version from the commandline via git: bleeding-edge version from the commandline via git:
``` ```console
$ git clone https://github.com/scottlamb/moonfire-nvr.git $ git clone https://github.com/scottlamb/moonfire-nvr.git
$ cd moonfire-nvr $ cd moonfire-nvr
``` ```
@ -32,8 +32,8 @@ $ cd moonfire-nvr
This command should prepare a deployment image for your local machine: This command should prepare a deployment image for your local machine:
``` ```console
$ docker buildx build --load --tag=moonfire-nvr -f docker/Dockerfile . $ sudo docker buildx build --load --tag=moonfire-nvr -f docker/Dockerfile .
``` ```
<details> <details>
@ -47,8 +47,8 @@ $ docker buildx build --load --tag=moonfire-nvr -f docker/Dockerfile .
due to an error in `libseccomp`, as described [in this askubuntu.com answer](https://askubuntu.com/a/1264921/1365248). due to an error in `libseccomp`, as described [in this askubuntu.com answer](https://askubuntu.com/a/1264921/1365248).
Try running in a privileged builder. As described in [`docker buildx build` documentation](https://docs.docker.com/engine/reference/commandline/buildx_build/#allow), Try running in a privileged builder. As described in [`docker buildx build` documentation](https://docs.docker.com/engine/reference/commandline/buildx_build/#allow),
run this command once: run this command once:
``` ```console
$ docker buildx create --use --name insecure-builder --buildkitd-flags '--allow-insecure-entitlement security.insecure' $ sudo docker buildx create --use --name insecure-builder --buildkitd-flags '--allow-insecure-entitlement security.insecure'
``` ```
then add `--allow security.insecure` to your `docker buildx build` commandlines. then add `--allow security.insecure` to your `docker buildx build` commandlines.
</details> </details>
@ -59,11 +59,11 @@ helpful to use the `dev` target. This is a self-contained developer environment
which you can use from its shell via `docker run` or via something like which you can use from its shell via `docker run` or via something like
Visual Studio Code's Docker plugin. Visual Studio Code's Docker plugin.
``` ```console
$ docker buildx build \ $ sudo docker buildx build \
--load --tag=moonfire-dev --target=dev -f docker/Dockerfile . --load --tag=moonfire-dev --target=dev -f docker/Dockerfile .
... ...
$ docker run \ $ sudo docker run \
--rm --interactive=true --tty \ --rm --interactive=true --tty \
--mount=type=bind,source=$(pwd),destination=/var/lib/moonfire-nvr/src \ --mount=type=bind,source=$(pwd),destination=/var/lib/moonfire-nvr/src \
moonfire-dev moonfire-dev
@ -86,8 +86,8 @@ architecture.
On the author's macOS machine with Docker desktop 3.0.4, building for On the author's macOS machine with Docker desktop 3.0.4, building for
multiple platforms at once will initially fail with the following error: multiple platforms at once will initially fail with the following error:
``` ```console
$ docker buildx build ... --platform=linux/arm64/v8,linux/arm/v7,linux/amd64 $ sudo docker buildx build ... --platform=linux/arm64/v8,linux/arm/v7,linux/amd64
[+] Building 0.0s (0/0) [+] Building 0.0s (0/0)
error: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use") error: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")
``` ```
@ -107,8 +107,8 @@ caveats:
suggests a workaround of building all three then using caching to quickly suggests a workaround of building all three then using caching to quickly
load the one of immediate interest: load the one of immediate interest:
``` ```
$ docker buildx build --platform=linux/arm64/v8,linux/arm/v7,linux/amd64 ... $ sudo docker buildx build --platform=linux/arm64/v8,linux/arm/v7,linux/amd64 ...
$ docker buildx build --load --platform=arm64/v8 ... $ sudo docker buildx build --load --platform=arm64/v8 ...
``` ```
On Linux hosts (as opposed to when using Docker Desktop on macOS/Windows), On Linux hosts (as opposed to when using Docker Desktop on macOS/Windows),
@ -190,7 +190,7 @@ in "Maintenance LTS" or "Active LTS" status: currently v12 or v14.
On recent Ubuntu or Raspbian Linux, the following command will install On recent Ubuntu or Raspbian Linux, the following command will install
most non-Rust dependencies: most non-Rust dependencies:
``` ```console
$ sudo apt-get install \ $ sudo apt-get install \
build-essential \ build-essential \
libavcodec-dev \ libavcodec-dev \
@ -212,7 +212,7 @@ manager](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based
On macOS with [Homebrew](https://brew.sh/) and Xcode installed, try the On macOS with [Homebrew](https://brew.sh/) and Xcode installed, try the
following command: following command:
``` ```console
$ brew install ffmpeg node $ brew install ffmpeg node
``` ```
@ -224,7 +224,7 @@ your Linux distribution's Rust packages, which tend to be too old.
Once prerequisites are installed, you can build the server and find it in Once prerequisites are installed, you can build the server and find it in
`target/release/moonfire-nvr`: `target/release/moonfire-nvr`:
``` ```console
$ cd server $ cd server
$ cargo test $ cargo test
$ cargo build --release $ cargo build --release
@ -233,7 +233,7 @@ $ sudo install -m 755 target/release/moonfire-nvr /usr/local/bin
You can build the UI via `npm` and find it in the `ui/build` directory: You can build the UI via `npm` and find it in the `ui/build` directory:
``` ```console
$ cd ui $ cd ui
$ npm install $ npm install
$ npm run build $ npm run build
@ -246,7 +246,7 @@ $ sudo rsync --recursive --delete --chmod=D755,F644 ui/build/ /usr/local/lib/moo
The author finds it convenient for local development to set up symlinks so that The author finds it convenient for local development to set up symlinks so that
the binaries in the working copy will run via just `nvr`: the binaries in the working copy will run via just `nvr`:
``` ```console
$ sudo mkdir /usr/local/lib/moonfire-nvr $ sudo mkdir /usr/local/lib/moonfire-nvr
$ sudo ln -s `pwd`/ui/build /usr/local/lib/moonfire-nvr/ui $ sudo ln -s `pwd`/ui/build /usr/local/lib/moonfire-nvr/ui
$ sudo mkdir /var/lib/moonfire-nvr $ sudo mkdir /var/lib/moonfire-nvr
@ -308,7 +308,7 @@ Internet](secure.md).
Some handy commands: Some handy commands:
``` ```console
$ sudo systemctl daemon-reload # reload configuration files $ sudo systemctl daemon-reload # reload configuration files
$ sudo systemctl start moonfire-nvr # start the service now $ sudo systemctl start moonfire-nvr # start the service now
$ sudo systemctl stop moonfire-nvr # stop the service now (but don't wait for it finish stopping) $ sudo systemctl stop moonfire-nvr # stop the service now (but don't wait for it finish stopping)

View File

@ -13,7 +13,16 @@ instead want to build Moonfire NVR yourself, see the [Build
instructions](build.md). instructions](build.md).
First, install [Docker](https://www.docker.com/) if you haven't already, First, install [Docker](https://www.docker.com/) if you haven't already,
and verify `docker run --rm hello-world` works. and verify `sudo docker run --rm hello-world` works.
<details>
<summary><tt>sudo</tt> or not?</summary>
If you prefer to save typing by not prefixing all `docker` and `nvr` commands
with `sudo`, see [Docker docs: Manage Docker as a non-root
user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user).
Note `docker` access is equivalent to root access security-wise.
</details>
Next, you'll need to set up your filesystem and the Moonfire NVR user. Next, you'll need to set up your filesystem and the Moonfire NVR user.
@ -30,7 +39,7 @@ Moonfire NVR keeps two kinds of state:
On most Linux systems, you can create the user as follows: On most Linux systems, you can create the user as follows:
``` ```console
$ sudo useradd --user-group --create-home --home /var/lib/moonfire-nvr moonfire-nvr $ sudo useradd --user-group --create-home --home /var/lib/moonfire-nvr moonfire-nvr
``` ```
@ -41,19 +50,44 @@ and managing a long-lived Docker container for its web interface.
As you set up this script, adjust the `tz` variable as appropriate for your As you set up this script, adjust the `tz` variable as appropriate for your
time zone. time zone.
Use your favorite editor to create `/usr/local/bin/nvr`, starting from the
configuration below:
```console
$ sudo nano /usr/local/bin/nvr
(see below for contents)
$ sudo chmod a+rx /usr/local/bin/nvr
``` ```
sudo sh -c 'cat > /usr/local/bin/nvr' <<'EOF'
`/usr/local/bin/nvr`:
```bash
#!/bin/bash -e #!/bin/bash -e
# Set your timezone here.
tz="America/Los_Angeles" tz="America/Los_Angeles"
container_name="moonfire-nvr"
# or eg "scottlamb/moonfire-nvr:v0.6.5" to specify a particular version.
image_name="scottlamb/moonfire-nvr:latest" image_name="scottlamb/moonfire-nvr:latest"
container_name="moonfire-nvr"
common_docker_run_args=( common_docker_run_args=(
--mount=type=bind,source=/var/lib/moonfire-nvr,destination=/var/lib/moonfire-nvr --mount=type=bind,source=/var/lib/moonfire-nvr,destination=/var/lib/moonfire-nvr
# Add additional mount lines here for each sample file directory
# outside of /var/lib/moonfire-nvr, eg:
# --mount=type=bind,source=/media/nvr/sample,destination=/media/nvr/sample
--user="$(id -u moonfire-nvr):$(id -g moonfire-nvr)" --user="$(id -u moonfire-nvr):$(id -g moonfire-nvr)"
# This avoids errors with broken seccomp on Raspberry Pi OS.
--security-opt=seccomp:unconfined --security-opt=seccomp:unconfined
# docker's default log driver won't rotate logs properly, and will throw
# away logs when you destroy and recreate the container. Using journald
# solves these problems.
# https://docs.docker.com/config/containers/logging/configure/
--log-driver=journald --log-driver=journald
--log-opt="tag=moonfire-nvr" --log-opt="tag=moonfire-nvr"
--env=RUST_BACKTRACE=1 --env=RUST_BACKTRACE=1
--env=TZ=":${tz}" --env=TZ=":${tz}"
) )
@ -65,11 +99,20 @@ run)
--detach=true \ --detach=true \
--restart=unless-stopped \ --restart=unless-stopped \
"${common_docker_run_args[@]}" \ "${common_docker_run_args[@]}" \
# This is the simplest way of configuring networking, although
# you can use eg --publish=8080:8080 if you prefer.
--network=host \ --network=host \
--name="${container_name}" \ --name="${container_name}" \
"${image_name}" \ "${image_name}" \
run \ run \
# Add any additional `moonfire-nvr run` arguments here, eg
# "--rtsp-library=ffmpeg" if the default "--rtsp-library=retina"
# isn't working.
--allow-unauthenticated-permissions='view_video: true' \ --allow-unauthenticated-permissions='view_video: true' \
"$@" "$@"
;; ;;
start|stop|logs|rm) start|stop|logs|rm)
@ -88,14 +131,12 @@ pull)
"$@" "$@"
;; ;;
esac esac
EOF
sudo chmod a+rx /usr/local/bin/nvr
``` ```
then try it out by initializing the database: then try it out by initializing the database:
``` ```console
$ nvr init $ sudo nvr init
``` ```
This will create a directory `/var/lib/moonfire-nvr/db` with a SQLite3 database This will create a directory `/var/lib/moonfire-nvr/db` with a SQLite3 database
@ -113,7 +154,7 @@ using UAS, as described there. UAS has been linked to filesystem corruption.
Set up the mount point: Set up the mount point:
``` ```console
$ sudo vim /etc/fstab $ sudo vim /etc/fstab
$ sudo mkdir /media/nvr $ sudo mkdir /media/nvr
$ sudo mount /media/nvr $ sudo mount /media/nvr
@ -126,12 +167,7 @@ In `/etc/fstab`, add a line similar to this:
UUID=23d550bc-0e38-4825-acac-1cac8a7e091f /media/nvr ext4 nofail,noatime,lazytime,data=writeback,journal_async_commit 0 2 UUID=23d550bc-0e38-4825-acac-1cac8a7e091f /media/nvr ext4 nofail,noatime,lazytime,data=writeback,journal_async_commit 0 2
``` ```
You'll have to lookup the correct uuid for your disk. One way to do that is You can look up the correct uuid for your disk via `blkid`.
via the following command:
```
$ ls -l /dev/disk/by-uuid
```
If you use the `nofail` attribute in `/etc/fstab` as described above, your If you use the `nofail` attribute in `/etc/fstab` as described above, your
system will boot successfully even when the hard drive is unavailable (such as system will boot successfully even when the hard drive is unavailable (such as
@ -140,18 +176,14 @@ recovering from problems.
Create the sample directory. Create the sample directory.
``` ```console
sudo mkdir /media/nvr/sample $ sudo mkdir /media/nvr/sample
sudo chown -R moonfire-nvr:moonfire-nvr /media/nvr $ sudo chown -R moonfire-nvr:moonfire-nvr /media/nvr
``` ```
Add a new `--mount` line to your Docker wrapper script `/usr/local/bin/nvr` Add a new `--mount` line to your Docker wrapper script `/usr/local/bin/nvr`
to expose this new volume to the Docker container, directly below the other to expose this new volume to the Docker container, right where a comment
mount lines. It will look similar to this: mentions "Additional mount lines".
```
--mount=type=bind,source=/media/nvr/sample,destination=/media/nvr/sample
```
### Completing configuration through the UI ### Completing configuration through the UI
@ -159,9 +191,18 @@ Once your system is set up, it's time to initialize an empty database
and add the cameras and sample directories. You can do this and add the cameras and sample directories. You can do this
by using the `moonfire-nvr` binary's text-based configuration tool. by using the `moonfire-nvr` binary's text-based configuration tool.
```console
$ sudo nvr config 2>debug-log
``` ```
$ nvr config 2>debug-log
``` <details>
<summary>Did it just return?</summary>
If `nvr config` returns you to the console prompt right away, look in the
`debug-log` file for why. One common reason is that you have Moonfire NVR
running; you'll need to shut it down first. Try `nvr stop` before `nvr config`
and `nvr start` afterward.
</details>
In the user interface, In the user interface,
@ -229,12 +270,12 @@ system](secure.md) first.
This command will start a detached Docker container for the web interface. This command will start a detached Docker container for the web interface.
It will automatically restart when your system does. It will automatically restart when your system does.
``` ```console
$ nvr run $ sudo nvr run
``` ```
You can temporarily disable the service via `nvr stop` and restart it later via You can temporarily disable the service via `nvr stop` and restart it later via
`nvr start`. `nvr start`. You'll need to do this before and after using `nvr config`.
The HTTP interface is accessible on port 8080; if your web browser is running The HTTP interface is accessible on port 8080; if your web browser is running
on the same machine, you can access it at on the same machine, you can access it at

View File

@ -64,14 +64,14 @@ Next ensure Moonfire NVR is not running and does not automatically restart if
the system is rebooted during the upgrade. If you followed the Docker the system is rebooted during the upgrade. If you followed the Docker
instructions, you can do this as follows: instructions, you can do this as follows:
``` ```console
$ nvr stop $ sudo nvr stop
``` ```
Then back up your SQLite database. If you are using the default path, you can Then back up your SQLite database. If you are using the default path, you can
do so as follows: do so as follows:
``` ```console
$ sudo -u moonfire-nvr cp /var/lib/moonfire-nvr/db/db{,.pre-upgrade} $ sudo -u moonfire-nvr cp /var/lib/moonfire-nvr/db/db{,.pre-upgrade}
``` ```
@ -91,9 +91,9 @@ manual for write-ahead logging](https://www.sqlite.org/wal.html):
Run the upgrade procedure using the new software binary. Run the upgrade procedure using the new software binary.
``` ```console
$ nvr pull # updates the docker image to the latest binary $ sudo nvr pull # updates the docker image to the latest binary
$ nvr upgrade # runs the upgrade $ sudo nvr upgrade # runs the upgrade
``` ```
As a rule of thumb, on a Raspberry Pi 4 with a 1 GiB database, an upgrade might As a rule of thumb, on a Raspberry Pi 4 with a 1 GiB database, an upgrade might
@ -102,9 +102,9 @@ take about four minutes for each schema version and for the final vacuum.
Next, you can run the system in read-only mode, although you'll find this only Next, you can run the system in read-only mode, although you'll find this only
works in the "insecure" setup. (Authorization requires writing the database.) works in the "insecure" setup. (Authorization requires writing the database.)
``` ```console
$ nvr rm $ sudo nvr rm
$ nvr run --read-only $ sudo nvr run --read-only
``` ```
Go to the web interface and ensure the system is operating correctly. If Go to the web interface and ensure the system is operating correctly. If
@ -115,10 +115,10 @@ more complicated.
Once you're satisfied, restart the system in read-write mode: Once you're satisfied, restart the system in read-write mode:
``` ```console
$ nvr stop $ sudo nvr stop
$ nvr rm $ sudo nvr rm
$ nvr run $ sudo nvr run
``` ```
Hopefully your system is functioning correctly. If not, there are two options Hopefully your system is functioning correctly. If not, there are two options

View File

@ -190,10 +190,10 @@ effectively allowing them to lie about the client's IP and protocol.
To make this take effect, you'll need to stop the running Docker container, To make this take effect, you'll need to stop the running Docker container,
delete it, and create/run a new one: delete it, and create/run a new one:
``` ```console
$ nvr stop $ sudo nvr stop
$ nvr rm $ sudo nvr rm
$ nvr run $ sudo nvr run
``` ```
## 7. Configure the webserver ## 7. Configure the webserver

View File

@ -106,13 +106,13 @@ Moonfire NVR names a few important thread types as follows:
You can use the following command to teach [`lnav`](http://lnav.org/) Moonfire You can use the following command to teach [`lnav`](http://lnav.org/) Moonfire
NVR's log format: NVR's log format:
``` ```console
$ lnav -i misc/moonfire_log.json $ lnav -i misc/moonfire_log.json
``` ```
`lnav` versions prior to 0.9.0 print a (harmless) warning message on startup: `lnav` versions prior to 0.9.0 print a (harmless) warning message on startup:
``` ```console
$ lnav -i git/moonfire-nvr/misc/moonfire_log.json $ lnav -i git/moonfire-nvr/misc/moonfire_log.json
warning:git/moonfire-nvr/misc/moonfire_log.json:line 2 warning:git/moonfire-nvr/misc/moonfire_log.json:line 2
warning: unexpected path -- warning: unexpected path --
@ -151,7 +151,7 @@ This log message is packed with debugging information:
file `/media/14tb/sample/00000003001c1ba6`. On-disk files are named by file `/media/14tb/sample/00000003001c1ba6`. On-disk files are named by
a fixed eight hexadecimal digits for the stream id and eight hexadecimal a fixed eight hexadecimal digits for the stream id and eight hexadecimal
digits for the recording id. You can convert with `printf`: digits for the recording id. You can convert with `printf`:
``` ```console
$ printf '%08x%08x\n' 3 1842086 $ printf '%08x%08x\n' 3 1842086
00000003001c1ba6 00000003001c1ba6
``` ```
@ -242,8 +242,8 @@ problem in more detail. The simplest solution is to add
If you are using the recommended `/usr/local/bin/nvr` wrapper script, If you are using the recommended `/usr/local/bin/nvr` wrapper script,
add this option to the `common_docker_run_args` section. add this option to the `common_docker_run_args` section.
``` ```console
$ docker run --rm -it moonfire-nvr:latest $ sudo docker run --rm -it moonfire-nvr:latest
clock_gettime failed: EPERM: Operation not permitted clock_gettime failed: EPERM: Operation not permitted
This indicates a broken environment. See the troubleshooting guide. This indicates a broken environment. See the troubleshooting guide.
@ -273,7 +273,7 @@ clean up the excess files. Moonfire NVR will start working again immediately.
If Moonfire NVR's own files are too large, follow this procedure: If Moonfire NVR's own files are too large, follow this procedure:
1. Shut it down via `SIGKILL`: 1. Shut it down via `SIGKILL`:
``` ```console
$ sudo killall -KILL moonfire-nvr $ sudo killall -KILL moonfire-nvr
``` ```
(Be sure to use `-KILL`. It won't shut down properly on `SIGTERM` or `SIGINT` (Be sure to use `-KILL`. It won't shut down properly on `SIGTERM` or `SIGINT`