Orchestrating Multi-Site Deployments and Daemon Health Monitoring Across Lightsail Infrastructure
This session involved coordinating deployments across three distinct web properties, troubleshooting a critical OAuth token expiration in an automated sync process, and implementing comprehensive health monitoring for the jada-agent orchestrator daemon running on AWS Lightsail. The work demonstrates patterns for managing multiple sites from a unified repository structure while maintaining proper separation of concerns and monitoring visibility.
What Was Done
- Created and deployed a new SEO landing page for 86from.com, including directory restructuring and CloudFront cache invalidation
- Debugged and fixed template syntax errors in a booking widget embedded across multiple properties
- Established remote health monitoring for the jada-agent.service daemon via Lightsail metrics API and SSH introspection
- Identified and documented a broken OAuth token in the port_sheet_sync process that requires re-authentication
- Implemented Google Analytics API integration for extracting multi-property performance data
Repository Structure and Multi-Site Management
The codebase is organized as a monorepo with distinct site directories under /Users/cb/Documents/repos/sites/:
sites/
├── 86from.com/
│ ├── site/
│ │ ├── index.html
│ │ └── what-does-86d-mean (new landing page)
│ └── (S3 bucket: 86from.com, CloudFront: distribution-specific ID)
├── sailjada.com/
│ ├── index.html
│ └── (S3 bucket: sailjada.com)
└── queenofsandiego.com/
├── BookingAutomation.gs (Google Apps Script)
└── (booking widget shared across properties)
This structure allows version control of HTML, CSS, and automation scripts while keeping deployment targets (S3 buckets, CloudFront distributions) logically associated with each domain.
Booking Widget Template Syntax Repair
During deployment of updates to sailjada.com's index.html and the new 86from.com landing page, a critical issue emerged: the booking widget embedded in multiple properties contained template syntax using double braces {{ }} that conflicted with CloudFront's cache behavior and browser parsing.
The investigation revealed that these braces were intended for server-side or client-side templating but were being rendered literally in the final HTML. The solution involved:
- Identifying all double-brace occurrences via grep within the booking widget section
- Confirming they appeared only within the
<script>tag block, not in global HTML - Replacing
{{ }}with single braces to prevent template engine conflicts - Validating JavaScript syntax for the entire booking widget block post-replacement
- Embedding a version tag with model ID in the widget comment for audit trails
This pattern ensures that booking automation (which relies on the BookingAutomation.gs Google Apps Script) can execute without template interpolation errors across all three properties.
Site Deployment and CDN Management
The 86dfrom.com directory was renamed to 86from.com and redeployed to its corresponding S3 bucket. The deployment pipeline:
- Sync local
/sites/86from.com/site/to the S3 bucket using the AWS CLI - Invalidate the CloudFront distribution cache with a wildcard pattern to ensure fresh assets
- Verify the staging bucket deployment before pushing to production CloudFront
The staging CloudFront distribution was used for pre-production validation, requiring identification of all active distributions to isolate the correct staging ID. This two-stage approach prevents serving stale or broken content to users.
Lightsail Daemon Health Monitoring
The jada-agent.service orchestrator daemon (running on 34.239.233.28) is the core of task automation. Since the private SSH key was not stored locally, health checks were performed using two complementary approaches:
1. AWS Lightsail Metrics API
CPU, memory, network, and status check metrics were pulled via the Lightsail API without SSH, providing historical baseline data:
- CPU average: 0.65% (normal for a 60-second polling loop)
- Memory utilization: 144MB of 914MB (~16%)
- Disk usage: 6.2GB of 39GB (~17%)
- Load average: 0.00 (idle between task cycles)
- Status check failures: 0 in the last 2 hours
2. Temporary SSH Credentials and Service Introspection
The Lightsail API was queried for temporary SSH access credentials, which were then used to retrieve:
- Service status:
systemctl status jada-agent.service→ Active, 3 days uptime - Recent session activity: parsed from daemon logs to extract session counts, exit codes, and task completion rates
- Error logs: searched for recurring patterns in the last 24 hours
- Running processes: verified no zombie or runaway processes consuming resources
The daemon completed 1 of 3 sessions successfully today (UTC), with 2 hitting the 30-turn Claude limit—an expected behavior when processing complex tasks but not a service failure.
OAuth Token Expiration: port_sheet_sync Process
A critical finding emerged during log analysis: the port_sheet_sync.py script has been failing every 30 minutes with a Google OAuth token error:
[port-sheet] token error: HTTP Error 400: Bad Request
This indicates that the stored Google OAuth credentials (client_id and client_secret) are either expired or revoked. The sync process bridges port sheet data and Google Sheets, so outages prevent data synchronization.
Resolution path:
- Re-run the auth flow via
auth_ga.pywith the appropriate account credentials - Update the stored token in the secrets directory
- Verify token structure contains all required scopes for Sheets API
- Monitor the next scheduled sync run (30-minute intervals) for success
Google Analytics Integration
As part of this session, Google Analytics API access was established to pull multi-property reports. The workflow involved:
- Using stored OAuth credentials (client_id/client_secret) from the jada service account
- Listing all GA4 properties under the dangerouscentaur account
- Extracting 7-day performance reports for 86dfrom.com (now 86from.com)
- Validating that the google-auth-oauthlib library is installed and available
This integration enables programmatic access to analytics dashboards, supporting automated reporting and anomaly detection.
Key Infrastructure Decisions
SSH Access Pattern: Rather than storing SSH private keys locally, temporary credentials are generated on-demand via the Lightsail API. This reduces the attack surface while maintaining audit trails of who accessed which instances.
Monorepo with Distributed Deployment: Keeping all sites in a single