Runbooks
Runbooks
How to operate the platform. Living document.
Platform overview
Two sites on one VPS (154.66.198.194):
- cpd.medilearn.africa — the product (login required for admin)
- documentation.mobilearn.africa — this docs site
Both run PageMotor with shared plugin patterns. Isolated system users (cpd, docs), isolated databases (cpd_pm, docs_pm), isolated PHP-FPM pools.
Signing in
Admin URL: https://cpd.medilearn.africa/admin and https://documentation.mobilearn.africa/admin. Both Kenn and Hasmukh have admin accounts on each site. Initial passwords were set during infrastructure build and should be rotated on first login.
Retrieve initial passwords once via SSH: ssh s2l cat /root/cpd-docs-handover-20260423.txt
Rotating the Claude API key
Recommended every quarter or whenever the key might have been exposed.
- Go to console.anthropic.com → API Keys
- Generate a new key
- Sign in to cpd.medilearn.africa/admin/ai/
- Open Architect: Claude Settings, paste the new key, Save
- Revoke the old key in the Anthropic console
- Save the new key in Apple Passwords (title: MobiLearn CPD — Claude API)
Rotating the Vimeo API token
- Sign in to developer.vimeo.com/apps as the Mobilearn user
- Generate a new Personal Access Token with scopes:
Public Private Video Files Edit - Sign in to cpd.medilearn.africa/admin/plugins, go to EP Courses → Integrations
- Paste the new token, Save
- Revoke the old token on Vimeo
Adding a new course pathway
- Sign in at
/admin/plugins, go to EP Courses → Manage Courses → + Add Course - Fill title, slug, description, outcome
- Save, then click Lessons on the row
- + Add Lesson → paste a Vimeo URL → click Fetch from Vimeo → save
- Return to courses list → click Authorise (domain) to whitelist the embed
- Create a CMS page with
for the landing pageCourse not found.
Featuring a new pathway on the home page
Edit /var/www/cpd/user-content/plugins/ep-cpd-home/plugin.php. In render_cpd_home(), add your new course slug and badge label where the featured cards are rendered.
Whitelisting new videos for cpd.medilearn.africa
When new MLUCT videos are added to Vimeo, they need the cpd.medilearn.africa domain added to their embed whitelist before they will play in the pathway modal.
Either add them one-by-one via the Vimeo video privacy settings, or batch-authorise via the EP Courses admin “Authorise cpd.medilearn.africa” button on the course row.
Re-running the Vimeo inventory audit
When the library grows, the taxonomy snapshot needs regenerating:
cd "~/Library/Mobile Documents/com~apple~CloudDocs/Claude Workspace/MobiLearn CPD/inventory" # Run the audit script (saved separately; ask Claude to regenerate if missing) # It produces raw_folders.json and taxonomy.json. scp taxonomy.json s2l:/var/www/cpd/user-content/inventory-taxonomy.json
Viewing interview sessions
Each interview is logged in the pm_ep_cpd_interviews table. Useful columns: session_id, status (active/completed), profile (JSON), ip, created_at. Query via SSH:
ssh s2l mysql --defaults-extra-file=/etc/mysql/debian.cnf cpd_pm -e "SELECT session_id, status, created_at, SUBSTRING(profile, 1, 100) FROM pm_ep_cpd_interviews ORDER BY id DESC LIMIT 20"
Adjusting rate limits
In /var/www/cpd/user-content/plugins/ep-cpd-interview/plugin.php, class constants:
MAX_MESSAGES— per interview (default 20)MAX_INTERVIEWS_PER_IP_PER_DAY— per IP (default 10)
SSL certificate renewal
Handled automatically by certbot’s cron timer. Manual renew: ssh s2l certbot renew
Database backups
Not yet automated. For ad-hoc backup:
ssh s2l sh -c "mysqldump --defaults-extra-file=/etc/mysql/debian.cnf cpd_pm | gzip > /root/cpd_pm_$(date +%%Y%%m%%d).sql.gz" scp s2l:/root/cpd_pm_*.sql.gz ~/Backups/
Recommended: set up a nightly cron for both cpd_pm and docs_pm, store in cloud storage.
System administration
File locations
/var/www/cpd/— CPD PageMotor install/var/www/docs/— Docs PageMotor install/etc/nginx/sites-enabled/{cpd,docs}— nginx vhosts/etc/php/8.3/fpm/pool.d/{cpd,docs}.conf— FPM pool configs
Restarts
systemctl reload nginx # nginx config change systemctl reload php8.3-fpm # PHP FPM change
Error logs
/var/www/cpd/php-errors.log— CPD site errors/var/www/docs/php-errors.log— docs site errors/var/log/nginx/error.log— nginx errors (shared)