docs: add Cloudflare tunnel setup guide and ports reference

Add step-by-step Cloudflare tunnel setup to README.md with Summit Dental Care as a multi-office example. Create docs/ports.md documenting all service hosts and ports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gitead
2026-05-20 23:25:44 -04:00
parent 8e6ada87d6
commit 58b2e4af93
2 changed files with 239 additions and 1 deletions

156
README.md
View File

@@ -172,7 +172,7 @@ cd apps/SeleniumService
## 📖 Developer Documentation
- [Setting up server environment](docs/server-setup.md) — the first step, to run this app in environment.
- [Development Hosts & Ports](docs/ports.md) — which app runs on which host/port
- [Development Hosts & Ports](docs/ports.md) — which app runs on which host/port, and how to configure `.env` for LAN or single-device access
---
@@ -195,3 +195,157 @@ Each package/app is 100% [TypeScript](https://www.typescriptlang.org/) (except t
- [TypeScript](https://www.typescriptlang.org/) for static type checking
- [ESLint](https://eslint.org/) for code linting
- [Prettier](https://prettier.io) for code formatting
---
## Cloudflare Tunnel Setup (Remote Access per Office)
This connects each office's local app to a public subdomain via a Cloudflare Tunnel — no port forwarding needed, local network access is unchanged.
**How it works:**
- Local network: other office PCs reach the app directly at `http://<machine-ip>:3000`
- Internet: anyone reaches the app via `https://<subdomain>.mydentalofficemanagement.com`
- Both paths hit the same app simultaneously with no conflict
---
### Step 1 — Add domain to Cloudflare (done once for all offices)
> Skip this step if the domain is already on Cloudflare.
1. Go to `dash.cloudflare.com`**Add a site** → enter `mydentalofficemanagement.com` (free plan)
2. Cloudflare scans existing DNS records — review and keep them
3. Cloudflare gives you 2 nameservers (e.g. `holly.ns.cloudflare.com`, `amir.ns.cloudflare.com`)
4. Log into **Ionos** → replace the domain's nameservers with Cloudflare's two
5. Wait 1030 min → Cloudflare emails you when active
6. DNSSEC: if not purchased on Ionos, it was never enabled — nothing to turn off
### Step 2 — Install `cloudflared` on the office PC
Run this in a terminal on the office machine:
```bash
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
cloudflared --version
```
### Step 3 — Authenticate with Cloudflare
```bash
cloudflared tunnel login
```
A browser window opens → click `mydentalofficemanagement.com` → terminal shows success and saves a certificate to `~/.cloudflared/cert.pem`.
### Step 4 — Create a tunnel for this office
Use a unique tunnel name per office:
```bash
cloudflared tunnel create <office-tunnel-name>
# Example: cloudflared tunnel create summit-dental-app
```
Note the **tunnel ID** (UUID) printed — you need it in Step 5.
### Step 5 — Create the config file
```bash
sudo mkdir -p /etc/cloudflared
sudo nano /etc/cloudflared/config.yml
```
Paste (replace tunnel ID, credentials path, and subdomain for this office):
```yaml
tunnel: <tunnel-ID>
credentials-file: /home/ee/.cloudflared/<tunnel-ID>.json
ingress:
- hostname: <subdomain>.mydentalofficemanagement.com
service: http://localhost:3000
- service: http_status:404
```
Save: `Ctrl+O` → Enter → `Ctrl+X`.
### Step 6 — Route DNS for this office's subdomain
```bash
cloudflared tunnel route dns <office-tunnel-name> <subdomain>.mydentalofficemanagement.com
```
### Step 7 — Install as a system service (auto-starts on boot)
```bash
sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared
```
### Step 8 — Allow the subdomain in Vite
In `apps/Frontend/vite.config.js`, add the subdomain to `server.allowedHosts` so Vite does not block external requests.
### Step 9 — Allow the subdomain in backend CORS
In `apps/Backend`, add the subdomain URL to the allowed CORS origins so login and API calls work from the public URL.
---
### Example — Adding Summit Dental Care
**Office subdomain:** `summitdentalcare.mydentalofficemanagement.com`
**Step 1:** Already done (domain is on Cloudflare).
**Step 2:** Install `cloudflared` on Summit Dental's PC.
**Step 3:** Run `cloudflared tunnel login` on Summit Dental's PC.
**Step 4:**
```bash
cloudflared tunnel create summit-dental-app
# Example output: Created tunnel summit-dental-app with id a1b2c3d4-...
```
**Step 5 — `/etc/cloudflared/config.yml`:**
```yaml
tunnel: a1b2c3d4-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/ee/.cloudflared/a1b2c3d4-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
ingress:
- hostname: summitdentalcare.mydentalofficemanagement.com
service: http://localhost:3000
- service: http_status:404
```
**Step 6:**
```bash
cloudflared tunnel route dns summit-dental-app summitdentalcare.mydentalofficemanagement.com
```
**Step 7:**
```bash
sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
```
**Step 8:** Add `summitdentalcare.mydentalofficemanagement.com` to `allowedHosts` in `vite.config.js`.
**Step 9:** Add `https://summitdentalcare.mydentalofficemanagement.com` to backend CORS allowed origins.
---
### Multi-office overview
Each office runs its own `cloudflared` tunnel on its own PC. Ports never conflict because each PC is a separate machine.
| Office | Local access | Public access | Tunnel name |
|---|---|---|---|
| Community Dentists of Lowell | `http://192.168.1.236:3000` | `https://communitydentistsoflowell.mydentalofficemanagement.com` | `dental-app` |
| Summit Dental Care | `http://<its-ip>:3000` | `https://summitdentalcare.mydentalofficemanagement.com` | `summit-dental-app` |
| Next office | `http://<its-ip>:3000` | `https://<subdomain>.mydentalofficemanagement.com` | `<office>-app` |