mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-12-08 00:32:26 -05:00
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:
243
guide/build.md
Normal file
243
guide/build.md
Normal 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.
|
||||
Reference in New Issue
Block a user