docs: update ARCHITECTURE.md and fix paths
- Add ARCHITECTURE.md with full 4-VPS infrastructure details - Update vps-agents specs: 16GB RAM, 8 dedicated vCPUs - Fix vps-ci specs in diagrams (8GB not 4GB) - Update monthly cost to $228 - Fix /root/cleargrow paths to /opt/repos in CLAUDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Add a comment to a YouTrack issue
|
||||
allowed-tools: Bash(curl:*)
|
||||
allowed-tools: Bash(curl:*), Bash(python3:*)
|
||||
argument-hint: [issue-id] [comment]
|
||||
---
|
||||
|
||||
@@ -12,14 +12,15 @@ Add a comment to a YouTrack issue.
|
||||
- Issue ID: $1 (e.g., CG-123)
|
||||
- Comment: $2 (the comment text)
|
||||
|
||||
## Configuration
|
||||
Get the YouTrack token from agent runner config:
|
||||
```bash
|
||||
YOUTRACK_TOKEN=$(python3 -c "import yaml; print(yaml.safe_load(open('/opt/agent_runner/config.yaml'))['youtrack']['token'])")
|
||||
```
|
||||
|
||||
## Task
|
||||
|
||||
1. Post comment to YouTrack API:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "$2"}' \
|
||||
"https://track.cleargrow.io/api/issues/$1/comments"
|
||||
```
|
||||
2. Confirm the comment was added
|
||||
3. Show link to the issue
|
||||
1. Extract token from config file
|
||||
2. Post comment to YouTrack API
|
||||
3. Confirm the comment was added
|
||||
4. Show link to the issue
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Create a new YouTrack issue
|
||||
allowed-tools: Bash(curl:*)
|
||||
allowed-tools: Bash(curl:*), Bash(python3:*)
|
||||
argument-hint: [summary]
|
||||
---
|
||||
|
||||
@@ -11,19 +11,18 @@ Create a new issue in YouTrack.
|
||||
## Arguments
|
||||
- Summary: $ARGUMENTS (brief title for the issue)
|
||||
|
||||
## Configuration
|
||||
Get the YouTrack token from agent runner config:
|
||||
```bash
|
||||
YOUTRACK_TOKEN=$(python3 -c "import yaml; print(yaml.safe_load(open('/opt/agent_runner/config.yaml'))['youtrack']['token'])")
|
||||
```
|
||||
|
||||
## Task
|
||||
|
||||
1. Prompt for additional details:
|
||||
1. Extract token from config file
|
||||
2. Prompt for additional details:
|
||||
- Description (optional)
|
||||
- Priority (Normal, Major, Critical)
|
||||
- Type (Bug, Feature, Task)
|
||||
|
||||
2. Create issue via YouTrack API:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"project":{"id":"CG"},"summary":"$ARGUMENTS","description":"..."}' \
|
||||
"https://track.cleargrow.io/api/issues?fields=idReadable,summary"
|
||||
```
|
||||
|
||||
3. Return the new issue ID and link
|
||||
3. Create issue via YouTrack API
|
||||
4. Return the new issue ID and link
|
||||
|
||||
@@ -1,25 +1,45 @@
|
||||
---
|
||||
description: List YouTrack issues by state
|
||||
allowed-tools: Bash(curl:*)
|
||||
allowed-tools: Bash
|
||||
argument-hint: [state]
|
||||
---
|
||||
|
||||
# List YouTrack Issues
|
||||
|
||||
List issues from YouTrack filtered by state.
|
||||
|
||||
## Arguments
|
||||
- State: $ARGUMENTS (Ready, In Progress, Verify, Document, Backlog, or "all")
|
||||
|
||||
## Task
|
||||
|
||||
Query YouTrack API for issues:
|
||||
List YouTrack issues filtered by state. Run this script with the state argument: "$ARGUMENTS"
|
||||
|
||||
```bash
|
||||
curl -s -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
"https://track.cleargrow.io/api/issues?query=project:CG%20State:${1:-Ready}&fields=idReadable,summary,State(name)"
|
||||
```
|
||||
STATE="$ARGUMENTS"
|
||||
YOUTRACK_TOKEN=$(python3 -c "import yaml; print(yaml.safe_load(open('/opt/agent_runner/config.yaml'))['youtrack']['token'])")
|
||||
|
||||
1. Parse and display issues in a readable format
|
||||
2. Show issue ID, summary, and current state
|
||||
3. If no token is set, explain how to set YOUTRACK_TOKEN environment variable
|
||||
# Build query - filter by state unless "all" specified
|
||||
if [ -z "$STATE" ] || [ "$STATE" = "Ready" ]; then
|
||||
QUERY="project:CG%20State:Ready"
|
||||
elif [ "$STATE" = "all" ]; then
|
||||
QUERY="project:CG"
|
||||
else
|
||||
# URL encode spaces in state names like "In Progress"
|
||||
ENCODED_STATE=$(echo "$STATE" | sed 's/ /%20/g')
|
||||
QUERY="project:CG%20State:${ENCODED_STATE}"
|
||||
fi
|
||||
|
||||
curl -s -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Accept: application/json" \
|
||||
"https://track.cleargrow.io/api/issues?fields=idReadable,summary,customFields(name,value(name))&query=${QUERY}" > /tmp/yt_issues.json
|
||||
|
||||
python3 << 'PYEOF'
|
||||
import json
|
||||
with open('/tmp/yt_issues.json') as f:
|
||||
data = json.load(f)
|
||||
if not data:
|
||||
print("No issues found.")
|
||||
else:
|
||||
print(f"{'ID':<10} {'State':<15} Summary")
|
||||
print('-' * 80)
|
||||
for issue in data:
|
||||
state = 'Unknown'
|
||||
for field in issue.get('customFields', []):
|
||||
if field.get('name') == 'State' and field.get('value'):
|
||||
state = field['value'].get('name', 'Unknown')
|
||||
print(f"{issue['idReadable']:<10} {state:<15} {issue['summary'][:55]}")
|
||||
print(f"\nTotal: {len(data)} issue(s)")
|
||||
PYEOF
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Start working on a YouTrack issue
|
||||
allowed-tools: Bash(curl:*), Bash(git:*)
|
||||
allowed-tools: Bash(curl:*), Bash(git:*), Bash(python3:*)
|
||||
argument-hint: [issue-id]
|
||||
---
|
||||
|
||||
@@ -11,11 +11,18 @@ Begin work on a YouTrack issue: fetch details, create branch, transition state.
|
||||
## Arguments
|
||||
- Issue ID: $ARGUMENTS (e.g., CG-123)
|
||||
|
||||
## Configuration
|
||||
Get the YouTrack token from agent runner config:
|
||||
```bash
|
||||
YOUTRACK_TOKEN=$(python3 -c "import yaml; print(yaml.safe_load(open('/opt/agent_runner/config.yaml'))['youtrack']['token'])")
|
||||
```
|
||||
|
||||
## Task
|
||||
|
||||
1. Fetch issue details from YouTrack
|
||||
2. Display issue summary and description
|
||||
3. Transition issue to "In Progress" state
|
||||
4. Create a feature branch: `feature/$ARGUMENTS-<kebab-case-summary>`
|
||||
5. Add a comment to the issue noting work has started
|
||||
6. Show next steps for the developer
|
||||
1. Extract token from config file
|
||||
2. Fetch issue details from YouTrack
|
||||
3. Display issue summary and description
|
||||
4. Transition issue to "In Progress" state
|
||||
5. Create a feature branch: `feature/$ARGUMENTS-<kebab-case-summary>`
|
||||
6. Add a comment to the issue noting work has started
|
||||
7. Show next steps for the developer
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Transition a YouTrack issue to a new state
|
||||
allowed-tools: Bash(curl:*)
|
||||
allowed-tools: Bash(curl:*), Bash(python3:*)
|
||||
argument-hint: [issue-id] [state]
|
||||
---
|
||||
|
||||
@@ -16,14 +16,15 @@ Change the state of a YouTrack issue.
|
||||
- Backlog → Ready → In Progress → Verify → Document → Review → Done
|
||||
- Any state → Triage (on failure)
|
||||
|
||||
## Configuration
|
||||
Get the YouTrack token from agent runner config:
|
||||
```bash
|
||||
YOUTRACK_TOKEN=$(python3 -c "import yaml; print(yaml.safe_load(open('/opt/agent_runner/config.yaml'))['youtrack']['token'])")
|
||||
```
|
||||
|
||||
## Task
|
||||
|
||||
1. Update issue state via YouTrack API:
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[{"name":"State","$type":"StateIssueCustomField","value":{"name":"$2"}}]' \
|
||||
"https://track.cleargrow.io/api/issues/$1?fields=idReadable,summary,State(name)"
|
||||
```
|
||||
2. Confirm the state change
|
||||
3. Show the updated issue status
|
||||
1. Extract token from config file
|
||||
2. Update issue state via YouTrack API
|
||||
3. Confirm the state change
|
||||
4. Show the updated issue status
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: View details of a YouTrack issue
|
||||
allowed-tools: Bash(curl:*)
|
||||
allowed-tools: Bash(curl:*), Bash(python3:*)
|
||||
argument-hint: [issue-id]
|
||||
---
|
||||
|
||||
@@ -11,17 +11,20 @@ View detailed information about a specific YouTrack issue.
|
||||
## Arguments
|
||||
- Issue ID: $ARGUMENTS (e.g., CG-123)
|
||||
|
||||
## Configuration
|
||||
Get the YouTrack token from agent runner config:
|
||||
```bash
|
||||
YOUTRACK_TOKEN=$(python3 -c "import yaml; print(yaml.safe_load(open('/opt/agent_runner/config.yaml'))['youtrack']['token'])")
|
||||
```
|
||||
|
||||
## Task
|
||||
|
||||
1. Fetch issue details from YouTrack API:
|
||||
```bash
|
||||
curl -s -H "Authorization: Bearer $YOUTRACK_TOKEN" \
|
||||
"https://track.cleargrow.io/api/issues/$ARGUMENTS?fields=idReadable,summary,description,State(name),Priority(name),created,updated,comments(text,author(name))"
|
||||
```
|
||||
2. Display:
|
||||
1. Extract token from config file
|
||||
2. Fetch issue details from YouTrack API
|
||||
3. Display:
|
||||
- Issue ID and summary
|
||||
- Description
|
||||
- State and priority
|
||||
- Created/updated timestamps
|
||||
- Recent comments
|
||||
3. Provide link to issue: `https://track.cleargrow.io/issue/$ARGUMENTS`
|
||||
4. Provide link to issue: `https://track.cleargrow.io/issue/$ARGUMENTS`
|
||||
|
||||
@@ -1,22 +1,43 @@
|
||||
---
|
||||
description: Check health of all platform services
|
||||
allowed-tools: Bash(docker:*), Bash(curl:*), Bash(systemctl:*)
|
||||
allowed-tools: Bash(docker:*), Bash(curl:*), Bash(systemctl:*), Bash(ssh:*)
|
||||
---
|
||||
|
||||
# Platform Health Check
|
||||
|
||||
Check the health of all ClearGrow development platform services.
|
||||
Check the health of all ClearGrow development platform services across the distributed VPS architecture.
|
||||
|
||||
## Docker Services
|
||||
!`cd /opt/devplatform && docker compose ps 2>/dev/null || echo "Docker compose not available"`
|
||||
## Architecture
|
||||
|
||||
- **vps-git** (139.144.29.179): Nginx, PostgreSQL, Gitea - **ACTIVE**
|
||||
- **vps-track** (170.187.143.45): Nginx, YouTrack - **ACTIVE**
|
||||
- **vps-ci** (173.230.138.66): Nginx, TeamCity, Build Agent, Registry - **ACTIVE**
|
||||
- **vps-agents** (45.79.204.236 - this server): Agent Runner, Claude Code - **ACTIVE**
|
||||
|
||||
## Task
|
||||
|
||||
1. Check Docker container status
|
||||
2. Test service endpoints:
|
||||
1. Check vps-git services:
|
||||
```bash
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker compose -f /opt/devplatform/docker-compose.yml ps"
|
||||
```
|
||||
|
||||
2. Check vps-track services:
|
||||
```bash
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "docker compose -f /opt/devplatform/docker-compose.yml ps"
|
||||
```
|
||||
|
||||
3. Check vps-ci services:
|
||||
```bash
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66 "docker compose -f /opt/devplatform/docker-compose.yml ps"
|
||||
```
|
||||
|
||||
4. Test service endpoints:
|
||||
- Gitea: `curl -s https://git.cleargrow.io/api/v1/version`
|
||||
- YouTrack: `curl -s https://track.cleargrow.io/api/config`
|
||||
- TeamCity: `curl -s https://ci.cleargrow.io/app/rest/server`
|
||||
3. Check Agent Runner: `systemctl status cleargrow-agent-runner`
|
||||
4. Report any services that are down or unhealthy
|
||||
5. Suggest remediation steps for any issues
|
||||
|
||||
5. Check vps-agents services (this server):
|
||||
- `systemctl status cleargrow-agent-runner`
|
||||
|
||||
6. Report any services that are down or unhealthy
|
||||
7. Suggest remediation steps for any issues
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: View platform service logs
|
||||
allowed-tools: Bash(docker:*), Bash(journalctl:*)
|
||||
allowed-tools: Bash(docker:*), Bash(journalctl:*), Bash(ssh:*)
|
||||
argument-hint: [service]
|
||||
---
|
||||
|
||||
@@ -9,15 +9,28 @@ argument-hint: [service]
|
||||
View logs for platform services.
|
||||
|
||||
## Arguments
|
||||
- Service: $ARGUMENTS (gitea, youtrack, teamcity, nginx, postgres, agent-runner, or "all")
|
||||
- Service: $ARGUMENTS (vps-git, vps-track, vps-ci, vps-agents, gitea, youtrack, teamcity, agent-runner, or "all")
|
||||
|
||||
## Architecture
|
||||
- **vps-git** (139.144.29.179): gitea, postgres, nginx
|
||||
- **vps-track** (170.187.143.45): youtrack, nginx
|
||||
- **vps-ci** (173.230.138.66): teamcity, teamcity-agent, registry, nginx
|
||||
- **vps-agents** (45.79.204.236 - this server): agent-runner
|
||||
|
||||
## Task
|
||||
|
||||
1. If service is "agent-runner":
|
||||
1. If service is "vps-git" or "gitea":
|
||||
- Run: `ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=50"`
|
||||
2. If service is "vps-track" or "youtrack":
|
||||
- Run: `ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=50"`
|
||||
3. If service is "vps-ci" or "teamcity":
|
||||
- Run: `ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=50"`
|
||||
4. If service is "vps-agents" or "agent-runner":
|
||||
- Run: `journalctl -u cleargrow-agent-runner --no-pager -n 50`
|
||||
2. If service is "all":
|
||||
- Show last 20 lines from each Docker service
|
||||
3. Otherwise:
|
||||
- Run: `docker compose -f /opt/devplatform/docker-compose.yml logs --tail=50 $ARGUMENTS`
|
||||
4. Highlight any errors or warnings
|
||||
5. Suggest solutions for any issues found
|
||||
5. If service is "all":
|
||||
- Show vps-git logs: `ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=20"`
|
||||
- Show vps-track logs: `ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=20"`
|
||||
- Show vps-ci logs: `ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=20"`
|
||||
- Show agent-runner logs: `journalctl -u cleargrow-agent-runner --no-pager -n 20`
|
||||
6. Highlight any errors or warnings
|
||||
7. Suggest solutions for any issues found
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Restart a platform service
|
||||
allowed-tools: Bash(docker:*), Bash(systemctl:*)
|
||||
allowed-tools: Bash(docker:*), Bash(systemctl:*), Bash(ssh:*)
|
||||
argument-hint: [service]
|
||||
---
|
||||
|
||||
@@ -9,18 +9,28 @@ argument-hint: [service]
|
||||
Restart a specific platform service.
|
||||
|
||||
## Arguments
|
||||
- Service: $ARGUMENTS (gitea, youtrack, teamcity, nginx, postgres, agent-runner, or "all")
|
||||
- Service: $ARGUMENTS (vps-git, vps-track, vps-ci, vps-agents, gitea, youtrack, teamcity, agent-runner, or "all")
|
||||
|
||||
## Current Status
|
||||
!`cd /opt/devplatform && docker compose ps --format "table {{.Name}}\t{{.Status}}" 2>/dev/null`
|
||||
## Architecture
|
||||
- **vps-git** (139.144.29.179): gitea, postgres, nginx
|
||||
- **vps-track** (170.187.143.45): youtrack, nginx
|
||||
- **vps-ci** (173.230.138.66): teamcity, teamcity-agent, registry, nginx
|
||||
- **vps-agents** (45.79.204.236 - this server): agent-runner
|
||||
|
||||
## Task
|
||||
|
||||
1. If service is "agent-runner":
|
||||
1. If service is "vps-git" or "gitea":
|
||||
- Run: `ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "systemctl restart vps-git"`
|
||||
2. If service is "vps-track" or "youtrack":
|
||||
- Run: `ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "systemctl restart vps-track"`
|
||||
3. If service is "vps-ci" or "teamcity":
|
||||
- Run: `ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66 "systemctl restart vps-ci"`
|
||||
4. If service is "vps-agents" or "agent-runner":
|
||||
- Run: `sudo systemctl restart cleargrow-agent-runner`
|
||||
2. If service is "all":
|
||||
- Run: `docker compose -f /opt/devplatform/docker-compose.yml restart`
|
||||
3. Otherwise:
|
||||
- Run: `docker compose -f /opt/devplatform/docker-compose.yml restart $ARGUMENTS`
|
||||
4. Wait for service to come back up
|
||||
5. Verify health after restart
|
||||
5. If service is "all":
|
||||
- Restart vps-git: `ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "systemctl restart vps-git"`
|
||||
- Restart vps-track: `ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "systemctl restart vps-track"`
|
||||
- Restart vps-ci: `ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66 "systemctl restart vps-ci"`
|
||||
- Restart agent-runner: `sudo systemctl restart cleargrow-agent-runner`
|
||||
6. Wait for service to come back up
|
||||
7. Verify health after restart
|
||||
|
||||
184
.claude/hooks/dangerous_command_check.py
Executable file
184
.claude/hooks/dangerous_command_check.py
Executable file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Dangerous command blocker hook for Claude Code.
|
||||
Prevents service outages by blocking dangerous Docker, systemctl, and system commands.
|
||||
Requires user confirmation before proceeding.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import re
|
||||
|
||||
# Define dangerous command patterns that require user confirmation
|
||||
DANGEROUS_PATTERNS = [
|
||||
# Docker compose operations that cause service outages
|
||||
{
|
||||
"patterns": [
|
||||
r"docker\s+compose\s+.*\b(down|stop|rm)\b",
|
||||
r"docker-compose\s+(down|stop|rm)",
|
||||
r"docker\s+compose\s+-f\s+\S+\s+(down|stop|rm)",
|
||||
],
|
||||
"reason": "Docker Compose stop/down/rm could cause platform service outage (Gitea, YouTrack, TeamCity, Registry)"
|
||||
},
|
||||
|
||||
# Docker compose restart (less dangerous but still disruptive)
|
||||
{
|
||||
"patterns": [
|
||||
r"docker\s+compose\s+.*\brestart\b",
|
||||
r"docker-compose\s+restart",
|
||||
],
|
||||
"reason": "Docker Compose restart will temporarily interrupt platform services"
|
||||
},
|
||||
|
||||
# Individual container stop/kill/rm operations on platform containers
|
||||
{
|
||||
"patterns": [
|
||||
r"docker\s+(stop|kill|rm)\s+.*devplatform",
|
||||
r"docker\s+(stop|kill|rm)\s+.*(gitea|youtrack|teamcity|postgres|nginx|registry)",
|
||||
],
|
||||
"reason": "Stopping/killing platform container will cause service outage"
|
||||
},
|
||||
|
||||
# Bulk container operations
|
||||
{
|
||||
"patterns": [
|
||||
r"docker\s+(stop|kill|rm)\s+\$\(", # docker stop $(...)
|
||||
r"docker\s+ps.*\|.*xargs.*docker\s+(stop|kill|rm)",
|
||||
],
|
||||
"reason": "Bulk container operation could affect platform services"
|
||||
},
|
||||
|
||||
# Systemctl operations on critical services
|
||||
{
|
||||
"patterns": [
|
||||
r"systemctl\s+(stop|disable|mask)\s+.*cleargrow",
|
||||
r"systemctl\s+(stop|disable|mask)\s+.*docker",
|
||||
r"systemctl\s+(stop|disable|mask)\s+.*nginx",
|
||||
r"systemctl\s+(stop|disable|mask)\s+.*postgres",
|
||||
],
|
||||
"reason": "Stopping system service will cause platform outage"
|
||||
},
|
||||
|
||||
# Systemctl restart (disruptive but recoverable)
|
||||
{
|
||||
"patterns": [
|
||||
r"systemctl\s+restart\s+.*cleargrow",
|
||||
r"systemctl\s+restart\s+.*docker",
|
||||
],
|
||||
"reason": "Restarting system service will temporarily interrupt platform"
|
||||
},
|
||||
|
||||
# System reboot/shutdown
|
||||
{
|
||||
"patterns": [
|
||||
r"\b(reboot|shutdown|halt|poweroff)\b",
|
||||
r"init\s+[0156]",
|
||||
],
|
||||
"reason": "System reboot/shutdown will cause complete platform outage"
|
||||
},
|
||||
|
||||
# Dangerous file operations on platform directories
|
||||
{
|
||||
"patterns": [
|
||||
r"rm\s+-[rf]+\s+.*/opt/devplatform",
|
||||
r"rm\s+-[rf]+\s+.*/opt/repos",
|
||||
r"rm\s+-[rf]+\s+.*/opt/agent_runner",
|
||||
],
|
||||
"reason": "Deleting platform directories will cause data loss and service outage"
|
||||
},
|
||||
|
||||
# Database operations
|
||||
{
|
||||
"patterns": [
|
||||
r"docker\s+exec.*postgres.*dropdb",
|
||||
r"docker\s+exec.*postgres.*psql.*DROP\s+DATABASE",
|
||||
r"psql.*DROP\s+(DATABASE|TABLE)",
|
||||
],
|
||||
"reason": "Database drop operation will cause data loss"
|
||||
},
|
||||
|
||||
# Docker system prune (could remove platform images/volumes)
|
||||
{
|
||||
"patterns": [
|
||||
r"docker\s+system\s+prune\s+-a",
|
||||
r"docker\s+volume\s+prune",
|
||||
r"docker\s+image\s+prune\s+-a",
|
||||
],
|
||||
"reason": "Docker prune could remove platform images or volumes"
|
||||
},
|
||||
]
|
||||
|
||||
# Safe patterns that should be allowed even if they match dangerous patterns
|
||||
SAFE_PATTERNS = [
|
||||
r"docker\s+compose.*\bup\b", # Starting services is safe
|
||||
r"docker\s+compose.*\blogs\b", # Viewing logs is safe
|
||||
r"docker\s+compose.*\bps\b", # Listing services is safe
|
||||
r"docker\s+ps\b", # Listing containers is safe
|
||||
r"systemctl\s+status\b", # Status checks are safe
|
||||
r"systemctl\s+is-active\b", # Active checks are safe
|
||||
r"docker\s+inspect\b", # Inspecting is safe
|
||||
r"docker\s+logs\b", # Logs are safe
|
||||
]
|
||||
|
||||
|
||||
def is_safe_command(command: str) -> bool:
|
||||
"""Check if command matches a known safe pattern."""
|
||||
for pattern in SAFE_PATTERNS:
|
||||
if re.search(pattern, command, re.IGNORECASE):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def check_dangerous_command(command: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Check if command matches any dangerous pattern.
|
||||
|
||||
Returns:
|
||||
(is_dangerous, reason)
|
||||
"""
|
||||
# First check if it's explicitly safe
|
||||
if is_safe_command(command):
|
||||
return False, ""
|
||||
|
||||
# Check against dangerous patterns
|
||||
for category in DANGEROUS_PATTERNS:
|
||||
for pattern in category["patterns"]:
|
||||
if re.search(pattern, command, re.IGNORECASE):
|
||||
return True, category["reason"]
|
||||
|
||||
return False, ""
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
command = tool_input.get("command", "")
|
||||
|
||||
# Only check Bash tool calls
|
||||
if tool_name != "Bash" or not command:
|
||||
sys.exit(0)
|
||||
|
||||
# Check if command is dangerous
|
||||
is_dangerous, reason = check_dangerous_command(command)
|
||||
|
||||
if is_dangerous:
|
||||
# Request user permission before proceeding
|
||||
output = {
|
||||
"decision": "ask",
|
||||
"message": f"POTENTIALLY DANGEROUS COMMAND\n\n{reason}\n\nCommand: {command}"
|
||||
}
|
||||
print(json.dumps(output))
|
||||
sys.exit(0)
|
||||
|
||||
# Allow safe commands to proceed
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -13,5 +13,18 @@
|
||||
"ask": [],
|
||||
"defaultMode": "default"
|
||||
},
|
||||
"alwaysThinkingEnabled": true
|
||||
"alwaysThinkingEnabled": true,
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/dangerous_command_check.py\""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,56 +5,108 @@ description: Self-hosted development platform management skill. Use when working
|
||||
|
||||
# DevPlatform Management Skill
|
||||
|
||||
## Platform Overview
|
||||
## Architecture
|
||||
|
||||
| Service | URL | Port | Purpose |
|
||||
|---------|-----|------|---------|
|
||||
| Gitea | git.cleargrow.io | 3000 | Git hosting |
|
||||
| YouTrack | track.cleargrow.io | 8080 | Issue tracking |
|
||||
| TeamCity | ci.cleargrow.io | 8111 | CI/CD |
|
||||
| PostgreSQL | (internal) | 5432 | Database |
|
||||
| Nginx | - | 80/443 | Reverse proxy |
|
||||
The platform is distributed across multiple VPS on Linode:
|
||||
|
||||
**Base directory**: `/opt/devplatform`
|
||||
| VPS | IP | Services | Status |
|
||||
|-----|-----|----------|--------|
|
||||
| **vps-git** | 139.144.29.179 | Nginx, PostgreSQL, Gitea | **Active** |
|
||||
| **vps-track** | 170.187.143.45 | Nginx, YouTrack | **Active** |
|
||||
| **vps-ci** | 173.230.138.66 | Nginx, TeamCity, Build Agent, Registry | **Active** |
|
||||
| **vps-agents** | 45.79.204.236 | Agent Runner, Claude Code, Toolchains | **Active** (this server) |
|
||||
|
||||
## Service URLs
|
||||
|
||||
| Service | URL | Location |
|
||||
|---------|-----|----------|
|
||||
| Gitea | https://git.cleargrow.io | vps-git |
|
||||
| YouTrack | https://track.cleargrow.io | vps-track |
|
||||
| TeamCity | https://ci.cleargrow.io | vps-ci |
|
||||
|
||||
## SSH Access
|
||||
|
||||
```bash
|
||||
# vps-git (Gitea)
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179
|
||||
|
||||
# vps-track (YouTrack)
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45
|
||||
|
||||
# vps-ci (TeamCity)
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66
|
||||
```
|
||||
|
||||
## Service Management
|
||||
|
||||
### Docker Compose Commands
|
||||
### vps-git (Gitea)
|
||||
```bash
|
||||
cd /opt/devplatform
|
||||
# SSH to vps-git
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179
|
||||
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
# On vps-git:
|
||||
systemctl status vps-git
|
||||
systemctl restart vps-git
|
||||
|
||||
# Stop all services
|
||||
docker compose down
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
docker compose -f /opt/devplatform/docker-compose.yml restart gitea
|
||||
```
|
||||
|
||||
# Restart specific service
|
||||
docker compose restart gitea
|
||||
docker compose restart youtrack
|
||||
docker compose restart teamcity
|
||||
### vps-track (YouTrack)
|
||||
```bash
|
||||
# SSH to vps-track
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45
|
||||
|
||||
# On vps-track:
|
||||
systemctl status vps-track
|
||||
systemctl restart vps-track
|
||||
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
docker compose -f /opt/devplatform/docker-compose.yml restart youtrack
|
||||
```
|
||||
|
||||
### vps-ci (TeamCity)
|
||||
```bash
|
||||
# SSH to vps-ci
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66
|
||||
|
||||
# On vps-ci:
|
||||
systemctl status vps-ci
|
||||
systemctl restart vps-ci
|
||||
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
docker compose -f /opt/devplatform/docker-compose.yml restart teamcity
|
||||
```
|
||||
|
||||
### vps-agents (This Server)
|
||||
```bash
|
||||
# Agent runner control (local - no SSH needed)
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
sudo systemctl restart cleargrow-agent-runner
|
||||
|
||||
# View logs
|
||||
docker compose logs -f # All services
|
||||
docker compose logs -f gitea # Specific service
|
||||
docker compose logs --tail=100 teamcity # Last 100 lines
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
sudo journalctl -u cleargrow-agent-runner --since "1 hour ago"
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
|
||||
# Resource usage
|
||||
docker stats --no-stream
|
||||
# Repository locations
|
||||
ls /opt/repos/ # controller, probe, docs
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
```bash
|
||||
# Run health check script
|
||||
/opt/devplatform/scripts/healthcheck.sh
|
||||
# Check vps-git
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker compose -f /opt/devplatform/docker-compose.yml ps"
|
||||
|
||||
# Check vps-track
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "docker compose -f /opt/devplatform/docker-compose.yml ps"
|
||||
|
||||
# Manual endpoint checks
|
||||
curl -s https://git.yourdomain.com/api/v1/version
|
||||
curl -s https://track.yourdomain.com/api/config
|
||||
curl -s https://ci.yourdomain.com/app/rest/server
|
||||
curl -s https://git.cleargrow.io/api/v1/version
|
||||
curl -s https://track.cleargrow.io/api/config
|
||||
curl -s https://ci.cleargrow.io/app/rest/server
|
||||
```
|
||||
|
||||
## Gitea Administration
|
||||
@@ -94,16 +146,19 @@ curl -X POST -H "Authorization: token YOUR_TOKEN" \
|
||||
https://git.cleargrow.io/api/v1/repos/owner/repo/hooks
|
||||
```
|
||||
|
||||
### User Management
|
||||
### User Management (on vps-git)
|
||||
```bash
|
||||
# SSH to vps-git first
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179
|
||||
|
||||
# Create user via CLI
|
||||
docker compose exec gitea gitea admin user create \
|
||||
docker compose -f /opt/devplatform/docker-compose.yml exec gitea gitea admin user create \
|
||||
--username newuser \
|
||||
--password "SecurePassword123" \
|
||||
--email user@example.com
|
||||
|
||||
# List users
|
||||
docker compose exec gitea gitea admin user list
|
||||
docker compose -f /opt/devplatform/docker-compose.yml exec gitea gitea admin user list
|
||||
```
|
||||
|
||||
## YouTrack Administration
|
||||
@@ -152,7 +207,7 @@ git commit -m "Fix sensor parsing CG-123 #fixed"
|
||||
git commit -m "Start work CG-123 #in-progress"
|
||||
```
|
||||
|
||||
## TeamCity Administration
|
||||
## TeamCity Administration (Legacy - pending migration)
|
||||
|
||||
### Build Configuration
|
||||
```bash
|
||||
@@ -175,15 +230,7 @@ Content-Type: application/json
|
||||
Events: Push
|
||||
```
|
||||
|
||||
### Build Agent
|
||||
```bash
|
||||
# Check agent status
|
||||
docker compose logs teamcity-agent --tail=50
|
||||
|
||||
# Agent is authorized in UI: Agents > Unauthorized > Authorize
|
||||
```
|
||||
|
||||
## Agent Runner
|
||||
## Agent Runner (Legacy - pending migration to vps-agents)
|
||||
|
||||
The Agent Runner automates YouTrack tasks using Claude Code.
|
||||
|
||||
@@ -234,135 +281,74 @@ repos:
|
||||
path: /opt/repos/docs
|
||||
```
|
||||
|
||||
### Manual Commands
|
||||
```bash
|
||||
cd /opt/agent_runner
|
||||
|
||||
# Test connections
|
||||
python runner.py --test-connection
|
||||
|
||||
# Check platform health
|
||||
python runner.py --health
|
||||
|
||||
# View queue status
|
||||
python runner.py --status
|
||||
|
||||
# Run single cycle
|
||||
python runner.py --once
|
||||
```
|
||||
|
||||
## Database Operations
|
||||
|
||||
### PostgreSQL
|
||||
### PostgreSQL (on vps-git)
|
||||
```bash
|
||||
# SSH to vps-git
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179
|
||||
|
||||
# Connect to database
|
||||
docker compose exec postgres psql -U devplatform
|
||||
docker compose -f /opt/devplatform/docker-compose.yml exec postgres psql -U gitea -d gitea
|
||||
|
||||
# List databases
|
||||
docker compose exec postgres psql -U devplatform -l
|
||||
docker compose -f /opt/devplatform/docker-compose.yml exec postgres psql -U postgres -l
|
||||
|
||||
# Dump database
|
||||
docker compose exec postgres pg_dump -U devplatform gitea > gitea_backup.sql
|
||||
|
||||
# Restore database
|
||||
cat gitea_backup.sql | docker compose exec -T postgres psql -U devplatform gitea
|
||||
```
|
||||
|
||||
## Backup & Recovery
|
||||
|
||||
### Manual Backup
|
||||
```bash
|
||||
/opt/devplatform/scripts/backup.sh
|
||||
|
||||
# Backup location
|
||||
ls -la /opt/devplatform/backups/
|
||||
```
|
||||
|
||||
### Restore
|
||||
```bash
|
||||
cd /opt/devplatform
|
||||
|
||||
# Stop services
|
||||
docker compose down
|
||||
|
||||
# Restore PostgreSQL
|
||||
docker compose up -d postgres
|
||||
cat backups/postgres_*.sql | docker compose exec -T postgres psql -U devplatform
|
||||
|
||||
# Restore data directories
|
||||
tar -xzf backups/gitea_*.tar.gz -C /opt/devplatform
|
||||
tar -xzf backups/youtrack_*.tar.gz -C /opt/devplatform
|
||||
tar -xzf backups/teamcity_*.tar.gz -C /opt/devplatform
|
||||
|
||||
# Fix permissions
|
||||
sudo chown -R 1000:1000 gitea/
|
||||
sudo chown -R 13001:13001 youtrack/
|
||||
sudo chown -R 1000:1000 teamcity/
|
||||
|
||||
# Start services
|
||||
docker compose up -d
|
||||
docker compose -f /opt/devplatform/docker-compose.yml exec postgres pg_dump -U gitea gitea > gitea_backup.sql
|
||||
```
|
||||
|
||||
## SSL Certificates
|
||||
|
||||
```bash
|
||||
# Check certificate expiry
|
||||
docker compose exec nginx openssl x509 \
|
||||
-in /etc/letsencrypt/live/git.cleargrow.io/fullchain.pem \
|
||||
-text -noout | grep "Not After"
|
||||
# vps-git certificate check
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 \
|
||||
"openssl x509 -in /etc/letsencrypt/live/git.cleargrow.io/fullchain.pem -text -noout | grep 'Not After'"
|
||||
|
||||
# Renew certificates
|
||||
docker compose run --rm certbot renew
|
||||
docker compose restart nginx
|
||||
# vps-track certificate check
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 \
|
||||
"openssl x509 -in /etc/letsencrypt/live/track.cleargrow.io/fullchain.pem -text -noout | grep 'Not After'"
|
||||
|
||||
# Renew certificates (auto-renew is configured via certbot)
|
||||
# Manual renewal if needed:
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "certbot renew"
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "certbot renew"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service not starting
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs [service] --tail=100
|
||||
|
||||
# Check config
|
||||
docker compose config
|
||||
# Check logs on specific VPS
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=100"
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "docker compose -f /opt/devplatform/docker-compose.yml logs --tail=100"
|
||||
|
||||
# Check resources
|
||||
docker stats --no-stream
|
||||
df -h
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker stats --no-stream && df -h"
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "docker stats --no-stream && df -h"
|
||||
```
|
||||
|
||||
### 502 Bad Gateway
|
||||
```bash
|
||||
# Check backend is running
|
||||
docker compose ps
|
||||
# Test internal connectivity on vps-git
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 \
|
||||
"docker compose -f /opt/devplatform/docker-compose.yml exec nginx wget -qO- http://gitea:3000/api/v1/version"
|
||||
|
||||
# Test internal connectivity
|
||||
docker compose exec nginx curl http://gitea:3000/api/v1/version
|
||||
docker compose exec nginx curl http://youtrack:8080/api/config
|
||||
docker compose exec nginx curl http://teamcity:8111/app/rest/server
|
||||
# Test internal connectivity on vps-track
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 \
|
||||
"docker compose -f /opt/devplatform/docker-compose.yml exec nginx wget -qO- http://youtrack:8080/api/config"
|
||||
|
||||
# External URLs
|
||||
curl -s https://git.cleargrow.io/api/v1/version
|
||||
curl -s https://track.cleargrow.io/api/config
|
||||
curl -s https://ci.cleargrow.io/app/rest/server
|
||||
```
|
||||
|
||||
### Database issues
|
||||
```bash
|
||||
# Check postgres
|
||||
docker compose exec postgres pg_isready -U devplatform
|
||||
|
||||
# Check connections
|
||||
docker compose exec postgres psql -U devplatform -c "SELECT count(*) FROM pg_stat_activity;"
|
||||
```
|
||||
|
||||
### Disk space
|
||||
```bash
|
||||
# Check usage
|
||||
df -h
|
||||
docker system df
|
||||
# Check usage on each VPS
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "df -h && docker system df"
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45 "df -h && docker system df"
|
||||
|
||||
# Clean up
|
||||
docker system prune -a
|
||||
docker volume prune
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179 "docker system prune -a"
|
||||
```
|
||||
|
||||
407
ARCHITECTURE.md
Normal file
407
ARCHITECTURE.md
Normal file
@@ -0,0 +1,407 @@
|
||||
# ClearGrow DevPlatform Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
Distributed 4-VPS architecture on Linode for the ClearGrow IoT development platform.
|
||||
|
||||
**Monthly Cost: $228**
|
||||
|
||||
## Migration Status
|
||||
|
||||
| VPS | Status | Public IP | Deployed |
|
||||
|-----|--------|-----------|----------|
|
||||
| **vps-git** | **ACTIVE** | 139.144.29.179 | 2025-12-10 |
|
||||
| **vps-track** | **ACTIVE** | 170.187.143.45 | 2025-12-10 |
|
||||
| **vps-ci** | **ACTIVE** | 173.230.138.66 | 2025-12-10 |
|
||||
| **vps-agents** | **ACTIVE** | 45.79.204.236 | 2025-12-10 |
|
||||
|
||||
**Migration Complete** - All services distributed across 4 VPS.
|
||||
|
||||
## Infrastructure Diagram
|
||||
|
||||
```
|
||||
INTERNET
|
||||
│
|
||||
┌─────────────┴─────────────┐
|
||||
│ Cloudflare DNS │
|
||||
│ │
|
||||
│ git.cleargrow.io ───────┼──► vps-git
|
||||
│ track.cleargrow.io ─────┼──► vps-track
|
||||
│ ci.cleargrow.io ────────┼──► vps-ci
|
||||
│ agents.cleargrow.io ────┼──► vps-agents (internal)
|
||||
└───────────────────────────┘
|
||||
│
|
||||
┌─────────────────────────┼─────────────────────────┐
|
||||
│ LINODE PRIVATE VLAN (10.0.0.0/24) │
|
||||
│ │ │
|
||||
┌────┴────┐ ┌────────┐ ┌─────┴─────┐ ┌──────────────┐│
|
||||
│ │ │ │ │ │ │ ││
|
||||
│ vps-git │ │vps- │ │ vps-ci │ │ vps-agents ││
|
||||
│ │ │track │ │ │ │ ││
|
||||
│10.0.0.10│ │10.0.0.20 │ 10.0.0.30 │ │ 10.0.0.40 ││
|
||||
└─────────┘ └────────┘ └───────────┘ └──────────────┘│
|
||||
│ │
|
||||
└───────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## VPS Specifications
|
||||
|
||||
### vps-git (Shared 2GB) - $12/mo - ACTIVE
|
||||
| Resource | Value |
|
||||
|----------|-------|
|
||||
| Plan | Linode 2GB Shared |
|
||||
| RAM | 2 GB |
|
||||
| CPU | 1 vCPU (shared) |
|
||||
| Storage | 50 GB SSD |
|
||||
| Transfer | 2 TB |
|
||||
| **Public IP** | **139.144.29.179** |
|
||||
| Private IP | 10.0.0.10 (pending VLAN setup) |
|
||||
| Public DNS | git.cleargrow.io |
|
||||
|
||||
**Services:**
|
||||
- Nginx (reverse proxy + SSL termination)
|
||||
- PostgreSQL 15 (databases for Gitea)
|
||||
- Gitea (Git hosting)
|
||||
|
||||
**Management:**
|
||||
```bash
|
||||
# SSH access
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179
|
||||
|
||||
# Service control
|
||||
systemctl status vps-git
|
||||
systemctl restart vps-git
|
||||
|
||||
# Docker management
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
```
|
||||
|
||||
### vps-track (Shared 4GB) - $24/mo - ACTIVE
|
||||
| Resource | Value |
|
||||
|----------|-------|
|
||||
| Plan | Linode 4GB Shared |
|
||||
| RAM | 4 GB |
|
||||
| CPU | 2 vCPU (shared) |
|
||||
| Storage | 80 GB SSD |
|
||||
| Transfer | 4 TB |
|
||||
| **Public IP** | **170.187.143.45** |
|
||||
| Private IP | 10.0.0.20 (pending VLAN setup) |
|
||||
| Public DNS | track.cleargrow.io |
|
||||
|
||||
**Services:**
|
||||
- Nginx (reverse proxy + SSL termination)
|
||||
- YouTrack (issue tracking, embedded database)
|
||||
|
||||
**JVM Configuration:**
|
||||
- Heap: 2.5GB (`-Xmx2560m`)
|
||||
|
||||
**Management:**
|
||||
```bash
|
||||
# SSH access
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45
|
||||
|
||||
# Service control
|
||||
systemctl status vps-track
|
||||
systemctl restart vps-track
|
||||
|
||||
# Docker management
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
```
|
||||
|
||||
### vps-ci (Shared 8GB) - $48/mo - ACTIVE
|
||||
| Resource | Value |
|
||||
|----------|-------|
|
||||
| Plan | Linode 8GB Shared |
|
||||
| RAM | 8 GB |
|
||||
| CPU | 4 vCPU (shared) |
|
||||
| Storage | 160 GB SSD |
|
||||
| Transfer | 5 TB |
|
||||
| **Public IP** | **173.230.138.66** |
|
||||
| Private IP | 10.0.0.30 (pending VLAN setup) |
|
||||
| Public DNS | ci.cleargrow.io |
|
||||
|
||||
**Services:**
|
||||
- Nginx (reverse proxy + SSL termination)
|
||||
- TeamCity Server (internal HSQLDB)
|
||||
- TeamCity Build Agent
|
||||
- Docker Registry (pull-through cache)
|
||||
|
||||
**JVM Configuration:**
|
||||
- TeamCity Server Heap: 3GB (`-Xmx3g`)
|
||||
|
||||
**Management:**
|
||||
```bash
|
||||
# SSH access
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66
|
||||
|
||||
# Service control
|
||||
systemctl status vps-ci
|
||||
systemctl restart vps-ci
|
||||
|
||||
# Docker management
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
```
|
||||
|
||||
### vps-agents (Dedicated 8 vCPU) - $144/mo - ACTIVE
|
||||
| Resource | Value |
|
||||
|----------|-------|
|
||||
| Plan | Linode Dedicated 16GB |
|
||||
| RAM | 16 GB |
|
||||
| CPU | 8 vCPU (dedicated AMD EPYC) |
|
||||
| Storage | 320 GB SSD |
|
||||
| Transfer | 6 TB |
|
||||
| **Public IP** | **45.79.204.236** |
|
||||
| Private IP | 10.0.0.40 (pending VLAN setup) |
|
||||
| Public DNS | agents.cleargrow.io (internal only) |
|
||||
|
||||
**Services:**
|
||||
- Agent Runner (Python daemon)
|
||||
- Claude Code (10 concurrent instances max)
|
||||
- Git repositories (working copies at `/opt/repos/`)
|
||||
- ESP-IDF toolchain (~2GB)
|
||||
- Zephyr SDK + nRF Connect SDK (~25GB)
|
||||
|
||||
**Resource Allocation:**
|
||||
| Component | RAM | CPU |
|
||||
|-----------|-----|-----|
|
||||
| OS + overhead | 512MB | - |
|
||||
| Agent Runner | 256MB | 0.5 |
|
||||
| Claude Code (10x) | 10GB | 6 |
|
||||
| Toolchains | 1GB | - |
|
||||
| Buffer | 4GB | 1.5 |
|
||||
|
||||
**Management:**
|
||||
```bash
|
||||
# This is the local server - no SSH needed
|
||||
|
||||
# Agent runner control
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
sudo systemctl restart cleargrow-agent-runner
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
|
||||
# Repository locations
|
||||
ls /opt/repos/ # controller, probe, docs
|
||||
```
|
||||
|
||||
## Network Architecture
|
||||
|
||||
### Public Ports
|
||||
|
||||
| VPS | Port | Service | Access |
|
||||
|-----|------|---------|--------|
|
||||
| vps-git | 443 | HTTPS (Gitea) | Public |
|
||||
| vps-git | 2222 | SSH (Git) | Public |
|
||||
| vps-track | 443 | HTTPS (YouTrack) | Public |
|
||||
| vps-ci | 443 | HTTPS (TeamCity) | Public |
|
||||
|
||||
### Private Network (VLAN)
|
||||
|
||||
All inter-service communication uses Linode Private VLAN (free, no transfer costs).
|
||||
|
||||
| Source | Destination | Port | Purpose |
|
||||
|--------|-------------|------|---------|
|
||||
| vps-agents | vps-git | 5432 | PostgreSQL (if needed) |
|
||||
| vps-agents | vps-git | 2222 | Git SSH (clone/push) |
|
||||
| vps-agents | vps-track | 8080 | YouTrack API |
|
||||
| vps-agents | vps-ci | 8111 | TeamCity API |
|
||||
| vps-ci | vps-git | 2222 | Git SSH (clone for builds) |
|
||||
| vps-track | vps-agents | 8765 | Webhook (issue events) |
|
||||
|
||||
### Firewall Rules
|
||||
|
||||
#### vps-git
|
||||
```
|
||||
# Public
|
||||
ALLOW TCP 443 from 0.0.0.0/0 # HTTPS
|
||||
ALLOW TCP 2222 from 0.0.0.0/0 # Git SSH
|
||||
|
||||
# Private VLAN
|
||||
ALLOW TCP 5432 from 10.0.0.0/24 # PostgreSQL
|
||||
ALLOW ALL from 10.0.0.0/24 # Internal
|
||||
|
||||
# Default
|
||||
DENY ALL
|
||||
```
|
||||
|
||||
#### vps-track
|
||||
```
|
||||
# Public
|
||||
ALLOW TCP 443 from 0.0.0.0/0 # HTTPS
|
||||
|
||||
# Private VLAN
|
||||
ALLOW ALL from 10.0.0.0/24 # Internal
|
||||
|
||||
# Default
|
||||
DENY ALL
|
||||
```
|
||||
|
||||
#### vps-ci
|
||||
```
|
||||
# Public
|
||||
ALLOW TCP 443 from 0.0.0.0/0 # HTTPS
|
||||
|
||||
# Private VLAN
|
||||
ALLOW ALL from 10.0.0.0/24 # Internal
|
||||
|
||||
# Default
|
||||
DENY ALL
|
||||
```
|
||||
|
||||
#### vps-agents
|
||||
```
|
||||
# Public
|
||||
ALLOW TCP 22 from <admin-ips> # SSH (restricted)
|
||||
|
||||
# Private VLAN
|
||||
ALLOW ALL from 10.0.0.0/24 # Internal
|
||||
|
||||
# Outbound
|
||||
ALLOW TCP 443 to api.anthropic.com # Claude API
|
||||
|
||||
# Default
|
||||
DENY ALL inbound from public
|
||||
```
|
||||
|
||||
## Service Distribution
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ vps-git (2GB) │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────────────────┐ │
|
||||
│ │ Nginx │ │ PostgreSQL │ │ Gitea │ │
|
||||
│ │ :443 │ │ :5432 │ │ :3000 │ │
|
||||
│ │ :80 │ │ │ │ :22 │ │
|
||||
│ └─────────────┘ └─────────────────┘ └─────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ vps-track (4GB) │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Nginx │ │ YouTrack │ │
|
||||
│ │ :443 │ │ :8080 │ │
|
||||
│ │ :80 │ │ (embedded database) │ │
|
||||
│ └─────────────┘ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ vps-ci (8GB) │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌───────────────────┐ ┌────────────┐ ┌──────────────┐ │
|
||||
│ │ Nginx │ │ TeamCity Server │ │ TC Agent │ │ Registry │ │
|
||||
│ │ :443 │ │ :8111 │ │ │ │ :5000 │ │
|
||||
│ │ :80 │ │ │ │ │ │ │ │
|
||||
│ └─────────────┘ └───────────────────┘ └────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ vps-agents (16GB) │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────┐ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ Agent Runner │ │ Claude Code Pool │ │
|
||||
│ │ :8765 │ │ (10 concurrent max) │ │
|
||||
│ │ (webhook) │ │ │ │
|
||||
│ └─────────────────┘ └─────────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Toolchains │ │
|
||||
│ │ /opt/esp-idf /opt/ncs /opt/zephyr-sdk /opt/repos │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Issue Processing Flow
|
||||
```
|
||||
1. Developer creates issue in YouTrack (vps-track)
|
||||
2. Issue moved to "Ready" state
|
||||
3. YouTrack webhook → Agent Runner (vps-agents:8765)
|
||||
4. Agent Runner spawns Claude Code instance
|
||||
5. Claude Code:
|
||||
- Clones repo from Gitea (vps-git:2222)
|
||||
- Analyzes code, implements fix
|
||||
- Commits and pushes to Gitea
|
||||
6. Gitea webhook → TeamCity (vps-ci)
|
||||
7. TeamCity runs CI pipeline
|
||||
8. Agent Runner updates YouTrack issue status
|
||||
```
|
||||
|
||||
### Interactive Development Flow
|
||||
```
|
||||
1. Developer SSH → vps-agents
|
||||
2. cd /opt/repos/controller
|
||||
3. claude (interactive session)
|
||||
4. Claude Code reads/writes code
|
||||
5. Developer reviews and commits
|
||||
6. git push → Gitea (vps-git)
|
||||
```
|
||||
|
||||
## Backup Strategy
|
||||
|
||||
| VPS | Data | Method | Frequency | Retention |
|
||||
|-----|------|--------|-----------|-----------|
|
||||
| vps-git | PostgreSQL | pg_dump → S3 | Daily | 30 days |
|
||||
| vps-git | Gitea repos | Already in Git | N/A | N/A |
|
||||
| vps-track | YouTrack | Built-in backup → S3 | Daily | 30 days |
|
||||
| vps-ci | TeamCity config | Built-in backup → S3 | Weekly | 4 weeks |
|
||||
| vps-agents | Repos | Working copies (disposable) | N/A | N/A |
|
||||
|
||||
Linode Backup Service: Optional $2-5/mo per VPS for full image snapshots.
|
||||
|
||||
## Scaling Considerations
|
||||
|
||||
### Vertical Scaling
|
||||
| VPS | Current | Next Tier | Trigger |
|
||||
|-----|---------|-----------|---------|
|
||||
| vps-git | 2GB | 4GB | >1000 repos or slow clones |
|
||||
| vps-track | 4GB | 8GB | >50 concurrent users |
|
||||
| vps-ci | 8GB | 16GB | Build queue backing up |
|
||||
| vps-agents | 16GB | 32GB | Need >10 concurrent agents |
|
||||
|
||||
### Horizontal Scaling
|
||||
- **vps-agents**: Can add vps-agents-2 with queue-based work distribution (requires Redis)
|
||||
- **vps-ci**: Can add additional TeamCity agents on separate VPS
|
||||
|
||||
## Cost Summary
|
||||
|
||||
| Component | Monthly |
|
||||
|-----------|---------|
|
||||
| vps-git (Shared 2GB) | $12 |
|
||||
| vps-track (Shared 4GB) | $24 |
|
||||
| vps-ci (Shared 8GB) | $48 |
|
||||
| vps-agents (Dedicated 16GB) | $144 |
|
||||
| **Subtotal (Compute)** | **$228** |
|
||||
| Linode Backups (optional) | ~$10 |
|
||||
| Object Storage for backups | ~$5 |
|
||||
| **Total (with backups)** | **~$243** |
|
||||
|
||||
## Domain Configuration
|
||||
|
||||
### DNS Records (Cloudflare)
|
||||
```
|
||||
git.cleargrow.io A 139.144.29.179 (DNS only, Let's Encrypt)
|
||||
track.cleargrow.io A 170.187.143.45 (DNS only, Let's Encrypt)
|
||||
ci.cleargrow.io A 173.230.138.66 (DNS only, Let's Encrypt)
|
||||
agents.cleargrow.io A 45.79.204.236 (internal use only)
|
||||
```
|
||||
|
||||
### SSL Certificates
|
||||
- **vps-git**: Let's Encrypt (certbot, auto-renew enabled, expires 2026-03-10)
|
||||
- **vps-track**: Let's Encrypt (certbot, auto-renew enabled, expires 2026-03-10)
|
||||
- **vps-ci**: Let's Encrypt (certbot, auto-renew enabled, expires 2026-03-10)
|
||||
- **vps-agents**: No SSL needed (internal services only)
|
||||
|
||||
## SSH Keys
|
||||
|
||||
The `cleargrow_ed25519` key is used for inter-server communication:
|
||||
```
|
||||
# Public key (add to new servers)
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBRfOE6jOtIE07fSbs8eb5Rd5S/jwmcQEU3ryvvrx9/G cleargrow-controller
|
||||
|
||||
# Key location on vps-agents
|
||||
~/.ssh/cleargrow_ed25519
|
||||
```
|
||||
57
CLAUDE.md
57
CLAUDE.md
@@ -2,11 +2,21 @@
|
||||
|
||||
## System Overview
|
||||
|
||||
Self-hosted development platform for the ClearGrow IoT agricultural monitoring system, consisting of:
|
||||
- **Gitea**: Git repository hosting at `git.cleargrow.io`
|
||||
- **YouTrack**: Issue tracking at `track.cleargrow.io`
|
||||
- **TeamCity**: CI/CD at `ci.cleargrow.io`
|
||||
- **Agent Runner**: Automated Claude Code task processing
|
||||
Self-hosted development platform for the ClearGrow IoT agricultural monitoring system.
|
||||
|
||||
**Architecture**: Distributed 4-VPS setup on Linode (see `ARCHITECTURE.md` for details)
|
||||
|
||||
| VPS | IP | Services | Status |
|
||||
|-----|-----|----------|--------|
|
||||
| **vps-git** | 139.144.29.179 | Nginx, PostgreSQL, Gitea | **Active** |
|
||||
| **vps-track** | 170.187.143.45 | Nginx, YouTrack | **Active** |
|
||||
| **vps-ci** | 173.230.138.66 | Nginx, TeamCity, Build Agent, Registry | **Active** |
|
||||
| **vps-agents** | 45.79.204.236 | Agent Runner, Claude Code, Toolchains | **Active** (this server) |
|
||||
|
||||
**Service URLs**:
|
||||
- **Gitea**: https://git.cleargrow.io (vps-git - 139.144.29.179)
|
||||
- **YouTrack**: https://track.cleargrow.io (vps-track - 170.187.143.45)
|
||||
- **TeamCity**: https://ci.cleargrow.io (vps-ci - 173.230.138.66)
|
||||
|
||||
## Repositories
|
||||
|
||||
@@ -15,30 +25,41 @@ Self-hosted development platform for the ClearGrow IoT agricultural monitoring s
|
||||
| **controller** | `/opt/repos/controller` | ESP-IDF (C) | ESP32-S3 touchscreen controller with Thread Border Router |
|
||||
| **probe** | `/opt/repos/probe` | Zephyr (C) | nRF52840 wireless sensor probes |
|
||||
| **docs** | `/opt/repos/docs` | Markdown | Technical documentation |
|
||||
| **devplatform** | `/root/claude` | Config | Platform configuration and Claude Code setup |
|
||||
|
||||
## Quick Commands
|
||||
|
||||
```bash
|
||||
# Platform management
|
||||
docker compose -f /opt/devplatform/docker-compose.yml up -d # Start all services
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f # View logs
|
||||
/opt/devplatform/scripts/healthcheck.sh # Check health
|
||||
/opt/devplatform/scripts/backup.sh # Run backup
|
||||
# vps-git management (Gitea)
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@139.144.29.179
|
||||
systemctl status vps-git
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
|
||||
# Controller firmware (ESP-IDF)
|
||||
# vps-track management (YouTrack)
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@170.187.143.45
|
||||
systemctl status vps-track
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
|
||||
# vps-ci management (TeamCity)
|
||||
ssh -i ~/.ssh/cleargrow_ed25519 root@173.230.138.66
|
||||
systemctl status vps-ci
|
||||
docker compose -f /opt/devplatform/docker-compose.yml ps
|
||||
docker compose -f /opt/devplatform/docker-compose.yml logs -f
|
||||
|
||||
# vps-agents (this server) - Agent Runner
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
|
||||
# Controller firmware (ESP-IDF) - on vps-agents
|
||||
cd /opt/repos/controller
|
||||
source ~/esp/esp-idf/export.sh
|
||||
idf.py build
|
||||
idf.py -p /dev/ttyUSB0 flash monitor
|
||||
|
||||
# Probe firmware (Zephyr)
|
||||
# Probe firmware (Zephyr) - on vps-agents
|
||||
cd /opt/repos/probe
|
||||
west build -b nrf52840dk_nrf52840
|
||||
west flash
|
||||
|
||||
# Agent runner
|
||||
sudo systemctl status cleargrow-agent-runner
|
||||
sudo journalctl -u cleargrow-agent-runner -f
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
18
README.md
18
README.md
@@ -80,6 +80,21 @@ git clone git@git.cleargrow.io:cleargrow/devplatform.git
|
||||
cd devplatform
|
||||
```
|
||||
|
||||
## Safety Hooks
|
||||
|
||||
Pre-execution hooks protect against accidental service outages by requiring confirmation for dangerous commands:
|
||||
|
||||
| Category | Protected Commands |
|
||||
|----------|-------------------|
|
||||
| Docker Compose | `down`, `stop`, `rm`, `restart` |
|
||||
| Docker Containers | `stop`, `kill`, `rm` on platform containers |
|
||||
| Systemctl | `stop`, `disable`, `restart` on critical services |
|
||||
| System | `reboot`, `shutdown`, `halt`, `poweroff` |
|
||||
| Destructive Deletes | `rm -rf` on platform directories |
|
||||
| Database | `DROP DATABASE`, `dropdb` |
|
||||
|
||||
When Claude attempts a dangerous command, you'll be prompted for confirmation before execution.
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
@@ -88,12 +103,15 @@ cd devplatform
|
||||
├── QUICK_REFERENCE.md # Command cheat sheet
|
||||
├── SYSTEM_OVERVIEW.md # Platform architecture
|
||||
└── .claude/
|
||||
├── settings.json # Permissions and hooks configuration
|
||||
├── agents/ # Sub-agent definitions
|
||||
├── commands/ # Slash commands
|
||||
│ ├── firmware/ # Build/flash/test commands
|
||||
│ ├── git/ # Git workflow commands
|
||||
│ ├── platform/ # Service management
|
||||
│ └── issues/ # YouTrack integration
|
||||
├── hooks/ # Safety hooks
|
||||
│ └── dangerous_command_check.py
|
||||
└── skills/ # Domain knowledge
|
||||
├── esp-idf/
|
||||
├── zephyr/
|
||||
|
||||
Reference in New Issue
Block a user