Runbook: Decommission Twenty CRM
Purpose
Complete removal of Twenty CRM service from RavenmaskOS infrastructure. Twenty was installed for evaluation but replaced by custom CRM solution.
Overview
- Service: Twenty CRM
- Domain: twenty.ravenhelm.dev (inactive)
- Reason: Replaced by custom CRM at crm.ravenhelm.dev
- Tracking: RAV-164
MCP Tools Used
| Tool | Purpose |
|---|---|
infra_docker_list_containers | Verify no Twenty containers |
infra_docker_list_volumes | Verify no Twenty volumes |
infra_list_data_directories | Find Twenty data directory |
infra_remove_data_directory | Remove Twenty data |
infra_zitadel_list_apps | Check for Twenty OIDC app |
infra_zitadel_delete_app | Delete Twenty OIDC app |
infra_trigger_discovery | Update CMDB |
Current State Assessment
| Component | Status | Tool Verification |
|---|---|---|
| Containers | ✅ Already removed | infra_docker_list_containers |
| Docker volumes | ✅ Already removed | infra_docker_list_volumes |
| Service directory | ✅ Never created | Manual check |
| Data directory | ⚠️ Exists: ~/ravenhelm/data/twenty/ | infra_list_data_directories |
| Secrets (.env) | ⚠️ Comments exist | Manual cleanup |
| Traefik routes | ✅ Already removed | N/A |
| Zitadel app | ❓ Check required | infra_zitadel_list_apps |
Prerequisites
- SSH access to odin as ravenhelm
- Confirmation that custom CRM is operational
- Linear ticket created for tracking: RAV-164
Procedure
Step 1: Verify Custom CRM is Operational
# Verify custom CRM is running
docker ps | grep crm
# Expected: crm-backend and crm-frontend running
# Test CRM endpoint
curl -I https://crm.ravenhelm.dev
# Expected: 200 OK
MCP Verification:
{"tool": "infra_docker_list_containers", "arguments": {"name_filter": "crm"}}
// Expected: crm-backend and crm-frontend in list
Step 2: Verify No Twenty Containers Remain
MCP Tool: infra_docker_list_containers
{"tool": "infra_docker_list_containers", "arguments": {"name_filter": "twenty"}}
// Expected: count = 0
Step 3: Verify No Twenty Volumes Remain
MCP Tool: infra_docker_list_volumes
{"tool": "infra_docker_list_volumes", "arguments": {"name_filter": "twenty"}}
// Expected: count = 0
Step 4: Remove Twenty Data Directory
MCP Tool: infra_remove_data_directory
# Check contents
ls -la ~/ravenhelm/data/twenty/
# Remove directory
rm -rf ~/ravenhelm/data/twenty/
# Verify removal
ls ~/ravenhelm/data/twenty/
# Expected: No such file or directory
Tool invocation:
// First verify it exists
{"tool": "infra_list_data_directories", "arguments": {}}
// Remove the directory
{"tool": "infra_remove_data_directory", "arguments": {"path": "/Users/ravenhelm/ravenhelm/data/twenty", "force": true}}
// Expected: action = "removed"
Step 5: Clean Up Secrets File
# Edit secrets file
nano ~/ravenhelm/secrets/.env
# Remove these lines (search for "Twenty" or "twenty"):
# - # Twenty CRM
# - # Twenty CRM API Key (for n8n and Norns)
# - TWENTY_* variables (if any)
# Save and exit
Note: Manual cleanup for safety - secrets editing not exposed via MCP.
Step 6: Check Zitadel for Twenty Application
MCP Tool: infra_zitadel_list_apps
- Access Zitadel Admin: https://auth.ravenhelm.dev
- Login with admin credentials
- Navigate to: Organization → Projects → Default Project → Applications
- Search for "Twenty" or "CRM"
- If found, delete the application
- Record Client ID for audit: _____________
Tool invocation:
// List all apps
{"tool": "infra_zitadel_list_apps", "arguments": {}}
// If Twenty app found, delete it
{"tool": "infra_zitadel_delete_app", "arguments": {"project_id": "<project-id>", "app_id": "<app-id>"}}
Step 7: Verify Traefik Has No Twenty Routes
# Check Traefik API for routes
curl -s http://localhost:8080/api/http/routers 2>/dev/null | jq '.[] | select(.name | contains("twenty"))' || echo "No twenty routes"
# If using Traefik dashboard
# Visit: https://traefik.ravenhelm.dev and search for "twenty"
Step 8: Remove Any n8n Workflows Using Twenty
- Access n8n: https://n8n.ravenhelm.dev
- Search workflows for "Twenty" or "CRM" references
- Disable or delete deprecated workflows
- Update any remaining workflows to use new CRM API
Step 9: Update Norns Configuration (if applicable)
If Norns had Twenty integration:
# Check Norns config for Twenty references
grep -r "twenty" ~/ravenhelm/docs/AI-ML-Platform/norns-agent/
# Update any configuration files found
Step 10: Update CMDB
MCP Tool: infra_trigger_discovery
# Trigger Vidar discovery to remove stale entities
curl -X POST https://vidar-api.ravenhelm.dev/api/v1/cmdb/discovery/trigger
Tool invocation:
{"tool": "infra_trigger_discovery", "arguments": {}}
Step 11: Update Documentation
cd /tmp/ravenmaskos.wiki
git pull
# Remove any Twenty-specific documentation
rm -f Features/Platform/Twenty.md 2>/dev/null
rm -f AI-ML-Platform/Twenty-Integration.md 2>/dev/null
# Update this runbook status
# Mark as completed
git add -A
git commit -m "Decommission: Remove Twenty CRM artifacts and documentation"
git push
Automated Execution Summary
For Vidar/SRE Agent automated execution:
// Step 1: Verify CRM replacement is running
{"tool": "infra_docker_list_containers", "arguments": {"name_filter": "crm"}}
// Step 2: Verify no Twenty containers
{"tool": "infra_docker_list_containers", "arguments": {"name_filter": "twenty"}}
// Step 3: Verify no Twenty volumes
{"tool": "infra_docker_list_volumes", "arguments": {"name_filter": "twenty"}}
// Step 4: Remove data directory
{"tool": "infra_remove_data_directory", "arguments": {"path": "/Users/ravenhelm/ravenhelm/data/twenty", "force": true}}
// Step 5: Check for Zitadel app (manual delete if found)
{"tool": "infra_zitadel_list_apps", "arguments": {}}
// Step 6: Update CMDB
{"tool": "infra_trigger_discovery", "arguments": {}}
Verification Checklist
# ✅ Data directory removed
[ ! -d ~/ravenhelm/data/twenty ] && echo "✅ Data directory removed" || echo "❌ Data directory exists"
# ✅ No Twenty in secrets (check manually)
grep -i twenty ~/ravenhelm/secrets/.env && echo "❌ Twenty still in secrets" || echo "✅ Secrets cleaned"
# ✅ No containers
docker ps -a | grep -i twenty && echo "❌ Containers exist" || echo "✅ No containers"
# ✅ No volumes
docker volume ls | grep -i twenty && echo "❌ Volumes exist" || echo "✅ No volumes"
MCP Verification:
{"tool": "infra_docker_list_containers", "arguments": {"name_filter": "twenty"}}
// Expected: count = 0
{"tool": "infra_docker_list_volumes", "arguments": {"name_filter": "twenty"}}
// Expected: count = 0
{"tool": "infra_list_data_directories", "arguments": {}}
// Expected: "twenty" not in directories list
Post-Decommission
- Update Linear ticket RAV-164 - Mark completed with checklist results
- Close any related incidents - Reference this runbook
- Team notification - Announce deprecation complete
Notes
- Twenty was evaluated as CRM solution but lacked flexibility needed for RavenmaskOS use case
- Custom CRM built at
/Users/ravenhelm/ravenhelm/services/crm/provides better integration with Norns and Bifrost - No user data migration required - Twenty was never in production