mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2024-12-24 06:05:55 -05:00
no more Docker!
* use `termion` rather than `ncurses` to limit runtime deps * cross-compile with `cross` instead of our own dockerfiles/scripts * update instructions * update release procedure and GitHub actions to match * prep changelog for `v0.7.8` Fixes #160 Closes #265
This commit is contained in:
parent
faf0201b52
commit
ee98bf5236
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -24,8 +24,7 @@ A clear and concise description of what you expected to happen.
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Server (please complete the following information):**
|
||||
- If using Docker: `docker ps` + `docker images`
|
||||
- If building from git: `moonfire-nvr --version`
|
||||
- `moonfire-nvr --version`
|
||||
- Attach a [log file](https://github.com/scottlamb/moonfire-nvr/blob/master/guide/troubleshooting.md#viewing-moonfire-nvrs-logs). Run with the `RUST_BACKTRACE=1` environment variable set if possible.
|
||||
|
||||
**Camera (please complete the following information):**
|
||||
|
19
.github/workflows/ci.yml
vendored
19
.github/workflows/ci.yml
vendored
@ -1,6 +1,10 @@
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
MOONFIRE_COLOR: always
|
||||
@ -37,11 +41,7 @@ jobs:
|
||||
restore-keys: |
|
||||
cargo-${{ matrix.rust }}-
|
||||
cargo-
|
||||
- name: Install dependencies
|
||||
# The retry here is to work around "Unable to connect to azure.archive.ubuntu.com" errors.
|
||||
# https://github.com/actions/runner-images/issues/6894
|
||||
run: sudo apt-get --option=APT::Acquire::Retries=3 update && sudo apt-get --option=APT::Acquire::Retries=3 install libncurses-dev libsqlite3-dev pkgconf
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install Rust
|
||||
@ -51,13 +51,10 @@ jobs:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
override: true
|
||||
components: ${{ matrix.extra_components }}
|
||||
- run: cd ui && npm ci
|
||||
- run: cd ui && npm run build
|
||||
- name: Test
|
||||
run: |
|
||||
cd server
|
||||
cargo test ${{ matrix.extra_args }} --all
|
||||
cargo test --features=bundled-ui ${{ matrix.extra_args }} --all
|
||||
cargo test --features=rusqlite/bundled ${{ matrix.extra_args }} --all
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' }}
|
||||
- name: Check formatting
|
||||
if: matrix.rust == 'stable'
|
||||
@ -70,7 +67,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- run: cd ui && npm ci
|
||||
@ -83,5 +80,5 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- run: find . -type f -print0 | xargs -0 .github/workflows/check-license.py
|
||||
|
104
.github/workflows/release.yml
vendored
104
.github/workflows/release.yml
vendored
@ -1,19 +1,109 @@
|
||||
name: Release
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.*
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
base:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: taiki-e/create-gh-release-action@v1
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: taiki-e/install-action@v2
|
||||
with:
|
||||
# (Optional) Path to changelog.
|
||||
changelog: CHANGELOG.md
|
||||
tool: parse-changelog
|
||||
- name: Generate changelog
|
||||
run: |
|
||||
VERSION_MINUS_V=${GITHUB_REF_NAME/#v/}
|
||||
parse-changelog CHANGELOG.md $VERSION_MINUS_V > CHANGELOG-$GITHUB_REF_NAME.md
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- run: cd ui && npm ci
|
||||
- run: cd ui && npm run build
|
||||
- run: cd ui && npm run test
|
||||
# Upload the UI and changelog as *job* artifacts (not *release* artifacts), used below.
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: moonfire-nvr-ui-${{ github.ref_name }}
|
||||
path: ui/build
|
||||
if-no-files-found: error
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: CHANGELOG-${{ github.ref_name }}
|
||||
path: CHANGELOG-${{ github.ref_name }}.md
|
||||
if-no-files-found: error
|
||||
|
||||
cross:
|
||||
needs: base # for bundled ui
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
- target: aarch64-unknown-linux-musl
|
||||
- target: armv7-unknown-linux-musleabihf
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Download UI
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: moonfire-nvr-ui-${{ github.ref_name }}
|
||||
path: ui/build
|
||||
|
||||
# actions-rust-cross doesn't actually use cross for x86_64.
|
||||
# Install the needed musl-tools in the host.
|
||||
- name: Install musl-tools
|
||||
run: sudo apt-get --option=APT::Acquire::Retries=3 update && sudo apt-get --option=APT::Acquire::Retries=3 install musl-tools
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
- name: Build
|
||||
uses: houseabsolute/actions-rust-cross@v0
|
||||
env:
|
||||
# (Required) GitHub token for creating GitHub Releases.
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
UI_BUILD_DIR: ../ui/build
|
||||
|
||||
# cross doesn't install `git` within its Docker container, so plumb
|
||||
# the version through rather than try `git describe` from `build.rs`.
|
||||
VERSION: ${{ github.ref_name }}
|
||||
with:
|
||||
working-directory: server
|
||||
target: ${{ matrix.target }}
|
||||
command: build
|
||||
args: --release --features bundled
|
||||
# Upload as a *job* artifact (not *release* artifact), used below.
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: moonfire-nvr-${{ github.ref_name }}-${{ matrix.target }}
|
||||
path: server/target/${{ matrix.target }}/release/moonfire-nvr
|
||||
if-no-files-found: error
|
||||
|
||||
release:
|
||||
needs: [ base, cross ]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts
|
||||
- name: ls before rearranging
|
||||
run: find . -ls
|
||||
- name: Rearrange
|
||||
run: |
|
||||
(cd artifacts/moonfire-nvr-ui-${GITHUB_REF_NAME} && zip -r ../../moonfire-nvr-ui-${GITHUB_REF_NAME}.zip .)
|
||||
(cd artifacts; for i in moonfire-nvr-*/moonfire-nvr; do mv $i "../$(dirname $i)"; done)
|
||||
- name: ls after rearranging
|
||||
run: find . -ls
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: artifacts/CHANGELOG-${{ github.ref_name }}/CHANGELOG-${{ github.ref_name }}.md
|
||||
files: |
|
||||
moonfire-nvr-*
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
.DS_Store
|
||||
*.swp
|
||||
/release-*
|
||||
/server/target
|
||||
.idea
|
||||
|
49
CHANGELOG.md
49
CHANGELOG.md
@ -1,17 +1,22 @@
|
||||
# Moonfire NVR change log
|
||||
|
||||
Below are some highlights in each release. For a full description of all
|
||||
changes, see Git history.
|
||||
|
||||
Each release is tagged in Git and on the Docker repository
|
||||
[`scottlamb/moonfire-nvr`](https://hub.docker.com/r/scottlamb/moonfire-nvr).
|
||||
changes, see Git history. Each release is tagged in git.
|
||||
|
||||
Backwards-incompatible database schema changes happen on on major version
|
||||
upgrades, e.g. `0.6.x` -> `0.7.x`. The config file format and
|
||||
upgrades, e.g. `v0.6.x` -> `v0.7.x`. The config file format and
|
||||
[API](ref/api.md) currently have no stability guarantees, so they may change
|
||||
even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
even on minor releases, e.g. `v0.7.5` -> `v0.7.6`.
|
||||
|
||||
## 0.7.7 (2023-08-03)
|
||||
## v0.7.8 (2023-10-18)
|
||||
|
||||
* release as self-contained Linux binaries (for `x86_64`, `aarch64`, and
|
||||
`armv8` architectures) rather than Docker images. This minimizes hassle and
|
||||
total download size. Along the way, we switched libc to from `glibc` to
|
||||
`musl` in the process. Please report any problems with the build or
|
||||
instructions!
|
||||
|
||||
## v0.7.7 (2023-08-03)
|
||||
|
||||
* fix [#289](https://github.com/scottlamb/moonfire-nvr/issues/289): crash on
|
||||
pressing the `Add` button in the sample file directory dialog
|
||||
@ -19,7 +24,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
* experimental (off by default) support for bundling UI files into the
|
||||
executable.
|
||||
|
||||
## 0.7.6 (2023-07-08)
|
||||
## v0.7.6 (2023-07-08)
|
||||
|
||||
* new log formats using `tracing`. This will allow richer context information.
|
||||
* bump minimum Rust version to 1.70.
|
||||
@ -53,7 +58,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
* improvements to `moonfire-nvr config`,
|
||||
thanks to [@sky1e](https://github.com/sky1e).
|
||||
|
||||
## 0.7.5 (2022-05-09)
|
||||
## v0.7.5 (2022-05-09)
|
||||
|
||||
* [#219](https://github.com/scottlamb/moonfire-nvr/issues/219): fix
|
||||
live stream failing with `ws close: 1006` on URLs with port numbers.
|
||||
@ -63,7 +68,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
Retina 0.3.10, improving compatibility with OMNY M5S2A 2812 cameras that
|
||||
send invalid `rtptime` values.
|
||||
|
||||
## 0.7.4 (2022-04-13)
|
||||
## v0.7.4 (2022-04-13)
|
||||
|
||||
* upgrade to Retina 0.3.9, improving camera interop and diagnostics.
|
||||
Fixes [#213](https://github.com/scottlamb/moonfire-nvr/issues/213),
|
||||
@ -74,13 +79,13 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
* [#206](https://github.com/scottlamb/moonfire-nvr/issues/206#issuecomment-1086442543):
|
||||
fix `teardown Sender shouldn't be dropped: RecvError(())` errors on shutdown.
|
||||
|
||||
## 0.7.3 (2022-03-22)
|
||||
## v0.7.3 (2022-03-22)
|
||||
|
||||
* security fix: check the `Origin` header on live stream WebSocket requests
|
||||
to avoid cross-site WebSocket hijacking (CSWSH).
|
||||
* RTSP connections always use the Retina library rather than FFmpeg.
|
||||
|
||||
## 0.7.2 (2022-03-16)
|
||||
## v0.7.2 (2022-03-16)
|
||||
|
||||
* introduce a configuration file `/etc/moonfire-nvr.toml`; you will need
|
||||
to create one when upgrading.
|
||||
@ -97,13 +102,13 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
* progress on [#70](https://github.com/scottlamb/moonfire-nvr/issues/184):
|
||||
shrink the binary from 154 MiB to 70 MiB by reducing debugging information.
|
||||
|
||||
## 0.7.1 (2021-10-27)
|
||||
## v0.7.1 (2021-10-27)
|
||||
|
||||
* bugfix: editing a camera from `nvr config` would erroneously clear the
|
||||
sample file directory associated with its streams.
|
||||
* RTSP transport (TCP or UDP) can be set per-stream from `nvr config`.
|
||||
|
||||
## 0.7.0 (2021-10-27)
|
||||
## v0.7.0 (2021-10-27)
|
||||
|
||||
* [schema version 7](guide/schema.md#version-7)
|
||||
* Changes to the [API](guide/api.md):
|
||||
@ -130,7 +135,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
currently may be either absent or the string `record`.
|
||||
* Added `POST /api/users/<id>` for altering a user's UI preferences.
|
||||
|
||||
## 0.6.7 (2021-10-20)
|
||||
## v0.6.7 (2021-10-20)
|
||||
|
||||
* trim whitespace when detecting time zone by reading `/etc/timezone`.
|
||||
* (Retina 0.3.2) better `TEARDOWN` handling with the default
|
||||
@ -142,7 +147,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
`--rtsp-library=retina` (see
|
||||
[scottlamb/retina#25](https://github.com/scottlamb/retina/25)).
|
||||
|
||||
## 0.6.6 (2021-09-23)
|
||||
## v0.6.6 (2021-09-23)
|
||||
|
||||
* fix [#146](https://github.com/scottlamb/moonfire-nvr/issues/146): "init
|
||||
segment fetch error" when browsers have cached data from `v0.6.4` and
|
||||
@ -167,7 +172,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
impatient to get fast results with ctrl-C when running interactively, rather
|
||||
than having to use `SIGKILL` from another terminal.
|
||||
|
||||
## 0.6.5 (2021-08-13)
|
||||
## v0.6.5 (2021-08-13)
|
||||
|
||||
* UI: improve video aspect ratio handling. Live streams formerly worked
|
||||
around a Firefox pixel aspect ratio bug by forcing all videos to 16:9, which
|
||||
@ -181,7 +186,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
`GET_PARAMETERS` as a RTSP keepalive. GW Security cameras would ignored
|
||||
the latter, causing Moonfire NVR to drop the connection every minute.
|
||||
|
||||
## 0.6.4 (2021-06-28)
|
||||
## v0.6.4 (2021-06-28)
|
||||
|
||||
* Default to a new pure-Rust RTSP library, `retina`. If you hit problems, you
|
||||
can switch back via `--rtsp-library=ffmpeg`. Please report a bug if this
|
||||
@ -189,7 +194,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
* Correct the pixel aspect ratio of 9:16 sub streams (eg a standard 16x9
|
||||
camera rotated 90 degrees) in the same way as 16:9 sub streams.
|
||||
|
||||
## 0.6.3 (2021-03-31)
|
||||
## v0.6.3 (2021-03-31)
|
||||
|
||||
* New user interface! Besides a more modern appearance, it has better
|
||||
error handling and an experimental live view UI.
|
||||
@ -199,7 +204,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
not calculated properly there might be unexpected gaps or overlaps in
|
||||
playback.
|
||||
|
||||
## 0.6.2 (2021-03-12)
|
||||
## v0.6.2 (2021-03-12)
|
||||
|
||||
* Fix panics when a stream's PTS has extreme jumps
|
||||
([#113](https://github.com/scottlamb/moonfire-nvr/issues/113))
|
||||
@ -209,7 +214,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
`moonfire-nvr check --delete-orphan-rows` command from actually deleting
|
||||
rows.
|
||||
|
||||
## 0.6.1 (2021-02-16)
|
||||
## v0.6.1 (2021-02-16)
|
||||
|
||||
* Improve the server's error messages on the console and in logs.
|
||||
* Switch the UI build from the `yarn` package manager to `npm`.
|
||||
@ -221,7 +226,7 @@ even on minor releases, e.g. `0.7.5` -> `0.7.6`.
|
||||
* Fix mangled favicons
|
||||
([#105](https://github.com/scottlamb/moonfire-nvr/issues/105))
|
||||
|
||||
## 0.6.0 (2021-01-22)
|
||||
## v0.6.0 (2021-01-22)
|
||||
|
||||
This is the first tagged version and first Docker image release. I chose the
|
||||
version number 0.6.0 to match the current schema version 6.
|
||||
|
@ -1,75 +0,0 @@
|
||||
# syntax=docker/dockerfile:1.2.1
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
# See documentation here:
|
||||
# https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md
|
||||
|
||||
# "dev-common" is the portion of "dev" (see below) which isn't specific to the
|
||||
# target arch. It's sufficient for building the non-arch-specific webpack.
|
||||
FROM --platform=$BUILDPLATFORM ubuntu:20.04 AS dev-common
|
||||
LABEL maintainer="slamb@slamb.org"
|
||||
ARG BUILD_UID=1000
|
||||
ARG BUILD_GID=1000
|
||||
ARG INVALIDATE_CACHE_DEV_COMMON=
|
||||
ENV LC_ALL=C.UTF-8
|
||||
COPY docker/dev-common.bash /
|
||||
RUN --mount=type=cache,id=var-cache-apt,target=/var/cache/apt,sharing=locked \
|
||||
/dev-common.bash
|
||||
CMD [ "/bin/bash", "--login" ]
|
||||
|
||||
# "dev" is a full development environment, suitable for shelling into or
|
||||
# using with the VS Code container plugin.
|
||||
FROM --platform=$BUILDPLATFORM dev-common AS dev
|
||||
LABEL maintainer="slamb@slamb.org"
|
||||
ARG BUILDARCH
|
||||
ARG TARGETARCH
|
||||
ARG INVALIDATE_CACHE_DEV=
|
||||
COPY docker/dev.bash /
|
||||
RUN --mount=type=cache,id=var-cache-apt,target=/var/cache/apt,sharing=locked \
|
||||
/dev.bash
|
||||
USER moonfire-nvr:moonfire-nvr
|
||||
WORKDIR /var/lib/moonfire-nvr
|
||||
|
||||
# Build the UI with node_modules and ui-dist outside the src dir.
|
||||
FROM --platform=$BUILDPLATFORM dev-common AS build-ui
|
||||
ARG INVALIDATE_CACHE_BUILD_UI=
|
||||
LABEL maintainer="slamb@slamb.org"
|
||||
WORKDIR /var/lib/moonfire-nvr/src/ui
|
||||
COPY docker/build-ui.bash /
|
||||
COPY ui /var/lib/moonfire-nvr/src/ui
|
||||
RUN --mount=type=tmpfs,target=/var/lib/moonfire-nvr/src/ui/node_modules \
|
||||
/build-ui.bash
|
||||
|
||||
# Build the Rust components. Note that dev.sh set up an environment variable
|
||||
# in .buildrc that similarly changes the target dir path.
|
||||
FROM --platform=$BUILDPLATFORM dev AS build-server
|
||||
LABEL maintainer="slamb@slamb.org"
|
||||
ARG INVALIDATE_CACHE_BUILD_SERVER=
|
||||
COPY docker/build-server.bash /
|
||||
COPY --from=build-ui /var/lib/moonfire-nvr/src/ui/build /var/lib/moonfire-nvr/src/ui/build
|
||||
RUN --mount=type=cache,id=target,target=/var/lib/moonfire-nvr/target,sharing=locked,mode=777 \
|
||||
--mount=type=cache,id=cargo,target=/cargo-cache,sharing=locked,mode=777 \
|
||||
--mount=type=bind,source=server,target=/var/lib/moonfire-nvr/src/server,readonly \
|
||||
/build-server.bash
|
||||
|
||||
# Deployment environment, now in the target platform.
|
||||
FROM --platform=$TARGETPLATFORM ubuntu:20.04 AS deploy
|
||||
LABEL maintainer="slamb@slamb.org"
|
||||
ARG INVALIDATE_CACHE_BUILD_DEPLOY=
|
||||
ENV LC_ALL=C.UTF-8
|
||||
COPY docker/deploy.bash /
|
||||
RUN --mount=type=cache,id=var-cache-apt,target=/var/cache/apt,sharing=locked \
|
||||
/deploy.bash
|
||||
COPY --from=dev-common /docker-build-debug/dev-common/ /docker-build-debug/dev-common/
|
||||
COPY --from=dev /docker-build-debug/dev/ /docker-build-debug/dev/
|
||||
COPY --from=build-server /docker-build-debug/build-server/ /docker-build-debug/build-server/
|
||||
COPY --from=build-server /usr/local/bin/moonfire-nvr /usr/local/bin/moonfire-nvr
|
||||
COPY --from=build-ui /docker-build-debug/build-ui /docker-build-debug/build-ui
|
||||
|
||||
# The install instructions say to use --user in the docker run commandline.
|
||||
# Specify a non-root user just in case someone forgets.
|
||||
USER 10000:10000
|
||||
WORKDIR /var/lib/moonfire-nvr
|
||||
ENTRYPOINT [ "/usr/local/bin/moonfire-nvr" ]
|
@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
# Build the "build-server" target. See Dockerfile.
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
mkdir /docker-build-debug/build-server
|
||||
exec > >(tee -i /docker-build-debug/build-server/output) 2>&1
|
||||
date
|
||||
uname -a
|
||||
find /cargo-cache -ls > /docker-build-debug/build-server/cargo-cache-before
|
||||
find ~/target -ls > /docker-build-debug/build-server/target-before
|
||||
|
||||
source ~/.buildrc
|
||||
|
||||
# The "mode" argument to cache mounts doesn't seem to work reliably
|
||||
# (as of Docker version 20.10.5, build 55c4c88, using a docker-container
|
||||
# builder), thus the chmod command.
|
||||
sudo chmod 777 /cargo-cache /var/lib/moonfire-nvr/target
|
||||
mkdir -p /cargo-cache/{git,registry}
|
||||
ln -s /cargo-cache/{git,registry} ~/.cargo
|
||||
|
||||
build_profile=release-lto
|
||||
cd src/server
|
||||
time cargo test --features=bundled-ui
|
||||
time cargo build --features=bundled-ui --profile=$build_profile
|
||||
find /cargo-cache -ls > /docker-build-debug/build-server/cargo-cache-after
|
||||
find ~/target -ls > /docker-build-debug/build-server/target-after
|
||||
sudo install -m 755 \
|
||||
~/platform-target/$build_profile/moonfire-nvr \
|
||||
/usr/local/bin/moonfire-nvr
|
||||
date
|
@ -1,24 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
# Build the "build-ui" target. See Dockerfile.
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
mkdir /docker-build-debug/build-ui
|
||||
exec > >(tee -i /docker-build-debug/build-ui/output) 2>&1
|
||||
|
||||
date
|
||||
uname -a
|
||||
node --version
|
||||
npm --version
|
||||
time npm ci
|
||||
time npm run build
|
||||
|
||||
find /var/lib/moonfire-nvr/src/ui/node_modules -ls \
|
||||
> /docker-build-debug/build-ui/node_modules-after
|
||||
date
|
@ -1,32 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
# Build the "deploy" target. See Dockerfile.
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
mkdir -p /docker-build-debug/deploy
|
||||
exec > >(tee -i /docker-build-debug/deploy/output) 2>&1
|
||||
find /var/cache/apt -ls > /docker-build-debug/deploy/var-cache-apt-before
|
||||
|
||||
date
|
||||
uname -a
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
time apt-get update
|
||||
time apt-get install --assume-yes --no-install-recommends \
|
||||
libncurses6 \
|
||||
libncursesw6 \
|
||||
locales \
|
||||
sudo \
|
||||
sqlite3 \
|
||||
tzdata \
|
||||
vim-nox
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
ln -s moonfire-nvr /usr/local/bin/nvr
|
||||
|
||||
find /var/cache/apt -ls > /docker-build-debug/deploy/var-cache-apt-after
|
||||
date
|
@ -1,82 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
# Build the "dev" target. See Dockerfile.
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
mkdir --mode=1777 /docker-build-debug
|
||||
mkdir /docker-build-debug/dev-common
|
||||
exec > >(tee -i /docker-build-debug/dev-common/output) 2>&1
|
||||
|
||||
date
|
||||
uname -a
|
||||
find /var/cache/apt -ls > /docker-build-debug/dev-common/var-cache-apt-before
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# This file cleans apt caches after every invocation. Instead, we use a
|
||||
# buildkit cachemount to avoid putting them in the image while still allowing
|
||||
# some reuse.
|
||||
rm /etc/apt/apt.conf.d/docker-clean
|
||||
|
||||
packages=()
|
||||
|
||||
# Install all packages necessary for building (and some for testing/debugging).
|
||||
packages+=(
|
||||
build-essential
|
||||
curl
|
||||
pkgconf
|
||||
locales
|
||||
sudo
|
||||
sqlite3
|
||||
tzdata
|
||||
vim-nox
|
||||
)
|
||||
time apt-get update
|
||||
time apt-get install --assume-yes --no-install-recommends "${packages[@]}"
|
||||
|
||||
# Install a more recent nodejs/npm than in the universe repository.
|
||||
time curl -sL https://deb.nodesource.com/setup_14.x | bash -
|
||||
time apt-get install nodejs
|
||||
|
||||
# Create the user. On the dev environment, allow sudo.
|
||||
groupadd \
|
||||
--gid="${BUILD_GID}" \
|
||||
moonfire-nvr
|
||||
useradd \
|
||||
--no-log-init \
|
||||
--home-dir=/var/lib/moonfire-nvr \
|
||||
--uid="${BUILD_UID}" \
|
||||
--gid=moonfire-nvr \
|
||||
--shell=/bin/bash \
|
||||
--create-home \
|
||||
moonfire-nvr
|
||||
echo 'moonfire-nvr ALL=(ALL) NOPASSWD: ALL' >>/etc/sudoers
|
||||
|
||||
# Install Rust. Note curl was already installed for yarn above.
|
||||
time su moonfire-nvr -lc "
|
||||
curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs |
|
||||
sh -s - -y"
|
||||
|
||||
# Put configuration for the Rust build into a new ".buildrc" which is used
|
||||
# both (1) interactively from ~/.bashrc when logging into the dev container
|
||||
# and (2) from a build-server RUN command. In particular, the latter can't
|
||||
# use ~/.bashrc because that script immediately exits when run from a
|
||||
# non-interactive shell.
|
||||
echo 'source $HOME/.buildrc' >> /var/lib/moonfire-nvr/.bashrc
|
||||
cat >> /var/lib/moonfire-nvr/.buildrc <<EOF
|
||||
source \$HOME/.cargo/env
|
||||
|
||||
# Set the target directory to be outside the src bind mount.
|
||||
# https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir
|
||||
export CARGO_BUILD_TARGET_DIR=/var/lib/moonfire-nvr/target
|
||||
EOF
|
||||
chown moonfire-nvr:moonfire-nvr /var/lib/moonfire-nvr/.buildrc
|
||||
|
||||
find /var/cache/apt -ls > /docker-build-debug/dev-common/var-cache-apt-after
|
||||
date
|
122
docker/dev.bash
122
docker/dev.bash
@ -1,122 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||
|
||||
# Build the "dev" target. See Dockerfile.
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
mkdir /docker-build-debug/dev
|
||||
exec > >(tee -i /docker-build-debug/dev/output) 2>&1
|
||||
|
||||
date
|
||||
uname -a
|
||||
find /var/cache/apt -ls > /docker-build-debug/dev/var-cache-apt-before
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
packages=()
|
||||
|
||||
if [[ "${BUILDARCH}" != "${TARGETARCH}" ]]; then
|
||||
# Set up cross compilation.
|
||||
case "${TARGETARCH}" in
|
||||
arm64)
|
||||
dpkg_arch=arm64
|
||||
gcc_target=aarch64-linux-gnu
|
||||
rust_target=aarch64-unknown-linux-gnu
|
||||
target_is_port=1
|
||||
;;
|
||||
arm)
|
||||
dpkg_arch=armhf
|
||||
gcc_target=arm-linux-gnueabihf
|
||||
rust_target=arm-unknown-linux-gnueabihf
|
||||
target_is_port=1
|
||||
;;
|
||||
amd64)
|
||||
dpkg_arch=amd64
|
||||
gcc_target=x86_64-linux-gnu
|
||||
rust_target=x86_64-unknown-linux-gnu
|
||||
target_is_port=0
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported cross-compile target ${TARGETARCH}." >&2
|
||||
exit 1
|
||||
esac
|
||||
apt_target_suffix=":${dpkg_arch}"
|
||||
case "${BUILDARCH}" in
|
||||
amd64|386) host_is_port=0 ;;
|
||||
*) host_is_port=1 ;;
|
||||
esac
|
||||
|
||||
time dpkg --add-architecture "${dpkg_arch}"
|
||||
|
||||
if [[ $target_is_port -ne $host_is_port ]]; then
|
||||
# Ubuntu stores non-x86 architectures at a different URL, so futz the
|
||||
# sources file to allow installing both host and target.
|
||||
# See https://github.com/rust-embedded/cross/blob/master/docker/common.sh
|
||||
perl -pi.bak -e '
|
||||
s{^deb (http://.*.ubuntu.com/ubuntu/) (.*)}
|
||||
{deb [arch=amd64,i386] \1 \2\ndeb [arch-=amd64,i386] http://ports.ubuntu.com/ubuntu-ports \2};
|
||||
s{^deb (http://ports.ubuntu.com/ubuntu-ports/) (.*)}
|
||||
{deb [arch=amd64,i386] http://archive.ubuntu.com/ubuntu \2\ndeb [arch-=amd64,i386] \1 \2}' \
|
||||
/etc/apt/sources.list
|
||||
cat /etc/apt/sources.list
|
||||
fi
|
||||
|
||||
packages+=(
|
||||
g++-${gcc_target/_/-}
|
||||
libc6-dev-${dpkg_arch}-cross
|
||||
qemu-user
|
||||
)
|
||||
fi
|
||||
|
||||
time apt-get update
|
||||
|
||||
# Install the packages for the target architecture.
|
||||
packages+=(
|
||||
libncurses-dev"${apt_target_suffix}"
|
||||
libsqlite3-dev"${apt_target_suffix}"
|
||||
)
|
||||
time apt-get update
|
||||
time apt-get install --assume-yes --no-install-recommends "${packages[@]}"
|
||||
|
||||
# Set environment variables for cross-compiling.
|
||||
# Also set up a symlink that points to the output platform's target dir, because
|
||||
# the target directory layout varies when cross-compiling, as described here:
|
||||
# https://doc.rust-lang.org/cargo/guide/build-cache.html
|
||||
if [[ -n "${rust_target}" ]]; then
|
||||
su moonfire-nvr -lc "rustup target install ${rust_target} &&
|
||||
ln -s target/${rust_target} platform-target"
|
||||
underscore_rust_target="${rust_target//-/_}"
|
||||
uppercase_underscore_rust_target="${underscore_rust_target^^}"
|
||||
cat >> /var/lib/moonfire-nvr/.buildrc <<EOF
|
||||
|
||||
# https://doc.rust-lang.org/cargo/reference/config.html
|
||||
export CARGO_BUILD_TARGET=${rust_target}
|
||||
export CARGO_TARGET_${uppercase_underscore_rust_target}_LINKER=${gcc_target}-gcc
|
||||
|
||||
# Use a pkg-config wrapper for the target architecture. This wrapper was
|
||||
# automatically created on "dpkg --add-architecture"; see
|
||||
# /etc/dpkg/dpkg.cfg.d/pkgconf-hook-config.
|
||||
#
|
||||
# https://github.com/rust-lang/pkg-config-rs uses the "PKG_CONFIG"
|
||||
# variable to to select the pkg-config binary to use. As of pkg-config 0.3.19,
|
||||
# it unfortunately doesn't understand the <target>_ prefix that the README.md
|
||||
# describes for other vars. Fortunately Moonfire NVR doesn't have any host tools
|
||||
# that need pkg-config.
|
||||
export PKG_CONFIG=${gcc_target}-pkg-config
|
||||
|
||||
# https://github.com/alexcrichton/cc-rs uses these variables to decide what
|
||||
# compiler to invoke.
|
||||
export CC_${underscore_rust_target}=${gcc_target}-gcc
|
||||
export CXX_${underscore_rust_target}=${gcc_target}-g++
|
||||
EOF
|
||||
else
|
||||
su moonfire-nvr -lc "ln -s target platform-target"
|
||||
fi
|
||||
|
||||
find /var/cache/apt -ls > /docker-build-debug/dev/var-cache-apt-after
|
||||
date
|
241
guide/build.md
241
guide/build.md
@ -2,7 +2,7 @@
|
||||
|
||||
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.
|
||||
binaries, see the [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
|
||||
@ -11,11 +11,9 @@ tracker](https://github.com/scottlamb/moonfire-nvr/issues) or
|
||||
stuck. Please also send pull requests to improve this doc.
|
||||
|
||||
* [Downloading](#downloading)
|
||||
* [Docker builds](#docker-builds)
|
||||
* [Release procedure](#release-procedure)
|
||||
* [Non-Docker setup](#non-docker-setup)
|
||||
* [Building](#building)
|
||||
* [Running interactively straight from the working copy](#running-interactively-straight-from-the-working-copy)
|
||||
* [Running as a `systemd` service](#running-as-a-systemd-service)
|
||||
* [Release procedure](#release-procedure)
|
||||
|
||||
## Downloading
|
||||
|
||||
@ -28,152 +26,16 @@ $ git clone https://github.com/scottlamb/moonfire-nvr.git
|
||||
$ cd moonfire-nvr
|
||||
```
|
||||
|
||||
## Docker builds
|
||||
## Building
|
||||
|
||||
This command should prepare a deployment image for your local machine:
|
||||
|
||||
```console
|
||||
$ sudo docker buildx build --load --tag=moonfire-nvr -f docker/Dockerfile .
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Common errors</summary>
|
||||
|
||||
* `docker: 'buildx' is not a docker command.`: You shouldn't see this with
|
||||
Docker 20.10. With Docker version 19.03 you'll need to prepend
|
||||
`DOCKER_CLI_EXPERIMENTAL=enabled` to `docker buildx build` commands. If
|
||||
your Docker version is older than 19.03, you'll need to upgrade.
|
||||
* `At least one invalid signature was encountered.`: this is likely
|
||||
due to an error in `libseccomp`, as described [in this askubuntu.com answer](https://askubuntu.com/a/1264921/1365248).
|
||||
Try running in a privileged builder. As described in [`docker buildx build` documentation](https://docs.docker.com/engine/reference/commandline/buildx_build/#allow),
|
||||
run this command once:
|
||||
```console
|
||||
$ sudo docker buildx create --use --name insecure-builder --buildkitd-flags '--allow-insecure-entitlement security.insecure'
|
||||
```
|
||||
then add `--allow security.insecure` to your `docker buildx build` commandlines.
|
||||
</details>
|
||||
|
||||
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.
|
||||
|
||||
```console
|
||||
$ sudo docker buildx build \
|
||||
--load --tag=moonfire-dev --target=dev -f docker/Dockerfile .
|
||||
...
|
||||
$ sudo 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.
|
||||
|
||||
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. (Note: this has been used
|
||||
successfully for building on x86-64 and compiling to arm but not the
|
||||
reverse.) 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:
|
||||
|
||||
```console
|
||||
$ sudo 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:
|
||||
```
|
||||
$ sudo docker buildx build --platform=linux/arm64/v8,linux/arm/v7,linux/amd64 ...
|
||||
$ sudo docker buildx build --load --platform=arm64/v8 ...
|
||||
```
|
||||
|
||||
On Linux hosts (as opposed to when using Docker Desktop on macOS/Windows),
|
||||
you'll likely see errors like the ones below. The solution is to [install
|
||||
emulators](https://github.com/tonistiigi/binfmt#installing-emulators).
|
||||
You may need to reinstall emulators on each boot of the host.
|
||||
|
||||
```
|
||||
Exec format error
|
||||
|
||||
Error while loading /usr/sbin/dpkg-split: No such file or directory
|
||||
Error while loading /usr/sbin/dpkg-deb: No such file or directory
|
||||
```
|
||||
|
||||
Moonfire NVR's `Dockerfile` has some built-in debugging tools:
|
||||
|
||||
* Each stage saves some debug info to `/docker-build-debug/<stage>`, and
|
||||
the `deploy` stage preserves the output from previous stages. The debug
|
||||
info includes:
|
||||
* output (stdout + stderr) from the build script, running long operations
|
||||
through the `time` command.
|
||||
* `find -ls` output on cache mounts before and after.
|
||||
* Each stage accepts a `INVALIDATE_CACHE_<stage>` argument. You can use eg
|
||||
`--build-arg=INVALIDATE_CACHE_BUILD_SERVER=$(date +%s)` to force the
|
||||
`build-server` stage to be rebuilt rather than use cached Docker layers.
|
||||
|
||||
### Release procedure
|
||||
|
||||
Releases are currently a bit manual. From a completely clean git work tree,
|
||||
|
||||
1. manually verify the current commit is pushed to github's master branch and
|
||||
has a green checkmark indicating CI passed.
|
||||
2. update version in `CHANGELOG.md`.
|
||||
3. run commands:
|
||||
```bash
|
||||
VERSION=x.y.z
|
||||
git commit -am "prepare version ${VERSION}"
|
||||
git tag -a "v${VERSION}" -m "version ${VERSION}"
|
||||
./release.bash
|
||||
git push
|
||||
git push origin "v${VERSION}"
|
||||
```
|
||||
|
||||
The `release.bash` script needs [`jq`](https://stedolan.github.io/jq/)
|
||||
installed to work.
|
||||
|
||||
## 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
|
||||
Moonfire NVR should run natively on any Unix-like system. It's been tested on
|
||||
Linux, macOS, and FreeBSD. (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:
|
||||
|
||||
* [SQLite3](https://www.sqlite.org/), at least version 3.8.2.
|
||||
(You can skip this if you compile with `--features=bundled` and
|
||||
don't mind the `moonfire-nvr sql` command not working.)
|
||||
|
||||
* [`ncursesw`](https://www.gnu.org/software/ncurses/), the UTF-8 version of
|
||||
the `ncurses` library.
|
||||
To build the server, you will need [SQLite3](https://www.sqlite.org/). You
|
||||
can skip this if compiling with `--features=rusqlite/bundled` and don't
|
||||
mind the `moonfire-nvr sql` command not working.
|
||||
|
||||
To build the UI, you'll need a [nodejs](https://nodejs.org/en/download/) release
|
||||
in "Maintenance" or "LTS" status: currently v14, v16, or v18.
|
||||
@ -184,7 +46,6 @@ most non-Rust dependencies:
|
||||
```console
|
||||
$ sudo apt-get install \
|
||||
build-essential \
|
||||
libncurses-dev \
|
||||
libsqlite3-dev \
|
||||
pkgconf \
|
||||
sqlite3 \
|
||||
@ -253,72 +114,24 @@ $ nvr run
|
||||
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`.
|
||||
## Release procedure
|
||||
|
||||
### Running as a `systemd` service
|
||||
Releases are currently a bit manual. From a completely clean git work tree,
|
||||
|
||||
If you want to deploy a non-Docker build on Linux, you may want to use
|
||||
`systemd`. Create `/etc/systemd/system/moonfire-nvr.service`:
|
||||
1. manually verify the current commit is pushed to github's master branch and
|
||||
has a green checkmark indicating CI passed.
|
||||
2. update versions:
|
||||
* update `server/Cargo.toml` version by hand; run `cargo test --workspace`
|
||||
to update `Cargo.lock`.
|
||||
* ensure `README.md` and `CHANGELOG.md` refer to the new version.
|
||||
3. run commands:
|
||||
```bash
|
||||
VERSION=x.y.z
|
||||
git commit -am "prepare version ${VERSION}"
|
||||
git tag -a "v${VERSION}" -m "version ${VERSION}"
|
||||
git push origin "v${VERSION}"
|
||||
```
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Moonfire NVR
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/moonfire-nvr run
|
||||
Environment=TZ=:/etc/localtime
|
||||
Environment=MOONFIRE_FORMAT=google-systemd
|
||||
Environment=MOONFIRE_LOG=info
|
||||
Environment=RUST_BACKTRACE=1
|
||||
Type=simple
|
||||
User=moonfire-nvr
|
||||
Restart=on-failure
|
||||
CPUAccounting=true
|
||||
MemoryAccounting=true
|
||||
BlockIOAccounting=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
You'll also need a `/etc/moonfire-nvr.toml`:
|
||||
|
||||
```toml
|
||||
[[binds]]
|
||||
ipv4 = "0.0.0.0:8080"
|
||||
allowUnauthenticatedPermissions = { viewVideo = true }
|
||||
|
||||
[[binds]]
|
||||
unix = "/var/lib/moonfire-nvr/sock"
|
||||
ownUidIsPrivileged = true
|
||||
```
|
||||
|
||||
Note this configuration is insecure. You can change that via replacing the
|
||||
`allowUnauthenticatedPermissions` here as described in [Securing Moonfire NVR
|
||||
and exposing it to the Internet](secure.md).
|
||||
|
||||
See [ref/config.md](../ref/config.md) for more about `/etc/moonfire-nvr.toml`.
|
||||
|
||||
Some handy commands:
|
||||
|
||||
```console
|
||||
$ 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.
|
||||
The rest should happen automatically—the tag push will fire off a GitHub
|
||||
Actions workflow which creates a release, cross-compiles statically compiled
|
||||
binaries for three different platforms, and uploads them to the release.
|
||||
|
182
guide/install.md
182
guide/install.md
@ -1,14 +1,14 @@
|
||||
# Installing Moonfire NVR <!-- omit in toc -->
|
||||
|
||||
* [Downloading, installing, and configuring Moonfire NVR with Docker](#downloading-installing-and-configuring-moonfire-nvr-with-docker)
|
||||
* [Downloading, installing, and configuring Moonfire NVR](#downloading-installing-and-configuring-moonfire-nvr)
|
||||
* [Dedicated hard drive setup](#dedicated-hard-drive-setup)
|
||||
* [Completing configuration through the UI](#completing-configuration-through-the-ui)
|
||||
* [Starting it up](#starting-it-up)
|
||||
|
||||
## Downloading, installing, and configuring Moonfire NVR with Docker
|
||||
## Downloading, installing, and configuring Moonfire NVR
|
||||
|
||||
This document describes how to download, install, and configure Moonfire NVR
|
||||
via the prebuilt Docker images available for x86-64, arm64, and arm. If you
|
||||
via the prebuilt Linux binaries available for x86-64, arm64, and arm. If you
|
||||
instead want to build Moonfire NVR yourself, see the [Build
|
||||
instructions](build.md).
|
||||
|
||||
@ -18,17 +18,16 @@ left, and pick the [latest tagged version](https://github.com/scottlamb/moonfire
|
||||
|
||||
![Selecting a version of install instructions](install-version.png)
|
||||
|
||||
Next, install [Docker](https://www.docker.com/) if you haven't already,
|
||||
and verify `sudo docker run --rm hello-world` works.
|
||||
Download the binary for your platform from the matching GitHub release.
|
||||
Install it as `/usr/local/bin/moonfire-nvr` and ensure it is executable, e.g.
|
||||
for version `v0.7.8` on Intel machines:
|
||||
|
||||
<details>
|
||||
<summary><tt>sudo</tt> or not?</summary>
|
||||
|
||||
If you prefer to save typing by not prefixing all `docker` and `nvr` commands
|
||||
with `sudo`, see [Docker docs: Manage Docker as a non-root
|
||||
user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user).
|
||||
Note `docker` access is equivalent to root access security-wise.
|
||||
</details>
|
||||
```console
|
||||
$ VERSION=v0.7.8
|
||||
$ ARCH=x86_64-unknown-linux-musl
|
||||
$ curl -OL "https://github.com/scottlamb/moonfire-nvr/releases/download/$VERSION/moonfire-nvr-$VERSION-$ARCH"
|
||||
$ sudo install -m 755 "moonfire-nvr-$VERSION-$ARCH" /usr/local/bin/moonfire-nvr
|
||||
```
|
||||
|
||||
Next, you'll need to set up your filesystem and the Moonfire NVR user.
|
||||
|
||||
@ -49,22 +48,12 @@ On most Linux systems, you can create the user as follows:
|
||||
$ 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.
|
||||
|
||||
Use your favorite editor to create `/etc/moonfire-nvr.toml` and
|
||||
`/usr/local/bin/nvr`, starting from the configurations below:
|
||||
Use your favorite editor to create `/etc/moonfire-nvr.toml`,
|
||||
starting from the configurations below:
|
||||
|
||||
```console
|
||||
$ sudo nano /etc/moonfire-nvr.toml
|
||||
(see below for contents)
|
||||
$ sudo nano /usr/local/bin/nvr
|
||||
(see below for contents)
|
||||
$ sudo chmod a+rx /usr/local/bin/nvr
|
||||
```
|
||||
|
||||
`/etc/moonfire-nvr.toml` (see [ref/config.md](../ref/config.md) for more explanation):
|
||||
@ -78,79 +67,10 @@ unix = "/var/lib/moonfire-nvr/sock"
|
||||
ownUidIsPrivileged = true
|
||||
```
|
||||
|
||||
`/usr/local/bin/nvr`:
|
||||
```bash
|
||||
#!/bin/bash -e
|
||||
|
||||
# Set your timezone here.
|
||||
tz="America/Los_Angeles"
|
||||
|
||||
image_name="scottlamb/moonfire-nvr:v0.7.7"
|
||||
container_name="moonfire-nvr"
|
||||
common_docker_run_args=(
|
||||
--mount=type=bind,source=/var/lib/moonfire-nvr,destination=/var/lib/moonfire-nvr
|
||||
--mount=type=bind,source=/etc/moonfire-nvr.toml,destination=/etc/moonfire-nvr.toml
|
||||
|
||||
# Add additional mount lines here for each sample file directory
|
||||
# outside of /var/lib/moonfire-nvr, e.g.:
|
||||
# --mount=type=bind,source=/media/nvr/sample,destination=/media/nvr/sample
|
||||
|
||||
--user="$(id -u moonfire-nvr):$(id -g moonfire-nvr)"
|
||||
|
||||
# This avoids errors with broken seccomp on older 32-bit hosts.
|
||||
# https://github.com/moby/moby/issues/40734
|
||||
--security-opt=seccomp:unconfined
|
||||
|
||||
# This is the simplest way of configuring networking, although
|
||||
# you can use e.g. --publish=8080:8080 in the run) case below if you
|
||||
# prefer.
|
||||
--network=host
|
||||
|
||||
# docker's default log driver won't rotate logs properly, and will throw
|
||||
# away logs when you destroy and recreate the container. Using journald
|
||||
# solves these problems.
|
||||
# https://docs.docker.com/config/containers/logging/configure/
|
||||
--log-driver=journald
|
||||
--log-opt="tag=moonfire-nvr"
|
||||
|
||||
--env=RUST_BACKTRACE=1
|
||||
--env=TZ=":${tz}"
|
||||
)
|
||||
|
||||
case "$1" in
|
||||
run)
|
||||
shift
|
||||
exec docker run \
|
||||
--detach=true \
|
||||
--restart=unless-stopped \
|
||||
"${common_docker_run_args[@]}" \
|
||||
--name="${container_name}" \
|
||||
"${image_name}" \
|
||||
run \
|
||||
"$@"
|
||||
;;
|
||||
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
|
||||
```
|
||||
|
||||
then try it out by initializing the database:
|
||||
Then initialize the database:
|
||||
|
||||
```console
|
||||
$ sudo nvr init
|
||||
$ sudo -u moonfire-nvr moonfire-nvr init
|
||||
```
|
||||
|
||||
This will create a directory `/var/lib/moonfire-nvr/db` with a SQLite3 database
|
||||
@ -189,10 +109,6 @@ system will boot successfully even when the hard drive is unavailable (such as
|
||||
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 the new sample directory `/media/nvr/sample` to the Docker container,
|
||||
right where a comment mentions "Additional mount lines".
|
||||
|
||||
### Completing configuration through the UI
|
||||
|
||||
Once your system is set up, it's time to initialize an empty database
|
||||
@ -200,16 +116,17 @@ and add the cameras and sample directories. You can do this
|
||||
by using the `moonfire-nvr` binary's text-based configuration tool.
|
||||
|
||||
```console
|
||||
$ sudo nvr config 2>debug-log
|
||||
$ sudo -u moonfire-nvr moonfire-nvr config 2>debug-log
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Did it return without doing anything?</summary>
|
||||
|
||||
If `nvr config` returns you to the console prompt right away, look in the
|
||||
`debug-log` file for why. One common reason is that you have Moonfire NVR
|
||||
running; you'll need to shut it down first. Try `nvr stop` before `nvr config`
|
||||
and `nvr start` afterward.
|
||||
If `moonfire-nvr config` returns you to the console prompt right away, look in
|
||||
the `debug-log` file for why. One common reason is that you have Moonfire NVR
|
||||
running; you'll need to shut it down first. If you are running a systemd
|
||||
service as described below, try `sudo systemctl stop moonfire-nvr` before
|
||||
editing the config and `sudo systemctl start moonfire-nvr` after.
|
||||
</details>
|
||||
|
||||
In the user interface,
|
||||
@ -277,15 +194,58 @@ starting it in this configuration to try it 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.
|
||||
|
||||
This command will start a detached Docker container for the web interface.
|
||||
It will automatically restart when your system does.
|
||||
Assuming you want to proceed, you can launch Moonfire NVR through `systemd`.
|
||||
Create `/etc/systemd/system/moonfire-nvr.service`:
|
||||
|
||||
```console
|
||||
$ sudo nvr run
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Moonfire NVR
|
||||
After=network-online.target
|
||||
|
||||
# If you use an external hard drive, uncomment this with a reference to the
|
||||
# mount point as written in `/etc/fstab`.
|
||||
# RequiresMountsFor=/media/nvr
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/moonfire-nvr run
|
||||
Environment=TZ=:/etc/localtime
|
||||
Environment=MOONFIRE_FORMAT=systemd
|
||||
Environment=MOONFIRE_LOG=info
|
||||
Environment=RUST_BACKTRACE=1
|
||||
Type=simple
|
||||
User=moonfire-nvr
|
||||
Restart=on-failure
|
||||
CPUAccounting=true
|
||||
MemoryAccounting=true
|
||||
BlockIOAccounting=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
You can temporarily disable the service via `nvr stop` and restart it later via
|
||||
`nvr start`. You'll need to do this before and after using `nvr config`.
|
||||
Then start it up as follows:
|
||||
|
||||
```console
|
||||
$ sudo systemctl daemon-reload # read in the new config file
|
||||
$ sudo systemctl enable --now moonfire-nvr # start the service now and on boot
|
||||
```
|
||||
|
||||
Some handy commands:
|
||||
|
||||
```console
|
||||
$ sudo systemctl daemon-reload # reload configuration files
|
||||
$ sudo systemctl start moonfire-nvr # start the service now without enabling on boot
|
||||
$ 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.
|
||||
|
||||
The HTTP interface is accessible on port 8080; if your web browser is running
|
||||
on the same machine, you can access it at
|
||||
|
@ -62,11 +62,11 @@ 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 followed the Docker
|
||||
the system is rebooted during the upgrade. If you followed the standard
|
||||
instructions, you can do this as follows:
|
||||
|
||||
```console
|
||||
$ sudo nvr stop
|
||||
$ sudo systemctl disable --now moonfire-nvr
|
||||
```
|
||||
|
||||
Then back up your SQLite database. If you are using the default path, you can
|
||||
@ -92,34 +92,27 @@ manual for write-ahead logging](https://www.sqlite.org/wal.html):
|
||||
|
||||
Run the upgrade procedure using the new software binary.
|
||||
|
||||
```console
|
||||
$ sudo nvr pull # updates the docker image to the latest binary
|
||||
$ sudo nvr upgrade # runs the upgrade
|
||||
```
|
||||
|
||||
As a rule of thumb, on a Raspberry Pi 4 with a 1 GiB database, an upgrade might
|
||||
take about four minutes for each schema version and for the final vacuum.
|
||||
|
||||
Next, you can run the system in read-only mode, although you'll find this only
|
||||
works in the "insecure" setup. (Authorization requires writing the database.)
|
||||
To just run directly within the console until you hit ctrl-C, use the following
|
||||
command:
|
||||
|
||||
```console
|
||||
$ sudo nvr rm
|
||||
$ sudo nvr run --read-only
|
||||
$ sudo -u moonfire-nvr moonfire-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
|
||||
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.
|
||||
and go back to the prior release. If you detect a problem after enabling
|
||||
read-write operation, a restore will be more complicated.
|
||||
|
||||
Once you're satisfied, restart the system in read-write mode:
|
||||
Once you're satisfied, ctrl-C and start the system in read-write mode:
|
||||
|
||||
```console
|
||||
$ sudo nvr stop
|
||||
$ sudo nvr rm
|
||||
$ sudo nvr run
|
||||
$ sudo systemctl enable --now moonfire-nvr
|
||||
```
|
||||
|
||||
Hopefully your system is functioning correctly. If not, there are two options
|
||||
@ -137,7 +130,8 @@ 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.
|
||||
|
||||
The `nvr check` command will show you what problems exist on your system.
|
||||
The `sudo -u moonfire-nvr moonfire-nvr check` command will show you what
|
||||
problems exist on your system.
|
||||
|
||||
### Unversioned to version 0
|
||||
|
||||
|
@ -161,8 +161,8 @@ your browser. See [How to secure Nginx with Let's Encrypt on Ubuntu
|
||||
|
||||
## 6. Reconfigure Moonfire NVR
|
||||
|
||||
If you follow the recommended Docker setup, your `/etc/moonfire-nvr.toml`
|
||||
will contain this line:
|
||||
If you follow the recommended setup, your `/etc/moonfire-nvr.toml` will contain
|
||||
this line:
|
||||
|
||||
```toml
|
||||
allowUnauthenticatedPermissions = { viewVideo = true }
|
||||
@ -185,18 +185,16 @@ This change has two effects:
|
||||
See also [ref/config.md](../ref/config.md) for more about the configuration file.
|
||||
|
||||
If the webserver is running on the same machine as Moonfire NVR, you might
|
||||
also change `--publish=8080:8080` to `--publish=127.0.0.1:8080:8080` in your
|
||||
`/usr/local/bin/nvr` script, preventing other machines on the network from
|
||||
impersonating the proxy, effectively allowing them to lie about the client's IP
|
||||
and protocol.
|
||||
also change the `ipv4 = "0.0.0.0:8080"` line in `/etc/moonfire-nvr/toml` to
|
||||
`ipv4 = "127.0.0.1:8080"`, so that only the local host can directly connect to
|
||||
Moonfire NVR. If other machines can connect directly, they can impersonate
|
||||
the proxy, which would effectively allow them to lie about the client's IP and
|
||||
protocol.
|
||||
|
||||
To make this take effect, you'll need to stop the running Docker container,
|
||||
delete it, and create/run a new one:
|
||||
To make this take effect, you'll need to restart Moonfire NVR:
|
||||
|
||||
```console
|
||||
$ sudo nvr stop
|
||||
$ sudo nvr rm
|
||||
$ sudo nvr run
|
||||
$ sudo systemctl restart moonfire-nvr
|
||||
```
|
||||
|
||||
## 7. Configure the webserver
|
||||
|
@ -11,7 +11,6 @@ need more help.
|
||||
* [Camera stream errors](#camera-stream-errors)
|
||||
* [Problems](#problems)
|
||||
* [Server errors](#server-errors)
|
||||
* [`clock_gettime failed: EPERM: Operation not permitted`](#clock_gettime-failed-eperm-operation-not-permitted)
|
||||
* [`Error: pts not monotonically increasing; got 26615520 then 26539470`](#error-pts-not-monotonically-increasing-got-26615520-then-26539470)
|
||||
* [Out of disk space](#out-of-disk-space)
|
||||
* [Database or filesystem corruption errors](#database-or-filesystem-corruption-errors)
|
||||
@ -29,9 +28,8 @@ While Moonfire NVR is running, logs will be written to 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. 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`.
|
||||
`moonfire-nvr config 2>debug-log` command, output will be in the
|
||||
`debug-log` file.
|
||||
* 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=systemd` to format logs as
|
||||
@ -56,8 +54,6 @@ Logging options are controlled by environment variables:
|
||||
consumption.
|
||||
* Errors include a backtrace if `RUST_BACKTRACE=1` is set.
|
||||
|
||||
If you use Docker, set these via Docker's `--env` argument.
|
||||
|
||||
With `MOONFIRE_FORMAT` left unset, log events look as follows:
|
||||
|
||||
```text
|
||||
@ -191,23 +187,6 @@ quickly enough. In the latter case, you'll likely see a
|
||||
|
||||
### Server errors
|
||||
|
||||
#### `clock_gettime failed: EPERM: Operation not permitted`
|
||||
|
||||
If commands fail with an error like the following, you're likely running
|
||||
Docker with an overly restrictive `seccomp` setup. [This stackoverflow
|
||||
answer](https://askubuntu.com/questions/1263284/apt-update-throws-signature-error-in-ubuntu-20-04-container-on-arm/1264921#1264921) describes the
|
||||
problem in more detail. The simplest solution is to add
|
||||
`--security-opt=seccomp:unconfined` to your Docker commandline.
|
||||
If you are using the recommended `/usr/local/bin/nvr` wrapper script,
|
||||
add this option to the `common_docker_run_args` section.
|
||||
|
||||
```console
|
||||
$ sudo docker run --rm -it moonfire-nvr:latest
|
||||
clock_gettime failed: EPERM: Operation not permitted
|
||||
|
||||
This indicates a broken environment. See the troubleshooting guide.
|
||||
```
|
||||
|
||||
#### `Error: pts not monotonically increasing; got 26615520 then 26539470`
|
||||
|
||||
If your streams cut out and you see error messages like this one in Moonfire
|
||||
@ -322,8 +301,7 @@ mechanism to fix old timestamps after the fact. Ideas and help welcome; see
|
||||
|
||||
#### `moonfire-nvr config` displays garbage
|
||||
|
||||
This happens if you're not using the premade Docker containers and have
|
||||
configured your machine is configured to a non-UTF-8 locale, due to
|
||||
This may happen if your machine is configured to a non-UTF-8 locale, due to
|
||||
gyscos/Cursive#13. As a workaround, try setting the environment variable
|
||||
`LC_ALL=C.UTF-8`.
|
||||
|
||||
|
51
release.bash
51
release.bash
@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This file is part of Moonfire NVR, a security camera network video recorder.
|
||||
# Copyright (C) 2021 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||
# SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception
|
||||
|
||||
# Pushes a release to Docker. See guides/build.md#release-procedure.
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
set_latest() {
|
||||
# Our images are manifest lists (for multiple architectures).
|
||||
# "docker tag" won't copy those. The technique below is adopted from here:
|
||||
# https://github.com/docker/buildx/issues/459#issuecomment-750011371
|
||||
local image="$1"
|
||||
local hashes=($(docker manifest inspect "${image}:${version}" |
|
||||
jq --raw-output '.manifests[].digest'))
|
||||
time docker manifest rm "${image}:latest" || true
|
||||
time docker manifest create \
|
||||
"${image}:latest" \
|
||||
"${hashes[@]/#/${image}@}"
|
||||
time docker manifest push "${image}:latest"
|
||||
}
|
||||
|
||||
build_and_push() {
|
||||
local image="$1"
|
||||
local target="$2"
|
||||
time docker buildx build \
|
||||
--push \
|
||||
--tag="${image}:${version}" \
|
||||
--target="${target}" \
|
||||
--platform=linux/amd64,linux/arm64/v8,linux/arm/v7 \
|
||||
-f docker/Dockerfile .
|
||||
}
|
||||
|
||||
version="$(git describe --dirty)"
|
||||
if [[ ! "${version}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Expected a vX.Y.Z version tag, got ${version}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$(git status --porcelain)" ]]; then
|
||||
echo "git status says there's extra stuff in this directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build_and_push scottlamb/moonfire-nvr deploy
|
||||
build_and_push scottlamb/moonfire-dev dev
|
||||
set_latest scottlamb/moonfire-nvr
|
||||
set_latest scottlamb/moonfire-dev
|
46
server/Cargo.lock
generated
46
server/Cargo.lock
generated
@ -303,10 +303,8 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"maplit",
|
||||
"ncurses",
|
||||
"signal-hook",
|
||||
"term_size",
|
||||
"termion",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
@ -982,12 +980,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
@ -1198,17 +1190,6 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a1fe2275b68991faded2c80aa4a33dba398b77d276038b8f50701a22e55918"
|
||||
|
||||
[[package]]
|
||||
name = "ncurses"
|
||||
version = "5.101.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e2c5d34d72657dc4b638a1c25d40aae81e4f1c699062f72f467237920752032"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.26.1"
|
||||
@ -1338,6 +1319,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
|
||||
[[package]]
|
||||
name = "odds"
|
||||
version = "0.4.0"
|
||||
@ -1581,6 +1568,15 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
|
||||
dependencies = [
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reffers"
|
||||
version = "0.7.0"
|
||||
@ -1994,13 +1990,15 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term_size"
|
||||
version = "0.3.2"
|
||||
name = "termion"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
||||
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
"numtoa",
|
||||
"redox_syscall",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -35,7 +35,7 @@ bpaf = { version = "0.9.1", features = ["autocomplete", "bright-color", "derive"
|
||||
bytes = "1"
|
||||
byteorder = "1.0"
|
||||
chrono = "0.4.23"
|
||||
cursive = "0.20.0"
|
||||
cursive = { version = "0.20.0", default-features = false, features = ["termion-backend"] }
|
||||
db = { package = "moonfire-db", path = "db" }
|
||||
futures = "0.3"
|
||||
fnv = "1.0"
|
||||
|
14
server/Cross.toml
Normal file
14
server/Cross.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[build.env]
|
||||
volumes = [
|
||||
# For the (optional) `bundled-ui` feature.
|
||||
"UI_BUILD_DIR",
|
||||
|
||||
# For tests which use the `America/Los_Angeles` zone.
|
||||
"ZONEINFO=/usr/share/zoneinfo",
|
||||
]
|
||||
|
||||
passthrough = [
|
||||
# Cross's default docker image doesn't install `git`, so `git_version!` doesn't work.
|
||||
# Allow passing through the version via this environment variable.
|
||||
"VERSION",
|
||||
]
|
@ -6,13 +6,17 @@
|
||||
|
||||
use std::fmt::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitCode;
|
||||
use std::process::Command;
|
||||
|
||||
const UI_DIR: &str = "../ui/build";
|
||||
const UI_BUILD_DIR_ENV_VAR: &str = "UI_BUILD_DIR";
|
||||
const DEFAULT_UI_BUILD_DIR: &str = "../ui/build";
|
||||
|
||||
type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
|
||||
fn ensure_link(original: &Path, link: &Path) {
|
||||
match std::fs::read_link(link) {
|
||||
Ok(dst) if dst == original => return,
|
||||
Ok(_) => std::fs::remove_file(link).expect("removing stale symlink should succeed"),
|
||||
Err(e) if e.kind() != std::io::ErrorKind::NotFound => {
|
||||
panic!("couldn't create link {link:?} to original path {original:?}: {e}")
|
||||
}
|
||||
@ -67,37 +71,30 @@ fn stringify_files(files: &FileMap) -> Result<String, std::fmt::Error> {
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
// Explicitly declare dependencies, so this doesn't re-run if other source files change.
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
fn handle_bundled_ui() -> Result<(), BoxError> {
|
||||
// Nothing to do if the feature is off. cargo will re-run if features change.
|
||||
if !cfg!(feature = "bundled-ui") {
|
||||
return ExitCode::SUCCESS;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ui_dir =
|
||||
std::env::var(UI_BUILD_DIR_ENV_VAR).unwrap_or_else(|_| DEFAULT_UI_BUILD_DIR.to_owned());
|
||||
|
||||
// If the feature is on, also re-run if the actual UI files change.
|
||||
println!("cargo:rerun-if-changed={UI_DIR}");
|
||||
println!("cargo:rerun-if-env-changed={UI_BUILD_DIR_ENV_VAR}");
|
||||
println!("cargo:rerun-if-changed={ui_dir}");
|
||||
|
||||
let out_dir: PathBuf = std::env::var_os("OUT_DIR")
|
||||
.expect("cargo should set OUT_DIR")
|
||||
.into();
|
||||
|
||||
let abs_ui_dir = std::fs::canonicalize(UI_DIR)
|
||||
.expect("ui dir should be accessible. Did you run `npm run build` first?");
|
||||
let abs_ui_dir = std::fs::canonicalize(&ui_dir).map_err(|e| format!("ui dir {ui_dir:?} should be accessible. Did you run `npm run build` first?\n\ncaused by:\n{e}"))?;
|
||||
|
||||
let mut files = FileMap::default();
|
||||
for entry in walkdir::WalkDir::new(&abs_ui_dir) {
|
||||
let entry = match entry {
|
||||
Ok(e) => e,
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"walkdir failed. Did you run `npm run build` first?\n\n\
|
||||
caused by:\n{e}"
|
||||
);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
let entry = entry.map_err(|e| {
|
||||
format!("walkdir failed. Did you run `npm run build` first?\n\ncaused by:\n{e}")
|
||||
})?;
|
||||
if !entry.file_type().is_file() {
|
||||
continue;
|
||||
}
|
||||
@ -135,6 +132,13 @@ fn main() -> ExitCode {
|
||||
);
|
||||
}
|
||||
|
||||
if !files.contains_key("index.html") {
|
||||
return Err(format!(
|
||||
"No `index.html` within {ui_dir:?}. Did you run `npm run build` first?"
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let files = stringify_files(&files).expect("write to String should succeed");
|
||||
let mut out_rs_path = std::path::PathBuf::new();
|
||||
out_rs_path.push(&out_dir);
|
||||
@ -145,5 +149,49 @@ fn main() -> ExitCode {
|
||||
out_link_path.push(&out_dir);
|
||||
out_link_path.push("ui_files");
|
||||
ensure_link(&abs_ui_dir, &out_link_path);
|
||||
return ExitCode::SUCCESS;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_version() -> Result<(), BoxError> {
|
||||
println!("cargo:rerun-if-env-changed=VERSION");
|
||||
if std::env::var("VERSION").is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Get version from `git describe`. Inspired by the `git-version` crate.
|
||||
// We don't use that directly because `cross`'s default docker image doesn't install `git`,
|
||||
// and thus we need the environment variable pass-through above.
|
||||
|
||||
// Avoid reruns when the output doesn't meaningfully change. I don't think this is quite right:
|
||||
// it won't recognize toggling between `-dirty` and not. But it'll do.
|
||||
let dir = Command::new("git")
|
||||
.arg("rev-parse")
|
||||
.arg("--git-dir")
|
||||
.output()?
|
||||
.stdout;
|
||||
let dir = String::from_utf8(dir).unwrap();
|
||||
let dir = dir.strip_suffix('\n').unwrap();
|
||||
println!("cargo:rerun-if-changed={dir}/logs/HEAD");
|
||||
println!("cargo:rerun-if-changed={dir}/index");
|
||||
|
||||
// Plumb the version through.
|
||||
let version = Command::new("git")
|
||||
.arg("describe")
|
||||
.arg("--always")
|
||||
.arg("--dirty")
|
||||
.output()?
|
||||
.stdout;
|
||||
let version = String::from_utf8(version).unwrap();
|
||||
let version = version.strip_suffix('\n').unwrap();
|
||||
println!("cargo:rustc-env=VERSION={version}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), BoxError> {
|
||||
// Explicitly declare dependencies, so this doesn't re-run if other source files change.
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
handle_bundled_ui()?;
|
||||
handle_version()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ struct BuildFile {
|
||||
encoding: FileEncoding,
|
||||
}
|
||||
|
||||
#[allow(unused)] // it's valid for a UI to have all uncompressed files or vice versa.
|
||||
#[derive(Copy, Clone)]
|
||||
enum FileEncoding {
|
||||
Uncompressed,
|
||||
|
@ -25,7 +25,8 @@ mod bundled_ui;
|
||||
|
||||
const DEFAULT_DB_DIR: &str = "/var/lib/moonfire-nvr/db";
|
||||
|
||||
const VERSION: &str = git_version::git_version!(args = ["--always", "--dirty"]);
|
||||
// This is either in the environment when `cargo` is invoked or set from within `build.rs`.
|
||||
const VERSION: &str = env!("VERSION");
|
||||
|
||||
/// Moonfire NVR: security camera network video recorder.
|
||||
#[derive(Bpaf, Debug)]
|
||||
|
Loading…
Reference in New Issue
Block a user