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>
135 lines
4.7 KiB
Markdown
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
|
|
```
|