update docs to recommend new Docker setup

and remove the old scripts, to reduce the supported ways of doing
things.
This commit is contained in:
Scott Lamb 2021-01-21 16:00:38 -08:00
parent 9349a2a164
commit 31801e20c3
13 changed files with 404 additions and 976 deletions

View File

@ -20,7 +20,7 @@ console-based (rather than web-based) configuration UI.
![screenshot](screenshot.png)
This is version 0.1, the initial release. Until version 1.0, there will be no
Moonfire NVR is currently at version 0.6. Until version 1.0, there will be no
compatibility guarantees: configuration and storage formats may change from
version to version. There is an [upgrade procedure](guide/schema.md) but it is
not for the faint of heart.

243
guide/build.md Normal file
View File

@ -0,0 +1,243 @@
# Building Moonfire NVR
This document has notes for software developers on building Moonfire NVR from
source code for development. If you just want to install precompiled
binaries, see the [Docker installation instructions](install.md) instead.
This document doesn't spell out as many details as the installation
instructions. Please ask on Moonfire NVR's [issue
tracker](https://github.com/scottlamb/moonfire-nvr/issues) or
[mailing list](https://groups.google.com/d/forum/moonfire-nvr-users) when
stuck. Please also send pull requests to improve this doc.
## Downloading
See the [github page](https://github.com/scottlamb/moonfire-nvr) (in case
you're not reading this text there already). You can download the
bleeding-edge version from the commandline via git:
```
$ git clone https://github.com/scottlamb/moonfire-nvr.git
```
## Docker builds
This command should prepare a deployment image for your local machine:
```
$ docker buildx build --load --tag=moonfire-nvr -f docker/Dockerfile .
```
If you want to iterate on code changes, doing a full Docker build from
scratch every time will be painfully slow. You will likely find it more
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
Visual Studio Code's Docker plugin.
```
$ docker buildx build --load --tag=moonfire-dev --target=dev
...
$ docker run \
--rm --interactive=true --tty \
--mount=type=bind,source=$(pwd),destination=/var/lib/moonfire-nvr/src \
moonfire-dev
```
The development image overrides cargo's output directory to
`/var/lib/moonfire-nvr/target`. (See `~moonfire-nvr/.buildrc`.) This avoids
using a bind filesystem for build products, which can be slow on macOS. It
also means that if you sometimes compile directly on the host and sometimes
within Docker, they don't trip over each other's target directories.
directories.
You can also cross-compile to a different architecture. Adding a
`--platform=linux/arm64/v8,linux/arm/v7,linux/amd64` argument will compile
Moonfire NVR for all supported platforms. For the `dev` target, this prepares
a build which executes on your local architecture and is capable of building
a binary for your desired target architecture.
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:
```
$ docker buildx build ... --platform=linux/arm64/v8,linux/arm/v7,linux/amd64
[+] 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")
```
Running `docker buildx create --use` once solves this problem, with a couple
caveats:
* you'll need to specify an additional `--load` argument to make builds
available to run locally.
* the `--load` argument only works for one platform at a time. With multiple
platforms, it gives an error like the following:
```
error: failed to solve: rpc error: code = Unknown desc = docker exporter does not currently support exporting manifest lists
```
[A comment on docker/buildx issue
#59](https://github.com/docker/buildx/issues/59#issuecomment-667548900)
suggests a workaround of building all three then using caching to quickly
load the one of immediate interest:
```
$ docker buildx build --platform=linux/arm64/v8,linux/arm/v7,linux/amd64 ...
$ docker buildx build --load --platform=arm64/v8 ...
```
Major caveat: something appears to be making `docker buildx build` frequently
redo builds rather than reusing cached results. The author is very annoyed by
this and would welcome help in understanding this problem...
## Non-Docker setup
You may prefer building without Docker on the host. Moonfire NVR should run
natively on any Unix-like system. It's been tested on Linux and macOS.
(In theory [Windows Subsystem for
Linux](https://docs.microsoft.com/en-us/windows/wsl/about) should also work.
Please speak up if you try it.)
On macOS systems native builds may be noticeably faster than using Docker's
Linux VM and filesystem overlay.
To build the server, you will need the following C libraries installed:
* [ffmpeg](http://ffmpeg.org/) version 2.x or 3.x, including `libavutil`,
`libavcodec` (to inspect H.264 frames), and `libavformat` (to connect to RTSP
servers and write `.mp4` files).
Note ffmpeg library versions older than 55.1.101, along with all versions of
the competing project [libav](http://libav.org), don't support socket
timeouts for RTSP. For reliable reconnections on error, it's strongly
recommended to use ffmpeg library versions >= 55.1.101.
* [SQLite3](https://www.sqlite.org/).
* [`ncursesw`](https://www.gnu.org/software/ncurses/), the UTF-8 version of
the `ncurses` library.
On recent Ubuntu or Raspbian Linux, the following command will install
all non-Rust dependencies:
```
$ sudo apt-get install \
build-essential \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libncurses5-dev \
libncursesw5-dev \
libsqlite3-dev \
pkgconf \
sqlite3 \
tzdata
```
On macOS with [Homebrew](https://brew.sh/) and Xcode installed, try the
following command:
```
$ brew install ffmpeg yarn
```
Next, you need Rust 1.45+ and Cargo. The easiest way to install them is by
following the instructions at [rustup.rs](https://www.rustup.rs/).
Finally, building the UI requires [yarn](https://yarnpkg.com/en/). (On macOS,
the `brew` command above installs it for you. On Linux, follow yarn's guide.)
Once prerequisites are installed, you can build the server and find it in
`target/release/moonfire-nvr`:
```
$ cargo test
$ cargo build --release
```
You can build the UI via `yarn` and find it in the `ui-dist` directory:
```
$ yarn
$ yarn build
```
### Running interactively straight from the working copy
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`:
```
$ sudo mkdir /usr/local/moonfire-nvr
$ sudo ln -s `pwd`/ui-dist /usr/local/moonfire-nvr/ui
$ sudo mkdir /var/lib/moonfire-nvr
$ sudo chown $USER:$USER /var/lib/moonfire-nvr
$ ln -s `pwd`/target/release/moonfire-nvr $HOME/bin/moonfire-nvr
$ ln -s moonfire-nvr $HOME/bin/nvr
$ nvr init
$ nvr config
$ nvr run
```
(Alternatively, you could symlink to `target/debug/moonfire-nvr` and compile
with `cargo build` rather than `cargo build --release`, for a faster build
cycle and slower performance.)
Note this `nvr` is a little different than the `nvr` shell script you create
when following the [install instructions](install.md). With that shell wrapper,
`nvr run` will create and run a detached Docker container with some extra
arguments specified in the script. This `nvr run` will directly run from the
terminal, with no extra arguments, until you abort with Ctrl-C. Likewise,
some of the shell script's subcommands that wrap Docker (`start`, `stop`, and
`logs`) have no parallel with this `nvr`.
## Running as a `systemd` service
If you want to deploy a non-Docker build on Linux, you may want to use
`systemd`. Create `/etc/systemd/system/moonfire-nvr.service`:
```
[Unit]
Description=Moonfire NVR
After=network-online.target
[Service]
ExecStart=/usr/local/bin/moonfire-nvr run \
--db-dir=/var/lib/moonfire-nvr/db \
--http-addr=0.0.0.0:8080 \
--allow-unauthenticated-permissions='view_video: true'
Environment=TZ=:/etc/localtime
Environment=MOONFIRE_FORMAT=google-systemd
Environment=MOONFIRE_LOG=info
Environment=RUST_BACKTRACE=1
Type=simple
User=moonfire-nvr
Nice=-20
Restart=on-failure
CPUAccounting=true
MemoryAccounting=true
BlockIOAccounting=true
[Install]
WantedBy=multi-user.target
```
Note that the arguments used here are insecure. You can change that via
replacing the `--allow-unauthenticated-permissions` argument here as
described in [Securing Moonfire NVR and exposing it to the
Internet](secure.md).
Some handy commands:
```
$ sudo systemctl daemon-reload # reload configuration files
$ 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 status moonfire-nvr # show if the service is running and the last few log lines
$ sudo systemctl enable moonfire-nvr # start the service on boot
$ sudo systemctl disable moonfire-nvr # don't start the service on boot
$ sudo journalctl --unit=moonfire-nvr --since='-5 min' --follow # look at recent logs and await more
```
See the [systemd](http://www.freedesktop.org/wiki/Software/systemd/)
documentation for more information. The [manual
pages](http://www.freedesktop.org/software/systemd/man/) for `systemd.service`
and `systemctl` may be of particular interest.

View File

@ -1,130 +0,0 @@
# Building and installing Moonfire NVR manually
This guide will walk you through building and installing Moonfire NVR manually.
You should have already downloaded the source code as mentioned in
[install.md](install.md), and after completing these instructions you should go
back to that page to complete configuration.
## Building from source
There are no binary packages of Moonfire NVR available yet, so it must be built
from source.
Moonfire NVR is written in the [Rust Programming
Language](https://www.rust-lang.org/en-US/). In the long term, I expect this
will result in a more secure, full-featured, easy-to-install software.
You will need the following C libraries installed:
* [ffmpeg](http://ffmpeg.org/) version 2.x or 3.x, including `libavutil`,
`libavcodec` (to inspect H.264 frames), and `libavformat` (to connect to RTSP
servers and write `.mp4` files).
Note ffmpeg library versions older than 55.1.101, along with all versions of
the competing project [libav](http://libav.org), don't support socket
timeouts for RTSP. For reliable reconnections on error, it's strongly
recommended to use ffmpeg library versions >= 55.1.101.
* [SQLite3](https://www.sqlite.org/).
* [`ncursesw`](https://www.gnu.org/software/ncurses/), the UTF-8 version of
the `ncurses` library.
On recent Ubuntu or Raspbian, the following command will install
all non-Rust dependencies:
```
$ sudo apt-get install \
build-essential \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libncurses5-dev \
libncursesw5-dev \
libsqlite3-dev \
pkgconf \
sqlite3 \
tzdata
```
Next, you need Rust 1.45+ and Cargo. The easiest way to install them is by
following the instructions at [rustup.rs](https://www.rustup.rs/).
Finally, building the UI requires [yarn](https://yarnpkg.com/en/).
Once prerequisites are installed, Moonfire NVR can be built as follows:
```
$ yarn
$ yarn build
$ cargo test
$ cargo build --release
$ sudo install -m 755 target/release/moonfire-nvr /usr/local/bin
$ sudo mkdir /usr/local/lib/moonfire-nvr
$ sudo cp -R ui-dist /usr/local/lib/moonfire-nvr/ui
```
## Creating the user and database
You can create Moonfire NVR's dedicated user and SQLite database with the
following commands:
```
$ sudo useradd --system --user-group --create-home --home /var/lib/moonfire-nvr moonfire-nvr
$ sudo -u moonfire-nvr -H sh -c 'cd && mkdir --mode=700 db'
$ sudo -u moonfire-nvr moonfire-nvr init
```
## System Service
Moonfire NVR can be run as a systemd service. Create
`/etc/systemd/system/moonfire-nvr.service`:
```
[Unit]
Description=Moonfire NVR
After=network-online.target
[Service]
ExecStart=/usr/local/bin/moonfire-nvr run \
--db-dir=/var/lib/moonfire-nvr/db \
--http-addr=0.0.0.0:8080 \
--allow-unauthenticated-permissions='view_video: true'
Environment=TZ=:/etc/localtime
Environment=MOONFIRE_FORMAT=google-systemd
Environment=MOONFIRE_LOG=info
Environment=RUST_BACKTRACE=1
Type=simple
User=moonfire-nvr
Nice=-20
Restart=on-failure
CPUAccounting=true
MemoryAccounting=true
BlockIOAccounting=true
[Install]
WantedBy=multi-user.target
```
Note that the HTTP port currently has no authentication, encryption, or
logging; it should not be directly exposed to the Internet.
Tell `systemd` to look for the new file:
```
$ sudo systemctl daemon-reload
```
See the [systemd](http://www.freedesktop.org/wiki/Software/systemd/)
documentation for more information. The [manual
pages](http://www.freedesktop.org/software/systemd/man/) for `systemd.service`
and `systemctl` may be of particular interest.
Don't enable or start the service just yet; you'll need to do some more
configuration first.
## Completing installation
After the steps on this page, go back to [Downloading, installing, and
configuring Moonfire NVR](install.md) to set up the sample file directory and
configure the system.

View File

@ -1,104 +0,0 @@
# Building and installing Moonfire NVR using provided scripts
This guide will walk you through building and installing Moonfire NVR with the
provided scripts. You should have already downloaded the source code as
mentioned in [install.md](install.md), and after completing these instructions
you should go back to that page to complete configuration.
There are no binary packages of Moonfire NVR available yet, so it must be built
from source. This is made easy using a few scripts that will do the job for you
unless you have very a different operating system. The scripts are written and
tested under ubuntu and raspbian but should not be hard to modify if necessary.
## Setting everything up
Start by executing the setup script:
$ cd moonfire-nvr
$ scripts/setup-ubuntu.sh
If this is the very first time you run this script, a file named `prep.config`
will be created and the script will stop. This file is where you will set
or change variables that describe the Moonfire installation you want. The
initial execution will put default values in this value, but only for the
most commonly changed variables. For a full list of variables, see below.
Once you modify this file (if desired), you run the setup script again. This
time it will use the values in the file and proceed with the setup.
The script will download and install any pre-requisites. Watch carefully for
error messages. It may be you have conflicting installations. If that is the
case you must either resolve those first, or go the manual route.
The script may be given the `-f` option. If you do, you are telling the script
that you do not want any existing installation of ffmpeg to be overwritten with
a newer one. This could be important to you. If you do use it, and the version
you have installed is not compatible with Moonfire, you will be told through
a message. If you have no ffmpeg installed, the option is effectively ignored
and the necessary version of ffmpeg will be installed.
The setup script should only need to be run once (after `prep.config` has been
created), although if you do a re-install of Moonfire, in particular a much
newer version, it is a good idea to run it again as requirements and pre-requisites
may have changed. Running the script multiple times should not have any negative effects.
*Note:* It is quite possible that during the running of the setup script,
in particular during the building of libavutil you will see several compiler
warnings. This, while undesirable, is a direct result of the original
developers not cleaning up the cause(s) of these warnings. They are, however,
just warnings and will not affect correct functioning of Moonfire.
Once the setup is complete, two steps remain: building and then installing.
There is a script for each of these scenarios, but since generally you would
want to install after a succesul build, the build script automatically invokes
the install script, unless specifically told not to.
## Building
The build script is involved like this:
$ scripts/build.sh
This script will perform all steps necessary to build a complete Moonfire
setup. If there are no build errors, this script will then automatically
invoke the install script (see below).
There are two options you may pass to this script. The first is `-B` which
means "build only". In other words, this will stop the automatic invocation
of the install script. The other option available is `-t` and causes the
script to ignore the results of any tests. In other words, even if tests
fail, the build phase will be considered successful. This can occasionally
be useful if you are doing development, and have temporarily broken one
or more test, but want to proceed anyway.
## Installing
The install step is performed by the script that can be manually invoked
like this:
$ scripts/install.sh
This script will copy various files resulting from the build to the correct
locations. It will also create a "service configuration" for systemctl that
can be used to control Moonfire. This service configuration can be prevented
by using the `-s` option to this script. It will also prevent the automatic
start of this configuration.
## Configuration variables
Although not all listed in the default `prep.config` file, these are the
available configuration variable and their defaults.
NVR_USER=moonfire-nvr
NVR_PORT=8080
NVR_HOME_BASE=/var/lib
DB_NAME=db
DB_DIR=$NVR_HOME/$DB_NAME
SERVICE_NAME=moonfire-nvr
SERVICE_DESC="Moonfire NVR"
SERVICE_BIN=/usr/local/bin/$SERVICE_NAME
## Completing installation
After the steps on this page, go back to [Downloading, installing, and
configuring Moonfire NVR](install.md) to set up the sample file directory and
configure the system.

View File

@ -1,47 +1,109 @@
# Downloading, installing, and configuring Moonfire NVR
# Downloading, installing, and configuring Moonfire NVR with Docker
This document describes how to download, install, and configure Moonfire NVR
on a Debian-based Linux system (such as Ubuntu or Raspbian).
via the prebuilt Docker images available for x86-64, arm64, and arm. If you
instead want to build Moonfire NVR yourself, see the [Build
instructions](build.md).
(In principle, Moonfire NVR supports any POSIX-compliant system, and the main
author uses macOS for development, but the documentation and scripts are
intended for Linux.)
## Downloading
See the [github page](https://github.com/scottlamb/moonfire-nvr) (in case
you're not reading this text there already). You can download the
bleeding-edge version from the commandline via git:
First, install [Docker](https://www.docker.com/) if you haven't already,
and verify you can run the container.
```
$ git clone https://github.com/scottlamb/moonfire-nvr.git
$ docker run --rm -it scottlamb/moonfire-nvr:latest
moonfire-nvr 0.6.0
security camera network video recorder
USAGE:
moonfire-nvr <SUBCOMMAND>
...
```
## Building and installing from source
There are no binary packages of Moonfire NVR available yet, so it must be built
from source. To do so, you can follow either of two paths:
* Scripted: You will run some shell scripts (after preparing one or two files,
and will be completely done. This is by far the easiest option, in
particular for first time builders/installers. Read more in [Scripted
Installation](install-scripted.md).
* Manual: see [instructions](install-manual.md).
Next, you'll need to set up your filesystem and the Monfire NVR user.
Moonfire NVR keeps two kinds of state:
* a SQLite database, typically <1 GiB. It should be stored on flash if
available.
* the "sample file directories", which hold the actual samples/frames of
* a SQLite database, typically <1 GiB. It should be stored on flash if
available. In most cases your root filesystem is on flash, so the
default location of `/var/lib/moonfire-nvr/db` will be fine.
* the "sample file directories", which hold the actual samples/frames of
H.264 video. These should be quite large and are typically stored on hard
drives.
drives. More below.
(See [schema.md](schema.md) for more information.)
By now Moonfire NVR's dedicated user and database should have been created for
you. Next you need to create a sample file directory.
On most Linux systems, you can create the user as follows:
## Dedicated hard drive seutp
```
$ sudo useradd --user-group --create-home --home /var/lib/moonfire-nvr moonfire-nvr
```
and create a script called `nvr` to run Moonfire NVR as the intended host user.
This script supports running Moonfire NVR's various administrative commands interactively
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
time zone.
```
sudo sh -c 'cat > /usr/local/bin/nvr' <<EOF
#!/bin/bash -e
tz=America/Los_Angeles
container_name=moonfire-nvr
image_name=scottlamb/moonfire-nvr:latest
common_docker_run_args=(
--mount=type=bind,source=/etc/localtime,destination=/etc/localtime
--mount=type=bind,source=/var/lib/moonfire-nvr,destination=/var/lib/moonfire-nvr
--user="$(id -u moonfire-nvr):$(id -g moonfire-nvr)"
--env=RUST_BACKTRACE=1
--env=TZ=:/etc/localtime
)
case "$1" in
run)
shift
exec docker run \
--detach=true \
--restart=on-failure \
"${common_docker_run_args[@]}" \
--publish=8080:8080 \
--name="${container_name}" \
"${image_name}" \
run \
--allow-unauthenticated-permissions='view_video: true' \
"$@"
;;
start|stop|logs|rm)
exec docker "$@" "${container_name}"
;;
pull)
exec docker pull "${image_name}"
;;
*)
exec docker run \
--interactive=true \
--tty \
--rm \
"${common_docker_run_args[@]}" \
"${image_name}" \
"$@"
;;
esac
EOF
sudo chmod a+rx /usr/local/bin/nvr
```
then try it out by initializing the database:
```
$ nvr init
```
This will create a directory `/var/lib/moonfire-nvr/db` with a SQLite3 database
within it.
## Dedicated hard drive setup
If a dedicated hard drive is available, set up the mount point:
@ -67,38 +129,32 @@ $ ls -l /dev/disk/by-uuid
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
when your external USB storage is unmounted). This is convenient, but you
likely want to ensure the `moonfire-nvr` service only starts when the mounting
is successful. Edit the systemd configuration to do so:
when your external USB storage is unmounted). This can be helpful when
recovering from problems.
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
mount lines. It will look similar to this:
```
$ sudo vim /etc/systemd/system/moonfire-nvr.service
$ sudo systemctl daemon-reload
```
You'll want to add a line similar to the following to the `[Unit]` section of
the file:
```
RequiresMountsFor=/media/nvr
--mount=type=bind,source=/media/nvr/sample,destination=/media/nvr/sample
```
## Completing configuration through the UI
Once your system is set up, it's time to initialize an empty database,
and add the cameras and sample directories to moonfire. You can do this
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
by using the `moonfire-nvr` binary's text-based configuration tool.
```
$ sudo -u moonfire-nvr moonfire-nvr init # Initialize empty db
$ sudo -u moonfire-nvr moonfire-nvr config 2>debug-log # Configure cameras and storage
$ nvr config 2>debug-log
```
In the user interface,
1. add your sample file dir(s) under "Directories and retention".
If you used a dedicated hard drive, use the directory you precreated
(`/media/surveillance/sample`). Otherwise, try
(eg `/media/nvr/sample`). Otherwise, try
`/var/lib/moonfire-nvr/sample`. Moonfire NVR will create the directory as
long as it has the required permissions on the parent directory.
@ -154,14 +210,16 @@ out, particularly if the machine it's running on is behind a home router's
firewall. You might not; in that case read through [secure the
system](secure.md) first.
The following commands will start Moonfire NVR and enable it for following
boots, respectively:
This command will start a detached Docker container for the web interface.
It will automatically restart when your system does.
```
$ sudo systemctl start moonfire-nvr
$ sudo systemctl enable moonfire-nvr
$ nvr run
```
You can temporarily disable the service via `nvr stop` and restart it later via
`nvr start`.
The HTTP interface is accessible on port 8080; if your web browser is running
on the same machine, you can access it at
[http://localhost:8080/](http://localhost:8080/).

View File

@ -53,16 +53,10 @@ SQLite database:
no longer in the dangerous mode.
Next ensure Moonfire NVR is not running and does not automatically restart if
the system is rebooted during the upgrade. If you are using systemd with the
service name `moonfire-nvr`, you can do this as follows:
the system is rebooted during the upgrade. If you followed the Docker
instructions, you can do this as follows:
$ sudo systemctl stop moonfire-nvr
$ sudo systemctl disable moonfire-nvr
The service takes a moment to shut down; wait until the following command
reports that it is not running:
$ sudo systemctl status moonfire-nvr
$ nvr stop
Then back up your SQLite database. If you are using the default path, you can
do so as follows:
@ -83,27 +77,34 @@ manual for write-ahead logging](https://www.sqlite.org/wal.html):
> 3.11.0 (2016-02-15), WAL mode works as efficiently with large transactions
> as does rollback mode.
Run the upgrade procedure using the new software binary (here referred to as
`new-moonfire-nvr`; if you are installing from source, you may find it as
`target/release/moonfire-nvr`).
Run the upgrade procedure using the new software binary.
$ sudo -u moonfire-nvr new-moonfire-nvr upgrade
```
$ nvr pull # updates the docker image to the latest binary
$ nvr upgrade # runs the upgrade
```
Then run the system in read-only mode to verify correct operation:
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.)
$ sudo -u moonfire-nvr new-moonfire-nvr run --read-only
```
$ nvr rm
$ nvr run --read-only
```
Go to the web interface and ensure the system is operating correctly. If
you detect a problem now, you can copy the old database back over the new one.
If you detect a problem after enabling read-write operation, a restore will be
you detect a problem now, you can copy the old database back over the new one
and edit your `nvr` script to use the corresponding older Docker image. If
you detect a problem after enabling read-write operation, a restore will be
more complicated.
Then install the new software to the path expected by your systemd
configuration and start it up:
Once you're satisfied, restart the system in read-write mode:
$ sudo install -m 755 new-moonfire-nvr /usr/local/bin/moonfire-nvr
$ sudo systemctl enable moonfire-nvr
$ sudo systemctl start moonfire-nvr
```
$ nvr stop
$ nvr rm
$ nvr run
```
Hopefully your system is functioning correctly. If not, there are two options
for restore; neither are easy:
@ -120,9 +121,7 @@ for restore; neither are easy:
* undo the changes by hand. There's no documentation on this; you'll need
to read the code and come up with a reverse transformation.
Once you're confident of correct operation, delete the unneeded backup:
$ sudo systemctl rm /var/lib/moonfire-nvr/db/db.pre-upgrade
The `nvr check` command will show you what problems exist on your system.
### Unversioned to version 0

View File

@ -149,16 +149,20 @@ your browser. See [How to secure Nginx with Let's Encrypt on Ubuntu
## 6. Reconfigure Moonfire NVR
In your `/etc/systemd/system/moonfire-nvr.service` file, look for these lines:
If you follow the recommended Docker setup, your `/usr/local/bin/nvr` script
will contain this line:
```
ExecStart=/usr/local/bin/moonfire-nvr run \
--db-dir=/var/lib/moonfire-nvr/db \
--http-addr=0.0.0.0:8080 \
--allow-unauthenticated-permissions='view_video: true'
```
Replace the last line with `--trust-forward-hdrs`. This change has two effects:
Replace it with the following:
```
--trust-forward-hdrs
```
This change has two effects:
* No `--allow-unauthenticated-permissions` means that web users must
authenticate.
@ -167,15 +171,17 @@ Replace the last line with `--trust-forward-hdrs`. This change has two effects:
in the next section.
If the webserver is running on the same machine as Moonfire NVR, you might
also change `0.0.0.0:8080` to `127.0.0.1:8080`, which prevents other machines
on the network from impersonating the proxy, effectively allowing them to lie
about the client's IP and protocol.
also change `--publish=8080:8080` to `--publish=127.0.0.1:8080:8080`, which
prevents other machines on the network from impersonating the proxy,
effectively allowing them to lie about the client's IP and protocol.
Run these commands to make the configuration take effect:
To make this take effect, you'll need to stop the running Docker container,
delete it, and create/run a new one:
```
$ sudo systemctl daemon-reload
$ sudo systemctl restart moonfire-nvr
$ nvr stop
$ nvr rm
$ nvr run
```
## 7. Configure the webserver

View File

@ -4,9 +4,12 @@
While Moonfire NVR is running, logs will be written to stderr.
* When running `moonfire-nvr config`, you typically should redirect stderr
* When running the configuration UI, you typically should redirect stderr
to a text file to avoid poor interaction between the interactive stdout
output and the logging.
output and the logging. If you use the recommended
`nvr config 2>debug-log` command, output will be in the `debug-log` file.
* When running detached through Docker, Docker saves the logs for you.
Try `nvr logs` or `docker logs moonfire-nvr`.
* When running through systemd, stderr will be redirected to the journal.
Try `sudo journalctl --unit moonfire-nvr` to view the logs. You also
likely want to set `MOONFIRE_FORMAT=google-systemd` to format logs as
@ -25,6 +28,8 @@ Logging options are controlled by environmental variables:
[glog](https://github.com/google/glog) package) and `google-systemd` (a
variation for better systemd compatibility).
If you use Docker, set these via Docker's `--env` argument.
## Problems
### `Error: pts not monotonically increasing; got 26615520 then 26539470`
@ -39,11 +44,5 @@ to disable B frames in the meantime.
### `moonfire-nvr config` displays garbage
This happens if your machine is configured to a non-UTF-8 locale, due to
gyscos/Cursive#13. As a workaround, type `export LC_ALL=en_US.UTF-8` prior to
running `moonfire-nvr config`.
### Logging in is very very slow
Ensure you're using a build compiled with the `--release` flag. See
[libpasta/libpasta#9](https://github.com/libpasta/libpasta/issues/9) for more
background.
gyscos/Cursive#13. As a workaround, try setting the environment variable
`LC_ALL=C.UTF-8`. This should automatically be set with the Docker container.

View File

@ -1,111 +0,0 @@
#!/bin/bash
#
# This file is part of Moonfire NVR, a security camera network video recorder.
# Copyright (C) 2016-17 The Moonfire NVR Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the
# OpenSSL library under certain conditions as described in each
# individual source file, and distribute linked combinations including
# the two.
#
# You must obey the GNU General Public License in all respects for all
# of the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the
# file(s), but you are not obligated to do so. If you do not wish to do
# so, delete this exception statement from your version. If you delete
# this exception statement from all source files in the program, then
# also delete it here.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
. `dirname ${BASH_SOURCE[0]}`/script-functions.sh
initEnvironmentVars
# Process command line options
#
while getopts ":Bt" opt; do
case $opt in
B) BUILD_ONLY=1
;;
t) IGNORE_TESTS=1
;;
:)
echo_fatal -x "Option -$OPTARG requires an argument."
;;
\?)
echo_fatal "Invalid option: -$OPTARG"
;;
esac
done
# Setup cargo if files are present
#
initCargo
# Check environment
#
rv=$(getVersion rustc 0.0)
if ! versionAtLeast "$rv" "$RUSTC_MIN_VERSION"; then
echo_fatal -x "rustc not present or version less than $RUSTC_MIN_VERSION"
fi
cv=$(getVersion cargo 0.0)
if ! versionAtLeast "$cv" "$CARGO_MIN_VERSION"; then
echo_fatal -x "cargo not present or version less than $CARGO_MIN_VERSION"
fi
yv=$(getVersion yarn 0.0)
if ! versionAtLeast "$yv" "$YARN_MIN_VERSION"; then
echo_fatal -x "yarn not present or version less than $YARN_MIN_VERSION"
fi
# Building main server component
#
if [ "${FORCE_CLEAN:-0}" -eq 1 ]; then
echo_info -x "Forcing clean server build..."
cargo clean
fi
echo_info -x "Building test version..."
if ! cargo test; then
echo_error -x "test failed." "Try to run the following manually for more info" \
"RUST_TEST_THREADS=1 cargo test --verbose" ''
if [ "${IGNORE_TESTS:-0}" -ne 1 ]; then
exit 1
fi
fi
if ! cargo build --release; then
echo_error -x "Server/release build failed." "Try to run the following manually for more info" \
"cargo build --release --verbose" ''
exit 1
fi
# Building UI components
#
echo_info -x "Building UI components..."
if ! yarn build; then
echo_fatal -x "UI build failed." "yarn build"
fi
# Stop if build only is desired
#
if [ "${BUILD_ONLY:-0}" != 0 ]; then
echo_info -x "Build (only) complete, exiting"
exit 0
fi
. `dirname ${BASH_SOURCE[0]}`/install.sh

View File

@ -1,3 +0,0 @@
#!/bin/sh
#
rm -fr node_modules

View File

@ -1,126 +0,0 @@
#!/bin/bash
#
# This file is part of Moonfire NVR, a security camera network video recorder.
# Copyright (C) 2016-17 The Moonfire NVR Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the
# OpenSSL library under certain conditions as described in each
# individual source file, and distribute linked combinations including
# the two.
#
# You must obey the GNU General Public License in all respects for all
# of the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the
# file(s), but you are not obligated to do so. If you do not wish to do
# so, delete this exception statement from your version. If you delete
# this exception statement from all source files in the program, then
# also delete it here.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
. `dirname ${BASH_SOURCE[0]}`/script-functions.sh
# Determine directory path of this script
#
initEnvironmentVars
# Process command line options
#
while getopts ":s" opt; do
case $opt in
s) NO_SERVICE=1
;;
:)
echo_fatal "Option -$OPTARG requires an argument."
;;
\?)
echo_fatal "Invalid option: -$OPTARG"
;;
esac
done
sudo_warn
sudo install -m 755 target/release/moonfire-nvr ${SERVICE_BIN}
if [ -x "${SERVICE_BIN}" ]; then
echo_info -x "Server Binary installed..."
else
echo_info -x "Server build failed to install..."
exit 1
fi
if [ ! -d "${LIB_DIR}" ]; then
sudo mkdir "${LIB_DIR}"
fi
if [ -d "ui-dist" ]; then
sudo mkdir -p "${LIB_DIR}/ui"
sudo cp -R ui-dist/. "${LIB_DIR}/ui/"
echo_info -x "Server UI installed..."
else
echo_fatal -x "Server UI failed to build or install..."
fi
if [ "${NO_SERVICE:-0}" != 0 ]; then
echo_info -x "Not configuring systemctl service. Done"
exit 0
fi
# Make sure user was created
#
if ! userExists "${NVR_USER}"; then
echo_fatal -x "NVR_USER=${NVR_USER} was not created. Do so manually or run the setup script."
fi
pre_install_prep
# Prepare service files for socket when using priviliged port
#
SOCKET_SERVICE_PATH="/etc/systemd/system/${SERVICE_NAME}.socket"
if [ $NVR_PORT -lt 1024 ]; then
echo_fatal -x "NVR_PORT ($NVR_PORT) < 1024: priviliged ports not supported"
fi
# Prepare service files for moonfire
#
SERVICE_PATH="/etc/systemd/system/${SERVICE_NAME}.service"
sudo sh -c "cat > ${SERVICE_PATH}" <<NVR_EOF
[Unit]
Description=${SERVICE_DESC}
After=network-online.target
[Service]
ExecStart=${SERVICE_BIN} run \\
--db-dir=${DB_DIR} \\
--ui-dir=${LIB_DIR}/ui \\
--http-addr=0.0.0.0:${NVR_PORT} \\
--allow-unauthenticated-permissions='view_video: true'
Environment=TZ=:/etc/localtime
Environment=MOONFIRE_FORMAT=google-systemd
Environment=MOONFIRE_LOG=info
Environment=RUST_BACKTRACE=1
Type=simple
User=${NVR_USER}
Nice=-20
Restart=on-failure
CPUAccounting=true
MemoryAccounting=true
BlockIOAccounting=true
[Install]
WantedBy=multi-user.target
NVR_EOF
sudo systemctl daemon-reload

View File

@ -1,263 +0,0 @@
#
# This file is part of Moonfire NVR, a security camera network video recorder.
# Copyright (C) 2016-2017 The Moonfire NVR Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the
# OpenSSL library under certain conditions as described in each
# individual source file, and distribute linked combinations including
# the two.
#
# You must obey the GNU General Public License in all respects for all
# of the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the
# file(s), but you are not obligated to do so. If you do not wish to do
# so, delete this exception statement from your version. If you delete
# this exception statement from all source files in the program, then
# also delete it here.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
if [ -z "$BASH_VERSION" ]; then
echo "Script must run using bash (/bin/bash), not dash (/bin/sh)."
exit 1
fi
# Useful constants
#
NODE_MIN_VERSION="10"
YARN_MIN_VERSION="1.0"
CARGO_MIN_VERSION="0.2"
RUSTC_MIN_VERSION="1.45"
normalizeDirPath()
{
echo "$( cd -P "$1" && pwd )"
}
resolvePath()
{
local d="$1"
while [ -h "$d" ]; do # resolve $d until file no longer a symlink
DIR="$( cd -P "$( dirname "$d" )" && pwd )"
d="$(readlink "$d")"
# if $d was rel symlink, resolve relative to path of symlink
[[ "$d" != /* ]] && ="$DIR/$d"
done
echo "$d"
}
functionsInit()
{
local p="$(resolvePath "${BASH_SOURCE[0]}")"
MOONFIRE_DIR="$(normalizeDirPath "`dirname "${p}"`/..")"
}
read_lines()
{
LINES_READ=()
while read -r line; do
LINES_READ+=("$line")
done
}
catPrefix()
{
sed -e "s/^/$2/" < "$1"
}
echo_multi()
{
local prefix=''
local plus=''
while [[ $# -gt 0 ]]; do
case "$1" in
# Define a prefix for each line
-p) shift; prefix="$1"; shift ;;
# Provide extra empty line at end
-x) shift; plus=1 ;;
# Insert contents of LINES_READ here
# Only works as leading option
-L) shift; set -- "${LINES_READ[@]}" "$@" ;;
# Stop processing options
-) shift; break ;;
# Non option break out
*) break ;;
esac
done
local A=("$@")
for l in "${A[@]/#/$prefix}"; do
echo "$l"
done
[ -n "$plus" ] && echo
}
echo_stderr()
{
echo_multi "$@" 1>&2
}
echo_info()
{
echo_multi -x -p '>>> ' "$@"
}
echo_warn()
{
echo_multi -p 'WARNING: ' "$@" 1>&2
}
echo_error()
{
echo_multi -p 'ERROR: ' "$@" 1>&2
}
echo_fatal()
{
echo_error "$@"
exit 1;
}
# Read possible user config and then compute all derived environment
# variables used by the script(s).
#
initEnvironmentVars()
{
test -z "${MOONFIRE_DIR}" && functionsInit
if [ -r "${MOONFIRE_DIR}/prep.config" ]; then
. "${MOONFIRE_DIR}/prep.config"
fi
NVR_USER="${NVR_USER:-moonfire-nvr}"
NVR_PORT="${NVR_PORT:-8080}"
NVR_HOME_BASE="${NVR_HOME_BASE:-/var/lib}"
NVR_HOME="${NVR_HOME_BASE}/${NVR_USER}"
DB_NAME="${DB_NAME:-db}"
DB_DIR="${DB_DIR:-$NVR_HOME/${DB_NAME}}"
SERVICE_NAME="${SERVICE_NAME:-moonfire-nvr}"
SERVICE_DESC="${SERVICE_DESC:-Moonfire NVR}"
SERVICE_BIN="${SERVICE_BIN:-/usr/local/bin/moonfire-nvr}"
LIB_DIR="${UI_DIR:-/usr/local/lib/moonfire-nvr}"
}
# Create file with confguration variables that are user changeable.
# Not all variables are included here, only the likely ones to be
# modified.
# If the file already exists, it will not be modified
#
makePrepConfig()
{
test -z "${MOONFIRE_DIR}" && functionsInit
if [ ! -f "${MOONFIRE_DIR}/prep.config" ]; then
cat >"${MOONFIRE_DIR}/prep.config" <<-EOF_CONFIG
NVR_USER=$NVR_USER
NVR_PORT=$NVR_PORT
SERVICE_NAME=$SERVICE_NAME
SERVICE_DESC="$SERVICE_DESC"
EOF_CONFIG
echo_info -x "File prep.config newly created. Inspect and change as necessary." \
"When done, re-run this setup script. Currently it contains:"
catPrefix "${MOONFIRE_DIR}/prep.config" " "
echo_info -x
exit 0
else
echo_info -x "Setting up with variables:"
catPrefix "${MOONFIRE_DIR}/prep.config" " "
echo_info -x
fi
}
# Extract version data from stdin, possibly grepping first against
# single argument.
#
extractVersion()
{
local pattern="$1"
if [ -n "${pattern}" ]; then
grep "$pattern" | sed -e 's/[^0-9.]*\([0-9. ]*\).*/\1/' | tr -d ' '
else
sed -e 's/[^0-9.]*\([0-9. ]*\).*/\1/' | tr -d ' '
fi
}
getAVersion()
{
local v=`$1 $2 2>/dev/null | extractVersion`
if [ "X${v}" = "X" ]; then echo "$3"; else echo "${v}"; fi
}
getVersion()
{
getAVersion $1 --version $2
}
getClassicVersion()
{
getAVersion $1 -version $2
}
versionAtLeast()
{
v1=(${1//./ } 0 0 0); v1=("${v1[@]:0:3}")
v2=(${2//./ } 0 0 0); v2=("${v2[@]:0:3}")
for i in 0 1 2; do
if [ "${v1[$i]}" -gt "${v2[$i]}" ]; then return 0; fi
if [ "${v1[$i]}" -lt "${v2[$i]}" ]; then return 1; fi
done
return 0
}
initCargo()
{
if [ -r ~/.cargo/env ]; then
source ~/.cargo/env
fi
}
userExists()
{
return $(id -u "$1" >/dev/null 2>&1)
}
sudo_warn()
{
echo_warn -x -p '!!!!! ' \
'------------------------------------------------------------------------------' \
'During this script you may be asked to input your root password' \
'This is for the purpose of using the sudo command and is necessary to complete' \
'the script successfully.' \
'------------------------------------------------------------------------------'
}
# Create user, group, and database directory if not there
#
prep_moonfire_user()
{
echo_info -x "Create user/group and directories we need..."
if ! userExists "${NVR_USER}"; then
sudo useradd --system ${NVR_USER} --user-group --create-home --home-dir "${NVR_HOME}"
fi
sudo -u ${NVR_USER} -H sh -c 'cd && test -d db || mkdir --mode=700 db'
}
pre_install_prep()
{
prep_moonfire_user
}

View File

@ -1,140 +0,0 @@
#!/bin/bash
#
# This file is part of Moonfire NVR, a security camera network video recorder.
# Copyright (C) 2016-2017 The Moonfire NVR Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the
# OpenSSL library under certain conditions as described in each
# individual source file, and distribute linked combinations including
# the two.
#
# You must obey the GNU General Public License in all respects for all
# of the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the
# file(s), but you are not obligated to do so. If you do not wish to do
# so, delete this exception statement from your version. If you delete
# this exception statement from all source files in the program, then
# also delete it here.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
. `dirname ${BASH_SOURCE[0]}`/script-functions.sh
initEnvironmentVars
makePrepConfig
export DEBIAN_FRONTEND=noninteractive
sudo_warn
# Setup all apt packages we need
#
echo_info -x 'Preparing and downloading packages we need...'
PKGS="build-essential \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libncurses-dev \
libncursesw-dev \
libsqlite3-dev \
pkgconf \
sqlite3 \
tzdata"
# Add yarn before NodeSource so it can all go in one update
#
yv=$(getVersion yarn "NA")
if [ ${yv} = "NA" ]; then
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg |\
sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" |\
sudo tee /etc/apt/sources.list.d/yarn.list
PKGS="$PKGS yarn"
fi
# Check for minimum node version
#
nv=$(getVersion node 0)
if ! versionAtLeast "$nv" "$NODE_MIN_VERSION"; then
# Nodesource will also make sure we have apt-transport-https
# and will run apt-get-update when done
#
curl -sL https://deb.nodesource.com/setup_${NODE_MIN_VERSION}.x |
sudo -E bash -
PKGS="$PKGS nodejs"
DO_UPDATE=0
else
PKGS="$PKGS apt-transport-https"
fi
# Run apt-get update if still necessary
#
if [ ${DO_UPDATE:-1} ]; then sudo apt-get update -y; fi
# Install necessary packages
#
sudo apt-get install -y $PKGS
sudo apt-get autoremove -y
echo_info -x
# If cargo appears installed, initialize for using it so rustc can be found
#
initCargo
# Make sure we have rust and cargo
rv=$(getVersion rustc 0.0)
if ! versionAtLeast "$rv" "$RUSTC_MIN_VERSION"; then
echo_info -x "Installing latest rust and cargo..."
curl https://sh.rustup.rs -sSf | sh -s - -y
initCargo
fi
cv=$(getVersion cargo "NA")
if [ ${cv} = "NA" ]; then
echo_fatal -x "Cargo is not (properly) installed, but rust is." \
"Suggest you install the latest rustup, or manually install cargo."
"Install using: curl https://sh.rustup.rs -sSf | sh -s -y"
fi
# Now make sure we have dev environment and tools for the UI portion
#
echo_info -x "Installing all dependencies with yarn..."
yarn install
echo_info -x
finish()
{
if [ -z "${OLDDIR}" ]; then
cd "${OLDDIR}"
fi
}
trap finish EXIT
# Rest of prep
#
pre_install_prep
read_lines <<-'INSTRUCTIONS'
Unless there are errors above, everything you need should have been installed
and you are now ready to build, install, and then use moonfire.
Build by executing the script: scripts/build.sh
Install by executing the script: scripts/install.sh (run automatically by build
step).
INSTRUCTIONS
echo_info -x -p ' ' -L