How phrendo/systemd-dashboard works
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 App · models.py Models · init_db.py Init DB · static Static
Components 14
Client
User-facing browser boundary
- Browser · User interface boundary
Flask app
Server-rendered dashboard and control plane
- App · Central Flask runtime that wires routes and host interactions
app.py - Templates · Server-rendered dashboard and service management pages
templates - Static · CSS and images for the dashboard UI
static - Models · Stored service registry and metadata
models.py - Init DB · Database schema initialization
init_db.py - Database · Persists monitored-service configuration
- Dashboard · Main monitoring dashboard view
templates/index.html - Manage UI · Administration page for monitored services
templates/manage_services.html
Linux host
Local systemd, journal, and authorization boundary
- systemd · Source of live service state and control target
- Journal · Host log stream for monitored services
- PolicyKit · Grants non-root service management permissions
- Service unit · systemd-managed runtime for the dashboard itself
- svc user · Dedicated non-root account running the dashboard
Connections 14
- 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