Move deployment README to repo root for visibility

This commit is contained in:
Gitead
2026-07-31 19:26:02 -04:00
parent 6709d2ef1d
commit e804e1c5e8

228
README.md Normal file
View File

@@ -0,0 +1,228 @@
# Deployment: app.mydentalofficemanagement.com
How this app is served in production: nginx serves a static production
build on this machine, and Cloudflare Tunnel exposes it publicly at
`https://app.mydentalofficemanagement.com` without opening any ports on
the router.
```
Browser → Cloudflare (DNS + edge) → Tunnel (cloudflared, systemd) → nginx (:80) → static files
```
## 1. Prerequisites
- Debian (tested on Debian 13 "trixie")
- sudo access
- Node.js + pnpm installed, repo cloned
- The domain `mydentalofficemanagement.com` already added as a zone in
Cloudflare, with a Cloudflare account you can log into
## 2. Install cloudflared
Debian's codename is usually too new for Cloudflare's apt repo, so install
the `.deb` package directly instead:
```bash
curl -fsSL -o /tmp/cloudflared.deb \
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i /tmp/cloudflared.deb
cloudflared --version
```
## 3. Authenticate cloudflared
```bash
cloudflared tunnel login
```
Opens a browser — log in and authorize the `mydentalofficemanagement.com`
zone. This writes `~/.cloudflared/cert.pem`.
## 4. Tunnel
This project uses an existing dashboard-managed tunnel named
**`mydentalmanagement`** (tunnel ID `027669d4-3d96-4f90-920d-e727cecf3b92`).
It already has other subdomains routed through it, so **reuse it** — don't
create a new tunnel for this app.
If it doesn't exist yet on a fresh Cloudflare account, create one:
```bash
cloudflared tunnel create mydentalmanagement
```
### Get a run token
```bash
cloudflared tunnel token mydentalmanagement
```
Copy the printed token for the next step. (This token authenticates this
machine to run the tunnel — treat it like a secret, don't commit it.)
### Install cloudflared as a service
```bash
sudo cloudflared service install <TOKEN>
sudo systemctl enable --now cloudflared
sudo systemctl status cloudflared
```
## 5. Cloudflare public hostname route
In the Cloudflare dashboard:
**Zero Trust → Networks → Tunnels → mydentalmanagement → Published
application routes → Add a published application route**
| Field | Value |
|---|---|
| Hostname | `app.mydentalofficemanagement.com` |
| Path | *(leave empty)* |
| Service Type | `HTTP` |
| URL | `localhost:80` |
Note: `mydentalmanagement` was originally a locally-configured tunnel and
had to be **migrated** to dashboard-managed mode the first time this was
set up (Cloudflare shows a one-time "Migrate" prompt for this). That step
is already done — future public hostname routes can just be added
directly from this tab.
If you see "A DNS record with this name already exists," a stale
CNAME/A record is occupying that hostname — delete it in **DNS → Records**
first, then re-add the route (this recreates the DNS record correctly as
part of the route).
## 6. Install nginx
```bash
sudo apt-get install -y nginx
sudo rm -f /etc/nginx/sites-enabled/default
```
If Apache is installed and already bound to port 80, disable it first
(only if nothing else depends on it):
```bash
sudo systemctl disable --now apache2
```
### nginx site config
Create `/etc/nginx/sites-available/app.mydentalofficemanagement.com.conf`:
```nginx
server {
listen 80;
server_name app.mydentalofficemanagement.com;
root /var/www/app.mydentalofficemanagement.com;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
```
```bash
sudo ln -s /etc/nginx/sites-available/app.mydentalofficemanagement.com.conf \
/etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo systemctl enable nginx
```
Note: `/var/www/...` is used (not a path under `/home/<user>/...`)
because nginx runs as `www-data`, and a typical home directory
(`drwx------`) blocks that user from traversing into it.
## 7. Build and deploy the app
`vite.config.ts` requires `PORT` and `BASE_PATH` env vars to even load
(`PORT` isn't actually used by the static build, but the config throws
without it regardless of command).
```bash
cd "artifacts/dental-app"
PORT=5173 BASE_PATH=/ npm run build
```
Deploy the build output:
```bash
sudo mkdir -p /var/www/app.mydentalofficemanagement.com
sudo cp -r dist/public/* /var/www/app.mydentalofficemanagement.com/
sudo chown -R www-data:www-data /var/www/app.mydentalofficemanagement.com
```
### Redeploying after code changes
Repeat the build + copy steps above any time the app changes:
```bash
cd "artifacts/dental-app"
PORT=5173 BASE_PATH=/ npm run build
sudo cp -r dist/public/* /var/www/app.mydentalofficemanagement.com/
```
## 8. Running the site
By default `nginx` and `cloudflared` are systemd services and can either
auto-start on boot or be started manually.
**Enable auto-start on boot:**
```bash
sudo systemctl enable nginx
sudo systemctl enable cloudflared
```
**Disable auto-start (manual start only):**
```bash
sudo systemctl disable nginx
sudo systemctl disable cloudflared
```
**Manually start the site** (needed after every reboot if auto-start is
disabled):
```bash
sudo systemctl start cloudflared
sudo systemctl start nginx
```
**Stop the site:**
```bash
sudo systemctl stop nginx
sudo systemctl stop cloudflared
```
**Check status:**
```bash
systemctl status nginx cloudflared
curl -I https://app.mydentalofficemanagement.com
```
No Node/Vite process is needed to serve the site — it's a static build
served directly by nginx.
## 9. Local development preview (not the public site)
To preview changes locally before building/deploying, separate from the
live public site:
```bash
cd "artifacts/dental-app"
PORT=5173 BASE_PATH=/ npm run dev
```
Then open `http://localhost:5173` in a browser on this machine.
## Troubleshooting
- **502 from the public URL**: check `sudo journalctl -u cloudflared -n 40`
for the exact error (often a port mismatch between the tunnel's
Published Application Route and what nginx is actually listening on).
- **nginx `502`/`403` locally**: check `sudo tail -n 30 /var/log/nginx/error.log`.
- **`cloudflared tunnel list` shows "no active connection"**: the
systemd service isn't running — `sudo systemctl status cloudflared`.
- **Port 80 already in use**: check `sudo ss -tlnp | grep ':80 '` to see
what's holding it (commonly Apache's default install).