From b81c09c3583e930d99b2a2cbf29706f8f3d63d28 Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Sun, 21 Jul 2024 22:37:56 -0400 Subject: [PATCH] change server verbiage to system --- .../{add-server.tsx => add-system.tsx} | 2 +- hub/site/src/components/command-palette.tsx | 46 +++++++++++-------- hub/site/src/components/router.tsx | 2 +- hub/site/src/components/routes/home.tsx | 2 +- .../routes/{server.tsx => system.tsx} | 22 ++++----- .../columns.tsx | 0 .../systems-table.tsx | 10 ++-- hub/site/src/lib/utils.ts | 2 +- hub/site/src/main.tsx | 20 ++++---- readme.md | 35 ++++++++++---- 10 files changed, 82 insertions(+), 59 deletions(-) rename hub/site/src/components/{add-server.tsx => add-system.tsx} (99%) rename hub/site/src/components/routes/{server.tsx => system.tsx} (96%) rename hub/site/src/components/{server-table => systems-table}/columns.tsx (100%) rename hub/site/src/components/{server-table => systems-table}/systems-table.tsx (97%) diff --git a/hub/site/src/components/add-server.tsx b/hub/site/src/components/add-system.tsx similarity index 99% rename from hub/site/src/components/add-server.tsx rename to hub/site/src/components/add-system.tsx index f55eb87..485f1e6 100644 --- a/hub/site/src/components/add-server.tsx +++ b/hub/site/src/components/add-system.tsx @@ -19,7 +19,7 @@ import { useStore } from '@nanostores/react' import { copyToClipboard } from '@/lib/utils' import { SystemStats } from '@/types' -export function AddServerButton() { +export function AddSystemButton() { const [open, setOpen] = useState(false) const port = useRef() as MutableRefObject const publicKey = useStore($publicKey) diff --git a/hub/site/src/components/command-palette.tsx b/hub/site/src/components/command-palette.tsx index 4f2f298..f405a66 100644 --- a/hub/site/src/components/command-palette.tsx +++ b/hub/site/src/components/command-palette.tsx @@ -1,7 +1,4 @@ -'use client' - import { - Database, DatabaseBackupIcon, Github, LayoutDashboard, @@ -30,7 +27,7 @@ import { navigate } from './router' export default function CommandPalette() { const [open, setOpen] = useState(false) - const servers = useStore($systems) + const systems = useStore($systems) useEffect(() => { const down = (e: KeyboardEvent) => { @@ -72,22 +69,26 @@ export default function CommandPalette() { GitHub - - - {servers.map((server) => ( - { - navigate(`/server/${server.name}`) - setOpen((open) => !open) - }} - > - - {server.name} - {server.host} - - ))} - + {systems.length > 0 && ( + <> + + + {systems.map((system) => ( + { + navigate(`/system/${system.name}`) + setOpen(false) + }} + > + + {system.name} + {system.host} + + ))} + + + )} {isAdmin() && ( <> @@ -95,6 +96,7 @@ export default function CommandPalette() { { + setOpen(false) window.open('/_/', '_blank') }} > @@ -104,6 +106,7 @@ export default function CommandPalette() { { + setOpen(false) window.open('/_/#/logs', '_blank') }} > @@ -113,6 +116,7 @@ export default function CommandPalette() { { + setOpen(false) window.open('/_/#/settings/backups', '_blank') }} > @@ -123,6 +127,7 @@ export default function CommandPalette() { { + setOpen(false) window.open('/_/#/settings/auth-providers', '_blank') }} > @@ -133,6 +138,7 @@ export default function CommandPalette() { { + setOpen(false) window.open('/_/#/settings/mail', '_blank') }} > diff --git a/hub/site/src/components/router.tsx b/hub/site/src/components/router.tsx index 0bf76f2..299710e 100644 --- a/hub/site/src/components/router.tsx +++ b/hub/site/src/components/router.tsx @@ -3,7 +3,7 @@ import { createRouter } from '@nanostores/router' export const $router = createRouter( { home: '/', - server: '/server/:name', + server: '/system/:name', 'forgot-password': '/forgot-password', }, { links: false } diff --git a/hub/site/src/components/routes/home.tsx b/hub/site/src/components/routes/home.tsx index 45a2097..7787447 100644 --- a/hub/site/src/components/routes/home.tsx +++ b/hub/site/src/components/routes/home.tsx @@ -1,7 +1,7 @@ import { Suspense, lazy, useEffect } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card' -const SystemsTable = lazy(() => import('../server-table/systems-table')) +const SystemsTable = lazy(() => import('../systems-table/systems-table')) export default function () { useEffect(() => { diff --git a/hub/site/src/components/routes/server.tsx b/hub/site/src/components/routes/system.tsx similarity index 96% rename from hub/site/src/components/routes/server.tsx rename to hub/site/src/components/routes/system.tsx index 6cbbfd6..f7c0d89 100644 --- a/hub/site/src/components/routes/server.tsx +++ b/hub/site/src/components/routes/system.tsx @@ -20,14 +20,14 @@ const DiskIoChart = lazy(() => import('../charts/disk-io-chart')) const BandwidthChart = lazy(() => import('../charts/bandwidth-chart')) export default function ServerDetail({ name }: { name: string }) { - const servers = useStore($systems) + const systems = useStore($systems) const updatedSystem = useStore($updatedSystem) const chartTime = useStore($chartTime) const [ticks, setTicks] = useState([] as number[]) const [server, setServer] = useState({} as SystemRecord) const [containers, setContainers] = useState([] as ContainerStatsRecord[]) - const [serverStats, setServerStats] = useState([] as SystemStatsRecord[]) + const [systemStats, setSystemStats] = useState([] as SystemStatsRecord[]) const [cpuChartData, setCpuChartData] = useState([] as { time: number; cpu: number }[]) const [memChartData, setMemChartData] = useState( [] as { time: number; mem: number; memUsed: number; memCache: number }[] @@ -57,7 +57,7 @@ export default function ServerDetail({ name }: { name: string }) { }, [name]) const resetCharts = useCallback(() => { - setServerStats([]) + setSystemStats([]) setCpuChartData([]) setMemChartData([]) setDiskChartData([]) @@ -72,11 +72,11 @@ export default function ServerDetail({ name }: { name: string }) { if (server.id && server.name === name) { return } - const matchingServer = servers.find((s) => s.name === name) as SystemRecord + const matchingServer = systems.find((s) => s.name === name) as SystemRecord if (matchingServer) { setServer(matchingServer) } - }, [name, server, servers]) + }, [name, server, systems]) // get stats useEffect(() => { @@ -95,7 +95,7 @@ export default function ServerDetail({ name }: { name: string }) { }) .then((records) => { // console.log('sctats', records) - setServerStats(records) + setSystemStats(records) }) }, [server, chartTime]) @@ -107,7 +107,7 @@ export default function ServerDetail({ name }: { name: string }) { // create cpu / mem / disk data for charts useEffect(() => { - if (!serverStats.length) { + if (!systemStats.length) { return } const cpuData = [] as typeof cpuChartData @@ -115,7 +115,7 @@ export default function ServerDetail({ name }: { name: string }) { const diskData = [] as typeof diskChartData const diskIoData = [] as typeof diskIoChartData const networkData = [] as typeof bandwidthChartData - for (let { created, stats } of serverStats) { + for (let { created, stats } of systemStats) { const time = new Date(created).getTime() cpuData.push({ time, cpu: stats.cpu }) memData.push({ @@ -133,17 +133,17 @@ export default function ServerDetail({ name }: { name: string }) { setDiskChartData(diskData) setDiskIoChartData(diskIoData) setBandwidthChartData(networkData) - }, [serverStats]) + }, [systemStats]) useEffect(() => { - if (!serverStats.length) { + if (!systemStats.length) { return } const now = new Date() const startTime = chartTimeData[chartTime].getOffset(now) const scale = scaleTime([startTime.getTime(), now], [0, cpuChartData.length]) setTicks(scale.ticks().map((d) => d.getTime())) - }, [chartTime, serverStats]) + }, [chartTime, systemStats]) // get container stats useEffect(() => { diff --git a/hub/site/src/components/server-table/columns.tsx b/hub/site/src/components/systems-table/columns.tsx similarity index 100% rename from hub/site/src/components/server-table/columns.tsx rename to hub/site/src/components/systems-table/columns.tsx diff --git a/hub/site/src/components/server-table/systems-table.tsx b/hub/site/src/components/systems-table/systems-table.tsx similarity index 97% rename from hub/site/src/components/server-table/systems-table.tsx rename to hub/site/src/components/systems-table/systems-table.tsx index 1207fbf..e83e77a 100644 --- a/hub/site/src/components/server-table/systems-table.tsx +++ b/hub/site/src/components/systems-table/systems-table.tsx @@ -59,7 +59,7 @@ import { import { useMemo, useState } from 'react' import { $systems, pb } from '@/lib/stores' import { useStore } from '@nanostores/react' -import { AddServerButton } from '../add-server' +import { AddSystemButton } from '../add-system' import { cn, copyToClipboard, isReadOnlyUser } from '@/lib/utils' import AlertsButton from '../table-alerts' import { navigate } from '../router' @@ -133,7 +133,7 @@ export default function SystemsTable() { ) }, - header: ({ column }) => sortableHeader(column, 'Server', Server), + header: ({ column }) => sortableHeader(column, 'System', Server), }, { accessorKey: 'info.cpu', @@ -259,7 +259,7 @@ export default function SystemsTable() { className="max-w-sm" />
- +
@@ -291,7 +291,7 @@ export default function SystemsTable() { onClick={(e) => { const target = e.target as HTMLElement if (!target.closest('[data-nolink]') && e.currentTarget.contains(target)) { - navigate(`/server/${row.original.name}`) + navigate(`/system/${row.original.name}`) } }} > @@ -314,7 +314,7 @@ export default function SystemsTable() { ) : ( - No servers found + No systems found )} diff --git a/hub/site/src/lib/utils.ts b/hub/site/src/lib/utils.ts index 8b6b558..48942f5 100644 --- a/hub/site/src/lib/utils.ts +++ b/hub/site/src/lib/utils.ts @@ -27,7 +27,7 @@ export async function copyToClipboard(content: string) { } } -export const updateServerList = () => { +export const updateSystemList = () => { pb.collection('systems') .getFullList({ sort: '+name' }) .then((records) => { diff --git a/hub/site/src/main.tsx b/hub/site/src/main.tsx index 5442513..035a036 100644 --- a/hub/site/src/main.tsx +++ b/hub/site/src/main.tsx @@ -11,7 +11,7 @@ import { updateAlerts, updateFavicon, updateRecordList, - updateServerList, + updateSystemList, } from './lib/utils.ts' import { buttonVariants } from './components/ui/button.tsx' import { @@ -44,16 +44,16 @@ import { } from './components/ui/dropdown-menu.tsx' import { AlertRecord, SystemRecord } from './types' import { $router, Link, navigate } from './components/router.tsx' -import ServerDetail from './components/routes/server.tsx' +import ServerDetail from './components/routes/system.tsx' -// const ServerDetail = lazy(() => import('./components/routes/server.tsx')) +// const ServerDetail = lazy(() => import('./components/routes/system.tsx')) const CommandPalette = lazy(() => import('./components/command-palette.tsx')) const LoginPage = lazy(() => import('./components/login/login.tsx')) const App = () => { const page = useStore($router) const authenticated = useStore($authenticated) - const servers = useStore($systems) + const systems = useStore($systems) useEffect(() => { // change auth store on auth change @@ -61,7 +61,7 @@ const App = () => { $authenticated.set(pb.authStore.isValid) }) // get servers / alerts - updateServerList() + updateSystemList() updateAlerts() // subscribe to real time updates for systems / alerts pb.collection('systems').subscribe('*', (e) => { @@ -79,15 +79,15 @@ const App = () => { // update favicon useEffect(() => { - if (!authenticated || !servers.length) { + if (!authenticated || !systems.length) { updateFavicon('favicon.svg') } else { let up = false - for (const server of servers) { - if (server.status === 'down') { + for (const system of systems) { + if (system.status === 'down') { updateFavicon('favicon-red.svg') return () => updateFavicon('favicon.svg') - } else if (server.status === 'up') { + } else if (system.status === 'up') { up = true } } @@ -97,7 +97,7 @@ const App = () => { return () => { updateFavicon('favicon.svg') } - }, [authenticated, servers]) + }, [authenticated, systems]) if (!page) { return

404

diff --git a/readme.md b/readme.md index 460bb7b..b36ed5b 100644 --- a/readme.md +++ b/readme.md @@ -28,23 +28,39 @@ A lightweight server resource monitoring hub with historical data, docker stats, 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 hub is a web application that provides a dashboard to view and manage your connected systems. It's built on top of [PocketBase](https://pocketbase.io/). The agent runs on each system you want to monitor. It creates a minimal SSH server through which it communicates system metrics to the hub. +[![Docker Image Size (tag)](https://img.shields.io/docker/image-size/henrygd/beszel-agent/0.0.1-alpha.3?logo=docker&label=agent%20image%20size)](https://hub.docker.com/r/henrygd/beszel-agent) +[![Docker Image Size (tag)](https://img.shields.io/docker/image-size/henrygd/beszel/0.0.1-alpha.3?logo=docker&label=hub%20image%20size)](https://hub.docker.com/r/henrygd/beszel) + +## Getting started + +If using the binary instead of docker, ignore 4-5 and run the agent using the binary instead. + +1. Start the hub (see [Installation](#installation)). The binary command is `beszel serve`. +2. Open http://localhost:8090 and create an admin user. +3. Click "Add system." Enter the name and host of the system you want to monitor. +4. Click "Copy docker compose" to copy the agent's docker-compose.yml file to your clipboard. +5. On the agent system, create the compose file and run `docker compose up` to start the agent. +6. Back in the hub, click the "Add system" button in the dialog to finish adding the system. + +If all goes well, you should see the system flip to green. If it goes red, check the Logs page, and see [troubleshooting tips](#faq--troubleshooting). + ## Installation -The hub and agent are distributed as single binary files, as well as docker images. +You may choose to install the hub and agent as single binaries, or as docker images. ### Docker **Hub**: See the example [docker-compose.yml](/hub/docker-compose.yml) file. -**Agent**: The hub provides compose content when adding a system to monitor, but you can also reference the example [docker-compose.yml](/agent/docker-compose.yml) file. +**Agent**: The hub provides compose content for the agent, but you can also reference the example [docker-compose.yml](/agent/docker-compose.yml) file. -The agent uses the `host` network mode, which automatically exposes the port. So change the port using an environment variable if you need to. It's set up this way so that can access stats for your host network interfaces. +The agent uses the host network mode so it can access network interface stats. This automatically exposes the port, so change the port using an environment variable if you need to. -If you don't want to use the host network, you may remove that line from the compose file and manually expose the port. This will prevent the network stats from populating. +If you don't need network stats, remove that line from the compose file and map the port manually. > **Note**: The docker version of the agent cannot automatically detect the filesystem to use for disk I/O stats, so include the `FILESYSTEM` environment variable if you want that to work ([instructions here](#finding-the-correct-filesystem)). @@ -78,10 +94,11 @@ Use `beszel update` and `beszel-agent update` to update to the latest version. ### Agent -| Name | Default | Description | -| ------------ | ------- | ------------------------------------------------ | -| `FILESYSTEM` | unset | Filesystem / partition to use for disk I/O stats | -| `PORT` | 45876 | Port to listen on | +| Name | Default | Description | +| ------------ | ------- | ---------------------------------------------------------- | +| `FILESYSTEM` | unset | Filesystem / partition to use for disk I/O stats | +| `KEY` | unset | Public SSH key to use for authentication. Provided in hub. | +| `PORT` | 45876 | Port to listen on | ## OAuth / OIDC setup