Files
www.kenjim.com/README.md
Kenji M bdab4de971 Add deployment architecture diagram and update README
Mermaid flowchart covers: GoDaddy DDNS, pfSense NAT + split DNS,
Let's Encrypt DNS-01, nginx SSL termination, Docker host-network
containers, Proton Bridge SMTP relay, and Gitea git workflow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 16:29:50 +00:00

135 lines
4.7 KiB
Markdown

# www.kenjim.com
KenJim Technologies marketing site — React SPA with Express contact form backend, deployed on **zet.home.arpa** behind nginx SSL termination.
## Deployment Architecture
```mermaid
flowchart TD
subgraph internet["Internet"]
browser(["Client browser"])
godaddy["GoDaddy DNS\nwww.kenjim.com CNAME → lair.kenjim.com\nlair.kenjim.com A → WAN IP (dynamic)"]
le["Let's Encrypt CA"]
end
subgraph pfsense["pfSense · home gateway"]
ddns["DDNS client\nupdates lair.kenjim.com A record\nwhen WAN IP changes"]
nat["NAT / Port Forward\nWAN :80 / :443 → zet :80 / :443"]
unbound["Unbound DNS Resolver\nwww / git / kenji.kenjim.com\n→ 172.27.0.35 (split DNS — bypasses NAT)"]
end
subgraph zet["zet.home.arpa · 172.27.0.35"]
subgraph ssl["SSL — acme.sh + Let's Encrypt"]
acme["acme.sh\nDNS-01 challenge via GoDaddy API"]
cert["/etc/nginx/ssl/kenjim.com/\nfullchain.pem · key.pem\nauto-renewed by cron"]
end
subgraph nginx_host["nginx · host process"]
nginxsrv[":80 → redirect HTTPS\n:443 · SSL termination\nproxy_pass → localhost:8080"]
end
subgraph docker["Docker · network_mode: host"]
fe["www-kenjim-frontend\nnginx :8080\nReact SPA (pre-built image)\n/api/* proxied → :3001"]
api["www-kenjim-api\nExpress.js :3001\nPOST /contact handler"]
end
bridge["Proton Mail Bridge\n127.0.0.1:1025 SMTP relay"]
gitea[("Gitea · git.kenjim.com\nkenjim/www.kenjim.com")]
end
protonmail["Proton Mail\ninfo@kenjim.com → kenji@kenjim.com"]
browser -->|"DNS lookup"| godaddy
browser -->|"HTTPS :443"| nat
nat -->|"port forward"| nginxsrv
unbound -.->|"LAN clients resolve direct"| nginxsrv
nginxsrv -->|"proxy_pass :8080"| fe
fe -->|"proxy /api/*"| api
api -->|"SMTP 127.0.0.1:1025"| bridge
bridge -->|"relay via Proton servers"| protonmail
acme <-->|"set DNS TXT record\nfor domain validation"| godaddy
acme <-->|"certificate issuance"| le
acme -->|"writes cert"| cert
cert -->|"loaded by"| nginxsrv
ddns -->|"keeps A record current"| godaddy
gitea -->|"git pull · docker compose up --build"| fe
gitea -->|"git pull · docker compose up --build"| api
```
## Structure
```
www.kenjim.com/
├── docker-compose.yml # both services run network_mode: host
├── frontend/
│ ├── Dockerfile # node:20 build → nginx:alpine serve
│ ├── nginx.conf # :8080, SPA fallback, /api/ proxy → :3001
│ └── src/ # React source (Vite)
└── backend/
├── Dockerfile
└── server.js # Express, POST /contact → nodemailer
```
## Development Workflow
Edit on Mac → push to Gitea → pull + rebuild on zet:
```
Mac Gitea (git.kenjim.com) zet.home.arpa
│ git push │ │
├──────────────────────────────►│ │
│ │ git pull │
│ ├─────────────────────────►│
│ │ │ docker compose up --build -d
```
## Running on zet
```bash
cd ~/workspace/src/personal/www.kenjim.com
docker compose up --build -d # build images and start
docker compose down # stop
docker compose logs -f # watch logs
docker logs www-kenjim-api # backend only
docker logs www-kenjim-frontend # frontend only
```
## Environment
`.env` lives on zet only (not in git). Required vars:
| Variable | Example | Notes |
|---|---|---|
| `SMTP_HOST` | `127.0.0.1` | Proton Bridge SMTP host |
| `SMTP_PORT` | `1025` | Proton Bridge SMTP port |
| `SMTP_SECURE` | `false` | Bridge uses STARTTLS, not SSL-on-connect |
| `SMTP_USER` | `kenji@kenjim.com` | Bridge auth credential |
| `SMTP_PASS` | `<bridge-password>` | From Bridge SMTP settings |
| `FROM_EMAIL` | `info@kenjim.com` | Sender address shown in emails |
| `CONTACT_TO` | `info@kenjim.com` | Destination for contact form submissions |
## SSL Certificate
Issued by Let's Encrypt via DNS-01 challenge using the GoDaddy API. Managed by acme.sh on zet:
```bash
# manual renewal (cron handles this automatically)
~/.acme.sh/acme.sh --renew -d kenjim.com --wildcard --dns dns_gd
```
Cert location: `/etc/nginx/ssl/kenjim.com/`
## Mac Setup (first time)
```bash
git clone http://kenjim@git.kenjim.com/kenjim/www.kenjim.com.git
cd www.kenjim.com
# edit frontend/src, then:
git add . && git commit -m "..." && git push
```