Deploy with ease. Maintain without fear.

Your agent ships it. Alerts tell you when it breaks, logs say why, project memory keeps the context, and nothing gets deleted without your approval.

paste into any agent
Deploy this project to Gagarin Cloud and give it a public address. Follow https://gagarin.cloud/llms.txt
what happens next
  1. 01It installs gg and the Gagarin skill.
  2. 02It runs gg login and hands you a link and a code.
  3. 03You sign in with GitHub or Google, check the code matches, and approve. $5 of credit is waiting, no card.
  4. 04It ships, and tells you the HTTPS address.
your agent

Teach your agent Gagarin once.

Install the plugin, the skill or the connector, and every session after that knows the commands, the rules and the errors. Or skip it: the sentence above works in any agent.

One plugin, everything in it.

The skill, the MCP server, /gagarin:setup, /gagarin:status, /gagarin:ship, and a subagent that takes a repository to a working HTTPS URL.

/plugin marketplace add gagarin-cloud/claude-plugin
/plugin install gagarin@gagarin-cloud
/gagarin:setup

Then say what you want: “deploy this”, “add a database”, “deploy on every push”.

Whichever door it uses, your agent can ship but not destroy. Deleting anything emails you a button, every time.
how it goes

You type one sentence. Your agent does the rest.

New session
saasapi/ · web/ · worker/ · AGENTS.md

The message is typed. Press enter.

shaperunningnot okmanaged↓reaches
webweb:1788884228INTERNAL
apiapi:1788884099INTERNAL
workerworker:1788884101INTERNAL
pgPostgres 17MANAGED
50 MB of 10.5 GBbackups on

Nothing deployed yet.

Ship your project$5 credits on sign-up • card not required
why Gagarin exists

Setting up one backend on managed Kubernetes took me 22 hours. On Gagarin it takes under three.

In October, while building Gagarin, I put my other company’s production backend on a new cloud: an API, its web apps, a CMS, Postgres, object storage and the cron jobs. The code already existed. Everything around it I set up from scratch: ingress, certificates, secrets, monitoring, CI. I knew the stack well, and it still took me two days. Each mark below is one of my commits.

Viktor, founder of Gagarin

22 h 8 min of work over two days, in 84 commits
day 1
000612182410:34 The cluster is up. Now the real work starts.20:25 Monitoring and alerts, then an hour fixing them
day 2
000612182400:14 Midnight: I move the production database13:46 I delete the git server I built last night20:07 Backups, and a drill to prove they restore
  1. day 1, 10:34 The cluster is up. Now the real work starts.
  2. day 1, 20:25 Monitoring and alerts, then an hour fixing them
  3. day 2, 00:14 Midnight: I move the production database
  4. day 2, 13:46 I delete the git server I built last night
  5. day 2, 20:07 Backups, and a drill to prove they restore
cluster, ingress, TLS, storage, backupsVault, secrets, isolation between appsa CI identity per app, allowed to deploy only that appmetrics, logs, alertsmoving the apps, their cron jobs and the dataDNS, mail, a CI runner, a git server removed the next day
  1. 5 minCreate the projectgg init backend
  2. 5 minTwo Postgres databases, one for the app and one for the CMSgg resource add backend/app postgres
  3. 25 minFreeze writes, dump the old databases, restore them through a local tunnelgg connect backend/app
  4. 10 minTwo extra database users with narrow grants, in SQLby handgg connect backend/app
  5. 15 minThree buckets, then copy the objects acrossgg resource add backend/uploads s3
  6. 10 minFive sets of secrets, as external resourcesgg resource add backend/api-env external --env-file .env.api
  7. 20 minSeven services, from the images already builtgg deploy backend/api:8080 api:v41 --deps app --deps api-env
  8. 10 minTwenty cron jobs, generated from the old jobs tablegg run backend/refund-reports ether:v41 --schedule "* * * * *" --deps app
  9. 15 minA small router, because the main domain sends paths to different servicesgg deps add backend/edge api web mcp www
  10. 15 minDomains, and their DNS records at the registrarby handgg domain add backend/edge example.com
  11. 20 minCI in six repositories deploys with gg shipgg creds create --name "gitlab: api"
  12. 2 minAlerts on, with the switch in the console on each phone, then a testby handmy.gagarin.cloud → backend → alerts
  13. 10 minCheck every route and every jobgg status backend
Skip the 22 hours$5 credits on sign-up • card not required
alerts

Flip one switch, and your phone tells you what broke.

You write no alert rules and wire up no pager. Open the project in the console on your phone and turn alerts on. When a service crashes, the notification names the service and the reason, and for a memory crash it names the size to move to.

saas3cnciet6
FOR YOUonly you, not the team
YOUR DEVICESmanage →
iPhoneTHIS DEVICE
WHAT SENDS3 kinds · fixed
A service is downafter three minutes, and again when it recovers
A deploy will not startwhile the previous version keeps serving
A container crashed and restartedwith the reason, at most once an hour
Flip the switch, then break something:
logs

Your logs are already there, for you and for your agent.

Everything a service prints is kept for a week, including the containers that crashed or were replaced. You read it in the console. Your agent reads the same lines with gg logs, finds the panic, and ships the fix.

your agent
checkout is throwing 500s
Bash gg logs saas/api --grep "panic:" --since 2d
panic: runtime error: invalid memory address or nil pointer dereference
Bash gg logs saas/api --previous
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x6c2f1a]
goroutine 41 [running]:
main.(*Cart).Total(0x0)
/src/cart.go:48 +0x1a
A guest checkout has no cart, and cart.go:48 calls Total on nil. I’ll return an empty total for a guest and ship it.
Bash gg ship saas/api:8080

The latest 12 lines api printed. A week is kept, crashed and replaced containers included. Not a stream — reload to see further.

12026/10/21 14:02:11 listening on :808022026/10/21 14:03:40 GET /api/orders 200 12ms32026/10/21 14:03:41 POST /api/checkout 200 31ms42026/10/21 14:03:52 GET /api/orders 200 9ms52026/10/21 14:04:07 POST /api/checkout 500 3ms6panic: runtime error: invalid memory address or nil pointer dereference7[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x6c2f1a]8goroutine 41 [running]:9main.(*Cart).Total(0x0)10	/src/cart.go:48 +0x1a112026/10/21 14:04:09 listening on :8080122026/10/21 14:04:12 GET /api/orders 200 11ms
project memory

Your agent remembers why you built it that way.

Every project keeps a memory its agents share: decisions and their reasons, gotchas, conventions. A new session reads the briefing before it reads the code, so it stops proposing the fix you already tried and reverted. Memory costs $0.10 a month per thousand memories.

memory · saas
  • overview
  • architecture
  • decision
  • convention
  • gotcha
  • howto
  • reference
  • state
  • ★ pinned
#1#2#3#4#5#6#7 ★#8#9#10#11#12#13#14#15#16
memory_get(saas, [7])
## #7 decision · Sessions stay in Postgres, not valkey
tags: sessions, auth · pinned · importance 5 · updated 2026-10-03
valkey keeps nothing across a restart: the first one logged every user out. Sessions live in pg’s sessions table; valkey may cache in front of it, never instead of it.
↔ #12 Login reads the sessions table on every request · #15 valkey restarts during deploys · #13 valkey caches rendered invoice PDFs, nothing else · #3 api, worker and web; pg is the only store of record

#7 is a decision. Its links are lit; thicker ones have been followed more.

16 memories · 20 links$0.0016 a month in use · reading is free
agent safety

Your agent builds. Only you can take things away.

Four actions break something that is running. Each one stops and emails you a button, and no flag hands that button to an agent. One click covers fifteen minutes, so a clean-up needs one approval, not ten.

  • gg destroyDeleting a service, a database or a project
  • gg domain rmTaking an address off the internet
  • gg deps rmWithdrawing a route between two services
  • gg transferHanding a project, and its bill, to someone else
  1. 1 your agent asks
  2. 2 your inbox
  3. 3 the console
  4. 4 your agent goes on
$ gg domain rm saas/web
Taking web off the internet.
Its address stops answering. Anything holding it — a browser tab, a
webhook, another team’s configuration — breaks with it.
gg: [approval_required] taking web off the internet — https://web-3cnciet6.fr-par-1.apps.gagarin.cloud will stop answering needs human approval
hint: we emailed you@example.com — ask them to open it, sign in, and approve (code K7QX-M4PA). Then run the same command again. Expires in 15 minutes.
CI

CI with one secret and no service accounts.

One command mints a credential for your pipeline. Put it in a secret, and the workflow is five steps you can read top to bottom. No IAM role to assume, no registry policy, no cluster role binding.

  • It can deploy. It cannot destroy, and no flag turns that on.
  • It expires: 90 days by default, 365 at most, and there is no never.
  • It cannot mint another, so a leaked one cannot issue its own replacements.
  • It is shown once. Gagarin keeps a hash.
$ gg creds create --name "github actions: acme/web"
minted "github actions: acme/web" for you@example.com
can deploy
expires 19 January 2027
id 7 (gg creds revoke 7)
gg_••••••••••••••••••••••••••••
That is the only time it is shown, and Gagarin stores no copy — it keeps a hash.
If you lose it, revoke it and mint another.
.github/workflows/deploy.yml
name: deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      GAGARIN_TOKEN: ${{ secrets.GAGARIN_TOKEN }}
    steps:
      - uses: actions/checkout@v4

      - name: install gg
        run: go install github.com/gagarin-cloud/gg@latest

      - name: log docker in to the Gagarin registry
        run: gg registry login

      - name: build and publish
        run: gg build acme/web:${{ github.sha }} --push

      - name: release
        run: gg deploy acme/web:8080 web:${{ github.sha }} --env-file .env.production

      - name: say what the cluster is doing
        run: gg status acme
leaving

Leaving takes one command.

gg eject writes out the Kubernetes objects Gagarin runs for your project: the real ones, with your routes as network policies and your environments as secrets. Apply them to any cluster, move your images and your data, and you have moved in an afternoon.

  • imagesstill in Gagarin’s registry: pull them, push them where you like
  • volume datathe claims come back empty; pg_dump works the way it always has
  • cluster, domain, billingyours to sort out
$ gg eject saas -o project.yaml
Wrote project.yaml (mode 0600 — it contains your environments in the clear).
Apply it anywhere with: kubectl apply -f project.yaml
Read the header first: the images are still in Gagarin’s registry.
Third-party keys from external resources are placeholders; the header lists them.
gg eject saas --with-secrets includes them instead.
project.yaml
# saas — exported from Gagarin
#
# These are the Kubernetes objects Gagarin runs for this project: not a
# description of them, the objects themselves. Applying this to any cluster with
# an ingress controller gives you what you had.
#
#   kubectl apply -f this-file.yaml
#   …
---
kind: Namespace
metadata: { name: saas }
# --- api -------------------------------------
---
kind: NetworkPolicy
metadata: { name: api, namespace: saas }
---
kind: Secret
metadata: { name: api, namespace: saas }
---
kind: Deployment
metadata: { name: api, namespace: saas }
---
kind: Service
metadata: { name: api, namespace: saas }
# --- pg --------------------------------------
---
kind: NetworkPolicy
metadata: { name: pg, namespace: saas }
---
kind: Secret
metadata: { name: pg, namespace: saas }
---
kind: PersistentVolumeClaim
metadata: { name: pg, namespace: saas }
---
kind: Deployment
metadata: { name: pg, namespace: saas }
---
kind: Service
metadata: { name: pg, namespace: saas }
# --- web -------------------------------------
---
kind: NetworkPolicy
metadata: { name: web, namespace: saas }
---
kind: Secret
metadata: { name: web, namespace: saas }
---
kind: Deployment
metadata: { name: web, namespace: saas }
---
kind: Service
metadata: { name: web, namespace: saas }
---
kind: Ingress
metadata: { name: web, namespace: saas }
# --- worker ----------------------------------
---
kind: NetworkPolicy
metadata: { name: worker, namespace: saas }
---
kind: Secret
metadata: { name: worker, namespace: saas }
---
kind: Deployment
metadata: { name: worker, namespace: saas }
---
kind: Service
metadata: { name: worker, namespace: saas }
Sign up and ship now$5 credits on sign-up • card not required
pricing

Three numbers. No tiers.

You pay for what runs, by the minute. There is no plan to choose, no seat to buy, no bandwidth meter, and no price that appears only after a call.

$0.014per hour, per thing that runs

Any service, resource or job while it is up. Call it $10 a month for a small one. Stopped is $0.

$0.15per GB of disk, per month

Volumes and database storage. It only grows when you ask it to.

$0bandwidth, seats, support, TLS

Not discounted — not metered. Domains and certificates are part of the platform, and so is the person who answers your email.

New accounts start with $5 on the house and no card is asked for until it runs low. We warn you before the balance reaches zero; if it does, your services stop and nothing is deleted — volumes, domains and data wait for you to put money back.

The full price list, including what a typical project costs →What the price includes: the ops work you stop doing →
wanna chat?

Let’s get your project online together.

Book half an hour on a video call. Bring your code, or just your questions, and we put it on Gagarin side by side. You leave with an address; I leave with a list of what to make easier.

30 minutes with Viktorfounder of Gagarin · on a video call
  • Bring your project, or just your questions.
  • We deploy it together, and you leave with an address.
  • Anything that slowed you down goes on my list to fix.
or open cal.com/gagarin/onboarding
status

Don’t take our word for it.

This panel reads the platform’s health endpoint from your browser, right now: the same URL our monitoring watches around the clock. No credential, no status page in between.

liveness · api.gagarin.cloudchecking
check
reading
control plane
—
cluster
—
reconciler
—

Reading the platform from your browser… api.gagarin.cloud/healthz/platform needs no credential and answers 200 only when all three of the above do.

questions

The things people ask first.

So you’re like Railway?

On the surface, yes: containers, databases, domains, an agent that drives it. Most platforms cover that ground now, and most of them draw a dependency graph too. The difference is what the graph does. On every one whose documentation we have read, an edge is a variable reference, and on the private network every service can reach every other whether the line is drawn or not. Here the graph is the firewall, the credential store and the delete guard, because there is exactly one place the truth lives and everything else is derived from it.

What if we outgrow it and want our own cluster?

Some teams, as they grow, want a Kubernetes cluster they run themselves, with every knob exposed. gg eject prints the Kubernetes manifests the platform itself reconciles from, out of the same renderer, so they cannot drift from what is running. Your images were always yours, in a registry you can pull from. The long version.

What are the limits?

Each database runs as a single instance with nightly backups kept fourteen days; replication and point-in-time recovery are not part of the service, so data you cannot afford to lose a day of belongs in a second copy as well. Services run at the size you choose rather than autoscaling. One region: Paris. What we have decided never to build is public, with the reasons. That list.

Can my agent really drive it?

That is the assumption the whole thing was built on. Every error carries a stable code and a fix_hint, so an agent branches on the code instead of reading tea leaves. The agent skill is published from the same repository as the Claude Code plugin and the MCP server, and a check there runs every command it names against the released CLI. Point yours at llms.txt and it will take it from there.

Does the safety get in my way?

It gets in the way of exactly five things, and shipping is not one of them. You can deploy, migrate, roll back, add a domain, resize, and read anything, all without asking anyone. Deleting a service, destroying a resource and removing a live address are what wait on a button in your inbox, pressed while signed in as you — each of them a thing you do a handful of times a year, and each of them a thing you cannot undo.

Is my data in the EU?

Managed Kubernetes at Scaleway in fr-par, Paris. A French company, French data centres, EU law. Everything the platform holds is there — your services, your volumes, your databases, your project memory — and none of it is replicated anywhere else. The handful of companies that see any part of it, and exactly which part, are named in the privacy policy: we list them rather than saying “our providers”, because that is not something you can check.