In short

solveiAgents runs on two Oracle Cloud VMs: an always-on ARM64 hosting the orchestrator, agents, and three vertical applications in production (MediLog, Survey, Legal), and a private NVIDIA A10 GPU, with no public IP, that powers on only on demand via an IAM Instance Principal and shuts itself down afterward. Only four managed OCI services are actually involved (IAM, VCN, Compute, Work Requests API); everything else — reverse proxy, storage, observability, backup — is self-managed containerized open-source software.

The infrastructure

Two machines, two different jobs

The entire solveiAgents platform — the orchestrator, fourteen specialized agents and, on top of them, three vertical applications already in production (MediLog, Survey, Legal) — runs on two Oracle Cloud Infrastructure (OCI) virtual machines, not one. The split isn't cosmetic: it reflects two opposite needs.

The first VPS is an Ampere ARM64 Compute instance with 24 GB of RAM, in a public VCN subnet, always on. It hosts everything that has to be able to respond at any moment: the reverse proxy, the orchestrator, the databases, and most of the agents — started and stopped on demand by an idle watcher, but on the container host hosting them, which never sleeps. The second is an NVIDIA A10 GPU, in a private subnet with no public address at all, powered on only when the compute power the ARM64 lacks is genuinely needed.

Diagram of solveiAgents' hybrid architecture on OCI: always-on public Ampere ARM64 VPS and on-demand private NVIDIA A10 GPU VPS
solveiAgents' hybrid architecture on OCI — click to enlarge

Here's how the work actually splits, in detail:

Always on · Ampere ARM64

Public VPS

  • nginx: reverse proxy and TLS for four domains (agents/medilog/survey.solvei.it + legal.solvei.it behind Nginx Proxy Manager)
  • FastAPI orchestrator + four Next.js frontends (platform, MediLog, Survey, Legal)
  • Fourteen on-demand agents + agent-call and agent-whisper, always on for video calls and transcription
  • Postgres, Redis (with AOF persistence), MinIO, Orthanc, HAPI FHIR
  • worker (arq queue) for scheduled jobs
  • Prometheus, Grafana, Loki, Tempo, Alertmanager
  • agent-blog (static Astro site) and Umami for analytics
On-demand · NVIDIA A10 GPU

Private VPS

  • No public IP address, no direct exposure to the internet
  • Reachable only from the public VPS, via the VCN's private IP
  • Powers on via an IAM Instance Principal when an agent requests heavy inference
  • Sensitive data always stays on the local Ollama LLM runner
  • An idle watcher shuts it down on its own; a hard uptime cap shuts it down regardless within a few hours
On-demand activation

What happens when an agent needs the GPU

No agent talks to OCI's APIs directly. When a task needs a model that doesn't run comfortably on the ARM64, it calls gpu_manager, or the orchestrator's equivalent service used for starting/stopping it independently of the frontends' GPU widget. Both authenticate to OCI with an Instance Principal: no API key stored anywhere — the public VM's own identity, authorized by a Dynamic Group and a dedicated IAM policy, is the credential.

On-demand activation flow
Agent
Heavy task
→
🔑 IAM
Instance Principal
→
⚡ A10 GPU
Powers on and runs inference
→
Result
Returns to the requesting agent

Once the task is done, the GPU doesn't stay on "just in case": an idle watcher shuts it down on its own after a configurable period. And if even that mechanism were to fail — an agent restart that resets an in-memory timer, a bug not yet discovered — a second, independent check, a hard uptime cap (four hours by default), shuts it down anyway.

How to think about it

The private GPU is more like a backup generator than a server: it's off most of the time, turns itself on when normal load isn't enough, and turns itself back off without anyone having to remember to do it — or pay for forgetting.

Let's clear up a misconception

What OCI actually does (and doesn't)

It's worth being precise here, because it's easy to picture a cloud infrastructure as a bundle of managed services — object storage, an API gateway, native monitoring — when in reality most of what runs on these two machines isn't an OCI service at all: it's containerized open-source software we manage ourselves. The OCI services actually involved number only four:

IAM — Instance Principal + Dynamic Group for authentication between the two VMs
VCN — public and private subnets, no complex peering
Compute — the always-on Ampere ARM64 and the on-demand A10 GPU
Work Requests API — used only to read the GPU's real uptime
What actually runs in-house

The reverse proxy is containerized nginx — not an OCI Load Balancer: a single container terminates TLS for four domains and routes by path. Object storage is self-hosted MinIO, S3-compatible — not OCI Object Storage. The blog is a static Astro site regenerated by a dedicated agent. And the entire observability stack — more on that shortly — is Prometheus, Grafana, Loki, Tempo, and Alertmanager running in containers, not OCI's native Cloud Monitoring.

The reason is simple: a single Ampere ARM64 instance is enough to run all of this comfortably, and keeping the stack open source gives us full control over data that, for the agents handling health or legal information, must never leave our infrastructure.

Network and security

Why the GPU has no public address

The private subnet isn't an implementation detail: it's the design choice that makes it acceptable to keep a machine running an LLM that processes real requests powered on, even for just a few minutes. No port is ever published to the internet on the GPU VPS; the only way to reach it is through the public VPS, over the VCN's private IP, and only with the right IAM credentials.

The same discipline applies to user authentication: Clerk, the identity provider used by every frontend, runs in production mode, with JWT verification centralized in a single shared module consumed by five different services.

Keeping it standing: observability

Logs, traces, and metrics: knowing what's happening before it becomes a problem

Centralized logs

Every agent — not just the three or four "main" ones — writes its own logs to Loki through a shared module.

Distributed traces

OpenTelemetry, exporting to Tempo, is now active on fifteen agents: every request carries a traceparent propagated from the orchestrator all the way into the agent serving it, so a slow request can be followed end to end instead of having to cross-reference logs by hand, service by service.

Metrics and alerts

Prometheus "watches" every active agent; two metrics purpose-built for supervision — agent_restarts_total and agent_up — feed a dedicated alert rule (AgentFlapping, an agent restarting more than three times in ten minutes) alongside the existing one for a circuit breaker stuck open too long. Alertmanager closes the loop: before it existed, rules only "fired" visually inside Prometheus, without notifying anyone.

Operational reporting

In practice, whoever operates the platform looks at two places. The auto-provisioned Grafana dashboard Solvei Agents Overview, with throughput, p50/p95 latency, and error rate per service. And the /monitoring panel in the frontend, with three sections: LiveSection shows in-flight requests in real time (status "classifying" → "streaming" → "completed," or "abandoned" if the client disconnected halfway through); LogViewer queries Loki by service, level, and time range without leaving the browser; DeployPanel runs git pull, build, restart, and an nginx reload as a live stream, straight from the UI.

An infrastructure isn't judged by how many managed services it runs — it's judged by how clearly you can explain what happens when something breaks.
If something breaks

Backup and disaster recovery

A daily pg_dump backup covers the entire Postgres instance — schema by schema: platform, MediLog's medical record, FHIR data, Survey, Legal, Umami. Alongside it, read-only tar archives for the binary data that doesn't live in the database: MinIO, Orthanc (DICOM studies), uploaded paper questionnaires, generated wikis, blog posts, Open WebUI data. An offsite rsync destination is available as an option, not enabled by default. A runbook (scripts/restore.sh) walks through the restore step by step — component by component, not all at once — with a dry-run mode on by default that prints the commands before actually running them.

The backup job now runs on the scheduled-job queue (more on that in the next paragraph), rather than as a direct call inside the orchestrator process: if the queue doesn't respond, the old direct path stays as a safety net — for backups, the risk of "nobody ran it" outweighs the risk of occasionally bypassing the queue.

Scheduling and resilience

What keeps everything standing when nobody's watching

A handful of mechanisms, all independent from each other, keep the platform consistent with no manual intervention:

Supervised queue (arq + Redis) — a dedicated worker service runs scheduled jobs; the daily backup was the first one migrated
State reconciler — corrects an agent's Redis state if it diverges from the real Docker state, at boot and every 60 seconds
Idle watcher — stops on-demand agents left unused, now including MediLog's medical/PHR engine too
Automatic retry and restart — a container that drops mid-stream gets restarted and the request retried exactly once
GPU watcher — idle-stop plus the independent hard uptime cap described above
What runs on top

Three vertical applications, one single platform

Everything described so far isn't an infrastructure exercise for its own sake: it's the foundation three real vertical products run on, sharing the same orchestrator, the same Postgres, the same Clerk authentication, and the same observability stack.

May 27, 2026 — MediLog

Digital medical record (PHR) — grown from patient demographics and clinical events into FHIR R4, OCR with automatic lab-value extraction, DICOM management with an OHIF viewer, patient-doctor video calls over mediasoup, and shared family profiles.

June 19, 2026 — Survey

Digitizing paper questionnaires — a hybrid OMR (optical mark recognition) pipeline plus a vision model for uncertain cases, a human-validation queue, a statistics dashboard.

July 4, 2026 — Legal

AI legal platform — a fork of an open-source project, integrated with 214 Italian legal tools via the MCP protocol (Normattiva, the Court of Cassation, the CJEU, interest and fee calculations, over a hundred document templates).

None of the three required new infrastructure from scratch: plugging in means registering a new agent in the existing registry, adding a schema to the shared Postgres, and getting everything this article described for free — logging, tracing, backups, and watchdogs included. It's probably the most concrete proof that the two-VPS architecture isn't just economically sound — it's also what lets a new vertical product get added in weeks, not months.

✦
To sum up

You don't need a huge cloud — you need an honest one

This architecture's value isn't in how many managed OCI services it uses — deliberately few — but in how clearly it separates "always on" from "on demand," and in the work that keeps both halves consistent: a log that always reaches Loki, a trace that crosses every service, a backup that runs even if the queue meant to trigger it doesn't respond, an agent that shuts itself down even when someone turned it on by hand by mistake.

This infrastructure was conceived as a "personal technology gym," but built using sound practices drawn from more than 35 years of hands-on experience 🙂 — and it could make a solid base for other kinds of projects. Sensitive data never leaves the infrastructure and only ever touches local services. Either way, to shrink the hypothetical attack surface, individual services exposed to the internet can be turned on and off through Nginx Proxy Manager (open source).

To push privacy even further, my next step is probably setting up a private email and messaging service based on open-source solutions... I'd say it's about time to stop sharing private information with Big Tech 🙂.

I hope this article is useful if you're considering a similar architecture for your own projects.