New · gea-ops · gea-hub + gea-agent, written in Go

Run your servers like a senior DevOps engineer.

One hub on one machine, one small agent on every server — added with a single line — and an API your backend calls. It installs PHP, Nginx and databases, builds Kubernetes clusters and load balancers, deploys with rollback, watches, alerts and backs up.

$149 $248 −40% Add DevOps Install guide
  • 349 ops in 33 groups
  • Linux amd64 · arm64, no database
  • Signed API, never a shell
  • Pay once, unlimited servers
How you use it

The hub once. The agent on every server, by one line.

gea-hub lives on one machine and is the only address your backend talks to. gea-agent is the part that goes on every server you want to manage — web, database, load balancer, Kubernetes node. You do not copy it there by hand: the hub hands it out.

  1. 1Set up the hub — once, on one machineCopy the package to your admin server and run deploy/setup-hub.sh with your domain. It installs gea-hub behind Nginx with HTTPS and prints the URL, app id and secret. No database.
  2. 2Give the three values to your backendURL, app id, secret — in .env. From there the backend makes its own limited keys: read-only for dashboards and AI, operate for deploys, admin for setup.
  3. 3Add every server with one linePOST /api/agents returns one command. Paste it as root on the server: it downloads gea-agent from your hub, writes the config and starts it. Nothing to copy by hand, no port to open on the server.
  4. 4Call the APIPoll the data, run ops and blueprints, receive events. The servers never get a command line from outside — only named ops with checked arguments.
Commands step by step
# 1 · on the admin server, once
sudo DOMAIN=ops.shop.vn EMAIL=ops@shop.vn \
     sh deploy/setup-hub.sh
#   GEA_OPS_URL=https://ops.shop.vn
#   GEA_OPS_APP=ops
#   GEA_OPS_SECRET=…          (shown once)

# 2 · your backend, for each server
POST /api/agents
{ "id": "web1", "profile": "full",
  "labels": { "role": "web", "env": "prod" } }
#   → install.one_line

# 3 · on that server, as root
curl -fsSL https://ops.shop.vn/install/3f9c…e1 | sudo sh
#   gea-agent: web1 → https://ops.shop.vn

Profiles: full (may install and change), standard (deploys and services), monitor (reads only). The link holds the server's token, works once and dies after 24 hours. Ubuntu or Debian with systemd, amd64 or arm64.

What it maps

One picture of everything you run.

Every agent reads its own server — Nginx sites, .env files, containers, databases, Kubernetes — and the hub joins them. Your backend draws this from GET /api/topology.

DomainsLoad balancerServersAppsDatashop.vnapi.shop.vnadmin.shop.vnlb1 · Nginx + HTTPSk8s ingressweb1 · 10.0.0.11web2 · 10.0.0.12k8s · 3 nodesShop · LaravelAPI · 6 podsAdmin · VybevMySQL · db1RedisPostgreSQL
domainload balancer / ingressserverappdatabase
What your backend handles

Each screen is one call.

ScreenCallWhat happens on the servers
Add a serverPOST /api/agentsOne line to paste on the server; the agent installs itself and reports in.
Build a serverPOST /api/blueprints/web.phpPHP-FPM, Nginx, the site, HTTPS — a plan of ops you can follow step by step, or preview with dry_run.
OverviewGET /api/overviewEvery server: CPU, RAM, disks, services down, failing checks.
MapGET /api/graph · /api/topologyDomains → load balancers → servers → apps → databases, with the connections actually seen between servers.
ImpactGET /api/impactIf this server or database stops, which apps and domains go with it.
ChartsGET /api/series · /api/capacity10-second points for 6 hours, minute points for 30 days; when a disk will be full.
Run an opPOST /api/agents/{id}/ops/{op}The agent checks allow / deny, runs it without a shell, reports progress, returns data — or a code and the fix.
Many serversPOST /api/ops/{op}The same op on a label (role=web) or a list, one batch to follow.
Deployrelease.deploy · compose.deploy · k8s.deployHealth checked; the previous version comes back by itself on failure.
Databasesdb.mysql.create · db.pg.user.createDatabases, accounts and grants; the password goes back to you once and is masked in the log.
Load balancerPUT /api/lbs/{name}Nginx + HTTPS written and tested; the pool follows servers going and coming.
BackupsPOST /api/blueprints/backup.scheduleNightly dumps and encrypted snapshots run on the server itself; an incident opens when a backup is late.
AlertsPUT /api/notify/channels · /rulesservice.down, check.fail, agent.offline, disk over 85 % — to Telegram, Slack, Discord, e-mail or your webhook.
Why is it slowdiag.collect · log.search · GET /api/timelineThe state of the server, the log lines and what changed just before.
AuditGET /api/tasks · X-Gea-UserWho ran what, on which server, when and why.
How the flows run

From an empty server to an alert on your phone.

Backendyour systemgea-hubone machineNew serverrootgea-agentweb1POST /api/agents {id: web1, profile: full}install.one_line · valid 24 hyou paste: curl …/install/… | sudo shdownloads gea-agent from the hubconfig + token + systemd · startedconnects out · metrics every 10 sinventory: sites, apps, databaseswebhook · agent.onlinethe server is empty: build itPOST /api/blueprints/web.php {agent, name, domains}plan: install PHP, Nginx · site · HTTPSwebhook · plan.done

Kubernetes: install gea-agent on a machine with kubectl and a kubeconfig for the cluster (a bastion or one node). What it may do inside the cluster is the RBAC of that kubeconfig; a refusal comes back as os_permission with the binding to create.

What it does for DevOps

The work of a DevOps team, as API calls.

Everything below is an op or an endpoint your backend calls — nobody logs in to a server.

Builds the server for you

PHP-FPM, Nginx, MySQL, PostgreSQL, MongoDB, Redis, Docker, Node.js, Python, Go — installed by an op, or a whole role by one blueprint: web.php, web.node, web.python, web.go, db.mysql, db.postgres, db.mongodb, cache.redis.

Map of everything

Domain → load balancer → server → site → app → which database, which Redis, which container, and who talks to whom. Found by itself; passwords never leave the server. Ask what breaks if one server goes down.

Metrics and history

CPU, RAM, disks, inodes, I/O, network every 10 s; services up or down; site checks with certificate days left; errors counted in logs. 30 days of history, capacity trends, what changed and when.

Alerts and incidents

Rules on events and on metrics send Telegram, Slack, Discord, e-mail or a signed webhook; an incident opens, is acknowledged, closes by itself when the value is back.

Deploys that roll back

Plain servers: releases / shared / current with a health check and the previous release back on failure. Compose, Kubernetes and Helm the same way. Progress while it runs; a running op can be cancelled.

Docker · Compose

Containers, logs, stats, exec, images, volumes, networks, builds, registries, prune — and compose up / pull / logs / deploy.

Kubernetes · Helm · k3s

Create a k3s cluster from empty servers (blueprint k8s.cluster), then nodes, drain, apply, diff, scale, autoscale, rollouts, ConfigMaps, Secrets, jobs, cert-manager, Helm releases.

Load balancers by themselves

Type the domains and the backends — IPs, host names or every server labelled role=web. HTTPS from Let's Encrypt; offline servers leave the pool and come back on their own.

Databases and backups

Create databases, accounts and grants on MySQL and PostgreSQL, accounts on MongoDB; dumps and restores; slow queries and sizes. Nightly dumps and encrypted restic backups with real restore checks, on a schedule.

Sites, apps, users, keys

Nginx sites with HTTPS, PHP / Node / Python / Go apps as systemd services, Linux users, SSH and deploy keys, cron lines, scheduled jobs that keep running when the hub is away.

Finding the cause

One op collects the state of a server at the bad moment; search logs, probe ports, read slow queries, Kafka lag and RabbitMQ queues; one timeline of events, deploys and changes.

Security

Firewall, CrowdSec bans, certificates, SSH settings, failed logins, pending updates, Trivy and Lynis. Keys limited by role, op, server and IP; a second signature the hub itself cannot forge.

When a server says no

Every refusal comes with the way to allow it.

Ops that only read are always allowed. Ops that change things must be allowed in that server's own config — the backend alone can never widen them. The answer names the file, the line and the commands:

{
  "ok": false,
  "code": "not_allowed",
  "error": "this server does not allow service.restart yet",
  "fix": {
    "file": "/etc/gea-ops/agent.json",
    "key": "allow", "add": ["service.restart"],
    "commands": [
      "sudo nano /etc/gea-ops/agent.json",
      "sudo systemctl restart gea-agent"
    ]
  }
}

Same for a missing tool (with its install commands), a stopped Docker daemon, a path outside the allowed folders, cluster RBAC, a database login, a timeout.

Load balancer in one call

Domains in, servers mapped, HTTPS on.

$ops->saveLb('shop', [
  'nodes'    => ['lb1'],
  'domains'  => ['shop.vn', 'www.shop.vn'],
  'backends' => [
    'labels' => ['role' => 'web'],
    'addrs'  => ['10.0.0.30 backup'],
  ],
  'tls' => true, 'email' => 'ops@shop.vn',
]);

The hub finds each server's address, writes the Nginx config, tests it before reloading, gets the certificate, and keeps the pool right as servers come and go.

The op catalog
system.*service.*pkg.*stack.*site.*app.*release.*user.*key.*cron.*job.*firewall.*security.*cert.*nginx.*apache.*haproxy.*lb.*file.*log.*net.*diag.*backup.*db.*kafka.*rabbitmq.*git.*docker.*compose.*k8s.*k3s.*helm.*agent.*

349 ops in 33 groups, 195 of them change something and must be allowed on the server. Every op has a name, typed arguments, a timeout and a description; GET /api/catalog lists them, API.md documents them, and your backend can draw its forms from them.

In the package
  • gea-hub · gea-agentLinux amd64 and arm64, with checksums and the Go source
  • deploy/setup-hub.shthe hub in one command
  • README.mdinstall, upgrade, what was tested
  • API.mdevery endpoint, key and op, with recipes
  • openapi.json · api.jsonthe same, for machines and AI
  • php/GeaOps.phpa ready client for PHP backends
Commands step by step
The API your backend calls
  • POST /api/agentsadd a server → the one-line install
  • POST /api/blueprints/{name}build a whole role: web, database, cluster
  • POST /api/agents/{id}/ops/{op}run any of the 349 ops
  • POST /api/plansseveral ops in order, results passed on
  • GET /api/graph · /api/impactwhat exists, what depends on what
  • GET /api/overview · /api/serieslive numbers and history for charts
  • GET /api/events · /api/timelinewhat happened, plus a signed webhook
  • PUT /api/notify/rules/{name}who is told about what
  • PUT /api/lbs/{name}create a load balancer
  • POST /api/keyslimited keys for each part of your system
  • GET /openapi.json · /api/catalogthe whole API, machine-readable

75 endpoints in all. Every request is signed with HMAC; every answer is JSON; every error has a code and a fix.

Honest limits: the installers are for Ubuntu and Debian (no RHEL / CentOS yet); Kafka and RabbitMQ are read-only; there is no request tracing and no cloud-provider API or cost data; connections between servers are sampled every 5 minutes, not continuously; the hub runs on one machine — back up /var/lib/gea-hub.

Pricing

Pay once. Ship for as long as you want.

From $59, lifetime. Free updates. Unlimited projects on your own server.