diff --git a/README.md b/README.md index 49904ea..d295d12 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ A help desk dashboard for ManageEngine ServiceDesk Plus (SDP) Cloud. It shows ea Everyone signs in with their own Zoho account, and every query runs as that person. It's built as a Docker image (`v0idf1sh/sdp-dashboard`) to run behind Nginx Proxy Manager, which limits access to MCCS network addresses. -![Dashboard](images/4.png) - ## Setup ### 1. Zoho API client @@ -60,6 +58,15 @@ npm run app `npm run app` runs `node src/server.js` from the project root. Then open . Leave `PUBLIC_URL` unset (or set it to `http://localhost:3000`) and register `http://localhost:3000/auth/callback` with the Zoho client. +### Testing on the server without Docker + +To try a branch on the VPS before building an image, run it directly with Node behind a separate test subdomain: + +- Use Node 24 to match the image, run `npm ci`, and keep a **test** `.env` in the repo root. Give it its own `SESSION_SECRET`, and set `PUBLIC_URL` to the test subdomain. Register that subdomain's `/auth/callback` with the Zoho client. +- Port 3000 is taken by Gitea on the VPS, so set `PORT` (for example `PORT=3001`) in the test `.env` only. **Leave `PORT` out of the production `.env`**: the container must listen on 3000, which its health check and the NPM host expect. +- NPM runs in Docker, so `localhost` in a proxy host means NPM's own container. Forward the test host to the gateway of NPM's network instead. Find it with `docker network inspect npm_default --format '{{(index .IPAM.Config 0).Gateway}}'`. If ufw is on, allow that network's subnet to the test port (`sudo ufw allow from to any port 3001 proto tcp`). +- Attach the same access list as production. + ## Deployment ### Image @@ -88,7 +95,8 @@ The compose file publishes no ports. Docker's port publishing bypasses the host - **Proxy host:** the dashboard's subdomain, forwarding to `http://sdp-dashboard:3000`. - **SSL:** request a certificate and turn on **Force SSL**. Sign-in cookies are secure-only when `PUBLIC_URL` is `https://`. -- **Access list:** allow MCCS' public IP blocks and deny everything else. Attach it to the proxy host. +- **Access list:** allow MCCS' public IP blocks and deny everything else. Attach it to the proxy host. To check it, load the site from a phone on mobile data; it should return 403 Forbidden. +- **Cloudflare:** if the DNS record is proxied (orange cloud), NPM may see Cloudflare's addresses instead of the visitor's. Then the access list blocks everyone, MCCS included. If allowed addresses get 403s, either switch the record to DNS only, or add `real_ip_header CF-Connecting-IP;` in the proxy host's **Advanced** tab. With the proxy on, use Cloudflare SSL mode **Full (strict)**; Flexible combined with Force SSL causes a redirect loop. ## Signing in diff --git a/SESSION.md b/SESSION.md index 72c340b..04f0622 100644 --- a/SESSION.md +++ b/SESSION.md @@ -6,7 +6,7 @@ A Claude Code session that turned the closed-ticket board into a dashboard, then The dashboard is now a stateless server meant to run as the Docker image `v0idf1sh/sdp-dashboard` on the RackNerd VPS, behind Nginx Proxy Manager. NPM's access list limits the site to MCCS' public IP blocks. Every user signs in with their own Zoho account. Filtering is still the central region from `.env`. -All of this is uncommitted on branch `v1.1.0`. **None of it has been run against live Zoho or built with Docker yet.** It was verified with stubbed Zoho and SDP calls only (see "Verified" below). +It's committed and pushed on branch `v2.0.0`. **Tested live on 2026-10-15** as a bare-metal run on the VPS (Node, `PORT=3001`) behind `dash-test` in NPM: Zoho sign-in, live SDP data, Sign out, and the IP access list (mobile data gets 403 Forbidden) all work. Still to check: hourly token renewal, and the first Docker image build and deploy. ## Auth rebuild and hosting (this session's last piece of work) @@ -21,7 +21,8 @@ All of this is uncommitted on branch `v1.1.0`. **None of it has been run against - End to end against the real `server.js` over a unix socket, with axios stubbed: login redirect and state cookie; callback with a forged or missing state, a refused sign-in and a bad code; cookie flags and encryption; tokens never reach the page; a tampered cookie; three concurrent calls with an expired token renewing once; a revoked refresh token; a session past `SESSION_DAYS`; an SDP 401 signing the user out; sign-out revoking the token. - The page script with stubbed DOM and fetch: the signed-out panel, `?signin=` messages, first-load backfill with no ding, a ding for a new close, and signing out mid-session. -- **Not verified:** a real Zoho sign-in, the `user/info` response shape, the Docker build, the Gitea workflow, NPM. +- **Live, bare metal behind NPM (2026-10-15):** Zoho sign-in, SDP data, Sign out, and the access list blocking mobile data. +- **Not verified yet:** token renewal after an hour, the Docker build, the Gitea workflow, the production container behind `sdp-dashboard:3000`. ## Earlier the same day (dashboard work) @@ -37,7 +38,7 @@ All of this is uncommitted on branch `v1.1.0`. **None of it has been run against - The "partial" note now names which query was cut off. - **Verified fixed:** the "partial" note is gone. 8. **Small fixes:** `[hidden]` CSS bug (Refresh now showed when disconnected); a misplaced comment in `server.js`. -9. **README rewritten**, with new screenshots in `images/`. `1.png` and `2.png` are rendered with sample data; `4.png` is from the live server; `3.png` is unchanged. +9. **README rewritten.** The screenshots it had then were removed after the auth rebuild; new ones are due. 10. **Credits:** page footer, README, `package.json` contributors, `server.js` header. Isaac Godin keeps the design credit. 11. **License:** MIT (LICENSE copyright Skylar Grant; package.json now says MIT, not ISC). 12. **Repo structure for working with Claude:** `CLAUDE.md`, `docs/ROADMAP.md`, `docs/NOTES.md`. @@ -49,20 +50,22 @@ New: `PUBLIC_URL`, `SESSION_SECRET`, `SESSION_DAYS` (optional), `TRUST_PROXY` (o ## Known issues - On a typical screen the status table scrolls sideways ("Need Info" gets cut off), because the page is capped at 1,320px. -- `images/1.png` and `images/2.png` show the old Connect screens and are no longer used in the README. +- No screenshots in the README for now (`images/` removed); Skylar is retaking them. - The README's reference links for Zoho's device flow were removed; links for the server-based (web) flow haven't been added. - Each open dashboard polls SDP with its own token. That's fine for a few viewers; watch SDP rate limits if wallboards multiply. ## Next steps -1. **Zoho client:** create the Server-based Application with the production redirect URI (and localhost for development). Put its ID and secret, `PUBLIC_URL` and a new `SESSION_SECRET` into the VPS `.env`. -2. **Gitea and Docker Hub:** add the `DHUB_UNAME` and `DHUB_PASS` secrets, make sure the runner has the `self-hosted` label and Docker, then push a `v*-prod*` tag. -3. **VPS:** check NPM's network name, then `docker compose up -d`. Set up the NPM proxy host (forward to `sdp-dashboard:3000`, SSL, Force SSL) and the MCCS access list. -4. **Check live:** sign in; go more than an hour without being asked to sign in again; sign out; confirm an outside IP is blocked. +Already done: Zoho Server-based client, NPM proxy hosts (`dash` and `dash-test`) with the MCCS access list, Cloudflare DNS, a wildcard certificate, and the bare-metal test. + +1. **Token renewal:** keep a tab open for more than an hour and confirm it stays signed in. +2. **First image:** check the `DHUB_UNAME` and `DHUB_PASS` secrets and the runner's `self-hosted` label, then push a `v*-prod*` tag and watch the workflow. +3. **Production container:** use a production `.env` with **no `PORT` line** and `PUBLIC_URL=https://` the production subdomain, check NPM's network name, then `docker compose up -d`. Confirm `docker ps` shows it healthy and the production subdomain signs in. +4. **Screenshots** for the README. 5. **Then:** per-browser settings, as designed in `docs/ROADMAP.md` (not started). ## To pick up Start a Claude Code session in this repo and say something like: -*"Read SESSION.md and docs/ROADMAP.md. The per-user Zoho sign-in and Docker setup are built but not yet tested live. Help me get it deployed and checked, then we'll plan the per-browser settings panel."* +*"Read SESSION.md and docs/ROADMAP.md. The per-user sign-in works live on bare metal; next is the first Docker deploy. Help me check the production container, then we'll plan the per-browser settings panel."* diff --git a/docs/NOTES.md b/docs/NOTES.md index 57905aa..d9c65ad 100644 --- a/docs/NOTES.md +++ b/docs/NOTES.md @@ -20,6 +20,12 @@ Docs: