# phrendo/systemd-dashboard architecture

> Architecture diagram of the GitHub repository phrendo/systemd-dashboard, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/phrendo/systemd-dashboard
- Repository: https://github.com/phrendo/systemd-dashboard

## Overview

1. **What this repository is**
   - SERVICES_DASH is a single-server Flask application that acts as a control plane for Linux `systemd` services.
   - It combines a web UI, a small persistence layer, and privileged OS interactions into one deployable process.

2. **Primary runtime boundary**
   - The browser is the user-facing boundary.
   - The Flask app is the application boundary.
   - Outside the app, it talks to the Linux host’s `systemd` and journal subsystem to read status/logs and issue start/stop/restart actions.

3. **Main application entrypoint**
   - `app.py` is the central runtime component.
   - It likely wires together the routes for the dashboard, service management, and log retrieval, and coordinates reads/writes to the database and system commands.

4. **Web UI structure**
   - The UI is server-rendered using Jinja templates in `templates/`.
   - `templates/index.html` is the main monitoring dashboard.
   - `templates/manage_services.html` is the administration page for adding/removing monitored services.
   - `static/` holds the CSS/images used for the dashboard presentation.

5. **Data model and persistence**
   - `models.py` defines the app’s stored state, which is almost certainly the monitored-services configuration and related metadata.
   - `init_db.py` bootstraps the local database schema before first run.
   - The database is used to remember which services should appear in the dashboard, separate from the live `systemd` state.

6. **Live monitoring data flow**
   - The dashboard fetches current service status from the host, not just from the database.
   - The app presents that live state to the browser and supports auto-refresh for logs, so the browser repeatedly requests updated status/log data from Flask.
   - This makes the DB a configuration store, while `systemd`/journald are the source of operational truth.

7. **Control-path data flow**
   - User actions in the browser trigger Flask routes that execute service operations on the host.
   - Those actions include start, stop, and restart.
   - Because those are privileged OS operations, the app is designed to run under a dedicated `services-dash` Linux user with PolicyKit authorization.

8. **Log access path**
   - The application reads system logs for each monitored service, apparently via the system journal.
   - The readme calls out membership in the `systemd-journal` group, which indicates the app needs host-level log visibility rather than an application-local log store.

9. **Operational/deployment boundary**
   - The app is intended to run on Linux with `systemd`, and production deployment is itself managed as a systemd service.
   - The repository’s readme describes a dedicated Unix user, working directory under `/opt/services-dash`, and a service unit that keeps the Flask process alive.
   - This means the dashboard is both a manager of services and a service managed by systemd.

10. **Security and permissions**
   - Access to service management is intentionally separated from normal web app privileges.
   - The repository uses a PolicyKit rule to allow the `services-dash` user to manage units, instead of running the app as root.
   - That is a key architectural boundary: the web tier stays non-root, while OS control is delegated through system policy.

11. **Project shape**
   - This is not a multi-service backend; it is a compact monolith with three concerns: UI rendering, database-backed service registry, and host integration.
   - There are no separate API, worker, or frontend build subsystems visible in the tree.
   - The architecture is therefore centered on synchronous request/response flows from browser to Flask to the local Linux control plane.

12. **How to draw it**
   - A good diagram would show:
     - Browser on the left
     - Flask app in the middle
     - Local database below Flask
     - `systemd` and journald on the right as external host services
     - Templates/static assets attached to the Flask UI layer
     - A deployment box around the whole app running as the `services-dash` system user under `systemd`

Main entry points: [`app.py`](https://github.com/phrendo/systemd-dashboard/blob/main/app.py) (App), [`models.py`](https://github.com/phrendo/systemd-dashboard/blob/main/models.py) (Models), [`init_db.py`](https://github.com/phrendo/systemd-dashboard/blob/main/init_db.py) (Init DB), [`static`](https://github.com/phrendo/systemd-dashboard/tree/main/static) (Static)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Client"]
  node_browser(("Browser<br/>client"))
end

subgraph group_app["Flask app"]
  node_app_py["App<br/>flask entrypoint<br/>[app.py]"]
  node_templates["Templates<br/>Jinja views"]
  node_static["Static<br/>assets"]
  node_models_py["Models<br/>data model<br/>[models.py]"]
  node_init_db_py["Init DB<br/>bootstrap<br/>[init_db.py]"]
  node_database[("Database<br/>local store")]
  node_index_html["Dashboard<br/>template<br/>[index.html]"]
  node_manage_html["Manage UI<br/>template"]
end

subgraph group_host["Linux host"]
  node_systemd["systemd<br/>service manager"]
  node_journal["Journal<br/>log source"]
  node_polkit["PolicyKit<br/>authorization"]
  node_unit["Service unit<br/>deployment"]
  node_svc_user(("svc user<br/>unix user"))
end

node_browser -->|"requests"| node_app_py
node_app_py -->|"renders"| node_index_html
node_app_py -->|"renders"| node_manage_html
node_app_py -->|"serves"| node_static
node_app_py -->|"uses"| node_models_py
node_models_py -->|"persists"| node_database
node_init_db_py -->|"initializes"| node_database
node_app_py -->|"controls"| node_systemd
node_app_py -->|"reads"| node_journal
node_app_py -->|"authorizes"| node_polkit
node_unit -->|"runs"| node_app_py
node_svc_user -->|"owns"| node_unit
node_svc_user -->|"allowed by"| node_polkit
node_app_py -.->|"updates"| node_browser

click node_app_py "https://github.com/phrendo/systemd-dashboard/blob/main/app.py"
click node_templates "https://github.com/phrendo/systemd-dashboard/tree/main/templates"
click node_static "https://github.com/phrendo/systemd-dashboard/tree/main/static"
click node_models_py "https://github.com/phrendo/systemd-dashboard/blob/main/models.py"
click node_init_db_py "https://github.com/phrendo/systemd-dashboard/blob/main/init_db.py"
click node_index_html "https://github.com/phrendo/systemd-dashboard/blob/main/templates/index.html"
click node_manage_html "https://github.com/phrendo/systemd-dashboard/blob/main/templates/manage_services.html"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_browser toneBlue
class node_app_py,node_templates,node_static,node_models_py,node_init_db_py,node_database,node_index_html,node_manage_html toneAmber
class node_systemd,node_journal,node_polkit,node_unit,node_svc_user toneMint
```

## Components

### Client

User-facing browser boundary

- **Browser**: client · User interface boundary

### Flask app

Server-rendered dashboard and control plane

- [App](https://github.com/phrendo/systemd-dashboard/blob/main/app.py): flask entrypoint · Central Flask runtime that wires routes and host interactions · `app.py`
- [Templates](https://github.com/phrendo/systemd-dashboard/tree/main/templates): Jinja views · Server-rendered dashboard and service management pages · `templates`
- [Static](https://github.com/phrendo/systemd-dashboard/tree/main/static): assets · CSS and images for the dashboard UI · `static`
- [Models](https://github.com/phrendo/systemd-dashboard/blob/main/models.py): data model · Stored service registry and metadata · `models.py`
- [Init DB](https://github.com/phrendo/systemd-dashboard/blob/main/init_db.py): bootstrap · Database schema initialization · `init_db.py`
- **Database**: local store · Persists monitored-service configuration
- [Dashboard](https://github.com/phrendo/systemd-dashboard/blob/main/templates/index.html): template · Main monitoring dashboard view · `templates/index.html`
- [Manage UI](https://github.com/phrendo/systemd-dashboard/blob/main/templates/manage_services.html): template · Administration page for monitored services · `templates/manage_services.html`

### Linux host

Local systemd, journal, and authorization boundary

- **systemd**: service manager · Source of live service state and control target
- **Journal**: log source · Host log stream for monitored services
- **PolicyKit**: authorization · Grants non-root service management permissions
- **Service unit**: deployment · systemd-managed runtime for the dashboard itself
- **svc user**: unix user · Dedicated non-root account running the dashboard

## Connections

- Browser → App: requests · Browser sends dashboard, management, and log requests to Flask
- App → Dashboard: renders · Flask renders the main monitoring dashboard
- App → Manage UI: renders · Flask renders service administration pages
- App → Static: serves · Dashboard assets are delivered from the static directory
- App → Models: uses · Application logic reads and updates the service registry model
- Models → Database: persists · Models map monitored-service state into the local database
- Init DB → Database: initializes · Bootstrap script creates or prepares the schema
- App → systemd: controls · Starts, stops, restarts, and queries host services
- App → Journal: reads · Fetches live logs for monitored services
- App → PolicyKit: authorizes · PolicyKit enables privileged unit management without root
- Service unit → App: runs · The dashboard is deployed as a systemd service
- svc user → Service unit: owns · Dedicated Unix user runs the service unit
- svc user → PolicyKit: allowed by · Non-root account is permitted to manage units through policy
- App → Browser: updates · Auto-refresh and response cycles return live status and logs
