People Aggregator Webhook — Setup
Sub-minute freshness for the people aggregator when Fluent CRM tags or custom fields change. Triggered by an outbound webhook from a Fluent CRM automation funnel; received on the agents VPS by scripts/people-webhook-daemon.py and runs build-people-index.py --force-remote.
As deployed, the receiver binds to 127.0.0.1:9090 only — it is not reachable from the public internet until the nginx exposure steps below are performed.
Components
Section titled “Components”| File | Location |
|---|---|
scripts/people-webhook-daemon.py | in this repo, synced to VPS at /srv/baseworks/knowledge-base/scripts/ |
scripts/people-webhook.service | in this repo; installed to /etc/systemd/system/ on VPS |
| Shared secret | /home/patrick/.people-webhook.secret on VPS (chmod 600, not in git) |
| Log | /home/patrick/scripts/people-webhook.log on VPS |
Installation on the agents VPS (one-time)
Section titled “Installation on the agents VPS (one-time)”# 1. Generate a shared secret and save itssh patrick@46.224.129.16openssl rand -hex 32 > ~/.people-webhook.secretchmod 600 ~/.people-webhook.secretcat ~/.people-webhook.secret # copy — used in FluentCRM funnel config
# 2. Install the systemd unitsudo cp /srv/baseworks/knowledge-base/scripts/people-webhook.service /etc/systemd/system/sudo systemctl daemon-reloadsudo systemctl enable --now people-webhook.servicesudo systemctl status people-webhook.service
# 3. Sanity check (from VPS)curl -s http://127.0.0.1:9090/healthcurl -i -X POST \ -H "Authorization: Bearer $(cat ~/.people-webhook.secret)" \ http://127.0.0.1:9090/webhook/people-index# expect HTTP 202, body: {"status": "queued"}Public exposure (when you are ready — NOT done by default)
Section titled “Public exposure (when you are ready — NOT done by default)”The receiver is local-only until you do this step. Two parts: nginx reverse proxy and a firewall rule. Pick a hostname — agents.baseworks.com is the natural fit.
nginx server block
Section titled “nginx server block”Create /etc/nginx/sites-available/agents.baseworks.com:
server { listen 80; server_name agents.baseworks.com; return 301 https://$host$request_uri;}
server { listen 443 ssl; server_name agents.baseworks.com; ssl_certificate /etc/ssl/cloudflare/baseworks.com.pem; ssl_certificate_key /etc/ssl/cloudflare/baseworks.com.key; ssl_protocols TLSv1.2 TLSv1.3;
# Only the webhook path is exposed. location = /webhook/people-index { proxy_pass http://127.0.0.1:9090; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
location = /health { proxy_pass http://127.0.0.1:9090; }
location / { return 404; }}Then:
sudo ln -s /etc/nginx/sites-available/agents.baseworks.com /etc/nginx/sites-enabled/sudo nginx -t && sudo systemctl reload nginxCloudflare DNS
Section titled “Cloudflare DNS”Add an A record agents → VPS IP, proxied (orange cloud). The VPS IP is in 00-inbox/claude-code-shared-context.md.
Fluent CRM Automation Funnel
Section titled “Fluent CRM Automation Funnel”In FluentCRM admin (crm.baseworks.com/wp-admin), go to FluentCRM → Automations → New Automation:
- Trigger: Pick one or more — e.g. “Tag Applied to Contact” (for the Tokyo Studio Alumni tag) and/or “Custom Field Updated” for
romaji_name. - Action: “Outgoing Webhook” (plugin comes with FluentCRM). Configure:
- URL:
https://agents.baseworks.com/webhook/people-index - Method: POST
- Headers:
Authorization: Bearer <paste secret from step 1> - Body: empty (the receiver doesn’t inspect body content).
- URL:
- Save and enable. Test by manually applying/removing a tag on a contact; confirm the receiver’s log shows a 202 response within a few seconds.
Security notes
Section titled “Security notes”- Shared-secret auth (Authorization Bearer header), constant-time compare.
- 30s cool-down coalesces duplicate triggers so a burst of CRM updates yields one aggregator run.
- No request body parsing — a malformed webhook can only cause a 401 (wrong secret) or 404 (wrong path).
- Rotate the secret by writing a new value into
/home/patrick/.people-webhook.secretand updating the FluentCRM funnel.systemctl reloadis not required — the daemon re-reads the file on every request. - To disable quickly:
sudo systemctl stop people-webhook.serviceand remove the nginx location block (orreturn 404it).
Related
Section titled “Related”- People Profiles Aggregation — Phase 2 Plan
00-inbox/claude-code-shared-context.md— VPS infrastructure state