diff --git a/main.go b/main.go
index c707962..7a27002 100644
--- a/main.go
+++ b/main.go
@@ -52,10 +52,12 @@ func main() {
Scheme: "http",
Host: "localhost:5173",
})
+ e.Router.GET("/icons/*", apis.StaticDirectoryHandler(os.DirFS("./site/public/icons"), false))
e.Router.Any("/*", echo.WrapHandler(proxy))
e.Router.Any("/", echo.WrapHandler(proxy))
default:
- e.Router.GET("/*", apis.StaticDirectoryHandler(os.DirFS("./site/dist"), true))
+ e.Router.GET("/icons/*", apis.StaticDirectoryHandler(os.DirFS("./site/dist/icons"), false))
+ e.Router.Any("/*", apis.StaticDirectoryHandler(os.DirFS("./site/dist"), true))
}
return nil
})
@@ -103,7 +105,7 @@ func main() {
// create ssh key if it doesn't exist
getSSHKey()
// api route to return public key
- e.Router.GET("/api/qoma/getkey", func(c echo.Context) error {
+ e.Router.GET("/api/beszel/getkey", func(c echo.Context) error {
requestData := apis.RequestInfo(c)
if requestData.AuthRecord == nil {
return apis.NewForbiddenError("Forbidden", nil)
@@ -120,7 +122,7 @@ func main() {
// other api routes
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
// check if first time setup on login page
- e.Router.GET("/api/qoma/first-run", func(c echo.Context) error {
+ e.Router.GET("/api/beszel/first-run", func(c echo.Context) error {
adminNum, err := app.Dao().TotalAdmins()
if err != nil {
return err
@@ -405,7 +407,7 @@ func handleStatusAlerts(newStatus string, oldRecord *models.Record) error {
sendAlert(EmailData{
to: user.Get("email").(string),
subj: fmt.Sprintf("Connection to %s is %s %v", systemName, alertStatus, emoji),
- body: fmt.Sprintf("Connection to %s is %s %v\n\n- Qoma", systemName, alertStatus, emoji),
+ body: fmt.Sprintf("Connection to %s is %s\n\n- Beszel", systemName, alertStatus),
})
}
return nil
diff --git a/migrations/initial-settings.go b/migrations/initial-settings.go
index dcb0a37..c528245 100644
--- a/migrations/initial-settings.go
+++ b/migrations/initial-settings.go
@@ -11,7 +11,7 @@ func init() {
dao := daos.New(db)
settings, _ := dao.FindSettings()
- settings.Meta.AppName = "Qoma"
+ settings.Meta.AppName = "Beszel"
settings.Meta.HideControls = true
return dao.SaveSettings(settings)
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..cec739f
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,77 @@
+# Beszel
+
+A lightweight resource monitoring hub with historical data, docker stats, and alerts.
+
+
+
+
+
+
+
+
+
+
+## Introduction
+
+Beszel has two components: the hub and the agent.
+
+The hub is a web application built on top of [PocketBase](https://pocketbase.io/) that provides a dashboard to view and manage your connected systems.
+
+The agent runs on each system you want to monitor. It provides a minimal SSH server through which it communicates system information to the hub.
+
+## Installation
+
+The hub and agent are distributed as single binary files, as well as docker images.
+
+> **Note**: The docker version does not support disk I/O stats, so use the binary version if that's important to you.
+
+### Docker
+
+### Binary
+
+## OAuth / OIDC integration
+
+Beszel supports OpenID Connect and many OAuth2 authentication providers (see list below). To enable this, you will need to:
+
+1. Create an OAuth2 application using your provider of choice. The redirect / callback URL should be `/api/oauth2-redirect`.
+2. When you have the client ID and secret, go to the "Auth providers" page and enable your provider.
+
+
+ Supported provider list
+
+- Apple
+- Bitbucket
+- Discord
+- Facebook
+- Gitea
+- Gitee
+- GitHub
+- GitLab
+- Google
+- Instagram
+- Kakao
+- LiveChat
+- mailcow
+- Microsoft
+- OpenID Connect
+- Patreon (v2)
+- Planning Center
+- Spotify
+- Strava
+- Twitch
+- Twitter
+- VK
+- Yandex
+
+
+## API
+
+Because Beszel is built on top of PocketBase, you can use the normal PocketBase API to read or update your data in your own applications.
+
+## Security
+
+The hub and agent communicate over SSH, so they do not need to be exposed to the internet.
+
+When the hub is started for the first time, it generates an ED25519 key pair.
+
+The agent's SSH server is configured to only accept connections using this key. It also does not provide a pty or accept any input, so it is not possible to execute commands on the agent.
diff --git a/site/index.html b/site/index.html
index e3e71c6..6002b70 100644
--- a/site/index.html
+++ b/site/index.html
@@ -4,7 +4,7 @@
- Qoma
+ Beszel
\ No newline at end of file
diff --git a/site/public/icons/bitbucket.svg b/site/public/icons/bitbucket.svg
new file mode 100644
index 0000000..75a844a
--- /dev/null
+++ b/site/public/icons/bitbucket.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/discord.svg b/site/public/icons/discord.svg
new file mode 100644
index 0000000..ebde05f
--- /dev/null
+++ b/site/public/icons/discord.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/facebook.svg b/site/public/icons/facebook.svg
new file mode 100644
index 0000000..6e28668
--- /dev/null
+++ b/site/public/icons/facebook.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/gitea.svg b/site/public/icons/gitea.svg
new file mode 100644
index 0000000..8915778
--- /dev/null
+++ b/site/public/icons/gitea.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/gitee.svg b/site/public/icons/gitee.svg
new file mode 100644
index 0000000..294cfba
--- /dev/null
+++ b/site/public/icons/gitee.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/github.svg b/site/public/icons/github.svg
new file mode 100644
index 0000000..c979f5e
--- /dev/null
+++ b/site/public/icons/github.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/gitlab.svg b/site/public/icons/gitlab.svg
new file mode 100644
index 0000000..4902ba1
--- /dev/null
+++ b/site/public/icons/gitlab.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/google.svg b/site/public/icons/google.svg
new file mode 100644
index 0000000..9f85fc9
--- /dev/null
+++ b/site/public/icons/google.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/instagram.svg b/site/public/icons/instagram.svg
new file mode 100644
index 0000000..ee03d71
--- /dev/null
+++ b/site/public/icons/instagram.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/lock.svg b/site/public/icons/lock.svg
new file mode 100644
index 0000000..dad77ab
--- /dev/null
+++ b/site/public/icons/lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/oidc.svg b/site/public/icons/oidc.svg
new file mode 100644
index 0000000..fe4c1cb
--- /dev/null
+++ b/site/public/icons/oidc.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/patreon.svg b/site/public/icons/patreon.svg
new file mode 100644
index 0000000..4d6de14
--- /dev/null
+++ b/site/public/icons/patreon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/spotify.svg b/site/public/icons/spotify.svg
new file mode 100644
index 0000000..885702b
--- /dev/null
+++ b/site/public/icons/spotify.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/strava.svg b/site/public/icons/strava.svg
new file mode 100644
index 0000000..8a63a00
--- /dev/null
+++ b/site/public/icons/strava.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/twitch.svg b/site/public/icons/twitch.svg
new file mode 100644
index 0000000..f1c7f61
--- /dev/null
+++ b/site/public/icons/twitch.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/public/icons/twitter.svg b/site/public/icons/twitter.svg
new file mode 100644
index 0000000..47967f1
--- /dev/null
+++ b/site/public/icons/twitter.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/src/components/add-server.tsx b/site/src/components/add-server.tsx
index a57cc3c..2b5bf78 100644
--- a/site/src/components/add-server.tsx
+++ b/site/src/components/add-server.tsx
@@ -27,8 +27,8 @@ export function AddServerButton() {
function copyDockerCompose(port: string) {
copyToClipboard(`services:
agent:
- image: 'henrygd/qoma-agent'
- container_name: 'qoma-agent'
+ image: 'henrygd/beszel-agent'
+ container_name: 'beszel-agent'
restart: unless-stopped
ports:
- '${port}:45876'
@@ -43,7 +43,7 @@ export function AddServerButton() {
return
}
// get public key
- pb.send('/api/qoma/getkey', {}).then(({ key }) => {
+ pb.send('/api/beszel/getkey', {}).then(({ key }) => {
$publicKey.set(key)
})
}, [open])
diff --git a/site/src/components/command-palette.tsx b/site/src/components/command-palette.tsx
index 3b6432d..16eba21 100644
--- a/site/src/components/command-palette.tsx
+++ b/site/src/components/command-palette.tsx
@@ -21,8 +21,9 @@ import {
} from '@/components/ui/command'
import { useEffect, useState } from 'react'
import { useStore } from '@nanostores/react'
-import { $systems, navigate } from '@/lib/stores'
+import { $systems } from '@/lib/stores'
import { isAdmin } from '@/lib/utils'
+import { navigate } from './router'
export default function CommandPalette() {
const [open, setOpen] = useState(false)
diff --git a/site/src/components/login.tsx b/site/src/components/login.tsx
deleted file mode 100644
index 4370e9d..0000000
--- a/site/src/components/login.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import { UserAuthForm } from '@/components/user-auth-form'
-import { Logo } from './logo'
-import { useEffect, useState } from 'react'
-import { pb } from '@/lib/stores'
-
-export default function () {
- const [isFirstRun, setFirstRun] = useState(false)
-
- useEffect(() => {
- document.title = 'Login / Qoma'
-
- pb.send('/api/qoma/first-run', {}).then(({ firstRun }) => {
- setFirstRun(firstRun)
- })
- }, [])
-
- return (
-
-
-
-
-
-
- Qoma
-
-
- {isFirstRun ? 'Please create an admin account' : 'Please sign in to your account'}
-
-
-
-
- {/* todo: add forgot password section to readme and link to section
- reset w/ command or link to pb reset */}
-
- Forgot password?
-
-