Skip to content

About

REST API and web dashboard exposing hardware and service state of an Android tablet repurposed as a Fedora home server

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

dashboard-api

REST API and web dashboard for an Android tablet repurposed as a home server.

The tablet runs atomic Fedora instead of Android and hosts a few household services in containers. This project exposes its state on a single HTTP endpoint, and renders it in a page served by the same backend.

Dashboard

Architecture

The fixed point of the project is the JSON contract, written before any code. It describes nine blocks: host, battery, thermal, disk, clock, services, containers, backup and DNS. It is what the backend, the web page and the Android app share.

Each block has an independent reader. A reader that fails returns null in its own fields without bringing down the response: if AdGuard is down, the DNS block is empty and everything else keeps working. That property is what makes the dashboard useful precisely when something is wrong.

The sources are of four different kinds:

Block Source
host, battery, thermal files under /proc and /sys
disk the JVM's FileStore
clock, services chronyc, systemctl through ProcessBuilder
containers podman in JSON
DNS AdGuard Home HTTP API
backup a state file written by the backup script

Endpoints

Prefix /api/v1. /status is the one the clients use; the others are there for debugging.

Path Contents
/status every block at once
/health ok
/host hostname, uptime, load, memory
/battery charge level, charging state, temperature
/thermal SoC temperature
/disk total and used space
/clock NTP offset and sync state
/services monitored systemd units
/containers podman containers
/backup result and date of the last backup
/adguard total and blocked DNS queries

The web page is served at the root and calls /api/v1/status every ten seconds. When the backend stops responding it keeps the last data on screen and flags the error instead of going blank.

Requirements

  • Java 25
  • A Linux host with /proc and /sys (paths are configurable)
  • Optional, for the corresponding blocks: chronyd, podman, AdGuard Home

Build

./mvnw clean package
java -jar target/dashboard-api-0.0.1-SNAPSHOT.jar

The dev profile reads a fake battery from fake-sys/, so the project runs on a machine that does not have those files:

./mvnw spring-boot:run -Dspring-boot.run.profiles=dev

On a system without chronyc, systemctl or podman the matching blocks return null. That is the intended behaviour, not an error.

Configuration

In application.properties:

Property Meaning
server.port HTTP port
server.address listening interface
dashboard.battery-path power_supply directory
dashboard.proc-path /proc
dashboard.thermal-path thermal zone under /sys/class/thermal
dashboard.disk-path mount point to measure
dashboard.backup-file backup state JSON
dashboard.services systemd units to monitor, comma separated
dashboard.adguard.url AdGuard Home URL
dashboard.adguard.username AdGuard user
dashboard.adguard.password read from ADGUARD_PASSWORD

The password is not in the file: it comes from the environment variable, which in production is provided by a systemd EnvironmentFile with restricted permissions.

Containers

To read rootful containers without running the backend as root, a sudo rule limited to the two required commands is enough:

<user> ALL=(root) NOPASSWD: /usr/bin/podman ps --format json, /usr/bin/podman stats --no-stream --format json

Without this rule the containers block stays empty and the rest still works.

Deployment

A systemd unit, with the password in a separate file:

[Service]
Type=simple
User=<user>
EnvironmentFile=/etc/dashboard-api.env
ExecStart=/usr/bin/java -jar /opt/dashboard-api/dashboard-api.jar
Restart=on-failure
RestartSec=10

The service listens on loopback only and is reachable over a Tailscale VPN, which also terminates TLS. Nothing is exposed to the public internet.

Stack

Spring Boot 4, Java 25, Jackson 3. No database: the backend stores nothing, every response is a reading of the current state.

Clients

  • The web page served by this backend
  • An Android app in Kotlin and Compose, with a home screen widget

About

REST API and web dashboard exposing hardware and service state of an Android tablet repurposed as a Fedora home server

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages