Skip to content

Cloud terminal and hosting estate

1. Current estate and costs

Where What runs there Cost
AWS Lightsail WordPress (2 GB, 2 vCPU, Mumbai) — one server Production WordPress (moneymarche.com), staging WordPress (staging.moneymarche.com), development WordPress, API production (port 5000) and API staging (5001), Mautic, SuiteCRM, MM-Cron (root cron, daily NAV at 04:00) 13.69 USD a month (September)
AWS snapshots Lightsail manual and automatic snapshots; one EC2 snapshot 11.79 (September); the #72 clean-up was done (Atul, 11 Oct), saving ≈ 5–10
AWS other S3, Secrets Manager, Lambda, SNS, CloudWatch ≈ 0
GST — 3.88
AWS total (September) ≈ 25.50 USD a month
Bluehost shared hosting (cPanel, sh008.webhostingservices.com), renewed Jun 2026 (≈ 2.75 years paid) Company email (A-34); MMCLONE engineering clone (WordPress 7.1.2, Elementor); a /moneymarche install on a temporary domain; WPDev (wpdev.moneymarche.com, per the local register) Payments of 21,197.52 on 6 Jun 2026 and 26 Jun 2023, and 12,701.52 on 7 Jun 2020 (Bluehost India account; shown with a $ sign but almost certainly rupees) ≈ ₹7,066 a year ≈ ₹589 a month. The June 2026 payment suggests a term to about June 2029; Atul's note says 2 years remain (to reconcile)
GitHub, GitLab Free plans 0

Budget freed (Atul, 11 Oct): the snapshot clean-up (≈ USD 5–10 a month) and the Copilot subscription.

2. The main finding: no separation between production and everything else

Production, staging, development, both APIs, the CRM, marketing automation and the crons share one 2 GB server. Consequences: - Load: a staging test, a cron run or Mautic can starve production. TEA issue #24 already covers an audit after the 23 Sep incident. - Safety: a mistake in staging or development runs on the production host, with production's credentials within reach. - Change: nothing can be tested on an environment that matches production without touching the production host. - Backups: snapshots cover the whole server, so restoring staging also means restoring production.

Separating staging from production is worth more than any agent tooling. The new machine should serve both purposes where that's safe.

3. What a cloud terminal box would do

A box for MMDEP tools, Linux, always on:

Function How Gain
Terminal-mode agents Claude Code CLI (one-year setup-token, or an API key), Codex CLI (API key), Gemini CLI and API scripts (paid project), git with gh and glab under agent accounts Unattended work independent of the laptop (A-17)
A GitLab runner (self-managed, Docker executor, registered to our groups) GitLab CI jobs run on our box Runners we host don't use GitLab's 400 compute minutes (A-25); tests and staging deploys no longer compete for minutes
A GitHub self-hosted runner (optional) Heavy MCL jobs or tests Free per GitHub's billing page (A-05; a fee is reported elsewhere, so check)
Test execution pytest, Python reports (Portfolio Engine), headless Selenium against staging and WPDev Portfolio Engine's main need, plus website regression tests
TEA collectors Read-only AWS CLI profile; read-only SSH with forced commands Audits on schedule, deterministic evidence
Staging deploys GitLab pipelines deploy to staging from the runner Production deploys stay manual and run by a person (spec §15.6–15.7)

What it must not hold: production credentials, deploy keys for production, client data, or AWS write access.

4. Options

Option What Monthly cost (before GST) Separation Effort
A. Tools box only Lightsail Linux 4 GB for §3; the production server unchanged +24 Agents leave the laptop; production still shared Low
B. Tools box + staging moved to Bluehost A, plus WordPress staging and development moved to Bluehost (prepaid; already hosts MMCLONE and WPDev) +24 WordPress staging is off production. API staging stays on the production server: shared hosting doesn't suit Python services Medium (one migration)
C. Tools box + separate staging box A, plus Lightsail Linux 2 GB for WordPress and API staging with sanitised data +36 Full staging separation Medium
D. One 8 GB box for tools and staging Tools and staging on one Lightsail 8 GB +44 Staging separated, but agents share a host with staging data Medium; agent access to staging data needs strict isolation
E. Upgrade the production server to 4 GB Production server 2 → 4 GB +12 No separation; only relieves load Low
✗ Oracle Cloud free tier Free Arm VM 0 — Not recommended: Oracle cut the free allowance in June 2026 (4 cores and 24 GB → 2 and 12) without notice; another vendor to run
✗ Other cheap VPS vendors e.g. European providers lower — Another vendor and account to manage (Atul's effort rule); no gain big enough

5. Recommendation

Revised timing (Atul, 11 Oct): decide now and set the box up before 16 Oct, so work continues during the vacation.

  1. Option A now: a Lightsail Linux 4 GB tools box in Mumbai (≈ USD 28 with GST), as DR-003's B2 with its approve item. It hosts the terminal agents, the GitLab runner (ending the minutes problem) and test execution. That's mostly paid for by the freed snapshot and Copilot budget.
  2. Then option B for WordPress: move staging and development WordPress to Bluehost, which is prepaid and already runs MMCLONE and WPDev. Production loses its two WordPress siblings at no extra cost. API staging stays on the production server for now.
  3. Decide C or E from evidence: TEA's health audit (#24) and a month of the tools box's measurements show whether production needs its own room (E) or API staging needs to leave as well (C).
  4. Bluehost: keep it for the remaining two years (prepaid) for WPDev, MMCLONE, and WordPress staging and development. Decide at renewal whether to retire it or use it for spec §15B phase 2 (a stateless MCP endpoint on its own subdomain).
  5. Stay with AWS and Bluehost: two vendors are enough. More vendors add accounts, bills and security work that cost more than they save at our size.

6. What stays on Atul's machine (part 3, to discuss)

  • Browser mode with Atul's sign-ins: Claude in Chrome; ChatGPT; the Opera connector for WPDev's visual tests; reading GitLab and AWS consoles.
  • The MMDEP hub (Windows-specific) until it's either ported to Linux or hosted.
  • Interactive Claude Code sessions and Windows-only tests.
  • Proprietary material Atul keeps local.

7. Security on the tools box

  • A separate Linux user for agents, no sudo.
  • Docker executor for runner jobs, so each job runs in its own container.
  • Agent accounts only (GitLab Developer; a GitHub machine account); tokens scoped to the repos.
  • Staging credentials only, from runner variables marked protected and masked.
  • Lightsail firewall: SSH only, by key, from Atul's IP or the Lightsail console.
  • Unattended security updates, nightly snapshots, a monthly cost alarm.
  • A kill switch: stop the runner service and set MCL_ENABLED=false.

8. New assumptions (to add to the register)

ID Assumption Source Conf.
A-23 One 2 GB Lightsail server hosts production, staging and development WordPress, API production and staging, Mautic, SuiteCRM and MM-Cron TEA master index (reconciled 20 Sep) V (dated)
A-24 Bluehost is shared cPanel hosting (prepaid, 2 years left) running MMCLONE and WPDev Governance issue #29; local register V / Atul
A-25 GitLab compute minutes apply only to GitLab-hosted runners; self-managed runners on our box don't consume them GitLab compute-minutes documentation (not fetched today: the docs redirected to sign-in) S
A-26 Oracle's free tier was reduced in June 2026 and can change without notice InfoQ, Jul 2026 S
A-27 Staging has its own database; it may depend on the API database, as found when production was copied to MMCLONE Atul, 11 Oct Atul; the API dependency to be mapped before staging moves or agents use it

8a. Decisions of 11 Oct (Atul)

  • Decide the server early so it works during the vacation.
  • Move Portfolio Engine's development deployment from Bluehost to AWS (the tools box) this week. Today it deploys from GitHub Actions over SSH to /home1/arevalif/portfolio-engine on Bluehost, as immutable releases with a separate snapshot cache. The same layout moves to the tools box; the app reads only its snapshot cache, which is built from public market data.
  • Bluehost was renewed in June 2026 (≈ 2.75 years paid): keep using it, for WPDev, MMCLONE and, later, staging WordPress.
  • The staging dependency check is done by copying staging to Bluehost first and fixing what breaks.

8b. GitLab runner: switching and control (Atul, 11 Oct)

Switching is reversible at any time: - Per project or group, Settings → CI/CD → Runners: turn GitLab's instance runners on or off, and enable or pause our own runners. - Jobs choose runners by tags in .gitlab-ci.yml. The same job can be pointed back at GitLab's runners by changing a tag or a setting. - Several runners can be registered (tools box, laptop), each paused or resumed from the GitLab UI.

Keeping pipelines from choking the machine:

Control Where Setting
Jobs at once Runner config.toml concurrent = 1 (raise only with evidence)
CPU and memory per job Docker executor cpus = "1.5", memory = "2g" (leaves room for agents)
Maximum job time Runner maximum_timeout, project CI timeout e.g. 30 minutes
Which pipelines run .gitlab-ci.yml rules MRs and protected branches only; no scheduled pipelines unless approved
Serialise heavy jobs resource_group Test suites and deploys never run in parallel
Untrusted code Protected runner (runs only on protected branches) or tags required MR code from agents runs in a container, without production secrets
Untagged jobs Runner setting Off: only jobs that ask for our runner by tag land on it

Transfer between groups (Atul's experience, A-31): a fallback only. Own runners remove the need. A transfer also changes URLs and remotes, and group-level CI variables, runners and labels don't move with the project.

Mirroring (A-09 changed): GitLab's mirroring has restrictions, so Claude's read-only view of GitLab code comes from our own scheduled job: fetch with a read token, push to a private GitHub mirror.

8c. Headless Chrome in a container (evaluated 11 Oct; not high priority)

Usable, and a good fit, started per job rather than kept running.

Use How Value
Selenium tests for production (read-only checks), WPDev and staging Official Selenium image (selenium/standalone-chrome) as a GitLab CI service container next to the test job; the existing Selenium suite points at it WPDev's tests no longer need the laptop and Opera; same Selenium version as production's tests
Agent browser testing Playwright (official image) or a Playwright MCP server for terminal agents (Claude Code, Codex), headless Agents check pages they change, take screenshots for the Work Result
Visual and performance checks Screenshots per release (visual diffs); Lighthouse for performance and SEO Evidence for website releases; regressions caught before Atul looks
Synthetic journeys A scheduled job runs key user journeys (search, compare page, forms in test mode) Early warning of a broken site
Report rendering HTML → PDF for Portfolio Engine reports Server-side, repeatable
MM-Cron sources that need JavaScript Only where no official download exists; respect site terms A last resort; the repair agent prefers files

Not for: Atul's signed-in browsing (Claude in Chrome stays on his machine), consoles that have APIs (GitLab, AWS: use APIs), or the ChatGPT web app (OpenAI's terms; A-12).

Resources: one Chrome session uses roughly 0.3–1 GB, plus shared memory (--shm-size=2g recommended for the Selenium image). On the 4 GB box: one browser at a time, capped at about 1.5 GB, consistent with concurrent = 1. Started per job, so it uses nothing when idle. Several parallel browsers would need the 8 GB box.

Security: - Containers with outbound network only; no host network. - Test accounts only; no real credentials in the browser. - Pinned image versions, updated monthly. - Screenshots of client-facing pages must not contain client data (test accounts only).

8d. A persistent browser on the server, viewed through a web page (Atul, 11 Oct)

Verified (11 Oct): - A browser desktop streamed to a web page: for example the linuxserver/chromium image. It serves the Chromium desktop on a web port (3000), protected by a username and password. - A persistent profile (bookmarks, cookies, extensions, open sessions) kept in a volume (/config) across restarts. - The Selenium image also offers a web view of its browser (port 7900), for watching tests. - Extensions: they run in a normal (headed) browser on a virtual display, as in these images. Chrome's "new headless" mode, which is regular Chrome since version 112, also loads extensions according to Playwright's documentation. To test with the build we choose.

What it enables: - Browser-mode work continues while the laptop is off or travelling. That includes Claude in Chrome installed in the server browser, so the reviewer chat could read GitLab or check WPDev pages from the server. - Anyone Atul allows can watch or take over the session from any browser.

Resources (estimates, A-32):

State Memory CPU
Desktop and browser idle ≈ 0.5–0.7 GB ≈ 0
5–10 ordinary tabs ≈ 1.5–3 GB Bursts on JavaScript-heavy pages
While someone watches the stream + encoding ≈ 0.2–0.5 core; 1–5 Mbit/s bandwidth

A browser that stays open all the time doesn't fit well on the 4 GB box next to the agents and runner jobs. It fits on the 8 GB box (USD 44 a month, ≈ 52 with GST). Lightsail can move from 4 GB to 8 GB later by restoring a snapshot to the bigger plan and reattaching the static IP.

Security: the main cost of this idea. A signed-in browser on a server is a valuable target. - The web view is never open to the internet: reach it only through an SSH tunnel, or firewall it to Atul's IP, with a strong password. - Separate identities where possible: the server browser signs in with agent accounts (GitLab Developer, a GitHub machine account), not Atul's owner accounts, and never the AWS root console or banking. - A separate container and Linux user from the runner jobs; the profile volume included in snapshots, which are encrypted by Lightsail. - Claude in Chrome on the server uses Atul's Claude allowance like any other session (MCL §7 applies).

8e. Test first on a trial (Atul, 11 Oct): the browser decision is parked

Trial options (checked 11 Oct):

Option What you get Fit
Lightsail 3 months free, existing account "Select bundles", one bundle per account, only for accounts that started Lightsail on or after 8 Jul 2021 Probably not available: the account has run Lightsail for years, and its first bundle would have used the offer. Check in the console
A new AWS account on the free plan USD 100 credits at sign-up, up to 200 by using services (EC2 among them); ends after 6 months or when the credits run out; some services only on the paid plan Recommended. Same vendor; a separate account from production, which is good practice for a tools box anyway; if the test works, upgrade the same account to paid and keep it, with nothing to migrate. 6 months of a 4 GB EC2 instance, or about 3 months of 8 GB, fits within the credits (estimate)
Google Cloud free trial USD 300 for 90 days; only if never a paying Google Cloud or Firebase customer; no GPUs or quota increases during the trial; Mumbai region available Good for a pure test, but a second vendor. Careful: enabling paid billing for Gemini first would end the trial eligibility, so decide the order
Azure free account Credits for 30 days Too short

Plan: 1. Atul creates a new AWS account on the free plan (a company email address; MFA on the root user; never used day to day). 2. Run the tools box test there for 2–3 weeks: agents, GitLab runner, headless Chrome jobs, and the server browser pilot (parked decision). 3. Measure memory, CPU and usage (A-32), then decide: keep it (upgrade to paid), resize, or drop. 4. Only after the test: Portfolio Engine's deployment moves for good.

9. Set-up before 16 Oct (if approved)

Day Step Who
12 Oct Approve; create the Lightsail Linux 4 GB instance in Mumbai with a static IP; firewall SSH only; create the agent accounts (GitHub machine account, GitLab Developer) Atul (console steps; purchases stay with Atul)
12–13 Oct Set-up script: agent user, Docker, GitLab runner (Docker executor), Python, gh/glab, Claude Code, Codex and Gemini CLIs; snapshots and a cost alarm Claude Code writes the script (story TB-1 [H], approve item); Atul runs it
13–14 Oct Register the runner to one GitLab group; dry run: Portfolio Engine tests and one Selenium run against staging Claude Code, then Atul checks
15 Oct Atul confirms; the box runs during the vacation (tests, runner, repair agent prototype later) Atul

The WordPress staging move to Bluehost (option B) waits until after the vacation, once the API dependency (A-27) is mapped.

10. Questions for Atul

  1. Bluehost: which plan, and its yearly cost? Is WPDev running there?
  2. Is the #72 snapshot clean-up done? How much did Copilot cost per month?
  3. Does staging hold copies of production data (A-27)?
  4. Agree with A (tools box) then B (WordPress staging to Bluehost)?