Skip to content

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.

AttributeValue
Instance nameKobe-Cloud-PC
OSUbuntu 24.04 LTS (Noble Numbat)
Instance typet3a.2xlarge
AWS accountProd — 807267566999
Regionus-west-2
Private IP10.50.2.8 (static, pinned in Terraform)
Subnetprod-workers10.50.2.0/24, us-west-2b
Public IPNone — no inbound internet access
Primary accessSSH via Twingate zero-trust overlay
Break-glass accessAWS Systems Manager (SSM) Session Manager
IAM roleCloudPCRole (ReadOnlyAccess + SSM + state S3 read + kobe/* Secrets Manager read)
Security agentsCortex XDR, auditd
Log forwardingauditd → 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

  1. Twingate client installedhttps://www.twingate.com/download (network name: cirius)
  2. Entra group membership — must be in PrivilegedUsers (Rory, Kevin, Greg) or a group with explicit access to the kobe-cloud-pc Twingate resource
  3. SSH private key — the key pair authorized on the Cloud PC (stored in Keeper under "Cloud PC SSH Key")
  4. Twingate connected — client shows green / "Connected" before attempting SSH

SSH Command

bash
ssh ubuntu@10.50.2.8

If you need to specify a key explicitly:

bash
ssh -i ~/.ssh/cloud-pc-key ubuntu@10.50.2.8

Add to ~/.ssh/config for convenience:

Host cloud-pc
    HostName 10.50.2.8
    User ubuntu
    IdentityFile ~/.ssh/cloud-pc-key

Then connect with:

bash
ssh cloud-pc

Key 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 text

Or from the Terraform outputs (if you have aws-infra checked out):

bash
terraform -chdir=~/src/aws-infra/prod output -raw cloudpc_instance_id

Start an SSM Session

bash
aws ssm start-session --target i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prod

You land as ssm-user. Elevate to ubuntu for normal operations:

bash
sudo -iu ubuntu

Or to root for system-level investigation:

bash
sudo -i

SSM vs Twingate — Capability Comparison

CapabilityTwingate SSHSSM
Full interactive shellYesYes
File transfer (scp/rsync)YesNo (use aws s3 cp workaround)
tmux / screen sessionsYesYes
Port forwardingYesYes (via SSM port-forward)
Works when Twingate is downNoYes
Works before bootstrap completesNoYes (SSM agent starts before bootstrap)
Session recorded to CloudTrailNoYes
Requires AWS credentialsNoYes

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-pager

Restart:

bash
sudo systemctl restart kobe

Stop / Start:

bash
sudo systemctl stop kobe
sudo systemctl start kobe

View recent logs:

bash
sudo journalctl -u kobe --since "1 hour ago" --no-pager

Tail live logs:

bash
sudo journalctl -u kobe -f

Verify 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 kobe

Detach 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 kobe

Claude 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 claude

If you need to restart Claude Code specifically, restart kobe.service:

bash
sudo systemctl restart kobe

Claude 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 kobe

Checking All Services at Once

bash
systemctl status kobe auditd --no-pager

For a broader service health overview:

bash
systemctl is-system-running
systemctl --failed --no-pager

Instance 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 5

Normal 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 agent

Check 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-pager

Cortex XDR

Verify Agent Is Running

bash
sudo /opt/traps/bin/cytool status

Expected output includes:

  • Connection status: Connected
  • Policy status: Applied

The service name is traps_agent. Check it directly:

bash
sudo systemctl status traps_agent --no-pager

If the Agent Shows Offline or Disconnected

Step 1 — Force a reconnect:

bash
sudo /opt/traps/bin/cytool reconnect force f64d4b7da6774ccca9adb4db22112652

The key (f64d4b7da6774ccca9adb4db22112652) is the Cirius Cortex tenant ID.

Step 2 — If reconnect does not resolve, restart the service:

bash
sudo systemctl restart traps_agent

Step 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 EndpointsKobe-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 -y

For a full distribution upgrade (rare — don't do this without Rory's explicit approval):

bash
sudo do-release-upgrade

Handling Kernel Updates

Kernel updates require a reboot. The process to follow:

  1. Check if a kernel update is pending before rebooting:

    bash
    dpkg -l | grep linux-image
    # Compare installed version to running kernel: uname -r
  2. Notify Rory / the team before rebooting. A reboot drops Twingate SSH, takes Kobe offline, and interrupts any in-flight work. Do not reboot silently.

  3. Stop the kobe service cleanly before rebooting:

    bash
    sudo systemctl stop kobe
  4. Reboot:

    bash
    sudo reboot
  5. Verify 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:

    bash
    ssh ubuntu@10.50.2.8 "uptime"
  6. Verify all services restarted:

    bash
    systemctl is-active kobe auditd amazon-ssm-agent traps_agent --no-pager
  7. Check the kobe service came up cleanly:

    bash
    sudo 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 kobe

AWS 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 table

EC2 instance status checks:

bash
aws ec2 describe-instance-status \
  --instance-ids i-0xxxxxxxxxxxxxxxx \
  --region us-west-2 --profile prod \
  --output table

Both SystemStatus and InstanceStatus should show ok.

Stop the Instance

bash
aws ec2 stop-instances --instance-ids i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prod

Use 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 prod

After 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 prod

Reboot via AWS CLI

bash
aws ec2 reboot-instances --instance-ids i-0xxxxxxxxxxxxxxxx --region us-west-2 --profile prod

Prefer 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 :22

Check on the Twingate side:

  • Twingate admin console → Connectors — are mutant-nuthatch and papaya-manul both Connected?
  • Admin console → Resources → kobe-cloud-pc — is the target still 10.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/CloudPCInstanceProfile

Check the SSM agent is registered:

bash
aws ssm describe-instance-information \
  --region us-west-2 --profile prod \
  --filters "Key=InstanceIds,Values=i-0xxxxxxxxxxxxxxxx" \
  --output table

If 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-agent

Verify your AWS CLI session has the right permissions:

bash
aws sts get-caller-identity --profile prod

You 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-pager

Common failure causes:

Symptom in logsLikely causeFix
Error: credentials expired or 401 from AnthropicClaude credentials refresh token expiredPull fresh from Secrets Manager (see Claude Code section)
Address already in use or tmux session conflictStale tmux session from unclean shutdownsudo -u ubuntu tmux kill-session -t kobe 2>/dev/null; sudo systemctl restart kobe
ENOENT or file not found for .env or telegram.confSecrets Manager pull failed during bootstrapRe-run secret materialization manually, then restart
OOM kill (oom-kill-constraint)Memory exhaustedCheck free -h, consider stopping heavy background jobs, or resize instance
Repeated crash/restart loopSee journalctl for specific errorRead 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-crash

Step 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.log

See 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): ReadOnlyAccess across the entire Prod AWS account + read access to Terraform state S3 buckets
  • kobe-sp (Azure Reader SP): ReadOnlyAccess across Azure infrastructure in both tenants
  • kobe/* Secrets Manager secrets: Azure SP credentials, Anthropic API key, GitHub tokens, SSH keys, database URLs
  • kobe-bot GitHub 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_secrets or 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-central via the syslog VM in the Logging account. Logs cannot be tampered with locally after forwarding.

  • 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 IP
  • aws-infra/prod/iam_cloudpc.tfCloudPCRole, instance profile
  • aws-infra/prod/scripts/kobe-bootstrap.sh — full first-boot provisioning script

Document History

DateChangeAuthor
May 2026Initial operations runbook — covers day-to-day access, service management, health checks, Cortex XDR, patching, AWS instance management, and troubleshootingKobe

Internal use only — Cirius Group