Phase 3 + 6
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# Phase 6.1 + 6.6 + 6.7: tools.acherryontop.com final form
|
||||
#
|
||||
# Apply on the server with:
|
||||
# curl -X POST http://localhost:2020/load \
|
||||
# -H 'Content-Type: text/caddyfile' \
|
||||
# --data-binary @/home/matt/Caddyfile.new
|
||||
# sudo cp /home/matt/Caddyfile.new /etc/caddy/Caddyfile
|
||||
# sudo cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%F)
|
||||
#
|
||||
# Differences from current /etc/caddy/Caddyfile:
|
||||
# 1. forward_auth gate added in front of /api/* and /chat-api/* (Phase 6.1).
|
||||
# 2. /uploads/* moved behind the forward_auth gate (Phase 6.7 — was public).
|
||||
# 3. LAN wildcards / Access-Control-Allow-Origin "*" defaults dropped from /api/* (Phase 6.6).
|
||||
# 4. Removed dead /api/{aircall,gorgias,clarity}/* routes (Phase 1 — already cleaned up here).
|
||||
#
|
||||
# Phase 4 (dashboard-server merge) is NOT yet reflected — klaviyo/meta/google/typeform
|
||||
# still route to their per-vendor PM2 apps in the live Caddyfile. Update those handle
|
||||
# blocks to localhost:3015 when dashboard-server ships.
|
||||
|
||||
tools.acherryontop.com {
|
||||
import security_headers
|
||||
|
||||
# Public: login endpoint
|
||||
handle /auth-inv/* {
|
||||
uri strip_prefix /auth-inv
|
||||
reverse_proxy localhost:3011
|
||||
}
|
||||
|
||||
# Public: static frontend assets (long-cache)
|
||||
@static path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2
|
||||
handle @static {
|
||||
header Cache-Control "public, max-age=2592000"
|
||||
root * /var/www/inventory/frontend/build
|
||||
file_server
|
||||
}
|
||||
|
||||
# ----- Authenticated zone -----
|
||||
# Phase 6.1: forward_auth subrequest to auth-server:/verify. 2xx → proceeds.
|
||||
# 401/403 → Caddy returns auth-server response to client; backend never sees it.
|
||||
@gated path /api/* /chat-api/* /uploads/*
|
||||
handle @gated {
|
||||
forward_auth localhost:3011 {
|
||||
uri /verify
|
||||
copy_headers Authorization
|
||||
}
|
||||
|
||||
# Phase 6.7: /uploads/* now behind the gate (was a public file_server before)
|
||||
handle /uploads/* {
|
||||
root * /var/www/inventory
|
||||
file_server
|
||||
}
|
||||
|
||||
# Vendor dashboard routes
|
||||
# NOTE: pre-Phase-4 these are still on separate ports; updates here when merged.
|
||||
handle /api/klaviyo/* { reverse_proxy localhost:3015 }
|
||||
handle /api/meta/* { reverse_proxy localhost:3015 }
|
||||
handle /api/google-analytics/* { reverse_proxy localhost:3015 }
|
||||
handle /api/typeform/* { reverse_proxy localhost:3015 }
|
||||
|
||||
# ACOT
|
||||
handle /api/acot/* { reverse_proxy localhost:3012 }
|
||||
|
||||
# Chat
|
||||
handle /chat-api/* {
|
||||
uri strip_prefix /chat-api
|
||||
reverse_proxy localhost:3014
|
||||
}
|
||||
|
||||
# Catch-all: inventory-server
|
||||
handle /api/* { reverse_proxy localhost:3010 }
|
||||
}
|
||||
|
||||
# Out-of-band probes (unauthenticated)
|
||||
handle /health { reverse_proxy localhost:3010 }
|
||||
|
||||
# SPA fallback (public assets)
|
||||
handle {
|
||||
root * /var/www/inventory/frontend/build
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
encode gzip
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
respond "{err.status_code} {err.status_text}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
# Server-side deployment artefacts for Phase 3 + 6
|
||||
|
||||
This directory contains proposed versions of files that live outside the
|
||||
inventory-server tree on production. Each is a recommendation — apply
|
||||
deliberately and only after the Node-side ESM + auth changes are deployed and
|
||||
smoke-tested.
|
||||
|
||||
| Source | Target | Phase |
|
||||
| --------------------------------------- | ------------------------------------- | -------- |
|
||||
| `Caddyfile.proposed` | `/etc/caddy/Caddyfile` | 6.1, 6.6, 6.7 |
|
||||
| `ecosystem.config.cjs.proposed` | `/var/www/ecosystem.config.cjs` | 6.4, 6.10 |
|
||||
|
||||
## Recommended apply order
|
||||
|
||||
1. **Deploy the Node code first** (this repo). PM2 reload picks up the new
|
||||
ESM-mode inventory-server and auth-server. At this point the frontend will
|
||||
start hitting 401s on every API call because the new `authenticate()`
|
||||
middleware is live and the frontend doesn't carry Bearer tokens on most
|
||||
fetches. **This is expected per the discussion in CONSOLIDATION_PLAN.md
|
||||
§6** — the frontend fetch-wrapper work is the next deliverable.
|
||||
|
||||
2. **Apply the ecosystem.cjs change** (Phase 6.4) to fix the `JWT_SECRET`
|
||||
shadow-override before the next pm2 restart silently re-introduces it.
|
||||
|
||||
3. **Apply the Caddyfile change** (Phase 6.1) only after the frontend is
|
||||
sending Bearer tokens. Until then, `forward_auth` will reject every page
|
||||
refresh at the edge.
|
||||
|
||||
## Caddyfile apply pattern
|
||||
|
||||
Caddy admin API is on `:2020` (matt has access). On-disk file needs root.
|
||||
|
||||
```bash
|
||||
# Upload + load atomically into the running Caddy
|
||||
curl -X POST http://localhost:2020/load \
|
||||
-H 'Content-Type: text/caddyfile' \
|
||||
--data-binary @/home/matt/Caddyfile.new
|
||||
|
||||
# Persist to disk (separate sudo step)
|
||||
sudo cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%F)
|
||||
sudo cp /home/matt/Caddyfile.new /etc/caddy/Caddyfile
|
||||
```
|
||||
|
||||
## ecosystem.cjs apply pattern
|
||||
|
||||
```bash
|
||||
sudo cp /var/www/ecosystem.config.cjs /var/www/ecosystem.config.cjs.bak.$(date +%F)
|
||||
sudo cp /home/matt/ecosystem.config.cjs.new /var/www/ecosystem.config.cjs
|
||||
pm2 reload ecosystem.config.cjs --update-env
|
||||
pm2 env new-auth-server | grep -i jwt # JWT_SECRET from .env only
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
Every applied file leaves a `.bak.YYYY-MM-DD` next to it. `sudo cp <bak>
|
||||
<original>` then `caddy reload` / `pm2 reload`.
|
||||
|
||||
Phase 6 changes are *additive* — if `forward_auth` causes problems, comment
|
||||
out the directive in the live Caddyfile and per-server middleware
|
||||
(`authenticate()` in inventory-server, in particular) continues protecting
|
||||
routes.
|
||||
@@ -0,0 +1,114 @@
|
||||
// Phase 6.4 + 6.10: proposed /var/www/ecosystem.config.cjs
|
||||
//
|
||||
// Diffs from the live file (CONSOLIDATION_PLAN.md §6.4 / §6.10):
|
||||
// 1. Drop the `JWT_SECRET: process.env.JWT_SECRET` override in new-auth-server's
|
||||
// env block. That override shadowed the .env value with whatever shell var was
|
||||
// exported when pm2 was last started — causing the silent-divergence footgun
|
||||
// called out in CLAUDE.md memory. With it removed, .env is the single source.
|
||||
// 2. Move ADD_WORD_TOKEN out of the inline env into /opt/lt-wordlist-api/.env.
|
||||
// The PM2 entry below no longer references it.
|
||||
// 3. Rename the placeholder script paths if you have any half-finished ones; this
|
||||
// version only lists the apps that actually run today (post-Phase-1 cleanup).
|
||||
//
|
||||
// To apply:
|
||||
// sudo cp /var/www/ecosystem.config.cjs /var/www/ecosystem.config.cjs.bak.$(date +%F)
|
||||
// sudo cp /home/matt/ecosystem.config.cjs.new /var/www/ecosystem.config.cjs
|
||||
// pm2 reload ecosystem.config.cjs --update-env
|
||||
//
|
||||
// Verify after reload:
|
||||
// pm2 env new-auth-server | grep -i jwt # should show JWT_SECRET from .env only
|
||||
// pm2 env new-auth-server | grep ADD_WORD # should be empty
|
||||
|
||||
const inventoryEnv = require('dotenv').config({ path: '/var/www/inventory/.env' }).parsed;
|
||||
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'new-auth-server', // Phase 8 may rename to 'auth-server' — cosmetic
|
||||
script: './inventory/auth/server.js',
|
||||
cwd: '/var/www',
|
||||
env: {
|
||||
...inventoryEnv,
|
||||
NODE_ENV: 'production',
|
||||
AUTH_PORT: 3011,
|
||||
// PHASE 6.4 FIX: no JWT_SECRET override here. .env wins.
|
||||
},
|
||||
max_memory_restart: '500M',
|
||||
error_file: '/var/log/pm2/new-auth-server-error.log',
|
||||
out_file: '/var/log/pm2/new-auth-server-out.log',
|
||||
},
|
||||
{
|
||||
name: 'inventory-server',
|
||||
script: './inventory/src/server.js',
|
||||
cwd: '/var/www',
|
||||
env: {
|
||||
...inventoryEnv,
|
||||
NODE_ENV: 'production',
|
||||
PORT: 3010,
|
||||
UPLOADS_DIR: '/var/www/inventory/uploads',
|
||||
},
|
||||
max_memory_restart: '1G',
|
||||
error_file: '/var/log/pm2/inventory-server-error.log',
|
||||
out_file: '/var/log/pm2/inventory-server-out.log',
|
||||
},
|
||||
{
|
||||
name: 'chat-server',
|
||||
script: './inventory/chat/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production', PORT: 3014 },
|
||||
max_memory_restart: '500M',
|
||||
},
|
||||
{
|
||||
name: 'acot-server',
|
||||
script: './inventory/dashboard/acot-server/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production', ACOT_PORT: 3012 },
|
||||
max_memory_restart: '1G',
|
||||
},
|
||||
// Per-vendor dashboard apps stay until Phase 4 merge ships.
|
||||
{
|
||||
name: 'klaviyo-server',
|
||||
script: './inventory/dashboard/klaviyo-server/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production' },
|
||||
max_memory_restart: '500M',
|
||||
},
|
||||
{
|
||||
name: 'meta-server',
|
||||
script: './inventory/dashboard/meta-server/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production' },
|
||||
max_memory_restart: '300M',
|
||||
},
|
||||
{
|
||||
name: 'google-server',
|
||||
script: './inventory/dashboard/google-server/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production' },
|
||||
max_memory_restart: '300M',
|
||||
},
|
||||
{
|
||||
name: 'typeform-server',
|
||||
script: './inventory/dashboard/typeform-server/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production' },
|
||||
max_memory_restart: '300M',
|
||||
},
|
||||
// PHASE 6.10: lt-wordlist-api now loads ADD_WORD_TOKEN from /opt/lt-wordlist-api/.env
|
||||
// (no longer hardcoded here). Rotate that token's value when applying this change.
|
||||
{
|
||||
name: 'lt-wordlist-api',
|
||||
script: '/opt/lt-wordlist-api/server.js',
|
||||
cwd: '/opt/lt-wordlist-api',
|
||||
env: { NODE_ENV: 'production' },
|
||||
max_memory_restart: '200M',
|
||||
},
|
||||
{
|
||||
name: 'acot-phone-server',
|
||||
script: './inventory/acot-phone/server.js',
|
||||
cwd: '/var/www',
|
||||
env: { ...inventoryEnv, NODE_ENV: 'production' },
|
||||
max_memory_restart: '300M',
|
||||
},
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user