See what your Raspberry Pi is doing, live, from an Android app: CPU, temperature, fan, memory, disks, network, power and throttling, with history charts, alerts and fan control. It works on your home Wi-Fi and, with the free relay, from any network.
PiMon has two parts:
| Part | What it is | Where it runs |
|---|---|---|
Agent (agent/) |
A small Python service (standard library only, nothing to pip install) that reads the Pi's sensors and serves them over a token-protected API |
On each Raspberry Pi |
App (android/) |
A Kotlin + Jetpack Compose Android app with live gauges, charts, alerts and fan control | On your phone |
- Quick start (5 minutes)
- Features
- Requirements
- 1. Install the agent on the Pi
- 2. Install the app on your phone
- 3. Pair the phone with the Pi
- Using the app
- Fan control
- Monitor from anywhere
- Benchmark and stress test
- Command reference
- Updating and uninstalling
- Troubleshooting
- Security
- Building from source
- Publishing on Google Play
- Project layout and API
- License
1. On the Pi, run this in a terminal (or over SSH):
curl -fsSL https://raw.githubusercontent.com/SabariLRM/RaspberryPi_Monitor/main/agent/install.sh | sudo bashIt installs the agent, starts it (and at every boot), and prints a QR code at the end.
2. On the phone, download and install the app:
⬇ Download PiMon.apk (or scan this with the phone's camera)
Open the downloaded file and tap Install. Android asks you to allow installing apps from your browser or file manager the first time; see the detailed steps.
3. Pair: open PiMon, tap + → Scan QR code and point the phone at the QR code in the Pi's terminal.
Done: the dashboard shows live readings. Show the code again at any time with sudo pimon pair.
No Pi at hand? Tap Try a demo in the app to see every feature with simulated data.
Live readings (every 2 seconds)
- CPU: usage overall and per core, clock speed, governor, load average, process count
- Temperature: CPU and RP1 I/O chip (Pi 5), NVMe and other sensors
- Fan: speed in RPM, power and cooling level, plus fan control
- Memory and swap
- Storage: every disk's usage, plus read and write speed
- Network: traffic per interface, Wi-Fi signal strength and network name, Tailscale address
- Power: input voltage, estimated board power (Pi 5), core voltage, and under-voltage and throttling flags (now and since boot)
- Processes: the top 10 by CPU and by memory
- System: model, OS, kernel and uptime
History charts for the last 5 minutes, 1 hour or 24 hours: tap and drag to read exact values.
Alerts (optional): a notification when a Pi gets too hot, has power problems, fills a disk or goes offline. Thresholds are set in the app's Settings.
Many Pis: add as many as you like; the home screen lists them all with their status.
Works anywhere: on your home network the phone talks to the Pi directly. Away from home, readings come through your own free, end-to-end encrypted Firebase relay or Tailscale.
Light and dark theme (follows the phone), °C or °F, no account, no ads, no tracking.
| Pi | Any Raspberry Pi running Raspberry Pi OS Bookworm or Trixie (Pi 5, 4, 3, Zero 2 W…). Other systemd Linux machines work too; Pi-only readings such as throttling and board power are just left out. Python 3.7 or newer (preinstalled). |
| Phone | Android 8.0 or newer |
| Network | Phone and Pi on the same network, or the relay / Tailscale for everywhere else |
The agent uses under 1% of one CPU core and about 25 MB of RAM.
curl -fsSL https://raw.githubusercontent.com/SabariLRM/RaspberryPi_Monitor/main/agent/install.sh | sudo bashOptions go after -s --, for example to skip the Tailscale question and turn on the relay in one go:
curl -fsSL https://raw.githubusercontent.com/SabariLRM/RaspberryPi_Monitor/main/agent/install.sh \
| sudo bash -s -- --no-tailscale --relay https://YOUR-DATABASE.firebasedatabase.appgit clone https://github.com/SabariLRM/RaspberryPi_Monitor.git
cd RaspberryPi_Monitor/agent
sudo ./install.sh- Creates an unprivileged
pimonsystem user (in thevideogroup so it can readvcgencmd). - Installs the agent to
/opt/pimonand apimoncommand. - Generates a random 256-bit access token in
/etc/pimon/config.json(readable only by root and the service). - Starts the
pimonsystemd service, which also starts at every boot. - Asks whether to set up Tailscale (optional, see Monitor from anywhere).
- Prints the pairing QR code.
Installer options: --tailscale, --no-tailscale, --relay URL, --port 9000 (default 8765), --uninstall.
Running the installer again upgrades the agent and keeps your token, so paired phones keep working.
Check it's running:
sudo pimon statusService: pimon is active
Port: 8765
Host: raspberrypi (Raspberry Pi 5 Model B Rev 1.0)
CPU: 3.7% Temp: 41.4 C Fan: 0 RPM
Memory: 10.1% Uptime: 2 h
Fan mode: auto
Address: http://192.168.1.50:8765
Relay: off
PiMon isn't on Google Play (yet), so you install the APK file directly. This is safe: it's the same app, signed with the same key for every release.
- On the phone, open PiMon.apk
(or go to the Releases page and tap
PiMon.apk). - When the download finishes, tap Open (or find it in Files → Downloads).
- The first time, Android says it can't install apps from this source: tap Settings, turn on Allow from this source, then go back.
- Tap Install.
- If Google Play Protect warns about an unknown app, tap More details → Install anyway. It warns about every app that doesn't come from the Play Store.
No internet on the phone, or prefer a cable? Copy the APK to the phone's Download folder over USB (choose
File transfer in the phone's USB notification), then open it in My Files → Downloads.
On the Pi:
sudo pimon pairIn the app: tap + → Scan QR code and scan the code in the terminal. Scanning it with the phone's normal
camera works too: the pimon:// link opens the app.
If the QR code is too big for your terminal, make the window larger, or add the Pi by hand: tap + → Enter details manually and type the Address, Token (and Relay and Channel, if shown) printed under the QR code.
To pair more phones, scan the same code. To pair more Pis, install the agent on each and scan each code.
- Home screen: every Pi with its status (online, via relay, offline), temperature and CPU. Tap one to open its dashboard.
- Dashboard: gauges for CPU, temperature, memory, disk, network, fan, clock, power and load. Warning banners appear for under-voltage, throttling or a lost connection.
- History: pick 5 min, 1 hour or 24 hours and a metric; drag across the chart to read values.
- Detail cards: temperatures and cooling (with fan control), per-core CPU, memory, storage, network interfaces, power rails, top processes and system information.
- Edit a Pi (pencil icon): rename it, change addresses, token or relay.
- Settings: °C or °F, and alerts: CPU temperature and disk thresholds, a Pi going offline, and power problems. Alerts are checked about every 15 minutes in the background; Check now runs a check immediately. The light or dark theme follows your phone.
On Pis with a speed-controlled fan (such as the Raspberry Pi 5 Active Cooler or a PWM case fan), open a Pi and scroll to Temperature & cooling → Fan speed:
- Auto (the default): the Pi's kernel sets the speed from the CPU temperature. On a Pi 5 the fan starts around 50 °C and steps up at 60, 67.5 and 75 °C.
- Manual: a slider sets a fixed level, from Off to Full speed (levels 0 to 4 on a Pi 5).
Safety comes first, so Auto always comes back on its own:
- when the CPU reaches 80 °C in Manual mode (the app tells you it switched),
- whenever the agent restarts or the Pi reboots,
- even if the agent crashes (systemd hands the fan back to the kernel).
The Pi's firmware also throttles the CPU at 85 °C whatever the fan does.
From the Pi's terminal:
sudo pimon fan auto # automatic (default)
sudo pimon fan 4 # full speed
sudo pimon fan 0 # off (until 80 °C)Fan control through the relay needs the updated Firebase rules (see Upgrading from 1.1).
At home the phone talks to the Pi directly over Wi-Fi. For mobile data or other networks, pick one option.
The Pi uploads encrypted readings to your own free Firebase Realtime Database over ordinary HTTPS, and the app reads them from there. It works even on networks that block VPNs (campus, office, hotel Wi-Fi) and needs nothing else on the phone.
-
Go to https://console.firebase.google.com and Create a project (Google Analytics isn't needed).
-
Open Build → Realtime Database → Create Database. Pick the location nearest you and Start in locked mode.
-
Open the Rules tab, replace everything with the output of
pimon relay --rules(the same asagent/firebase-rules.json) and click Publish. -
On the Data tab, copy the database URL, then on the Pi run:
sudo pimon relay https://YOUR-PROJECT-default-rtdb.REGION.firebasedatabase.app
It tests the database (write, read back, rules), turns the relay on and prints a new QR code.
-
Scan the new QR code in PiMon (it updates the existing Pi).
How it behaves:
- The app always tries the Pi directly first. When that fails it switches to the relay (the dashboard says via relay) and switches back automatically when you're home again.
- The Pi uploads every 60 s while nobody is looking (keeping alerts working) and every 3 s while the app is open.
- Private: readings are gzipped and encrypted on the Pi with keys derived from the pairing token (HMAC-SHA256 keystream plus HMAC-SHA256 authentication). Firebase only ever sees ciphertext. The rules forbid listing, fix the document shapes and sizes, and force server timestamps.
- Free: each Pi stores under 100 KB. A few hours of viewing a day is well under 1 GB a month; the free Spark plan allows 10 GB.
sudo pimon statusshows whether uploads work.sudo pimon relay --offturns it off and deletes its data.
Version 1.2 adds a cmd document to the rules so the app can change the fan speed through the relay. If you set up
the relay with 1.1, run pimon relay --rules, paste the output into the Rules tab and click Publish again.
Everything else keeps working without it.
Tailscale (free for personal use) builds a private, encrypted network between your devices. Updates are fully live and nothing goes through a cloud database, but it needs the Tailscale app on the phone, and some networks block it.
- On the Pi: answer Y when the installer asks, or run
sudo /opt/pimon/install.sh --tailscale, and open the login link it prints. - On the phone: install Tailscale from Google Play and sign in with the same account.
- On the Pi:
sudo pimon pair, then scan again in PiMon.
Other options: a reverse proxy or tunnel with HTTPS in front of port 8765 (add its address with
sudo pimon pair --url https://...). Forwarding port 8765 on your router is not recommended, because the agent
speaks plain HTTP.
tools/benchmark.py is a 10-minute thermal and CPU benchmark: 30 s idle, 9 minutes of full
load on every core, then 30 s of cool-down. Watch the Pi heat up in the app while it runs.
curl -fsSL https://raw.githubusercontent.com/SabariLRM/RaspberryPi_Monitor/main/tools/benchmark.py -o benchmark.py
sudo apt install stress-ng # optional, gives a more comparable score
python3 benchmark.pyEvery 2 seconds it prints temperature, clock speed, CPU usage, fan speed, board power and throttling flags, then a summary. For example, on a Pi 5 with the Active Cooler:
=== Summary ===
Idle temperature: 42.2 C
Peak temperature: 61.5 C
Last minute of load: 60.8 C average
After cool-down: 47.9 C
Clock under load: 2400 MHz average, 2400 MHz lowest
Fan under load: 4180 rpm average, 4997 rpm highest
Board power: 5.6 W average, 5.8 W highest
Score (stress-ng matrixprod): 184.9 ops/s (higher is better; compare runs with the same settings)
Verdict: Excellent: cool under sustained full load, no throttling.
Readings: /home/pi/benchmark-20260922-204527.csv
All readings are saved to a CSV file in the current folder, which you can open in any spreadsheet. Options: --minutes 5 (shorter run),
--threads 2 (load fewer cores), --csv FILE. Ctrl+C stops early and still prints the summary. It's safe: the
Pi protects itself at 85 °C.
Tip: compare a run on Auto with a run at a fixed fan level to see what your cooling is worth.
| Command | What it does |
|---|---|
pimon status |
Service state; with sudo also live readings, fan mode and relay health |
sudo pimon pair |
Show the pairing QR code again |
sudo pimon pair --url https://pi.example.com |
Add an extra address (e.g. a reverse proxy) to the QR code |
sudo pimon fan auto / sudo pimon fan 0…4 |
Fan speed: automatic (default) or a fixed level |
sudo pimon relay https://…firebasedatabase.app |
Turn on the Firebase relay |
sudo pimon relay --off |
Turn the relay off and delete its data |
pimon relay --rules |
Print the Firebase rules to paste into the console |
sudo pimon rotate-token |
New token: every paired phone loses access until paired again |
sudo pimon uninstall |
Remove the agent, its user and its config |
journalctl -u pimon -f |
Follow the agent's log |
sudo systemctl restart pimon |
Restart the agent |
Configuration lives in /etc/pimon/config.json (port, bind, interval, token, relay). Restart the agent
after editing it.
Agent: run the one-line install again (or git pull and sudo ./install.sh). Your token and relay settings
are kept.
App: download the new PiMon.apk from the latest release
and install it over the old one. Your Pis and settings are kept.
Uninstall the agent: sudo pimon uninstall. It stops the service, hands the fan back to automatic control, and
removes /opt/pimon, /etc/pimon and the pimon user. Tailscale, if installed, is left in place.
Uninstall the app: long-press PiMon → Uninstall.
"Connection lost" at home
- Is the agent running?
sudo pimon status - Are the phone and Pi on the same Wi-Fi? Some routers isolate devices on guest networks.
- Did the Pi's address change (new router, DHCP)? Run
sudo pimon pairand scan again, which updates the existing Pi.
"Connection lost" away from home
- Without the relay or Tailscale, the Pi is only reachable at home. See Monitor from anywhere.
- With the relay, check
sudo pimon statuson the Pi shows a recent upload. - Check the phone's network allows Firebase: open
https://YOUR-DATABASE.firebasedatabase.app/pimon/YOUR-CHANNEL/live/t.jsonin the phone's browser (the channel is shown bysudo pimon pair). A number means it works; an error or a login page means that network blocks it or needs you to sign in first. - Make sure the Pi was paired after turning the relay on: open the Pi → Edit and check the Relay fields are filled.
"The Pi rejected the access token": the token was rotated. Run sudo pimon pair and scan again.
"The relay database refused access": the Firebase rules are missing or old. Paste pimon relay --rules into
the Rules tab and Publish.
Fan controls are greyed out or say "not allowed": the agent was installed before 1.2. Run the installer again.
Fan control says "Update the agent": the agent is older than 1.2. Run the installer again.
The fan never spins: check sudo pimon status shows Fan mode: auto. A Pi 5 fan stays off below about 50 °C.
Run sudo pimon fan 4 to test it.
"App not installed" on the phone: an app with the same name but a different signature is installed (for example one you built yourself). Uninstall it first, then install the APK.
Logs: journalctl -u pimon -n 50 on the Pi.
- Every API call needs the token (256-bit random, compared in constant time). Only
/api/v1/pingis open. - On your home network traffic is plain HTTP; over Tailscale it's encrypted by WireGuard; through the relay it's encrypted and authenticated end to end.
- On a shared network (dorm, office, café) other devices can reach port 8765 but still need the token. To restrict
it, set
"bind": "127.0.0.1"in/etc/pimon/config.jsonif you only use the relay, or"bind": "100.x.y.z"(your Tailscale IP) with Tailscale, thensudo systemctl restart pimon. - Someone who learns your database URL and a Pi's channel ID could delete that Pi's relay documents, but can't read or forge readings or commands. Relay commands carry a random ID and timestamp so they can't be replayed.
- The process list includes command lines, so anyone with the token can see them.
- The service runs as an unprivileged user with systemd sandboxing. Its only extra permission is writing the fan's two control files.
- The phone keeps tokens in app-private storage with Android backup disabled. Lost your phone? Run
sudo pimon rotate-tokenon each Pi. - Privacy policy: PRIVACY.md. The app collects nothing; data only goes between your phone, your Pis and your own relay database.
Requirements: JDK 17+ and the Android SDK (Android Studio includes both).
cd android
./gradlew assembleDebug # debug APK: app/build/outputs/apk/debug/
./gradlew bundleRelease assembleRelease # signed AAB + APK (needs keystore.properties)
./gradlew testDebugUnitTest # unit tests (parsing, pairing links, relay crypto, fan control, demo data)
./gradlew testDebugUnitTest -Pscreenshots # re-render app/screenshots/
./gradlew testDebugUnitTest -PpimonUrl=http://PI:8765 -PpimonToken=TOKEN # live test against a real agent
./gradlew testDebugUnitTest -PrelayUrl=https://… -PrelayChannel=… -PrelayToken=… # live test through a relayScreenshot tests use Robolectric's native runtime, which doesn't run on ARM64 Linux (for example on a Pi); build those on an x86-64 machine or a Mac.
Agent tests (standard library only):
python3 -m unittest discover -s agent/tests -vThey include agent/tests/fake_rtdb.py, a small stand-in for the Firebase REST API that
enforces the same rules. You can also point a test agent at it (python3 agent/tests/fake_rtdb.py 18800).
Release signing reads android/keystore.properties (never committed):
storeFile=/home/you/pimon-keys/pimon-upload.jks
storePassword=...
keyAlias=pimon-upload
keyPassword=...Create a key with
keytool -genkeypair -keystore pimon-upload.jks -alias pimon-upload -keyalg RSA -keysize 4096 -validity 10000.
Keep it safe: updates must be signed with the same key.
Tech: Kotlin 2.4, AGP 9.4, Compose BOM 2026.09, Material 3, WorkManager for alerts, Google code scanner (no camera permission needed), no other third-party libraries. minSdk 26 (Android 8), targetSdk 36.
- Choose your package name first. Change
applicationIdinandroid/app/build.gradle.kts(currentlydev.pimon.app) to something unique, e.g.io.github.yourname.pimon. It can never change after the first upload. - Create a Play Console developer account (one-time US$25 fee plus identity verification).
- Create the app, enroll in Play App Signing, and upload
app-release.aab. New personal accounts must first run a closed test with at least 12 testers for 14 days. - Store listing assets are in
android/app/screenshots/:play_icon_512.png,play_feature_graphic.pngand phone screenshots1_devices.png…7_onboarding.png(1080×2160). - Short description: Live CPU, temperature, fan, memory & network stats for your Raspberry Pi.
- Privacy policy: host PRIVACY.md publicly (e.g. GitHub Pages) and paste its URL.
- Data safety: the app collects and shares no data. App access: reviewers can use Try a demo.
- Content rating: utility app, no user-generated content, no ads.
agent/
pimon_agent.py the agent: collector, HTTP API, relay uploader, fan control and CLI (Python 3.7+, stdlib only)
install.sh installer / upgrader / uninstaller
firebase-rules.json security rules for the optional relay database
tests/ agent tests and a fake Firebase server
android/
app/src/main/java/dev/pimon/app/
data/ API client (direct + relay), relay crypto, JSON models, storage, demo data
ui/ Compose screens, charts, theme
alerts/ WorkManager background checks and notifications
app/src/test/ unit tests, live tests, screenshot tests and captured fixtures
app/screenshots/ screenshots and Play Store graphics
tools/
benchmark.py 10-minute thermal and CPU benchmark
docs/ README images
PRIVACY.md privacy policy
All endpoints except ping need Authorization: Bearer <token>.
| Endpoint | Returns |
|---|---|
GET /api/v1/ping |
{"app":"pimon","version":"1.2.1"} |
GET /api/v1/stats |
Current snapshot (host, cpu, temperature, fan with control, memory, swap, disks, disk_io, network, power, processes) |
GET /api/v1/history?range=SECONDS |
Column-oriented time series (≤360 points): 2-second samples for the last hour, 1-minute averages for 24 hours |
POST /api/v1/fan |
Body {"mode": "auto"} or {"mode": "manual", "level": N}. Returns the fan control state |
Stored under /pimon/<channel>/. Each (except watch) is an envelope
{"v": 1, "t": <server time ms>, "n": <nonce>, "c": <ciphertext>, "m": <MAC>}.
| Document | Contents | Written |
|---|---|---|
live |
The /api/v1/stats snapshot |
by the Pi: every 60 s, every 3 s while the app is open |
h300, h3600, h86400 |
History for 5 min, 1 h, 24 h | by the Pi: every 15 s / 60 s / 5 min, only while the app is open |
watch |
Server timestamp | by the app every 30 s while it's open |
cmd |
A command such as a fan change, with a random ID and timestamp so it can't be replayed | by the app; the Pi deletes it after running it |
MIT: free to use, modify and share, including commercially, as long as the copyright notice is kept.




