diff --git a/README.md b/README.md new file mode 100644 index 0000000..26785f5 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# NGX Monitor + +NGX Monitor is an Android client for `ngx_http_monitoring_module`. It is built with Kotlin and Jetpack Compose for monitoring a fleet of local or private Nginx servers from a phone. + +## Features + +- Fleet dashboard for multiple servers with live status, tags, favorites, search, and critical-first sorting. +- Server detail cockpit with system, Nginx, request, disk, history, alert, and route diagnostics views. +- JSON API polling via `/monitor/api` and health checks via `/monitor/health`. +- Foreground live streaming via `/monitor/live` Server-Sent Events. +- Encrypted per-server credentials for monitor tokens and optional Nginx Basic Auth. +- Local SQLite history with 1-minute summaries, 15-minute raw snapshots, and 30-day pruning. +- Background periodic checks with local Android notifications. +- VPN/DNS resilience with per-server fallback LAN IP aliases while preserving HTTPS hostnames for TLS/SNI. + +## Monitor API + +The app expects each server base URL to expose `/monitor`. + +Common endpoints used by the app: + +- `GET /monitor/api` +- `GET /monitor/health` +- `GET /monitor/live` + +Authentication rules: + +- Monitor tokens are sent as `X-Monitor-Token`. +- Basic Auth is sent on every monitor request when configured. +- If both are enabled on the server, configure both in the app. + +## Local Network And VPN Notes + +For private domains, keep the main server URL as the HTTPS domain, for example: + +```text +https://edge-1.home.example +``` + +If VPN or DNS breaks local resolution, add fallback LAN IPs in the server editor: + +```text +192.168.1.20, 192.168.1.21 +``` + +The app keeps the URL hostname unchanged and only substitutes DNS results internally. This keeps HTTPS certificate verification and SNI aligned with the private domain. + +Android or the VPN app may still block LAN access completely. In that case, the app shows the failure in the Route panel but cannot override the VPN policy. + +## Security + +- Prefer HTTPS for monitor endpoints. +- Prefer header tokens over query-string tokens. +- Avoid sharing screenshots that expose internal hostnames or route details. +- Keep monitor endpoints behind least-privilege ACLs. +- Do not reuse production admin passwords for Basic Auth. + +## Build + +From the project root: + +```powershell +$env:GRADLE_USER_HOME='C:\Users\meghdad\AndroidStudioProjects\NGXhttpMonitoringClient\.gradle-user' +.\gradlew.bat :app:assembleDebug --console=plain +``` + +Debug APK output: + +```text +app/build/outputs/apk/debug/app-debug.apk +``` + +Run unit tests: + +```powershell +$env:GRADLE_USER_HOME='C:\Users\meghdad\AndroidStudioProjects\NGXhttpMonitoringClient\.gradle-user' +.\gradlew.bat :app:testDebugUnitTest --console=plain +``` + +## Project Structure + +```text +app/src/main/java/net/rodakot/ngxhttpmonitoringclient/ + background/ JobScheduler checks and notifications + data/ SQLite storage, encrypted credentials, HTTP/SSE client + domain/ URL rules, alert evaluation, route planning, sampling policy + model/ Server, metric, alert, and route data models + ui/ Compose command-deck UI + ui/theme/ Material theme and colors +``` + +## App Assets + +- Launcher icon foreground/background: `app/src/main/res/drawable/ic_launcher_foreground.xml`, `ic_launcher_background.xml` +- Splash artwork: `app/src/main/res/drawable/splash_hero.xml` +- Splash background: `app/src/main/res/drawable/splash_screen.xml` + +These assets are vector drawables, so they scale cleanly across screen densities. diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3dbaf6f..01aaca6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,7 +21,7 @@ android:name=".MainActivity" android:exported="true" android:label="@string/app_name" - android:theme="@style/Theme.NGXHttpMonitoringClient"> + android:theme="@style/Theme.NGXHttpMonitoringClient.Launcher"> diff --git a/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/MainActivity.kt b/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/MainActivity.kt index 4f306b7..36e98ea 100644 --- a/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/MainActivity.kt +++ b/app/src/main/java/net/rodakot/ngxhttpmonitoringclient/MainActivity.kt @@ -16,6 +16,7 @@ import net.rodakot.ngxhttpmonitoringclient.ui.theme.NGXHttpMonitoringClientTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { + setTheme(R.style.Theme_NGXHttpMonitoringClient) super.onCreate(savedInstanceState) enableEdgeToEdge() requestNotificationPermission() diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 07d5da9..88046d4 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -5,166 +5,17 @@ android:viewportWidth="108" android:viewportHeight="108"> + + android:pathData="M8,22h92M8,42h92M8,62h92M8,82h92M22,8v92M42,8v92M62,8v92M82,8v92" + android:strokeColor="#2235D38B" + android:strokeWidth="1" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:fillColor="#1035D38B" + android:pathData="M18,18h72a10,10 0,0 1,10 10v52a10,10 0,0 1,-10 10h-72a10,10 0,0 1,-10 -10v-52a10,10 0,0 1,10 -10z" /> diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 2b068d1..7b0a0a0 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,30 +1,35 @@ + - - - - - - - - - \ No newline at end of file + android:fillColor="#FF202733" + android:pathData="M25,23h58a9,9 0,0 1,9 9v44a9,9 0,0 1,-9 9h-58a9,9 0,0 1,-9 -9v-44a9,9 0,0 1,9 -9z" /> + + + + + + + + diff --git a/app/src/main/res/drawable/splash_hero.xml b/app/src/main/res/drawable/splash_hero.xml new file mode 100644 index 0000000..6fda7ac --- /dev/null +++ b/app/src/main/res/drawable/splash_hero.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/splash_screen.xml b/app/src/main/res/drawable/splash_screen.xml new file mode 100644 index 0000000..30047c5 --- /dev/null +++ b/app/src/main/res/drawable/splash_screen.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..fd1d8ab --- /dev/null +++ b/app/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 0000000..5740853 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml new file mode 100644 index 0000000..0b066df --- /dev/null +++ b/app/src/main/res/values-v31/themes.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..6876402 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,10 +1,10 @@ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 + #FF0E1116 + #FF171C23 + #FF35D38B + #FF4CC9F0 + #FFFFB84D + #FFFF5A52 #FFFFFFFF - \ No newline at end of file + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 3307e31..e0a6d1d 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,5 +1,18 @@ - + + +