mirror of
https://github.com/kerberos-io/agent.git
synced 2026-03-03 16:50:15 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
414f74758c | ||
|
|
25403ccdab | ||
|
|
4c03132b83 | ||
|
|
470f8f1cb6 | ||
|
|
5308376a67 | ||
|
|
2b112d29cf | ||
|
|
20d2517e74 | ||
|
|
12902e2482 | ||
|
|
baca44beef | ||
|
|
d7580744e2 | ||
|
|
04f4bc9bf2 | ||
|
|
d879174f4c | ||
|
|
5a1a62a723 | ||
|
|
c519b01092 | ||
|
|
c2ff7ff785 | ||
|
|
44ec8c0534 | ||
|
|
21c0e01137 |
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
@@ -43,6 +43,7 @@ jobs:
|
||||
run: docker buildx build --platform linux/$(echo ${{matrix.architecture}} | tr - /) -t $REPO-arch:arch-$(echo ${{matrix.architecture}} | tr / -)-${{steps.short-sha.outputs.sha}} --output type=tar,dest=output-${{matrix.architecture}}.tar .
|
||||
- name: Strip binary
|
||||
run: mkdir -p output/ && tar -xf output-${{matrix.architecture}}.tar -C output && rm output-${{matrix.architecture}}.tar && cd output/ && tar -cf ../agent-${{matrix.architecture}}.tar -C home/agent . && rm -rf output
|
||||
# We'll make a GitHub release and push the build (tar) as an artifact
|
||||
- uses: rickstaa/action-create-tag@v1
|
||||
with:
|
||||
tag: ${{ steps.short-sha.outputs.sha }}
|
||||
@@ -54,6 +55,17 @@ jobs:
|
||||
name: ${{ steps.short-sha.outputs.sha }}
|
||||
tag: ${{ steps.short-sha.outputs.sha }}
|
||||
artifacts: "agent-${{matrix.architecture}}.tar"
|
||||
# Taken from GoReleaser's own release workflow.
|
||||
# The available Snapcraft Action has some bugs described in the issue below.
|
||||
# The mkdirs are a hack for https://github.com/goreleaser/goreleaser/issues/1715.
|
||||
#- name: Setup Snapcraft
|
||||
# run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get -yq --no-install-suggests --no-install-recommends install snapcraft
|
||||
# mkdir -p $HOME/.cache/snapcraft/download
|
||||
# mkdir -p $HOME/.cache/snapcraft/stage-packages
|
||||
#- name: Use Snapcraft
|
||||
# run: tar -xf agent-${{matrix.architecture}}.tar && snapcraft
|
||||
build-other:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
||||
@@ -10,7 +10,7 @@ ENV GOSUMDB=off
|
||||
##########################################
|
||||
# Installing some additional dependencies.
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
RUN apt-get upgrade -y && apt-get update && apt-get install -y --no-install-recommends \
|
||||
git build-essential cmake pkg-config unzip libgtk2.0-dev \
|
||||
curl ca-certificates libcurl4-openssl-dev libssl-dev libjpeg62-turbo-dev && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
18
README.md
18
README.md
@@ -18,6 +18,7 @@
|
||||
[](https://brianmacdonald.github.io/Ethonate/address#0xf4a759C9436E2280Ea9cdd23d3144D95538fF4bE)
|
||||
<a target="_blank" href="https://twitter.com/kerberosio?ref_src=twsrc%5Etfw"><img src="https://img.shields.io/twitter/url.svg?label=Follow%20%40kerberosio&style=social&url=https%3A%2F%2Ftwitter.com%2Fkerberosio" alt="Twitter Widget"></a>
|
||||
[](https://discord.gg/Bj77Vqfp2G)
|
||||
[](https://snapcraft.io/kerberosio)
|
||||
|
||||
[**Docker Hub**](https://hub.docker.com/r/kerberos/agent) | [**Documentation**](https://doc.kerberos.io) | [**Website**](https://kerberos.io) | [**View Demo**](https://demo.kerberos.io)
|
||||
|
||||
@@ -41,6 +42,7 @@ There are a myriad of cameras out there (USB, IP and other cameras), and it migh
|
||||
|
||||
1. [Quickstart - Docker](#quickstart---docker)
|
||||
2. [Quickstart - Balena](#quickstart---balena)
|
||||
3. [Quickstart - Snap](#quickstart---snap)
|
||||
|
||||
### Introduction
|
||||
|
||||
@@ -82,6 +84,16 @@ Run Kerberos Agent with [Balena Cloud](https://www.balena.io/) super powers. Mon
|
||||
|
||||
[](https://dashboard.balena-cloud.com/deploy?repoUrl=https://github.com/kerberos-io/balena-agent)
|
||||
|
||||
## Quickstart - Snap
|
||||
|
||||
Run Kerberos Agent with our [Snapcraft package](https://snapcraft.io/kerberosio).
|
||||
|
||||
snap install kerberosio
|
||||
|
||||
Once installed you can find your Kerberos Agent configration at `/var/snap/kerberosio/common`. Run the Kerberos Agent as following
|
||||
|
||||
sudo kerberosio.agent -action=run -port=80
|
||||
|
||||
## A world of Kerberos Agents
|
||||
|
||||
The Kerberos Agent is an isolated and scalable video (surveillance) management agent with a strong focus on user experience, scalability, resilience, extension and integration. Next to the Kerberos Agent, Kerberos.io provides many other tools such as [Kerberos Factory](https://github.com/kerberos-io/factory), [Kerberos Vault](https://github.com/kerberos-io/vault) and [Kerberos Hub](https://github.com/kerberos-io/hub) to provide additional capabilities: bring your own cloud, bring your own storage, central overview, live streaming, machine learning etc.
|
||||
@@ -120,6 +132,7 @@ We have documented the different deployment models [in the `deployments` directo
|
||||
- [Terraform](https://github.com/kerberos-io/agent/tree/master/deployments#5-terraform)
|
||||
- [Salt](https://github.com/kerberos-io/agent/tree/master/deployments#6-salt)
|
||||
- [Balena](https://github.com/kerberos-io/agent/tree/master/deployments#8-balena)
|
||||
- [Snap](https://github.com/kerberos-io/agent/tree/master/deployments#9-snap)
|
||||
|
||||
By default your Kerberos Agents will store all its configuration and recordings inside the container. To help you automate and have a more consistent data governance, you can attach volumes to configure and persist data of your Kerberos Agents, and/or configure each Kerberos Agent through environment variables.
|
||||
|
||||
@@ -183,8 +196,11 @@ Next to attaching the configuration file, it is also possible to override the co
|
||||
| `AGENT_CAPTURE_IPCAMERA_ONVIF_XADDR` | ONVIF endpoint/address running on the camera. | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_ONVIF_USERNAME` | ONVIF username to authenticate against. | "" |
|
||||
| `AGENT_CAPTURE_IPCAMERA_ONVIF_PASSWORD` | ONVIF password to authenticate against. | "" |
|
||||
| `AGENT_CAPTURE_MOTION` | Toggle for enabling or disabling motion. | "true" |
|
||||
| `AGENT_CAPTURE_LIVEVIEW` | Toggle for enabling or disabling liveview. | "true" |
|
||||
| `AGENT_CAPTURE_SNAPSHOTS` | Toggle for enabling or disabling snapshot generation. | "true" |
|
||||
| `AGENT_CAPTURE_RECORDING` | Toggle for enabling making recordings. | "true" |
|
||||
| `AGENT_CAPTURE_CONTINUOUS` | Toggle for enabling continuous or motion based recording. | "false" |
|
||||
| `AGENT_CAPTURE_CONTINUOUS` | Toggle for enabling continuous "true" or motion "false". | "false" |
|
||||
| `AGENT_CAPTURE_PRERECORDING` | If `CONTINUOUS` set to `false`, specify the recording time (seconds) before after motion event. | "10" |
|
||||
| `AGENT_CAPTURE_POSTRECORDING` | If `CONTINUOUS` set to `false`, specify the recording time (seconds) after motion event. | "20" |
|
||||
| `AGENT_CAPTURE_MAXLENGTH` | The maximum length of a single recording (seconds). | "30" |
|
||||
|
||||
@@ -54,7 +54,9 @@ All of the previously deployments, `docker`, `kubernetes` and `openshift` are gr
|
||||
|
||||
## 6. Terraform
|
||||
|
||||
To be written
|
||||
Terraform is a tool for infrastructure provisioning to build infrastructure through code, often called Infrastructure as Code. So, Terraform allows you to automate and manage your infrastructure, your platform, and the services that run on that platform. By using Terraform you can deploy your Kerberos Agents remotely at scale.
|
||||
|
||||
> Learn more [about Kerberos Agent with Terraform](https://github.com/kerberos-io/agent/tree/master/deployments/terraform).
|
||||
|
||||
## 7. Salt
|
||||
|
||||
@@ -67,3 +69,11 @@ Balena Cloud provide a seamless way of building and deploying applications at sc
|
||||
Together with the Balena.io team we've build a Balena App, called [`video-surveillance`](https://hub.balena.io/apps/2064752/video-surveillance), which any can use to deploy a video surveillance system in a matter of minutes with all the expected management features you can think of.
|
||||
|
||||
> Learn more [about Kerberos Agent with Balena](https://github.com/kerberos-io/agent/tree/master/deployments/balena).
|
||||
|
||||
## 9. Snap
|
||||
|
||||
The Snap Store, also known as the Ubuntu Store , is a commercial centralized software store operated by Canonical. Similar to AppImage or Flatpak the Snap Store is able to provide up to date software no matter what version of Linux you are running and how old your libraries are.
|
||||
|
||||
We have published our own snap `Kerberos Agent` on the Snap Store, allowing you to seamless install a Kerberos Agent on your Linux devive.
|
||||
|
||||
> Learn more [about Kerberos Agent with Snap](https://github.com/kerberos-io/agent/tree/master/deployments/snap).
|
||||
|
||||
15
deployments/snap/README.md
Normal file
15
deployments/snap/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Deployment with Snap Store
|
||||
|
||||
By browsing to the Snap Store, you'll be able [to find our own snap `Kerberos Agent`](https://snapcraft.io/kerberosio). You can either install the `Kerberos Agent` through the command line.
|
||||
|
||||
snap install kerberosio
|
||||
|
||||
Or use the Desktop client to have a visual interface.
|
||||
|
||||

|
||||
|
||||
Once installed you can find your Kerberos Agent configration at `/var/snap/kerberosio/common`. Run the Kerberos Agent as following.
|
||||
|
||||
sudo kerberosio.agent -action=run -port=80
|
||||
|
||||
If successfull you'll be able to browse to port `80` or if you defined a different port. This will open the Kerberos Agent interface.
|
||||
BIN
deployments/snap/snapstore.png
Normal file
BIN
deployments/snap/snapstore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 616 KiB |
41
deployments/terraform/README.md
Normal file
41
deployments/terraform/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Deployment with Terraform
|
||||
|
||||
If you are using Terraform as part of your DevOps stack, you might utilise it to deploy your Kerberos Agents. Within this deployment folder we have added an example Terraform file `docker.tf`, which installs the Kerberos Agent `docker` container on a remote system over `SSH`. We might create our own provider in the future, or add additional examples for example `snap`, `kubernetes`, etc.
|
||||
|
||||
For this example we will install Kerberos Agent using `docker` on a remote `linux` machine. Therefore we'll make sure we have the `TelkomIndonesia/linux` provider initialised.
|
||||
|
||||
terraform init
|
||||
|
||||
Once initialised you should see similar output:
|
||||
|
||||
Initializing the backend...
|
||||
|
||||
Initializing provider plugins...
|
||||
- Reusing previous version of telkomindonesia/linux from the dependency lock file
|
||||
- Using previously-installed telkomindonesia/linux v0.7.0
|
||||
|
||||
Go and open the `docker.tf` file and locate the `linux` provider, modify following credentials accordingly. Make sure they match for creating an `SSH` connection.
|
||||
|
||||
provider "linux" {
|
||||
host = "x.y.z.u"
|
||||
port = 22
|
||||
user = "root"
|
||||
password = "password"
|
||||
}
|
||||
|
||||
Apply the `docker.tf` file, to install `docker` and the `kerberos/agent` docker container.
|
||||
|
||||
terraform apply
|
||||
|
||||
Once done you should see following output, and you should be able to reach the remote machine on port `80` or if configured differently the specified port you've defined.
|
||||
|
||||
Do you want to perform these actions?
|
||||
Terraform will perform the actions described above.
|
||||
Only 'yes' will be accepted to approve.
|
||||
|
||||
Enter a value: yes
|
||||
|
||||
linux_script.install_docker_kerberos_agent: Modifying... [id=a56cf7b0-db66-4f9b-beec-8a4dcef2a0c7]
|
||||
linux_script.install_docker_kerberos_agent: Modifications complete after 3s [id=a56cf7b0-db66-4f9b-beec-8a4dcef2a0c7]
|
||||
|
||||
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
|
||||
47
deployments/terraform/docker.tf
Normal file
47
deployments/terraform/docker.tf
Normal file
@@ -0,0 +1,47 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
linux = {
|
||||
source = "TelkomIndonesia/linux"
|
||||
version = "0.7.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "linux" {
|
||||
host = "x.y.z.u"
|
||||
port = 22
|
||||
user = "root"
|
||||
password = "password"
|
||||
}
|
||||
|
||||
locals {
|
||||
image = "kerberos/agent"
|
||||
version = "latest"
|
||||
port = 80
|
||||
}
|
||||
|
||||
resource "linux_script" "install_docker" {
|
||||
lifecycle_commands {
|
||||
create = "apt update && apt install -y $PACKAGE_NAME"
|
||||
read = "apt-cache policy $PACKAGE_NAME | grep 'Installed:' | grep -v '(none)' | awk '{ print $2 }' | xargs | tr -d '\n'"
|
||||
update = "apt update && apt install -y $PACKAGE_NAME"
|
||||
delete = "apt remove -y $PACKAGE_NAME"
|
||||
}
|
||||
environment = {
|
||||
PACKAGE_NAME = "docker"
|
||||
}
|
||||
}
|
||||
|
||||
resource "linux_script" "install_docker_kerberos_agent" {
|
||||
lifecycle_commands {
|
||||
create = "docker pull $IMAGE:$VERSION && docker run -d -p $PORT:80 --name agent $IMAGE:$VERSION"
|
||||
read = "docker inspect agent"
|
||||
update = "docker pull $IMAGE:$VERSION && docker rm agent --force && docker run -d -p $PORT:80 --name agent $IMAGE:$VERSION"
|
||||
delete = "docker rm agent --force"
|
||||
}
|
||||
environment = {
|
||||
IMAGE = local.image
|
||||
VERSION = local.version
|
||||
PORT = local.port
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func main() {
|
||||
flag.Parse()
|
||||
|
||||
timezone, _ := time.LoadLocation("CET")
|
||||
log.Log.Init(timezone)
|
||||
log.Log.Init(configDirectory, timezone)
|
||||
|
||||
switch action {
|
||||
|
||||
@@ -102,11 +102,11 @@ func main() {
|
||||
|
||||
// Check the folder permissions, it might be that we do not have permissions to write
|
||||
// recordings, update the configuration or save snapshots.
|
||||
utils.CheckDataDirectoryPermissions()
|
||||
utils.CheckDataDirectoryPermissions(configDirectory)
|
||||
|
||||
// Set timezone
|
||||
timezone, _ := time.LoadLocation(configuration.Config.Timezone)
|
||||
log.Log.Init(timezone)
|
||||
log.Log.Init(configDirectory, timezone)
|
||||
|
||||
// Check if we have a device Key or not, if not
|
||||
// we will generate one.
|
||||
|
||||
@@ -17,15 +17,15 @@ import (
|
||||
"github.com/kerberos-io/joy4/av"
|
||||
)
|
||||
|
||||
func CleanupRecordingDirectory(configuration *models.Configuration) {
|
||||
func CleanupRecordingDirectory(configDirectory string, configuration *models.Configuration) {
|
||||
autoClean := configuration.Config.AutoClean
|
||||
if autoClean == "true" {
|
||||
if autoClean != "false" {
|
||||
maxSize := configuration.Config.MaxDirectorySize
|
||||
if maxSize == 0 {
|
||||
maxSize = 300
|
||||
}
|
||||
// Total size of the recording directory.
|
||||
recordingsDirectory := "./data/recordings"
|
||||
recordingsDirectory := configDirectory + "/data/recordings"
|
||||
size, err := utils.DirSize(recordingsDirectory)
|
||||
if err == nil {
|
||||
sizeInMB := size / 1000 / 1000
|
||||
@@ -51,7 +51,7 @@ func CleanupRecordingDirectory(configuration *models.Configuration) {
|
||||
}
|
||||
}
|
||||
|
||||
func HandleRecordStream(queue *pubsub.Queue, configuration *models.Configuration, communication *models.Communication, streams []av.CodecData) {
|
||||
func HandleRecordStream(queue *pubsub.Queue, configDirectory string, configuration *models.Configuration, communication *models.Communication, streams []av.CodecData) {
|
||||
|
||||
config := configuration.Config
|
||||
|
||||
@@ -134,13 +134,13 @@ func HandleRecordStream(queue *pubsub.Queue, configuration *models.Configuration
|
||||
}
|
||||
|
||||
// Create a symbol link.
|
||||
fc, _ := os.Create("./data/cloud/" + name)
|
||||
fc, _ := os.Create(configDirectory + "/data/cloud/" + name)
|
||||
fc.Close()
|
||||
|
||||
recordingStatus = "idle"
|
||||
|
||||
// Clean up the recording directory if necessary.
|
||||
CleanupRecordingDirectory(configuration)
|
||||
CleanupRecordingDirectory(configDirectory, configuration)
|
||||
}
|
||||
|
||||
// If not yet started and a keyframe, let's make a recording
|
||||
@@ -192,7 +192,7 @@ func HandleRecordStream(queue *pubsub.Queue, configuration *models.Configuration
|
||||
"769"
|
||||
|
||||
name = s + ".mp4"
|
||||
fullName = "./data/recordings/" + name
|
||||
fullName = configDirectory + "/data/recordings/" + name
|
||||
|
||||
// Running...
|
||||
log.Log.Info("Recording started")
|
||||
@@ -259,7 +259,7 @@ func HandleRecordStream(queue *pubsub.Queue, configuration *models.Configuration
|
||||
}
|
||||
|
||||
// Create a symbol link.
|
||||
fc, _ := os.Create("./data/cloud/" + name)
|
||||
fc, _ := os.Create(configDirectory + "/data/cloud/" + name)
|
||||
fc.Close()
|
||||
|
||||
recordingStatus = "idle"
|
||||
@@ -315,7 +315,7 @@ func HandleRecordStream(queue *pubsub.Queue, configuration *models.Configuration
|
||||
"769"
|
||||
|
||||
name := s + ".mp4"
|
||||
fullName := "./data/recordings/" + name
|
||||
fullName := configDirectory + "/data/recordings/" + name
|
||||
|
||||
// Running...
|
||||
log.Log.Info("HandleRecordStream: Recording started")
|
||||
@@ -406,11 +406,11 @@ func HandleRecordStream(queue *pubsub.Queue, configuration *models.Configuration
|
||||
}
|
||||
|
||||
// Create a symbol linc.
|
||||
fc, _ := os.Create("./data/cloud/" + name)
|
||||
fc, _ := os.Create(configDirectory + "/data/cloud/" + name)
|
||||
fc.Close()
|
||||
|
||||
// Clean up the recording directory if necessary.
|
||||
CleanupRecordingDirectory(configuration)
|
||||
CleanupRecordingDirectory(configDirectory, configuration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ import (
|
||||
"github.com/kerberos-io/agent/machinery/src/webrtc"
|
||||
)
|
||||
|
||||
func PendingUpload() {
|
||||
ff, err := utils.ReadDirectory("./data/cloud/")
|
||||
func PendingUpload(configDirectory string) {
|
||||
ff, err := utils.ReadDirectory(configDirectory + "/data/cloud/")
|
||||
if err == nil {
|
||||
for _, f := range ff {
|
||||
log.Log.Info(f.Name())
|
||||
@@ -41,12 +41,12 @@ func PendingUpload() {
|
||||
}
|
||||
}
|
||||
|
||||
func HandleUpload(configuration *models.Configuration, communication *models.Communication) {
|
||||
func HandleUpload(configDirectory string, configuration *models.Configuration, communication *models.Communication) {
|
||||
|
||||
log.Log.Debug("HandleUpload: started")
|
||||
|
||||
config := configuration.Config
|
||||
watchDirectory := "./data/cloud/"
|
||||
watchDirectory := configDirectory + "/data/cloud/"
|
||||
|
||||
if config.Offline == "true" {
|
||||
log.Log.Debug("HandleUpload: stopping as Offline is enabled.")
|
||||
@@ -121,8 +121,8 @@ func HandleUpload(configuration *models.Configuration, communication *models.Com
|
||||
|
||||
// Check if we need to remove the original recording
|
||||
// removeAfterUpload is set to false by default
|
||||
if config.RemoveAfterUpload == "true" {
|
||||
err := os.Remove("./data/recordings/" + fileName)
|
||||
if config.RemoveAfterUpload != "false" {
|
||||
err := os.Remove(configDirectory + "/data/recordings/" + fileName)
|
||||
if err != nil {
|
||||
log.Log.Error("HandleUpload: " + err.Error())
|
||||
}
|
||||
@@ -614,7 +614,7 @@ func VerifyHub(c *gin.Context) {
|
||||
// @Summary Will verify the persistence.
|
||||
// @Description Will verify the persistence.
|
||||
// @Success 200 {object} models.APIResponse
|
||||
func VerifyPersistence(c *gin.Context) {
|
||||
func VerifyPersistence(c *gin.Context, configDirectory string) {
|
||||
|
||||
var config models.Config
|
||||
err := c.BindJSON(&config)
|
||||
@@ -636,7 +636,7 @@ func VerifyPersistence(c *gin.Context) {
|
||||
} else {
|
||||
|
||||
// Open test-480p.mp4
|
||||
file, err := os.Open("./data/test-480p.mp4")
|
||||
file, err := os.Open(configDirectory + "/data/test-480p.mp4")
|
||||
if err != nil {
|
||||
msg := "VerifyPersistence: error reading test-480p.mp4: " + err.Error()
|
||||
log.Log.Error(msg)
|
||||
@@ -741,7 +741,7 @@ func VerifyPersistence(c *gin.Context) {
|
||||
"_6-967003_" + config.Name + "_200-200-400-400_24_769.mp4"
|
||||
|
||||
// Open test-480p.mp4
|
||||
file, err := os.Open("./data/test-480p.mp4")
|
||||
file, err := os.Open(configDirectory + "/test-480p.mp4")
|
||||
if err != nil {
|
||||
msg := "VerifyPersistence: error reading test-480p.mp4: " + err.Error()
|
||||
log.Log.Error(msg)
|
||||
|
||||
@@ -20,14 +20,14 @@ import (
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
func GetImageFromFilePath() (image.Image, error) {
|
||||
snapshotDirectory := "./data/snapshots"
|
||||
func GetImageFromFilePath(configDirectory string) (image.Image, error) {
|
||||
snapshotDirectory := configDirectory + "/data/snapshots"
|
||||
files, err := ioutil.ReadDir(snapshotDirectory)
|
||||
if err == nil && len(files) > 1 {
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].ModTime().Before(files[j].ModTime())
|
||||
})
|
||||
filePath := "./data/snapshots/" + files[1].Name()
|
||||
filePath := configDirectory + "/data/snapshots/" + files[1].Name()
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -44,7 +44,7 @@ func GetImageFromFilePath() (image.Image, error) {
|
||||
// selected language, and if the installation was completed or not.
|
||||
func ReadUserConfig(configDirectory string) (userConfig models.User) {
|
||||
for {
|
||||
jsonFile, err := os.Open("./data/config/user.json")
|
||||
jsonFile, err := os.Open(configDirectory + "/data/config/user.json")
|
||||
if err != nil {
|
||||
log.Log.Error("Config file is not found " + configDirectory + "/data/config/user.json, trying again in 5s: " + err.Error())
|
||||
time.Sleep(5 * time.Second)
|
||||
@@ -84,9 +84,14 @@ func OpenConfig(configDirectory string, configuration *models.Configuration) {
|
||||
collection := db.Collection("configuration")
|
||||
|
||||
var globalConfig models.Config
|
||||
err := collection.FindOne(context.Background(), bson.M{
|
||||
res := collection.FindOne(context.Background(), bson.M{
|
||||
"type": "global",
|
||||
}).Decode(&globalConfig)
|
||||
})
|
||||
|
||||
if res.Err() != nil {
|
||||
log.Log.Error("Could not find global configuration, using default configuration.")
|
||||
}
|
||||
err := res.Decode(&globalConfig)
|
||||
if err != nil {
|
||||
log.Log.Error("Could not find global configuration, using default configuration.")
|
||||
}
|
||||
@@ -94,10 +99,14 @@ func OpenConfig(configDirectory string, configuration *models.Configuration) {
|
||||
|
||||
var customConfig models.Config
|
||||
deploymentName := os.Getenv("DEPLOYMENT_NAME")
|
||||
err = collection.FindOne(context.Background(), bson.M{
|
||||
res = collection.FindOne(context.Background(), bson.M{
|
||||
"type": "config",
|
||||
"name": deploymentName,
|
||||
}).Decode(&customConfig)
|
||||
})
|
||||
if res.Err() != nil {
|
||||
log.Log.Error("Could not find configuration for " + deploymentName + ", using global configuration.")
|
||||
}
|
||||
err = res.Decode(&customConfig)
|
||||
if err != nil {
|
||||
log.Log.Error("Could not find configuration for " + deploymentName + ", using global configuration.")
|
||||
}
|
||||
|
||||
@@ -165,7 +165,8 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
||||
}
|
||||
|
||||
if cameraSettings.RTSP != rtspUrl || cameraSettings.SubRTSP != subRtspUrl || cameraSettings.Width != width || cameraSettings.Height != height || cameraSettings.Num != num || cameraSettings.Denum != denum || cameraSettings.Codec != videoStream.(av.VideoCodecData).Type() {
|
||||
if cameraSettings.Initialized {
|
||||
|
||||
if cameraSettings.RTSP != "" && cameraSettings.SubRTSP != "" && cameraSettings.Initialized {
|
||||
decoder.Close()
|
||||
if subStreamEnabled {
|
||||
subDecoder.Close()
|
||||
@@ -260,10 +261,10 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
||||
}
|
||||
|
||||
// Handle recording, will write an mp4 to disk.
|
||||
go capture.HandleRecordStream(queue, configuration, communication, streams)
|
||||
go capture.HandleRecordStream(queue, configDirectory, configuration, communication, streams)
|
||||
|
||||
// Handle Upload to cloud provider (Kerberos Hub, Kerberos Vault and others)
|
||||
go cloud.HandleUpload(configuration, communication)
|
||||
go cloud.HandleUpload(configDirectory, configuration, communication)
|
||||
|
||||
// Handle ONVIF actions
|
||||
go onvif.HandleONVIFActions(configuration, communication)
|
||||
|
||||
@@ -21,7 +21,7 @@ var Log = Logging{
|
||||
|
||||
var gologging = logging.MustGetLogger("gologger")
|
||||
|
||||
func ConfigureGoLogging(timezone *time.Location) {
|
||||
func ConfigureGoLogging(configDirectory string, timezone *time.Location) {
|
||||
// Logging
|
||||
var format = logging.MustStringFormatter(
|
||||
`%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`,
|
||||
@@ -32,7 +32,7 @@ func ConfigureGoLogging(timezone *time.Location) {
|
||||
stdBackend := logging.NewLogBackend(os.Stderr, "", 0)
|
||||
stdBackendLeveled := logging.NewBackendFormatter(stdBackend, format)
|
||||
fileBackend := logging.NewLogBackend(&lumberjack.Logger{
|
||||
Filename: "./data/log/machinery.txt",
|
||||
Filename: configDirectory + "/data/log/machinery.txt",
|
||||
MaxSize: 2, // megabytes
|
||||
Compress: true, // disabled by default
|
||||
}, "", 0)
|
||||
@@ -75,10 +75,10 @@ type Logging struct {
|
||||
Level string
|
||||
}
|
||||
|
||||
func (self *Logging) Init(timezone *time.Location) {
|
||||
func (self *Logging) Init(configDirectory string, timezone *time.Location) {
|
||||
switch self.Logger {
|
||||
case "go-logging":
|
||||
ConfigureGoLogging(timezone)
|
||||
ConfigureGoLogging(configDirectory, timezone)
|
||||
case "logrus":
|
||||
ConfigureLogrus(timezone)
|
||||
default:
|
||||
|
||||
@@ -78,7 +78,7 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
||||
}
|
||||
|
||||
// The total number of recordings stored in the directory.
|
||||
recordingDirectory := "./data/recordings"
|
||||
recordingDirectory := configDirectory + "/data/recordings"
|
||||
numberOfRecordings := utils.NumberOfMP4sInDirectory(recordingDirectory)
|
||||
|
||||
// All days stored in this agent.
|
||||
@@ -115,7 +115,7 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
||||
if eventFilter.NumberOfElements == 0 {
|
||||
eventFilter.NumberOfElements = 10
|
||||
}
|
||||
recordingDirectory := "./data/recordings"
|
||||
recordingDirectory := configDirectory + "/data/recordings"
|
||||
files, err := utils.ReadDirectory(recordingDirectory)
|
||||
if err == nil {
|
||||
events := utils.GetSortedDirectory(files)
|
||||
@@ -137,7 +137,7 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
||||
})
|
||||
|
||||
api.GET("/days", func(c *gin.Context) {
|
||||
recordingDirectory := "./data/recordings"
|
||||
recordingDirectory := configDirectory + "/data/recordings"
|
||||
files, err := utils.ReadDirectory(recordingDirectory)
|
||||
if err == nil {
|
||||
events := utils.GetSortedDirectory(files)
|
||||
@@ -205,7 +205,7 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
||||
})
|
||||
|
||||
api.POST("/persistence/verify", func(c *gin.Context) {
|
||||
cloud.VerifyPersistence(c)
|
||||
cloud.VerifyPersistence(c, configDirectory)
|
||||
})
|
||||
|
||||
// Streaming handler
|
||||
@@ -215,7 +215,7 @@ func AddRoutes(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware, configDirect
|
||||
// We will only send an image once per second.
|
||||
time.Sleep(time.Second * 1)
|
||||
log.Log.Info("AddRoutes (/stream): reading from MJPEG stream")
|
||||
img, err := components.GetImageFromFilePath()
|
||||
img, err := components.GetImageFromFilePath(configDirectory)
|
||||
return img, err
|
||||
}
|
||||
h := components.StartMotionJPEG(imageFunction, 80)
|
||||
|
||||
@@ -76,7 +76,9 @@ func StartServer(configDirectory string, configuration *models.Configuration, co
|
||||
r.Use(static.Serve("/media", static.LocalFile(configDirectory+"/www", true)))
|
||||
r.Use(static.Serve("/settings", static.LocalFile(configDirectory+"/www", true)))
|
||||
r.Use(static.Serve("/login", static.LocalFile(configDirectory+"/www", true)))
|
||||
r.Handle("GET", "/file/*filepath", Files)
|
||||
r.Handle("GET", "/file/*filepath", func(c *gin.Context) {
|
||||
Files(c, configDirectory)
|
||||
})
|
||||
|
||||
// Run the api on port
|
||||
err = r.Run(":" + configuration.Port)
|
||||
@@ -85,8 +87,8 @@ func StartServer(configDirectory string, configuration *models.Configuration, co
|
||||
}
|
||||
}
|
||||
|
||||
func Files(c *gin.Context) {
|
||||
func Files(c *gin.Context, configDirectory string) {
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
c.Header("Content-Type", "video/mp4")
|
||||
c.File("./data/recordings" + c.Param("filepath"))
|
||||
c.File(configDirectory + "/data/recordings" + c.Param("filepath"))
|
||||
}
|
||||
|
||||
@@ -110,15 +110,15 @@ func CountDigits(i int64) (count int) {
|
||||
return count
|
||||
}
|
||||
|
||||
func CheckDataDirectoryPermissions() error {
|
||||
recordingsDirectory := "./data/recordings"
|
||||
configDirectory := "./data/config"
|
||||
snapshotsDirectory := "./data/snapshots"
|
||||
cloudDirectory := "./data/cloud"
|
||||
func CheckDataDirectoryPermissions(configDirectory string) error {
|
||||
recordingsDirectory := configDirectory + "/data/recordings"
|
||||
configurationDirectory := configDirectory + "/data/config"
|
||||
snapshotsDirectory := configDirectory + "/data/snapshots"
|
||||
cloudDirectory := configDirectory + "/data/cloud"
|
||||
|
||||
err := CheckDirectoryPermissions(recordingsDirectory)
|
||||
if err == nil {
|
||||
err = CheckDirectoryPermissions(configDirectory)
|
||||
err = CheckDirectoryPermissions(configurationDirectory)
|
||||
if err == nil {
|
||||
err = CheckDirectoryPermissions(snapshotsDirectory)
|
||||
if err == nil {
|
||||
|
||||
6
snap/hooks/configure
vendored
Normal file
6
snap/hooks/configure
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
cp -R $SNAP/data $SNAP_COMMON/
|
||||
cp -R $SNAP/www $SNAP_COMMON/
|
||||
cp -R $SNAP/version $SNAP_COMMON/
|
||||
cp -R $SNAP/mp4fragment $SNAP_COMMON/
|
||||
23
snap/snapcraft.yaml
Normal file
23
snap/snapcraft.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
name: kerberosio # you probably want to 'snapcraft register <name>'
|
||||
base: core22 # the base snap is the execution environment for this snap
|
||||
version: '3.0.0' # just for humans, typically '1.2+git' or '1.3.2'
|
||||
summary: A stand-alone open source video surveillance system # 79 char long summary
|
||||
description: |
|
||||
Kerberos Agent is an isolated and scalable video (surveillance) management
|
||||
agent made available as Open Source under the MIT License. This means that
|
||||
all the source code is available for you or your company, and you can use,
|
||||
transform and distribute the source code; as long you keep a reference of
|
||||
the original license. Kerberos Agent can be used for commercial usage.
|
||||
|
||||
grade: stable # stable # must be 'stable' to release into candidate/stable channels
|
||||
confinement: strict # use 'strict' once you have the right plugs and slots
|
||||
environment:
|
||||
GIN_MODE: release
|
||||
apps:
|
||||
agent:
|
||||
command: main -config /var/snap/kerberosio/common
|
||||
plugs: [ network, network-bind ]
|
||||
parts:
|
||||
agent:
|
||||
source: . #https://github.com/kerberos-io/agent/releases/download/21c0e01/agent-amd64.tar
|
||||
plugin: dump
|
||||
@@ -729,7 +729,7 @@ class Settings extends React.Component {
|
||||
/>
|
||||
)}
|
||||
{verifyOnvifError && (
|
||||
<InfoBar type="alert" message={`${verifyOnvifErrorMessage}`} />
|
||||
<InfoBar type="alert" message={verifyOnvifErrorMessage} />
|
||||
)}
|
||||
|
||||
{loadingHub && (
|
||||
|
||||
Reference in New Issue
Block a user