Deployment & Operations

PopIt3 runs on a Linux server (home machine) with cron-scheduled jobs during working hours.

Server Setup

OS: LinuxPython: 3.9+Databases: ~/.email3.mail.gdbm, ~/.jobserve.gdbm, ~/.jobserve_applications.gdbmConfig: ~/.netrc (POP3 OAuth + WebDAV creds), ~/.openai (API key)Reports: Deployed via WebDAV staging to www.critchley.biz

Authentication

~/.netrc - Credential Storage

POP3 (XOAUTH2):machine outlook.office365.com login <email@outlook.com> account MSAL:<client_id> password <refresh_token>WebDAV:machine webdav.critchley.biz login <username> password <password>Permissions: chmod 600 ~/.netrc

~/.openai - OpenAI API Key

Plain text file with API key for GPT-4o-mini

Cron Schedule (Actual)

Active jobs (verified against actual crontab, 2026-07-08):Email sync — popit3.py: 0,5,10,15,20,30,35,40,45,50,55 6-22 — fetch new mail, process, deleteReprocessing — popit3.py --reprocess: 05 23 and 25 6-22 — re-analyze existing emails (picks up unscored jobs)Infrastructure (shared with gdata-server, not popit3-specific): 58 5 — start gravlax (hosts notes backend + popit3 OAuth WSGI scripts) 59 22 — stop gravlax (commented out 2026-07-08 evening during a live incident; must be re-enabled afterward — see below) 02 6 / 45 21 — start/stop kelp (separate AWS instance, unrelated to popit3/gdata-server) 50 22 — unmount /z WebDAV mount before gravlax stops /2 — check-hibernate (laptop sleep/wake housekeeping)Currently disabled (commented out in the live crontab, not deleted): job_analysis_report.py (5 6-21 ) — report generation is off update_outlook_netrc.pl (50 7-20 *) — superseded by the WebDAV auto-recovery in popit3.py itself (see popit3/outlook-token-renewal) noodle start/stop, notes-system backup, envoy weekly maintenance — all off, unrelated to current workGotcha (2026-07-08): popit3.py's three lines were temporarily commented out during the stuck-process incident (see popit3/ops) and correctly re-enabled afterward. Separately, the gravlax-stop line was commented out to keep gravlax up while working on gdata-server live -- that one was missed once (22:59 fired while disabled) before being caught up manually. When disabling any cron line for an in-progress session, always re-enable it before finishing, and check whether its scheduled time already passed while disabled -- if so, run the equivalent command manually to catch up rather than silently skipping it.

Outlook Credential Refresh

Script: ~/py/popit3/update_outlook_netrc.pl

Fetches https://webdav.critchley.biz/private/creds/auth.txt using WebDAV credentials from ~/.netrc. Sends If-Modified-Since based on ~/.netrc mtime — exits silently (304) if remote is not newer. On success, replaces the machine outlook.office365.com block in ~/.netrc with the fresh credentials.

To generate new credentials: visit https://www.critchley.biz/msauth to run the OAuth2 flow — see msauth

Job API Server

job_api.py runs as a FastAPI server, reverse proxied from: https://cv.critchley.biz/jobs → local FastAPI instanceKNOWN ISSUE: Not currently auto-starting. Needs either:• systemd unit file for FastAPI, OR• Rewrite as pure WSGI to run under existing web serverTo start manually: python3 job_api.py (starts uvicorn on default port)

WebDAV Deploy Pipeline

Report deployment is a two-step process:1. Upload to webdav.critchley.biz/staging/JobAnalysis/<timestamped>.html2. GET https://www.critchley.biz/deploy/JobAnalysis/<filename> — triggers a server-side WSGI script that copies from staging to productionThe deploy endpoint is a Python WSGI script on the web server.Staging cleanup: keeps only 5 most recent files in staging/.Production cleanup: none — old production files persist until overwritten.

File Locations

Source code: /home/john/py/popit3/Databases: ~/ (.email3.mail.gdbm, .jobserve.gdbm, .jobserve_applications.gdbm)Mail archives: ~/py/popit3/jsMail/ (JobServe), ~/py/popit3/wfMail/ (Workfit), ~/Mail/ (general)Parsed emails: ~/py/popit3/parsed/ (JSON copies of parsed emails)

Troubleshooting

Locked database:• Error: gdbm.error with errno 11 (EAGAIN) / GDataLockedError• Cause: Another cron job has the DB open• The staggered cron schedule minimises this; job_api returns 503 Retry-AfterAuthentication failures:• Check ~/.netrc permissions (must be 600)• Visit https://www.critchley.biz/msauth to refresh OAuth2 token, then cron will pick up the new auth.txt within the hourWebDAV deployment fails:• Check webdav.critchley.biz credentials in ~/.netrcOpenAI API errors:• Check ~/.openai file has valid key• Verify API quota not exceeded

version 4  ·  updated 2026-07-08