Appearance
Cloud PC Operations Guide
What the Cloud PC Is
The Cloud PC is an Ubuntu 24.04 EC2 instance in the AWS Prod account (807267566999, us-west-2) that serves as the primary development environment for Cirius infrastructure work. It runs Kobe — the AI assistant (Claude Code) — along with the Telegram bot service that Kobe uses to communicate through Telegram channels.
| Attribute | Value |
|---|---|
| Instance name | Kobe-Cloud-PC |
| OS | Ubuntu 24.04 LTS (Noble Numbat) |
| Instance type | t3a.2xlarge |
| AWS account | Prod — 807267566999 |
| Region | us-west-2 |
| Private IP | 10.50.2.8 (static, pinned in Terraform) |
| Subnet | prod-workers — 10.50.2.0/24, us-west-2b |
| Public IP | None — no inbound internet access |
| Primary access | SSH via Twingate zero-trust overlay |
| Break-glass access | AWS Systems Manager (SSM) Session Manager |
| IAM role | CloudPCRole (ReadOnlyAccess + SSM + state S3 read + kobe/* Secrets Manager read) |
| Security agents | Cortex XDR, auditd |
| Log forwarding | auditd → syslog VM in Logging account → LAW (cirius-logging-law-central) |
Why this machine matters. Everything that runs here — Kobe, Claude Code, the Telegram bot — has read access to all infra repos and cloud credentials spanning both Azure tenants and the entire AWS org. Treat it as a privileged workstation. A compromise of this host is a compromise of significant infrastructure visibility.
Connecting via Twingate SSH
Prerequisites
- Twingate client installed — https://www.twingate.com/download (network name:
cirius) - Entra group membership — must be in
PrivilegedUsers(Rory, Kevin, Greg) or a group with explicit access to thekobe-cloud-pcTwingate resource - SSH private key — the key pair authorized on the Cloud PC (stored in Keeper under "Cloud PC SSH Key")
- Twingate connected — client shows green / "Connected" before attempting SSH
SSH Command
bash
ssh ubuntu@10.50.2.8If you need to specify a key explicitly:
bash
ssh -i ~/.ssh/cloud-pc-key ubuntu@10.50.2.8Add to ~/.ssh/config for convenience:
Host cloud-pc
HostName 10.50.2.8
User ubuntu
IdentityFile ~/.ssh/cloud-pc-keyThen connect with:
bash
ssh cloud-pcKey Authentication
Authentication is SSH public key only — password authentication is disabled. Authorized public keys are provisioned via cloud-init during bootstrap. If your key is not working, verify it is in /home/ubuntu/.ssh/authorized_keys on the instance (use SSM to check, see below).
SSM Break-Glass Access
When to Use SSM
- Twingate is down or your client cannot connect
- The instance just came up and bootstrap is still running (SSH user not yet configured)
- Diagnosing cloud-init failures before the host is fully provisioned
- Emergency access when Twingate connectors are offline
SSM does not require Twingate. It uses the SSM agent (pre-installed on Ubuntu 24.04) reaching out to the AWS SSM endpoint over standard HTTPS. CloudPCRole has AmazonSSMManagedInstanceCore attached.
Get the Instance ID
bash
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=Kobe-Cloud-PC" "Name=instance-state-name,Values=running" \
--region us-west-2 --profile prod \
--query "Reservations[0].Instances[0].InstanceId" --output textOr from the Terraform outputs (if you have aws-infra checked out):
bash
terraform -chdir=~/src/aws-infra/prod output -raw cloudpc_instance_idStart an SSM Session
bash
aws ssm start-session --target i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prodYou land as ssm-user. Elevate to ubuntu for normal operations:
bash
sudo -iu ubuntuOr to root for system-level investigation:
bash
sudo -iSSM vs Twingate — Capability Comparison
| Capability | Twingate SSH | SSM |
|---|---|---|
| Full interactive shell | Yes | Yes |
| File transfer (scp/rsync) | Yes | No (use aws s3 cp workaround) |
| tmux / screen sessions | Yes | Yes |
| Port forwarding | Yes | Yes (via SSM port-forward) |
| Works when Twingate is down | No | Yes |
| Works before bootstrap completes | No | Yes (SSM agent starts before bootstrap) |
| Session recorded to CloudTrail | No | Yes |
| Requires AWS credentials | No | Yes |
SSM sessions are logged to CloudTrail. Use it for break-glass only — prefer Twingate for routine work.
If SSM Does Not List the Instance
bash
aws ssm describe-instance-information \
--region us-west-2 --profile prod \
--filters "Key=InstanceIds,Values=i-0xxxxxxxxxxxxxxxx"An empty result means the SSM agent has not registered. Wait 60 seconds and retry. If it never appears: check that the instance has internet egress (VPC route via NAT or firewall), confirm CloudPCRole is attached, and verify the SSM agent is running (requires a separate path in — if totally locked out, see the Cloud PC Rebuild runbook).
Service Management
Telegram Bot Service
The Telegram bot runs as a systemd service named kobe. It manages a tmux session named kobe that runs Claude Code with the Telegram channel plugin.
Check status:
bash
systemctl status kobe --no-pagerRestart:
bash
sudo systemctl restart kobeStop / Start:
bash
sudo systemctl stop kobe
sudo systemctl start kobeView recent logs:
bash
sudo journalctl -u kobe --since "1 hour ago" --no-pagerTail live logs:
bash
sudo journalctl -u kobe -fVerify the tmux session is alive:
bash
tmux ls
# Expect: kobe: 1 windows (created ...)Attach to the tmux session (view Kobe's live terminal):
bash
tmux attach -t kobeDetach without killing the session: Ctrl-B D
If kobe.service fails to start due to a stale tmux session:
bash
sudo -u ubuntu tmux kill-session -t kobe 2>/dev/null || true
sudo systemctl restart kobeClaude Code
Claude Code is not a separate systemd service — it runs inside the kobe tmux session managed by kobe.service. To check if Claude Code is running:
bash
pgrep -a node | grep claudeIf you need to restart Claude Code specifically, restart kobe.service:
bash
sudo systemctl restart kobeClaude Code credentials (OAuth refresh token) live at /home/ubuntu/.claude/.credentials.json. If Claude Code reports authentication failures, the refresh token may have expired. Pull the current credential from Secrets Manager and restart:
bash
aws secretsmanager get-secret-value \
--secret-id kobe/claude-credentials \
--region us-west-2 \
--query SecretString --output text \
> /home/ubuntu/.claude/.credentials.json
sudo systemctl restart kobeChecking All Services at Once
bash
systemctl status kobe auditd --no-pagerFor a broader service health overview:
bash
systemctl is-system-running
systemctl --failed --no-pagerInstance Health
CPU, Memory, and Disk
bash
# CPU and memory (top, single snapshot)
top -bn1 | head -20
# Memory breakdown
free -h
# Disk usage
df -h
# Disk I/O (if investigating performance)
iostat -x 1 5Normal ranges for a t3a.2xlarge (8 vCPU, 32 GB RAM):
- CPU: typically low except during active Kobe work sessions (Claude Code inference + tool calls)
- Memory: 4–8 GB used at idle with all services running; can climb to 12–16 GB during heavy Kobe runs
- Disk: root volume is 50 GB; stay under 80% (
/should show <40 GB used in normal operation)
Processes That Should Be Running
bash
pgrep -a node # Claude Code (should show at least one node process)
pgrep -a tmux # tmux server for the kobe session
pgrep -a auditd # audit daemon
pgrep -a amazon-ssm # SSM agentCheck all expected services together:
bash
systemctl is-active kobe auditd amazon-ssm-agent --no-pager
# Each line should print "active"auditd Status
bash
sudo systemctl is-active auditd
sudo auditctl -s # audit system status
sudo auditctl -l # list active rules
sudo ausearch -ts recent -m EXECVE # recent execution events (last 10 min)If auditd is not active:
bash
sudo systemctl start auditd
sudo systemctl enable auditd
sudo journalctl -u auditd --since "30 minutes ago" --no-pagerCortex XDR
Verify Agent Is Running
bash
sudo /opt/traps/bin/cytool statusExpected output includes:
Connection status: ConnectedPolicy status: Applied
The service name is traps_agent. Check it directly:
bash
sudo systemctl status traps_agent --no-pagerIf the Agent Shows Offline or Disconnected
Step 1 — Force a reconnect:
bash
sudo /opt/traps/bin/cytool reconnect force f64d4b7da6774ccca9adb4db22112652The key (f64d4b7da6774ccca9adb4db22112652) is the Cirius Cortex tenant ID.
Step 2 — If reconnect does not resolve, restart the service:
bash
sudo systemctl restart traps_agentStep 3 — Check the agent logs:
bash
sudo journalctl -u traps_agent --since "1 hour ago" --no-pager
ls /var/log/traps/Step 4 — Verify in the Cortex console.
Log into the Cortex XDR console and check Endpoints → Kobe-Cloud-PC. If it still shows offline after a forced reconnect and service restart, the issue may be egress (NAT/firewall blocking the Cortex distribution service endpoints). Check VPC flow logs and firewall policy.
If the host was recently rebuilt, Cortex will register a new endpoint entry with the same hostname. The old entry stays as Disconnected — delete it manually in the Cortex console once the new endpoint shows Connected + Applied. Cortex does not auto-dedupe on hostname.
Updating the Instance
Standard APT Update Workflow
bash
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get autoremove -yFor a full distribution upgrade (rare — don't do this without Rory's explicit approval):
bash
sudo do-release-upgradeHandling Kernel Updates
Kernel updates require a reboot. The process to follow:
Check if a kernel update is pending before rebooting:
bashdpkg -l | grep linux-image # Compare installed version to running kernel: uname -rNotify Rory / the team before rebooting. A reboot drops Twingate SSH, takes Kobe offline, and interrupts any in-flight work. Do not reboot silently.
Stop the kobe service cleanly before rebooting:
bashsudo systemctl stop kobeReboot:
bashsudo rebootVerify Twingate SSH reconnects after the instance comes back up. The instance typically takes 30–60 seconds to come up; Twingate connectivity resumes once the OS is fully booted. Test from your workstation:
bashssh ubuntu@10.50.2.8 "uptime"Verify all services restarted:
bashsystemctl is-active kobe auditd amazon-ssm-agent traps_agent --no-pagerCheck the kobe service came up cleanly:
bashsudo journalctl -u kobe --since "10 minutes ago" --no-pager
If kobe does not come up on its own after a reboot:
bash
sudo systemctl restart kobeAWS Instance Management
Checking Instance Status
bash
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=Kobe-Cloud-PC" \
--region us-west-2 --profile prod \
--query "Reservations[0].Instances[0].{State:State.Name,InstanceId:InstanceId,PrivateIP:PrivateIpAddress,Type:InstanceType}" \
--output tableEC2 instance status checks:
bash
aws ec2 describe-instance-status \
--instance-ids i-0xxxxxxxxxxxxxxxx \
--region us-west-2 --profile prod \
--output tableBoth SystemStatus and InstanceStatus should show ok.
Stop the Instance
bash
aws ec2 stop-instances --instance-ids i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prodUse to save cost during extended downtime. The static IP (10.50.2.8) is reserved and will be reassigned on restart — no Twingate reconfiguration needed.
Start the Instance
bash
aws ec2 start-instances --instance-ids i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prodAfter starting, wait for instance status checks to reach ok before expecting services to be available:
bash
aws ec2 wait instance-status-ok --instance-ids i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prodReboot via AWS CLI
bash
aws ec2 reboot-instances --instance-ids i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prodPrefer rebooting from inside the instance (sudo reboot) when possible — it gives services a chance to shut down cleanly. Use the CLI reboot for unresponsive instances.
AWS Console
All of the above operations are also available in the AWS Console: EC2 → Instances → Kobe-Cloud-PC → Instance state
Make sure you are in the us-west-2 region and the Prod account (807267566999).
Troubleshooting
Cannot Connect via Twingate
Immediate fallback: use SSM. See SSM Break-Glass Access above.
Once on the instance via SSM, check what is failing:
bash
# Is the instance actually running?
systemctl is-system-running
# Is the SSH daemon running?
systemctl status ssh --no-pager
# Any recent authentication failures?
sudo journalctl -u ssh --since "30 minutes ago" --no-pager
# Check SSH is listening
ss -tlnp | grep :22Check on the Twingate side:
- Twingate admin console → Connectors — are
mutant-nuthatchandpapaya-manulbothConnected? - Admin console → Resources →
kobe-cloud-pc— is the target still10.50.2.8? - Ask affected users to sign out of Twingate and sign back in (flushes local resource cache)
If Twingate connectors are offline, that is a separate incident — see Twingate Operations.
SSM Not Working
If aws ssm start-session hangs or returns an error:
Check the instance profile is attached:
bash
aws ec2 describe-instances \
--instance-ids i-0xxxxxxxxxxxxxxxx \
--region us-west-2 --profile prod \
--query "Reservations[0].Instances[0].IamInstanceProfile.Arn" \
--output text
# Should return: arn:aws:iam::807267566999:instance-profile/CloudPCInstanceProfileCheck the SSM agent is registered:
bash
aws ssm describe-instance-information \
--region us-west-2 --profile prod \
--filters "Key=InstanceIds,Values=i-0xxxxxxxxxxxxxxxx" \
--output tableIf no output, the SSM agent is not registered. Most likely cause: internet egress is blocked (the agent cannot reach the SSM endpoint at ssm.us-west-2.amazonaws.com). Check VPC route tables and the Palo Alto firewall policy for the prod-workers subnet.
Verify the SSM agent is running (requires alternative access path):
bash
sudo systemctl status amazon-ssm-agent --no-pager
sudo systemctl restart amazon-ssm-agentVerify your AWS CLI session has the right permissions:
bash
aws sts get-caller-identity --profile prodYou need ssm:StartSession permission in the prod account.
Service Crashed
Step 1 — Read the logs:
bash
sudo journalctl -u kobe --since "2 hours ago" --no-pager
# Or get more context:
sudo journalctl -u kobe -n 500 --no-pagerCommon failure causes:
| Symptom in logs | Likely cause | Fix |
|---|---|---|
Error: credentials expired or 401 from Anthropic | Claude credentials refresh token expired | Pull fresh from Secrets Manager (see Claude Code section) |
Address already in use or tmux session conflict | Stale tmux session from unclean shutdown | sudo -u ubuntu tmux kill-session -t kobe 2>/dev/null; sudo systemctl restart kobe |
ENOENT or file not found for .env or telegram.conf | Secrets Manager pull failed during bootstrap | Re-run secret materialization manually, then restart |
OOM kill (oom-kill-constraint) | Memory exhausted | Check free -h, consider stopping heavy background jobs, or resize instance |
| Repeated crash/restart loop | See journalctl for specific error | Read full stacktrace, fix root cause before restarting |
Step 2 — Restart and monitor:
bash
sudo systemctl restart kobe
sudo journalctl -u kobe -f
# Watch for a clean startup vs. immediate re-crashStep 3 — Root cause before closing. If the service crashed due to an expired secret or bad configuration, fix the underlying problem — do not just restart and walk away. Log what happened in Slack or the incident tracker.
Cloud-Init / Bootstrap Issues (only relevant post-rebuild)
bash
sudo cloud-init status --long
sudo tail -100 /var/log/cloud-init-output.log
sudo tail -50 /var/log/kobe-init.logSee Cloud PC Rebuild runbook for full diagnostics.
Security Considerations
This machine is a privileged workstation. Treat it accordingly.
What has access to what:
CloudPCRole(instance profile):ReadOnlyAccessacross the entire Prod AWS account + read access to Terraform state S3 bucketskobe-sp(Azure Reader SP):ReadOnlyAccessacross Azure infrastructure in both tenantskobe/*Secrets Manager secrets: Azure SP credentials, Anthropic API key, GitHub tokens, SSH keys, database URLskobe-botGitHub account: member access to Cirius-Group-Inc — can read all private repos- All seven infra repos are cloned to
/home/ubuntu/src/with write access via the kobe GitHub SSH key
Operational rules:
- Do not install unauthorized software on this instance
- Do not store plaintext secrets outside of
~/.env_secretsor the designated secret paths - Do not leave long-running processes that are not managed by systemd — orphaned processes are invisible to monitoring
- SSH key access is controlled — if you add a new public key to
authorized_keys, document who it belongs to and why - Cortex XDR and auditd are monitoring for suspicious execution patterns — do not attempt to suppress or disable either agent
- If you suspect the instance is compromised: snapshot first, then isolate — stop the instance from the AWS Console (which preserves the EBS volume), notify Rory, and follow Incident Response. Do not reboot or clean up — preserve forensic state.
- auditd logs are forwarded to
cirius-logging-law-centralvia the syslog VM in the Logging account. Logs cannot be tampered with locally after forwarding.
Related Documentation
- Cloud PC Rebuild Runbook — full rebuild procedure when this instance needs to be replaced
- Twingate Operations — Twingate connector health, user management
- Cortex XDR Operations — Cortex console, policy management, agent enrollment
- Incident Response — what to do if the instance is compromised
- Break-Glass Procedure — escalation path when all normal access fails
aws-infra/prod/ec2_cloudpc.tf— instance declaration, security group, static IPaws-infra/prod/iam_cloudpc.tf—CloudPCRole, instance profileaws-infra/prod/scripts/kobe-bootstrap.sh— full first-boot provisioning script
Document History
| Date | Change | Author |
|---|---|---|
| May 2026 | Initial operations runbook — covers day-to-day access, service management, health checks, Cortex XDR, patching, AWS instance management, and troubleshooting | Kobe |