diff --git a/PI_DEPLOYMENT.md b/PI_DEPLOYMENT.md deleted file mode 100644 index 0062f33..0000000 --- a/PI_DEPLOYMENT.md +++ /dev/null @@ -1,108 +0,0 @@ -# Production Deployment & Architecture Guide (Raspberry Pi) - -This document provides a comprehensive overview of how the Wayfinder application is deployed, networked, and configured on the production Raspberry Pi (`2ndFloor`), along with critical instructions for future development teams. - ---- - -## 🏗️ 1. Architecture Overview - -In the production environment, the application consists of four main components interacting as follows: - -1. **Ngrok (Public Gateway):** Exposes the Pi's internal Nginx server to the public internet via a secure HTTPS URL. -2. **Nginx (Web Server & Reverse Proxy):** Listens on port `80`. It serves the compiled React frontend directly to users and forwards any API requests to the Node.js backend. -3. **Node.js/Express (Backend):** Listens on port `5000`. Managed entirely by `systemd`. Handles searching, navigation logic, and fetching Ngrok config. -4. **PostgreSQL (Database):** Hosted locally on the Pi on port `5432`. Stores all room layouts, nodes, and librarian mappings. - -### Why this setup? -Nginx cleanly separates static frontend files from the API. The frontend doesn't need to boot up a Node.js server. Ngrok points strictly to Nginx (Port 80) so that mobile devices scanning the QR Code can hit a secure HTTPS endpoint instead of the Pi's local network IP. - ---- - -## 📂 2. Crucial File Locations on the Pi - -If you SSH into the Pi (`ssh wayfinder@2ndFloor`), the files you need to care about are spread across the system: - -* **Source Code repo:** `/home/wayfinder/WayfinderMain/` -* **Nginx Configuration:** `/etc/nginx/sites-available/default` -* **Frontend Compiled Files:** `/var/www/` *(Nginx serves everything inside this folder)* -* **Backend System Service:** `/etc/systemd/system/wayfinder-backend.service` -* **Ngrok System Service:** `/etc/systemd/system/ngrok.service` -* **Backend Dedicated Logs:** `/var/log/wayfinder/backend.log` -* **Nginx Logs:** `/var/log/nginx/error.log` and `/var/log/nginx/access.log` - ---- - -## 🌐 3. Networking & Ngrok Routing - -The networking stack routes traffic using endpoints and headers to ensure things don't break across different devices. - -1. **The Routing Mechanism:** - * When a user requests `https://[ngrok-url]/`, Nginx serves `index.html` from `/var/www/`. - * When a user requests `https://[ngrok-url]/api/...`, Nginx intercepts this via its `location /api` block and **reverse proxies** the request to `http://localhost:5000/api/...`. - * **Wait, why `/api`?** We specifically added the `/api` prefix to all backend routes to let Nginx accurately differentiate between someone requesting a React web page and someone querying the Postgres database. - -2. **The "Mobile Handoff" Flow:** - * The kiosk (running on `localhost` or via Tailscale) generates a QR code. - * The QR code dynamically fetches the active Ngrok URL via a custom endpoint `/api/config`. - * **Important:** Free Ngrok accounts inject an intrusive browser warning page on the first visit. To prevent this from breaking JSON API fetch calls on the mobile device, **every frontend `fetch()` request must include the header:** - `"ngrok-skip-browser-warning": "true"` - ---- - -## 🛠️ 4. Deploying Updates to the Pi - -When the `main` branch is updated on GitHub, it does **not** instantly go live on the Pi. You must pull the new code, rebuild it, copy the frontend to Nginx, and restart the backend. - -**Run the following command chain on the Pi to perform a full deployment update:** - -```bash -# 1. Pull latest code -cd /home/wayfinder/WayfinderMain -git fetch origin main && git reset --hard origin/main && git pull origin main - -# 2. Rebuild the backend -cd backend -npm install -npm run build - -# 3. Rebuild the frontend -cd ../frontend -npm install -npm run build - -# 4. Deploy frontend to Nginx -sudo rm -rf /var/www/* -sudo cp -r dist/* /var/www/ - -# 5. Restart backend service -sudo systemctl restart wayfinder-backend -``` - ---- - -## 🧑‍💻 5. Guide for Future Development Teams - -When picking up this project, adhere to the following standards to ensure production stability: - -### Modifying the Frontend -* Do not hardcode API requests to `http://localhost:5000`. -* Use relative routes like `fetch("/api/search")`. -* When making a new API request, ensure the `ngrok-skip-browser-warning` header is present. If it's missing, mobile API requests will fail due to Ngrok returning standard HTML instead of JSON. - -### Modifying the Backend Services -* Ensure all new routes begin with `/api/` (e.g., `app.use("/api/new-feature", ...)`). -* Do not rely on `console.log()` for persistent data analysis. In production, these are appended to `/var/log/wayfinder/backend.log`. Use this log to debug deployment errors! -* Keep the local `.env` file cleanly updated. Do NOT commit the production database password to GitHub. - -### Modifying the Database -The Postgres database sits strictly on the Pi. -* **User:** `postgres` -* **Password:** Same as the Pi's user password (`FindYourWay`) -* If you modify the tables, update `backend/src/db/init.sql`. To fully wipe and re-initialize the database on the Pi, you can execute: - `sudo -u postgres psql -f /home/wayfinder/WayfinderMain/backend/src/db/init.sql` - -### Debugging Services -If the app stops responding on the Pi, always check the `systemd` statuses first to see what crashed: -* `systemctl status nginx` -* `systemctl status wayfinder-backend` -* `systemctl status ngrok` diff --git a/README.md b/README.md index 103922c..788e201 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,37 @@ # Wayfinder -Welcome to the Wayfinder Project! -## How to run locally +Kiosk + mobile wayfinding app for Lockwood Library. +- Frontend: `frontend/` (React/Vite) +- Backend: `backend/` (Express/TypeScript) +- DB: PostgreSQL for librarian search +- Production: Nginx + Ngrok on Raspberry Pi +Read `docs/HANDOFF.md` first, then `docs/OPERATIONS.md`. -### Step 1 - Clone the Repository - -First, clone the repository to your local machine using Git: - -```bash -git clone https://github.com/Munchken105/Wayfinder.git -``` - -You may or may not need to ```cd``` into your repo where you cloned it. - -### Step 2 - From the root directory, run the commands: +## Local Setup ```bash -cd backend +git clone +cd WayfinderMain/backend npm install ``` - -This will install the backend dependencies. - -### Step 3 - Start the database - -Ensure you have PostgreSQL installed on your local machine. To check, simply run this command on a terminal: - -```bash -postgres --version -``` - -It should display something like: - -```postgres (PostgreSQL) 17.6``` - -where the number is the version of your installed PostgreSQL. This means that PostgreSQL is properly installed on your local machine. - -If an error occurs, you do not have PostgreSQL installed. Download it at this [link](https://www.postgresql.org/download/) before going to the next step. Ensure you remember the password you set. - -Afterward when it is properly installed, run: - +Create `backend/.env` with `DB_USER`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `PORT`. ```bash npm run db:init -``` - -You may be prompted to type in your password. Enter in your password so the database can be hosted. - -### Step 4 - Define environment variables - -Make a .env file in the /backend directory with the following: - -``` -DB_USER=postgres -DB_PASSWORD=your_password -DB_HOST=localhost -DB_PORT=5432 -DB_NAME=wayfinder - -PORT=5000 -``` - -Replace "your_password" with your own password that connects to the user "postgres" so that the database can run. - -### Step 5 - Start the backend - -```bash npm run dev -``` - -This will start the development server for the backend. - -### Step 6 - On a separate terminal and from the root directory, run the commands: - -```bash -cd frontend +cd ../frontend npm install -``` - -This will install the frontend dependencies. - -### Step 7 - Start the frontend - -```bash npm run dev ``` +Open `http://localhost:5173`. -This will start the development server for the frontend. - -### Step 8 - Open a browser and visit [http://localhost:5173](http://localhost:5173) to open the frontend - -This should connect to the backend automatically. +## Notes -## Tailscale SSH +- Vite proxies `/api/*` to `http://localhost:5000`. +- QR links use `/floors?q=&mode=stairs|elevator`. +- Health check is `http://localhost:5000/health` (not `/api/health`). -### Step 1 - Go to tailscale.com Login using the Wayfinder Gmail Account (Found on our private Doc) +## API -### Step 2 Connect to tailnet +`GET /api/search`, `GET /api/nodes`, `GET /api/rooms`, `GET /api/navigation/from/:start/to/:end`, `GET /api/floor/:floorNumber/routes`, `GET /api/config`, `GET /health` -Open Terminal -```bash -tailscale up -``` - -### Step 3 - ssh -```bash -ssh wayfinder@2ndFloor -``` -you are now sshed into the our 2ndFloor rasbery pi as more pi's come along ill update each pi with its own ssh instructions +See `docs/PI_DEPLOYMENT.md` for Pi architecture. diff --git a/SQL_UPDATE_GUIDE.md b/SQL_UPDATE_GUIDE.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md new file mode 100644 index 0000000..9c6b146 --- /dev/null +++ b/docs/HANDOFF.md @@ -0,0 +1,30 @@ +# Wayfinder Handoff + +Read in order: `../README.md` -> `PI_DEPLOYMENT.md` -> `OPERATIONS.md`. + +## System Snapshot + +- Kiosk selects room, backend computes route, QR opens phone deep link. +- Frontend routes: `/`, `/floors`, `/mobile` (`/floors` is current QR target). +- Backend API runs on `:5000`. +- Navigation graph lives in `backend/src/server.ts`. +- Search data lives in PostgreSQL via `backend/src/db/init.sql`. + +## Source of Truth + +`nginx-default`, `wayfinder-backend.service`, `scripts/deploy-pi.sh`, `scripts/redeploy-from-local.sh`, `backend/src/db/init.sql` + +## Critical Risks + +- `/api/navigation/from/:start/to/:end` ignores `:start`. +- Nginx proxies `/api` only; `/health` is backend-root. +- `db:init` is destructive reset. +- Rollback is manual. +- Kiosk OS/browser autostart config is not in this repo. + +## Ownership to Confirm + +- Canonical repo URL and branch policy. +- Pi, Ngrok, and Tailscale owners. +- Secret manager + credential rotation owner. +- Backup location + retention policy. diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md new file mode 100644 index 0000000..de29105 --- /dev/null +++ b/docs/OPERATIONS.md @@ -0,0 +1,61 @@ +# Operations Runbook +## Local Dev +```bash +git clone +cd WayfinderMain/backend +npm install +``` +Create `backend/.env` with `DB_USER`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `PORT`. +```bash +npm run db:init +npm run dev +cd ../frontend +npm install +npm run dev +``` +Smoke test: +```bash +curl -s http://localhost:5000/health +curl -s "http://localhost:5000/api/search?q=computer" +curl -s http://localhost:5000/api/rooms | head +``` +## Deploy / Verify / Rollback +```bash +cd /home/wayfinder/WayfinderMain +git fetch origin main +git checkout main +git reset --hard origin/main +WAYFINDER_REBOOT=0 bash scripts/deploy-pi.sh +systemctl is-active nginx wayfinder-backend ngrok +curl -s http://127.0.0.1:5000/health +curl -s -H "ngrok-skip-browser-warning: true" http://127.0.0.1/api/rooms | head +git rev-parse --short HEAD +``` +Remote deploy from laptop: +```bash +WAYFINDER_REBOOT=0 ./scripts/redeploy-from-local.sh +``` +Rollback: +```bash +cd /home/wayfinder/WayfinderMain +git log --oneline -n 20 +git reset --hard +WAYFINDER_REBOOT=0 bash scripts/deploy-pi.sh +``` +## Troubleshooting + DB Ops +```bash +systemctl status wayfinder-backend nginx ngrok --no-pager +systemctl list-unit-files | rg -i ngrok || pgrep -af ngrok +journalctl -u wayfinder-backend -n 200 --no-pager +sudo tail -n 200 /var/log/wayfinder/backend.log +sudo nginx -t +curl -s http://127.0.0.1:4040/api/tunnels +sudo -u postgres pg_dump -Fc wayfinder > /home/wayfinder/backups/wayfinder_$(date +%F_%H%M).dump +sudo -u postgres pg_restore -d wayfinder --clean --if-exists /home/wayfinder/backups/.dump +``` +Notes: +- `/health` is backend-root (`:5000`), not proxied under `/api`. +- Ngrok setup was completed on Pi using Wayfinder shared Google sign-in + ngrok guided setup. +- On current Pi, ngrok and nginx auto-start on boot. +- Keep secrets only in `backend/.env` and secret manager. +- If SSH host key changed after reimage: `ssh-keygen -R 2ndFloor`. diff --git a/docs/PI_DEPLOYMENT.md b/docs/PI_DEPLOYMENT.md new file mode 100644 index 0000000..d8d0479 --- /dev/null +++ b/docs/PI_DEPLOYMENT.md @@ -0,0 +1,48 @@ +# Raspberry Pi Deployment + +## Architecture +Traffic path: +1. Ngrok (public HTTPS) +2. Nginx on `:80` (serves `/var/www`) +3. `/api/*` proxied to backend on `http://localhost:5000` +4. Express backend handles navigation/search +5. PostgreSQL stores librarian search data +Important: navigation graph is in `backend/src/server.ts`, not PostgreSQL. + +## Canonical Paths +- Repo: `/home/wayfinder/WayfinderMain` +- Nginx config: `/etc/nginx/sites-available/default` (from repo `nginx-default`) +- Backend unit: `/etc/systemd/system/wayfinder-backend.service` (from repo template) +- Ngrok auth/setup: done on Pi via Wayfinder shared Google sign-in + ngrok quickstart flow +- Frontend deploy dir: `/var/www` +- Logs: `/var/log/wayfinder/backend.log`, `/var/log/nginx/error.log`, `/var/log/nginx/access.log` + +## Deploy + +```bash +cd /home/wayfinder/WayfinderMain +git fetch origin main +git checkout main +git reset --hard origin/main +WAYFINDER_REBOOT=0 bash scripts/deploy-pi.sh +``` +`scripts/deploy-pi.sh` builds backend/frontend, copies frontend to `/var/www`, restarts backend, and reboots unless `WAYFINDER_REBOOT=0`. + +## Verify + +```bash +systemctl is-active nginx +systemctl is-active wayfinder-backend +systemctl is-active ngrok +curl -s http://127.0.0.1:5000/health +curl -s -H "ngrok-skip-browser-warning: true" http://127.0.0.1/api/rooms | head +curl -s -H "ngrok-skip-browser-warning: true" http://127.0.0.1:5000/api/config +``` +Expected: services `active`, health JSON, rooms JSON, ngrok `publicUrl` when tunnel is up. + +## Known Caveats + +- Nginx template proxies `/api` only; `/health` is backend-root on `:5000`. +- QR handoff uses `/floors?q=&mode=stairs|elevator`. +- Ngrok and Nginx both auto-start on boot on current Pi; verify startup manager if re-imaging (`systemd` is likely but not guaranteed). +- Keep secrets only in `backend/.env` and secret manager; never in docs. diff --git a/docs/SQL_UPDATE_GUIDE.md b/docs/SQL_UPDATE_GUIDE.md new file mode 100644 index 0000000..d35bf64 --- /dev/null +++ b/docs/SQL_UPDATE_GUIDE.md @@ -0,0 +1,21 @@ +# SQL Update Guide + +Use this when editing `backend/src/db/init.sql`. + +## Required insert order from file comments + +1. Add new `librarians` rows above the comment: "To insert future librarians..." +2. Add new `subjects` rows above the comment: "To insert future subjects..." +3. Add at least one `librarian_subjects` row for every new librarian (required by final comment). + +## Rules + +- Keep existing insert order stable so expected IDs remain predictable. +- `npm run db:init` is destructive (`DROP DATABASE IF EXISTS wayfinder`); back up first. +- After updates, re-run init and verify search: + +```bash +cd backend +npm run db:init +curl -s "http://localhost:5000/api/search?q=" +```