Troubleshooting
Diagnostic procedures for common issues.
Quick Diagnostics
# Server health at a glance
ssh camlab 'docker compose -f /opt/camlab/docker-compose.yml ps'
ssh camlab 'free -h && df -h && uptime'
# Container resource usage
ssh camlab 'docker stats --no-stream'
# Recent errors across all containers
ssh camlab 'docker compose -f /opt/camlab/docker-compose.yml logs --tail 20 --since 1h'
Problem: Ghost Returns 502
Symptoms: Blog URL returns 502 Bad Gateway
Diagnose:
# Check if Ghost container is running
docker compose ps ghost-cam4
# Check Ghost logs
docker compose logs --tail 50 ghost-cam4
# Check if MySQL is accessible from Ghost
docker exec ghost-cam4 sh -c 'nc -zv mysql 3306'
Common causes:
- Ghost container crashed → docker compose restart ghost-cam4
- MySQL not ready → docker compose restart mysql, wait 30s, restart Ghost
- Out of memory → check free -h, consider upgrading or stopping unused services
Problem: n8n Workflow Fails
Symptoms: Workflow execution shows error in n8n UI
Diagnose:
# Check n8n logs
docker compose logs --tail 100 n8n
# Check runner logs (for the blog that failed)
docker compose logs --tail 50 runner-cam4
# Check if runner container is responsive
docker exec runner-cam4 echo "alive"
# Check if Claude Code works in runner
docker exec runner-cam4 claude --version
Common causes:
- Runner container crashed → docker compose restart runner-cam4
- Anthropic API key expired → check .env, verify at console.anthropic.com
- MCP server down → check relevant MCP container logs
- Workspace full → docker exec runner-cam4 df -h /workspace
Problem: Ghost MCP Returns 403
Symptoms: MCP tool calls fail with "Invalid token"
Diagnose:
# Check MCP server logs
docker compose logs --tail 50 ghost-mcp
# Test with curl (use the blog's MCP token from .env)
curl -X POST http://localhost:3002/<token> \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Common causes:
- Token mismatch between .env and runner .mcp.json
- Ghost MCP container needs restart after .env change
- Ghost API key expired/regenerated but MCP not updated
Problem: Reddit MCP Not Responding
Symptoms: Researcher agent fails, can't reach Reddit
Diagnose:
docker compose ps reddit-mcp
docker compose logs --tail 50 reddit-mcp
curl http://localhost:8080/sse
Common causes:
- Reddit API credentials expired → check Reddit app at reddit.com/prefs/apps
- Container crashed → docker compose restart reddit-mcp
- Rate limited by Reddit → wait, check logs for 429 errors
Problem: Runware Images Not Generating
Symptoms: Photographer agent fails or produces no images
Diagnose:
docker compose ps runware-mcp
docker compose logs --tail 50 runware-mcp
curl http://localhost:8081/mcp
Common causes:
- Runware API key expired or out of credits
- Container unhealthy → docker compose restart runware-mcp
- Network issue → check from runner: docker exec runner-cam4 curl http://runware-mcp:8081/mcp
Problem: High Memory Usage
Symptoms: Server slow, swap usage high, OOM kills in logs
Diagnose:
free -h
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
dmesg | grep -i "oom\|killed" | tail -20
Fix: - If a specific container is bloated → restart it - If all containers are normal but total is high → consider upgrading to CPX41 - Emergency: stop non-essential containers (dozzle, glances)
Problem: Disk Running Low
Symptoms: df -h shows > 80% usage
Diagnose:
Fix:
# Clean Docker build cache and unused images
docker system prune -f
docker image prune -a -f # WARNING: removes all unused images
# Clean old Ghost content (if applicable)
# Check workspace cleanup
du -sh /opt/camlab/runners/*/workspace/
# Check MySQL binary logs
docker exec mysql ls -lh /var/lib/mysql/
Problem: Caddy TLS Certificate Failure
Symptoms: Browser shows certificate error, Caddy logs show ACME failures
Diagnose:
sudo systemctl status caddy
sudo journalctl -u caddy --since "1 hour ago"
# Check if port 80 is accessible (needed for ACME challenges)
curl -I http://blog.cam4.camlab.dev
Common causes:
- DNS not pointing to server → verify with dig blog.cam4.camlab.dev
- Port 80 blocked by firewall → sudo ufw status
- Rate limited by Let's Encrypt → wait 1 hour, retry
Diagnostic Command Reference
| What | Command |
|---|---|
| All container status | docker compose ps |
| Container resource usage | docker stats --no-stream |
| Specific container logs | docker compose logs --tail 100 <name> |
| Follow logs live | docker compose logs -f <name> |
| Disk usage by directory | du -sh /opt/camlab/*/ |
| Docker disk usage | docker system df |
| Check open ports | sudo ss -tlnp |
| DNS resolution | dig +short <domain> |
| TLS certificate info | echo | openssl s_client -connect <domain>:443 2>/dev/null | openssl x509 -noout -dates |
| MySQL connection test | docker exec mysql mysqladmin -u root -p ping |
| System resource overview | htop or visit glances.camlab.dev |