Commit Graph

60 Commits

Author SHA1 Message Date
Scott Lamb 4b397670a4 revamp webpack config
* simplify it. Go from six checked-in config files + one local one to
  three checked-in configs + commandline options. I find it less
  confusing to have the options plumbed through fewer layers.

* support developing against a https production server, as described in
  guide/developing-ui.md.

* fix the source map. The sourceMap parameter in prod.config.js as far
  as I can tell evaluated to false when run with production config, and
  anyway UglifyJS seems to be incompatible with the specified
  cheap-module-source-map. Use source-map instead.
2020-03-01 19:26:45 -08:00
Scott Lamb 92266612b5 switch to websocket for live stream (#59)
The multipart stream / hanging GET approach worked in a prototype for a
single stream, but Chrome has a per-host limit of six connections. If I
try streaming all my cameras at once, I hit that limit. I can't open all
the streams, much less additional connections to load init segments and
such. Websockets apparently has a much higher limit of 256.
2020-02-29 14:39:16 -08:00
Scott Lamb 8af7bca6c2 upgrade to hyper 0.13 ecosystem
This doesn't take much advantage of async fns so far. For example, the
with_{form,json}_body functions are still designed to be used with
future combinators when it'd be more natural to call them from async
fns now. But it's a start.

Similarly, this still uses the old version of reqwest. Small steps.

Requires Rust 1.40 now. (1.39 is a requirement of async, and 1.40 is a
requirement of http-serve 0.2.0.)
2020-01-09 16:07:46 -08:00
Scott Lamb 154d0c30c0 note caveat on signals schema 2019-12-28 08:00:38 -06:00
Scott Lamb 72d301af6e get rid of deprecated mem::uninitialized()
This requires a Rust version bump, as MaybeUninit was introduced in Rust
1.36.
2019-12-28 07:51:47 -06:00
Scott Lamb 81ae879ac6 mount options for fewer write operations 2019-07-20 15:33:51 -07:00
Scott Lamb f1112031c2 Merge branch 'master' into new-schema 2019-07-10 17:03:30 -07:00
Scott Lamb d2e18ca5e2 improve `flush_if_sec` docs 2019-07-10 15:17:55 -07:00
Scott Lamb fb50617a7b add links to the wiki 2019-07-10 11:45:25 -07:00
Scott Lamb 34253fb96a add links to the wiki 2019-07-10 11:43:58 -07:00
Scott Lamb 106cf8cb4b Merge branch 'master' into new-schema 2019-07-10 02:03:13 -07:00
Scott Lamb 81d4fd67d4 suggest RequireMountsFor in systemd service file
Besides using one line instead of two, this avoids the need to do hex
escaping of characters like hyphens.
2019-07-10 02:00:10 -07:00
Scott Lamb 71c64908ec Merge branch 'master' into new-schema 2019-07-10 00:59:42 -07:00
Scott Lamb 1c904b925a many improvements to install docs/procedures
* in markdown files, use code fences rather than indented blocks.
    This is harder to screw up (one of them was off by a space so didn't
    render properly) and allows me to add info strings.

  * uniformly use "useradd" to create the user and group in all three
    places (install-manual.md, script-functions.sh, Dockerfile) rather
    than addgroup + adduser. Create a full home dir, which I suspect was
    the problem in #67. Don't allow customizing group name; it's always
    the same as the user.

  * install the sqlite3 package so that the "moonfire-nvr sql" command
    works properly.

  * remove "setup_db" function, which was out of place. Since the
    creation of the "moonfire-nvr init" command, this has to happen
    after installation of the binary. install.md gives instructions on
    this part anyway so remove it from the script.

  * give a proper command to create the db dir. It was creating it
    within the current directory, not within /var/lib/moonfire-nvr.
    Don't bother creating sample directory; "moonfire-nvr config"
    will do this.

  * when setting owners on a newly created directory, use a single
    "install -d" command rather than "mkdir" + "chown".

  * address confusion about whether sample file dirs need to be
    precreated. (Only when Moonfire NVR doesn't have write permissions
    on the parent.)

  * always just install the packaged version of ffmpeg rather than
    building our own. This has been usable since Debian/Raspbian 9
    Stretch; Debian/Raspbian 10 Buster is out now so there's no excuse
    for still running Debian/Raspbian 8 Jessie.

  * don't chown the UI directory; it can be owned by root as with
    the binary.

  * in scripts/install.sh, don't enable/start the service yet. It hasn't
    been configured.
2019-07-10 00:56:43 -07:00
Scott Lamb d61b5e1bdd Use fixed-size directory meta files
Add a new schema version 5; now 4 means the directory meta may or may
not be upgraded.

Fixes #65: now it's possible to open the directory even if it lies on a
completely full disk.
2019-07-04 23:30:37 -05:00
Scott Lamb afe693ef95 fix obsolete flag name 2019-06-20 16:22:46 -07:00
Scott Lamb eaf6608597 tweak and document version 3->4 upgrade 2019-06-20 16:03:59 -07:00
Scott Lamb a5ffe3ca2c bump minimum Rust version
The master version of rust-protobuf requires the TryFrom feature,
stabilized in 1.34.
2019-06-19 15:56:04 -07:00
Scott Lamb fda7e4ca2b add concept of user/session permissions
(I also considered the names "capabilities" and "scopes", but I think
"permissions" is the most widely understood.)

This is increasingly necessary as the web API becomes more capable.
Among other things, it allows:

* non-administrator users who can view but not access camera passwords
  or change any state
* workers that update signal state based on cameras' built-in motion
  detection or a security system's events but don't need to view videos
* control over what can be done without authenticating

Currently session permissions are just copied from user permissions, but
you can also imagine admin sessions vs not, as a checkbox when signing
in. This would match the standard Unix workflow of using a
non-administrative session most of the time.

Relevant to my current signals work (#28) and to the addition of an
administrative API (#35, including #66).
2019-06-19 15:34:20 -07:00
Scott Lamb b629fe6ac1 upgrade rusqlite, bump required Rust to 1.33
The new rusqlite requires the transpose_result feature, stabilized in
this Rust version.
2019-05-31 16:19:04 -07:00
Scott Lamb 3668c69d4b bump required Rust version to 1.32
travis-ci pointed out that the dependency bump broke 1.31:

   Compiling docopt v1.1.0
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
   --> /home/travis/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-1.1.0/src/parse.rs:48:5
    |
48  |   use regex;
    |       ^^^^^
    |

Looks like uniform_paths was stabilized in 1.32, and I verified locally that
version builds.
2019-05-31 16:09:42 -07:00
Scott Lamb d7a0cb9a7c Remove mention of #36 from troubleshooting guide
The 091217b workaround of telling ffmpeg to only request the video
stream works perfectly fine for now. I'll revisit when adding audio
support (#34).

Fixes #36
2019-02-13 22:25:33 -08:00
Scott Lamb ff58f24785 update deps 2018-12-28 10:13:03 -06:00
Scott Lamb 4580038013 fix --require-auth flag
Apparently with docopt, --require-auth=false doesn't work, so booleans
with a default value of true can't be turned off. Toggle the default to
false to deal with this, for now. I'd prefer the default be true, but
I also would prefer to not use a negative --no-require-auth or
--allow-unauthenticated flag. I think I'll switch from docopt to clap
in the near future; it seems to be what the cool kids use.
2018-12-28 08:39:50 -06:00
Scott Lamb 278a87d5fd tweaks to guide/secure.md
after reading the rendered version online
2018-12-27 16:29:26 -06:00
Scott Lamb 24674f5b50 document proxy setup in guide/secure.md (for #26)
The guide is not as quick to follow and amateur-friendly as I'd like. A
few things that might improve matters:

   * complete #27 (built-in https+letsencrypt), so that when not sharing
     the port, users don't need to use nginx or certbot.
   * more ubiquitous IPv6 (out of my control but should happen over
     time) to reduce need to share the port
   * embed a dynamic DNS client
   * support UPnP Internet Gateway Device Control Protocol (if common
     routers have this enabled? probably not for security reasons.)

It's progress, though. Enough that I think I'll merge the auth branch
into master shortly.
2018-12-27 16:00:15 -06:00
Scott Lamb 422cd2a75e preliminary web support for auth (#26)
Some caveats:

  * it doesn't record the peer IP yet, which makes it harder to verify
    sessions are valid. This is a little annoying to do in hyper now
    (see hyperium/hyper#1410). The direct peer might not be what we want
    right now anyway because there's no TLS support yet (see #27).  In
    the meantime, the sane way to expose Moonfire NVR to the Internet is
    via a proxy server, and recording the proxy's IP is not useful.
    Maybe better to interpret a RFC 7239 Forwarded header (and/or
    the older X-Forwarded-{For,Proto} headers).

  * it doesn't ever use Secure (https-only) cookies, for a similar reason.
    It's not safe to use even with a tls proxy until this is fixed.

  * there's no "moonfire-nvr config" support for inspecting/invalidating
    sessions yet.

  * in debug builds, logging in is crazy slow. See libpasta/libpasta#9.

Some notes:

  * I removed the Javascript "no-use-before-defined" lint, as some of
    the functions form a cycle.

  * Fixed #20 along the way. I needed to add support for properly
    returning non-OK HTTP statuses to signal unauthorized and such.

  * I removed the Access-Control-Allow-Origin header support, which was
    at odds with the "SameSite=lax" in the cookie header. The "yarn
    start" method for running a local proxy server accomplishes the same
    thing as the Access-Control-Allow-Origin support in a more secure
    manner.
2018-11-27 11:08:33 -08:00
Scott Lamb 071be03c6f update most deps, notably including reqwest
Fixes #60

The reqwest dependency is significant because the old version required
an old version of openssl, complicating compilation on newer platforms.
reqwest also pulled in old/duplicate versions of hyper, tokio, etc.
Nice to drop a lot of that cruft.

I left rusqlite and uuid alone because they had breaking changes I
didn't want to mess with at the moment.

Bumped the minimum Rust version to 1.30.0, as required by the
new encoding_rs crate (and perhaps other things).
2018-11-20 09:32:55 -08:00
Scott Lamb aa81eae65a more robust timezone detection (fixes #12) 2018-08-31 17:19:24 -07:00
Scott Lamb 91ef07b9a7 bump required rust to 1.27
1.26 doesn't work with the updated rusqlite:

error[E0658]: use of unstable library feature 'duration_extras' (see issue #46507)
  --> /home/travis/.cargo/registry/src/github.com-1ecc6299db9ec823/rusqlite-0.14.0/src/busy.rs:26:49
   |
26 |             .and_then(|t| t.checked_add(timeout.subsec_millis().into()))
   |                                                 ^^^^^^^^^^^^^
2018-08-28 21:47:02 -07:00
Scott Lamb 0cc4d191c0 bump minimum Rust version to 1.26
1.25 also fails with the upgraded reffers because u128 isn't stable:

error[E0658]: 128-bit type is unstable (see issue #35118)
   --> /home/travis/.cargo/git/checkouts/reffers-rs-0d00fc7f893338b3/49a4d75/src/rc_bitmask.rs:194:34
    |
194 | rc_bit_mask_internal!(primitive, u128, 42, 42, 42);
    |                                  ^^^^
2018-08-27 21:32:51 -07:00
Scott Lamb 6ab416caed bump minimum Rust version
travis-ci pointed out that building with 1.21 broke with a recent dep
upgrade (8c52c36). reffers now uses nested groups of imports, which is a
feature introduced with Rust 1.25. Prior to 1.25, it fails as follows:

error: expected one of `,` or `as`, found `::`
 --> /home/travis/.cargo/git/checkouts/reffers-rs-0d00fc7f893338b3/49a4d75/src/arc.rs:6:46
  |
6 | use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
  |                                              ^^ expected one of `,` or `as` here
2018-08-25 06:33:50 -07:00
Scott Lamb 5bba71345c few small markdown tweaks 2018-08-24 21:04:13 -07:00
Scott Lamb 489fda6abe add missing guide/install-scripted.md
I mistakenly lost a "git mv easy-install.md install-scripted.md" when
reworking the commit, I suppose.
2018-08-24 20:59:56 -07:00
Scott Lamb c5345c1e11 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".
2018-08-24 20:45:46 -07:00
Scott Lamb 01e8dab67f fourth attempt at travis config
* upgrade min required rust to 1.21; crossbeam-deque requires the
  ord_max_min feature, apparently stabilized in this version.

* use "make --jobs=2" to build ffmpeg so it goes faster.
  https://docs.travis-ci.com/user/reference/overview/ says there are 2
  cores available.
2018-08-07 15:51:19 -05:00
Scott Lamb 62a1bad8b9 third attempt at travis config
* upgrade minimum required Rust from 1.17 to 1.20; reffers 0.4.2
  apparently uses std::mem::ManuallyDrop, introduced in 1.20

* install ffmpeg from source (requiring sudo access) rather than using
  the ancient one from Ubuntu Trusty to meet the minimum version
  requirements specified in ffmpeg/build.rs.
2018-08-07 15:28:34 -05:00
Scott Lamb 299c0b1802 Merge branch 'master' (early part) into new-schema
Catch the new-schema branch up with everything up to (but not including) the
big UI refactoring. I'll merge that separately.
2018-03-24 22:29:40 -07:00
Scott Lamb 1c9f2a4d83 initial schema for user authentication (#26)
This is only the database schema, which I'm adding now in the hopes of
freezing schema version 3. There's no way yet to create users, much less
actually authenticate.
2018-03-21 23:57:45 -07:00
Scott Lamb dfee66c84b support additional recording_integrity timestamps
These are not actually populated by the code yet. I'm trying to get the
v3 schema frozen as soon as possible; actually using the fields can come
later.

Add some explanation of their value in time.md, along with some general
musing on leap seconds, and a correction on the frequency error of my cameras.
2018-03-21 22:32:41 -07:00
Dolf Starreveld 353a860146 Normalize case of "Moonfire" 2018-03-08 21:52:15 -08:00
Dolf Starreveld 5727adf3df Settings can now be taken from separate file with local override.
* Various settings in settings-nvr.js module
* settings-nvr-local.js can override settings-nvr.js
* settings-nvr-local is unchecked file
* Both files can be straight maps, or functions returning maps
* webpack env and args available to those functions
2018-03-08 18:26:41 -08:00
Dolf Starreveld 760b8d95fb Rewrite of the installation script and accompanying documentation. (#15)
Rewrite of the installation script and accompanying documentation.
2018-03-03 06:41:15 -08:00
Scott Lamb b037c9bdd7 knob to reduce db commits (SSD write cycles)
This improves the practicality of having many streams (including the doubling
of streams by having main + sub streams for each camera). With these tuned
properly, extra streams don't cause any extra write cycles in normal or error
cases. Consider the worst case in which each RTSP session immediately sends a
single frame and then fails. Moonfire retries every second, so this would
formerly cause one commit per second per stream. (flush_if_sec=0 preserves
this behavior.) Now the commits can be arbitrarily infrequent by setting
higher values of flush_if_sec.

WARNING: this isn't production-ready! I hacked up dir.rs to make tests pass
and "moonfire-nvr run" work in the best-case scenario, but it doesn't handle
errors gracefully. I've been debating what to do when writing a recording
fails. I considered "abandoning" the recording then either reusing or skipping
its id. (in the latter case, marking the file as garbage if it can't be
unlinked immediately). I think now there's no point in abandoning a recording.
If I can't write to that file, there's no reason to believe another will work
better. It's better to retry that recording forever, and perhaps put the whole
directory into an error state that stops recording until those writes go
through. I'm planning to redesign dir.rs to make this happen.
2018-02-22 16:35:34 -08:00
Scott Lamb 253f3de399 reorganize the sample file directory
The filenames now represent composite ids (stream id + recording id) rather
than a separate uuid system with its own reservation for a few benefits:

  * This provides more information when there are inconsistencies.

  * This avoids the need for managing the reservations during recording. I
    expect this to simplify delaying flushing of newly written sample files.
    Now the directory has to be scanned at startup for files that never got
    written to the database, but that's acceptably fast even with millions of
    files.

  * Less information to keep in memory and in the recording_playback table.

I'd considered using one directory per stream, which might help if the
filesystem has trouble coping with huge directories. But that would mean each
dir has to be fsync()ed separately (more latency and/or more multithreading).
So I'll stick with this until I see concrete evidence of a problem that would
solve.

Test coverage of the error conditions is poor. I plan to do some restructuring
of the db/dir code, hopefully making steps toward testability along the way.
2018-02-20 10:11:10 -08:00
Scott Lamb e7f5733f29 new database/sample file dir interlock scheme
The idea is to avoid the problems described in src/schema.proto; those
possibilities have bothered me for a while. A bonus is that (in a future
commit) it can replace the sample file uuid scheme in favor of using
<camera_uuid>-<stream_type>/<recording_id> for several advantages:

  * on data integrity problems (specifically, extra sample files), more
    information to use to understand what happened.
  * no more reserving sample files prior to using them. This avoids some extra
    database transactions on startup (now there's an extra two total rather
    than an extra one per stream). It also simplifies an upcoming change I
    want to make in which some streams are not flushed immediately, reducing
    the write load significantly (maybe one per minute total rather than one
    per stream per minute).
  * get rid of eight bytes per playback cache entry in RAM (and nine bytes
    per recording_playback row on flash).

The implementation is still pretty rough in places:

  * Lack of tests.
  * Poor ode organization. In particular, SampleFileDirectory::write_meta
    shouldn't be exposed beyond db. I'm thinking about moving db.rs and
    SampleFileDirectory to a new crate, moonfire_nvr_db. This would improve
    compile times as well.
  * No tooling for renaming a sample file directory.
  * Config subcommand still panics in conditions that can be reasonably
    expected to happen.
2018-02-14 23:35:52 -08:00
Scott Lamb 89b6bccaa3 support multiple sample file directories
This is still pretty basic support. There's no config UI support for
renaming/moving the sample file directories after they are created, and no
error checking that the files are still in the expected place. I can imagine
sysadmins getting into trouble trying to change things. I hope to address at
least some of that in a follow-up change to introduce a versioning/locking
scheme that ensures databases and sample file dirs match in some way.

A bonus change that kinda got pulled along for the ride: a dialog pops up in
the config UI while a stream is being tested. The experience was pretty bad
before; there was no indication the button worked at all until it was done,
sometimes many seconds later.
2018-02-11 23:04:02 -08:00
Scott Lamb 6f309e432f store rfc6381_codec in the database
This avoids having codec-specific logic to synthesize it in db.rs. It's not
too much of a problem now with only H.264 support, but it'd be a pain when
supporting H.265 and other codecs.
2018-02-05 11:57:59 -08:00
Scott Lamb cc6579b211 upgrader for v1->v2 2018-02-03 22:19:02 -08:00
Scott Lamb d192d98129 more fixes to the upgrade guide 2018-01-30 21:14:53 -08:00