From c5345c1e11da4a7d6400b4211c7a3871ad7e5709 Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Fri, 24 Aug 2018 20:45:46 -0700 Subject: [PATCH] simplify and fix installation instructions * install.md, install-manual.md, and easy-install.md had a lot of redundancy. Rework them so the common prefix and suffix are in install.md and it's clear when to navigate back and forth. This removes from very stale references to prep.sh and cameras.sql in install-manual.md (which never should have mentioned these scripts anyway). * remove all the SAMPLE_MEDIA_DIR, SAMPLE_FILE_DIR, and SAMPLE_FILE_PATH stuff from the scripts. This was too complicated (one variable will suffice) and inconsistent in terminology (a couple "samples dir" occurrences slipped through review; they should have been "sample file dir"). It also wasn't really useful enough because the procedure for a mount point is manual anyway, and because some installs will have multiple sample file dirs anyway. * in the mount point procedure, fix the paths to be consistent. Also describe the "nofail" and "Requires=" config I have on my machine. * fix some incorrect info about how to use "moonfire-nvr config" and describe "flush_if_sec". --- design/schema.md | 2 +- guide/easy-install.md | 145 ----------------------------- guide/install-manual.md | 122 +++++-------------------- guide/install.md | 177 ++++++++++++++++++------------------ scripts/build.sh | 2 +- scripts/script-functions.sh | 36 +------- 6 files changed, 111 insertions(+), 373 deletions(-) delete mode 100644 guide/easy-install.md diff --git a/design/schema.md b/design/schema.md index 1f40af1..3a20742 100644 --- a/design/schema.md +++ b/design/schema.md @@ -429,7 +429,7 @@ These invariants are updated through the following procedure: `ENOENT. 4. For each stream, `unlink()` all the existing files with recording ids >= `next_recording_id`. -4. `fsync()` the samples directory. +4. `fsync()` the sample file directory. 5. Delete all rows from the `garbage` table. The procedures can be batched: while for a given recording, the steps must be diff --git a/guide/easy-install.md b/guide/easy-install.md deleted file mode 100644 index 9702357..0000000 --- a/guide/easy-install.md +++ /dev/null @@ -1,145 +0,0 @@ -# Installing Moonfire NVR using provided scripts - -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. -You'll start by downloading Moonfire if you have not already done so. - -## 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 command line via git: - - $ git clone https://github.com/scottlamb/moonfire-nvr.git - -## Preparation steps for easy install - -There are a few things to prepare if you want a truly turnkey install, but -they are both optional. - -### Dedicated media directory - -An optional, but strongly suggested, step is to setup a dedicated hard disk -for recording video. -Moonfire works best if the video samples are collected on a hard drive of -sufficient capacity and separate from the root and main file systems. This -is particularly important on Raspberry Pi based systems as the flash based -main file systems have a limited lifetime and are way too small to hold -any significant amount of video. -If a dedicated hard drive is available, set up the mount point (in this -example we'll use /media/nvr/samples): - - $ sudo vim /etc/fstab - $ sudo mount /mount/media/samples - -In the fstab you would add a line similar to this: - - /dev/disk/by-uuid/23d550bc-0e38-4825-acac-1cac8a7e091f /media/nvr ext4 defaults,noatime 0 1 - -You'll have to lookup the correct uuid for your disk. One way to do that is -to issue the following commands: - - $ ls -l /dev/disk/by-uuid - -Locate the device where your disk will be mounted (or is mounted), for example -`/dev/sda1`. Now lookup the filename linked to that from the output of the -`ls` command. This is the uuid you need. - -The setup script (see below) will create the necessary sample file dir on the mounted -hard disk. - - -## 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. - -*WARNING* 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. In the most frequent -scenarios you will probably only change SAMPLE_MEDIA_DIR to point -to your mounted external disk (/media/nvr in the example above). - - NVR_USER=moonfire-nvr - NVR_GROUP=$NVR_USER - NVR_PORT=8080 - NVR_HOME_BASE=/var/lib - DB_NAME=db - DB_DIR=$NVR_HOME/$DB_NAME - SAMPLE_FILE_DIR=sample - SAMPLE_MEDIA_DIR=$NVR_HOME - SERVICE_NAME=moonfire-nvr - SERVICE_DESC="Moonfire NVR" - SERVICE_BIN=/usr/local/bin/$SERVICE_NAME diff --git a/guide/install-manual.md b/guide/install-manual.md index 7f434d3..e8413e1 100644 --- a/guide/install-manual.md +++ b/guide/install-manual.md @@ -1,14 +1,9 @@ -# Installing Moonfire NVR +# Building and installing Moonfire NVR manually -This document describes how to install Moonfire NVR on a Linux system. - -## 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 command line via git: - - $ git clone https://github.com/scottlamb/moonfire-nvr.git +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 @@ -54,34 +49,6 @@ following the instructions at [rustup.rs](https://www.rustup.rs/). Finally, building the UI requires [yarn](https://yarnpkg.com/en/). -You can continue to follow the build/install instructions below for a manual -build and install, or alternatively you can run the prep script called `prep.sh`. - - $ cd moonfire-nvr - $ ./prep.sh - -The script will take the following command line options, should you need them: - -* `-S`: Skip updating and installing dependencies through apt-get. This too can be - useful on repeated builds. - -You can edit variables at the start of the script to influence names and -directories, but defaults should suffice in most cases. For details refer to -the script itself. We will mention just one option, needed when you follow the -suggestion to separate database and samples between flash storage and a hard disk. -If you have the hard disk mounted on, lets say `/media/nvr`, and you want to -store the video samples inside a directory named `samples` there, you would set: - - SAMPLE_FILE_DIR=/media/nvr/samples - -The script will perform all necessary steps to leave you with a fully built, -installed moonfire-nvr binary. The only thing -you'll have to do manually is add your camera configuration(s) to the database. -Alternatively, before running the script, you can create a file named `cameras.sql` -in the same directory as the `prep.sh` script and it will be automatically -included for you. -For instructions, you can skip to "[Camera configuration and hard disk mounting](#camera)". - Once prerequisites are installed, Moonfire NVR can be built as follows: $ yarn @@ -92,74 +59,21 @@ Once prerequisites are installed, Moonfire NVR can be built as follows: $ sudo mkdir /usr/local/lib/moonfire-nvr $ sudo cp -R ui-dist /usr/local/lib/moonfire-nvr/ui -## Further configuration +## Creating the user and database -Moonfire NVR should be run under a dedicated user. It keeps two kinds of -state: - - * a SQLite database, typically <1 GiB. It should be stored on flash if - available. - * the "sample file directory", which holds the actual samples/frames of - H.264 video. This should be quite large and typically is stored on a hard - drive. - -(See [schema.md](schema.md) for more information.) - -Both kinds of state are intended to be accessed only by Moonfire NVR itself. -However, the interface for adding new cameras is not yet written, so you will -have to manually insert cameras with the `sqlite3` command line tool prior to -starting Moonfire NVR. - -Manual commands would look something like this: +You can create Moonfire NVR's dedicated user and SQLite database with the +following commands: $ sudo addgroup --system moonfire-nvr $ sudo adduser --system moonfire-nvr --home /var/lib/moonfire-nvr $ sudo mkdir /var/lib/moonfire-nvr + $ sudo chown moonfire-nvr:moonfire-nvr /var/lib/moonfire-nvr $ sudo -u moonfire-nvr -H mkdir db sample $ sudo -u moonfire-nvr moonfire-nvr init -### Camera configuration and hard drive mounting +## System Service -If a dedicated hard drive is available, set up the mount point: - - $ sudo vim /etc/fstab - $ sudo mount /var/lib/moonfire-nvr/sample - -Once setup is complete, it is time to add camera configurations to the -database. If the daemon is running, you will need to stop it temporarily: - - $ sudo systemctl stop moonfire-nvr - -You can configure the system through a text-based user interface: - - $ sudo -u moonfire-nvr moonfire-nvr config 2>debug-log - -In the user interface, add your cameras under the "Edit cameras" dialog. -There's a "Test" button to verify your settings directly from the dialog. - -After the cameras look correct, go to "Edit retention" to assign disk space to -each camera. Leave a little slack (at least 100 MB per camera) between the total -limit and the filesystem capacity, even if you store nothing else on the disk. -There are several reasons this is needed: - - * The limit currently controls fully-written files only. There will be up - to two minutes of video per camera of additional video. - * The rotation happens after the limit is exceeded, not proactively. - * Moonfire NVR currently doesn't account for the unused space in the final - filesystem block at the end of each file. - * Moonfire NVR doesn't account for the space used for directory listings. - * If a file is open when it is deleted (such as if a HTTP client is - downloading it), it stays around until the file is closed. Moonfire NVR - currently doesn't account for this. - -When finished, start the daemon: - - $ sudo systemctl start moonfire-nvr - -### System Service - -Moonfire NVR can be run as a systemd service. If you used `prep.sh` this has -been done for you. If not, Create +Moonfire NVR can be run as a systemd service. Create `/etc/systemd/system/moonfire-nvr.service`: [Unit] @@ -188,14 +102,20 @@ been done for you. If not, Create Note that the HTTP port currently has no authentication, encryption, or logging; it should not be directly exposed to the Internet. -Complete the installation through `systemctl` commands: +Tell `systemd` to look for the new file: $ sudo systemctl daemon-reload - $ sudo systemctl start moonfire-nvr - $ sudo systemctl status moonfire-nvr - $ sudo systemctl enable moonfire-nvr 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. diff --git a/guide/install.md b/guide/install.md index 23c204c..4968541 100644 --- a/guide/install.md +++ b/guide/install.md @@ -1,34 +1,32 @@ -# Installing Moonfire NVR +# Downloading, installing, and configuring Moonfire NVR -This document describes how to install Moonfire NVR on a Linux system. +This document describes how to download, install, and configure Moonfire NVR +on a Debian-based Linux system (such as Ubuntu or Raspbian). + +(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 command line via git: +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 -## Building from source +## 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 two paths: +from source. To do so, you can follow either of two paths: -* Scripted install: 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. This process is fully - described. Read more in [Easy Installation](easy-install.md) -* Manual build and install. This is explained in detail in these - [instructions](install-manual.md) + * 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). -Regardless of the approach for setup and installation above that you choose, -please read the further configuration instructions below. - -## Further configuration - -Moonfire NVR should be run under a dedicated user. It keeps two kinds of -state: +Moonfire NVR keeps two kinds of state: * a SQLite database, typically <1 GiB. It should be stored on flash if available. @@ -36,32 +34,56 @@ state: H.264 video. These should be quite large and are typically stored on hard drives. -Both states are intended to be accessed by moonfire-nvr only, but can be -changed after building. See below. (See [schema.md](schema.md) for more information.) -The database changes and sample file directory changes require the moonfire-nvr -binary to be built, so can only be done after completing the build. The other -settings and preparations should be done before building. -Manual commands would look something like this: +By now Moonfire NVR's dedicated user and database should have been created for +you. Next you need to create a sample file directory. - $ sudo addgroup --system moonfire-nvr - $ sudo adduser --system moonfire-nvr --home /var/lib/moonfire-nvr - $ sudo mkdir /var/lib/moonfire-nvr - $ sudo -u moonfire-nvr -H mkdir db sample - $ sudo -u moonfire-nvr moonfire-nvr init +## Creating a sample file directory -### Camera configuration and hard drive mounting +### ...on a dedicated hard drive If a dedicated hard drive is available, set up the mount point: $ sudo vim /etc/fstab - $ sudo mount /var/lib/moonfire-nvr/sample + $ sudo mkdir /media/nvr + $ sudo mount /media/nvr + $ sudo mkdir /media/nvr/sample + $ sudo chown moonfire-nvr:moonfire-nvr /media/nvr/sample -Once setup is complete, it is time to add camera configurations to the -database. If the daemon is running, you will need to stop it temporarily: +In the fstab you'd add a line similar to this: - $ sudo systemctl stop moonfire-nvr + /dev/disk/by-uuid/23d550bc-0e38-4825-acac-1cac8a7e091f /media/nvr ext4 defaults,noatime,nofail 0 2 + +You'll have to lookup the correct uuid for your disk. One way to do that is +to issue the following commands: + + $ 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: + + $ sudo vim /etc/systemd/system/moonfire-nvr.service + $ sudo systemctl daemon-reload + +You'll want to add a line like `Requires=media-nvr.mount` to the `[Unit]` +section of the file. + +### ...without a dedicated hard drive + +If you don't have a dedicated hard drive available, simply create a directory +owned by the dedicated user. It's convenient to place it within the +installation's directory (typically `/var/lib/moonfire-nvr`): + + $ sudo -u moonfire-nvr -H mkdir sample + +## Completing configuration through the UI + +Once setup is complete, it is time to add sample file directory and camera +configurations to the database. You can configure the system's database through a text-based user interface: @@ -69,70 +91,45 @@ You can configure the system's database through a text-based user interface: In the user interface, - 1. add your sample file dirs under "Edit cameras and retention" - 2. add cameras under the "Edit cameras and streams" dialog. - There's a "Test" button to verify your settings directly from the dialog. - Be sure to assign each stream you want to capture to a sample file - directory. - 3. Assign disk space to your cameras back in "Edit cameras and retention". + 1. add your sample file dir(s) under "Directories and retention". + 2. add cameras under "Cameras and streams". + + * There's a "Test" button to verify your settings directly from the add/edit + camera dialog. + + * Be sure to assign each stream you want to capture to a sample file + directory and check the "record" box. + + * `flush_if_sec` should typically be about 60. This causes the database to + be flushed when the first instant of a completed recording second is a + minute old. Lower values cause less video to be lost on power loss; + higher values reduce wear on the SSD holding the SQLite database. + 3. Assign disk space to your cameras back in "Directories and retention". Leave a little slack (at least 100 MB per camera) between the total limit and the filesystem capacity, even if you store nothing else on the disk. There are several reasons this is needed: - * The limit currently controls fully-written files only. There will be up - to two minutes of video per camera of additional video. - * The rotation happens after the limit is exceeded, not proactively. - * Moonfire NVR currently doesn't account for the unused space in the final - filesystem block at the end of each file. - * Moonfire NVR doesn't account for the space used for directory listings. - * If a file is open when it is deleted (such as if a HTTP client is - downloading it), it stays around until the file is closed. Moonfire NVR - currently doesn't account for this. + * The limit currently controls fully-written files only. There will be up + to two minutes of video per camera of additional video. + * The rotation happens after the limit is exceeded, not proactively. + * Moonfire NVR currently doesn't account for the unused space in the final + filesystem block at the end of each file. + * Moonfire NVR doesn't account for the space used for directory listings. + * If a file is open when it is deleted (such as if a HTTP client is + downloading it), it stays around until the file is closed. Moonfire NVR + currently doesn't account for this. -When finished, start the daemon: +## Starting it up + +When finished, start the daemon and enable it for following boots: $ sudo systemctl start moonfire-nvr + $ sudo systemctl enable moonfire-nvr -### System Service - -Moonfire NVR can be run as a systemd service. If you used `prep.sh` this has -been done for you. If not, 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 - 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-abnormal - CPUAccounting=true - MemoryAccounting=true - BlockIOAccounting=true - - [Install] - WantedBy=multi-user.target +You can access the HTTP interface on http://localhost:8080/ by default. Note that the HTTP port currently has no authentication, encryption, or logging; it should not be directly exposed to the Internet. -Complete the installation through `systemctl` commands: - - $ sudo systemctl daemon-reload - $ sudo systemctl start moonfire-nvr - $ sudo systemctl status moonfire-nvr - $ sudo systemctl enable moonfire-nvr - -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. +If the system isn't working, see the [Troubleshooting +guide](troubleshooting.md). diff --git a/scripts/build.sh b/scripts/build.sh index 24f94d7..5d5b53d 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -91,7 +91,7 @@ if ! cargo test; then fi if ! cargo build --release; then echo_error -x "Server/release build failed." "Try to run the following manually for more info" \ - "RUST_TEST_THREADS=1 cargo build --release --verbose" '' + "cargo build --release --verbose" '' exit 1 fi diff --git a/scripts/script-functions.sh b/scripts/script-functions.sh index b7b5d61..c9ded0c 100755 --- a/scripts/script-functions.sh +++ b/scripts/script-functions.sh @@ -157,8 +157,6 @@ initEnvironmentVars() NVR_HOME="${NVR_HOME_BASE}/${NVR_USER}" DB_NAME="${DB_NAME:-db}" DB_DIR="${DB_DIR:-$NVR_HOME/${DB_NAME}}" - SAMPLE_FILE_DIR="${SAMPLE_FILE_DIR:-sample}" - SAMPLE_MEDIA_DIR="${SAMPLE_MEDIA_DIR:-$NVR_HOME}" SERVICE_NAME="${SERVICE_NAME:-moonfire-nvr}" SERVICE_DESC="${SERVICE_DESC:-Moonfire NVR}" SERVICE_BIN="${SERVICE_BIN:-/usr/local/bin/moonfire-nvr}" @@ -177,8 +175,6 @@ makePrepConfig() cat >"${MOONFIRE_DIR}/prep.config" <<-EOF_CONFIG NVR_USER=$NVR_USER NVR_PORT=$NVR_PORT - SAMPLE_FILE_DIR=$SAMPLE_FILE_DIR - #SAMPLE_MEDIA_DIR=/mount/media SERVICE_NAME=$SERVICE_NAME SERVICE_DESC="$SERVICE_DESC" EOF_CONFIG @@ -292,38 +288,10 @@ setup_db() # fix_ownership() { - sudo chown -R ${NVR_USER}.${NVR_USER} "$1" + sudo chown -R ${NVR_USER}:${NVR_USER} "$1" echo_info -x "Fix ownership of files in \"$1\"..." } -# Make sure samples directory is ready -# -prep_sample_file_dir() -{ - if [ -z "${SAMPLE_MEDIA_DIR}" ]; then - echo_fatal -x "SAMPLE_MEDIA_DIR variable not configured. Check configuration." - exit 1 - fi - SAMPLE_FILE_PATH="${SAMPLE_MEDIA_DIR}/${SAMPLE_FILE_DIR}" - if [ "${SAMPLE_FILE_PATH##${NVR_HOME}}" != "${SAMPLE_FILE_PATH}" ]; then - # Under the home directory, create if not there - if [ ! -d "${SAMPLE_FILE_PATH}" ]; then - echo_info -x "Created sample file directory: \"$SAMPLE_FILE_PATH\"..." - mkdir_moonfire -p "${SAMPLE_FILE_PATH}" - fi - else - if [ ! -d "${SAMPLE_FILE_PATH}" ]; then - read_lines <<-MSG1 - Samples directory $SAMPLE_FILE_PATH does not exist. - If a mounted file system, make sure /etc/fstab is properly configured, - and file system is mounted and directory created. - MSG1 - echo_fatal -L - fi - fi - fix_ownership "${SAMPLE_FILE_PATH}" -} - # Create user and groups if not there # prep_moonfire_user() @@ -358,7 +326,5 @@ pre_install_prep() { prep_moonfire_user setup_db - prep_sample_file_dir fix_localtime } -