All updates

Volumes, Templates & Databases

Persistent volumes, one-click templates, managed databases, and a batch of quality-of-life improvements.

What's New

This release brings three major features — templates for one-click multi-service deployments, managed databases for PostgreSQL, Redis, MySQL, and MongoDB, and persistent volumes for durable block storage — along with a batch of improvements across the dashboard.

Templates

Templates let you deploy pre-configured multi-service stacks with a single click. Browse the template catalog, configure any variables (passwords, ports, resource limits), and deploy — all services are created and wired together automatically.

Templates are available from the project canvas (right-click → Template) or from the deploy page at ml.ink/deploy. Your agent can also deploy templates via the CLI:

terminal
$ ink template deploy grafana-prometheus-loki-tempo --name my-observability
✓ Template deployed: my-observability
Services grafana, prometheus, loki, tempo
Status ● building
URLs grafana.ml.ink, prometheus.ml.ink, loki.ml.ink, tempo.ml.ink

We're adding more templates every week — observability stacks, CMS platforms, API gateways, and more. If you have a stack you'd like to see, let us know.

Managed Databases

Deploy managed databases with one click — no Dockerfiles, no configuration files, no connection string wrangling. Pick an engine, give it a name, and it's running with persistent storage and auto-injected credentials.

Supported engines: PostgreSQL 17, Redis 7, MySQL 8, and MongoDB 7. Each database gets a durable volume that survives restarts and redeploys. Connection strings and auth tokens are automatically set as environment variables, so your application code connects instantly.

Your agent can deploy databases the same way — via CLI or MCP:

terminal
$ ink template deploy postgres --name my-postgres
✓ Template deployed: my-postgres
Services postgres-a7x
Status ● building
URL postgres-a7x.ml.ink
Volume 25 GB mounted at /data
Env vars POSTGRES_PASSWORD (auto-generated)

Persistent Volumes

Attach durable block storage to any service. Data persists across restarts, redeploys, and scaling events — your databases and stateful workloads never lose a byte.

  • Configurable size — choose the right amount of durable block storage per volume
  • Custom mount paths — mount anywhere inside your container
  • Works with everything — databases, app services, any workload
  • Per-minute billing — pay only while the volume exists

Under the hood, volumes are backed by Ceph — a distributed storage system originally developed at CERN to handle the data firehose from the Large Hadron Collider, the most complex machine ever built by humans. When you need to store and replicate petabytes of particle collision data across thousands of nodes, you build storage infrastructure that doesn't lose bytes. That same technology now backs your volumes on Ink: data is replicated across multiple nodes in the cluster, so if a node goes down, Ceph serves your data from another replica without interruption.

Storage
Persistent Volume
terminal
$ ink deploy my-api --repo acme/api --volume-mount-path /data --volume-size-gi 25
✓ Service created: my-api
Status ● building
URL https://my-api.ml.ink
Volume 25 GB mounted at /data

Non-root Container Support

Most container images default to running as root (UID 0), which is convenient but means a container escape could give an attacker root on the host. The INK_RUN_AS_USER environment variable lets you lock that down — set it to any non-negative UID and your container process runs under that identity instead of root.

INK_RUN_AS_USER=1000

How it works under the hood

When you set INK_RUN_AS_USER, Ink configures the Kubernetes Pod SecurityContext with runAsUser set to your specified UID. The container process starts as that user regardless of what the Dockerfile's USER directive says.

For volume-backed services running as a non-root user, Ink also sets the Pod's fsGroup to match your UID with a change policy of OnRootMismatch. This tells Kubernetes to recursively update the group ownership of mounted volume paths so your non-root process can read and write them — no init containers, no manual chown, no permission-denied errors on first boot.

If you're running as root (UID 0), fsGroup is intentionally left unset since root already has full filesystem access.

Priority and overrides

There are three sources for the runtime user, evaluated in order:

  1. Template explicit — the template YAML declares a runAsUser (e.g. Postgres images that ship as UID 999). This cannot be overridden by the environment variable.
  2. Template default — for volume-backed templates, Ink defaults to UID 0 so existing images work out of the box. Also cannot be overridden via env var.
  3. Env explicit — you set INK_RUN_AS_USER in the service environment. This is the one you control for custom deployments.

If your service is created from a template that manages the runtime user, setting INK_RUN_AS_USER will return an error asking you to update the template configuration instead. This prevents accidental permission mismatches between what the image expects and what the container runs as.

Validation

The value must be a non-negative integer — Ink validates this at deploy time and returns a clear error if the value is empty, non-numeric, or negative. The last occurrence wins if you accidentally set it twice.

terminal
$ ink deploy my-api --repo acme/api --env INK_RUN_AS_USER=1000 --volume-mount-path /data --volume-size-gi 10
✓ Service created: my-api
Runtime user 1000
fsGroup 1000 (OnRootMismatch)
Volume 10 GB mounted at /data
Status ● building

Other Improvements

Redeploy button

Redeploy any service from the dashboard with one click — no need to push a new commit or touch the CLI.

Project canvas groups

Organize services into visual groups on the project canvas. Each group has a color, icon, and label — drag services between groups, or use URL icons to match your project's branding.

Frontend
web-appjust now
256Mi0.25 vCPU
docs-sitejust now
128Mi0.1 vCPU
Backend
apijust now
512Mi0.5 vCPU
postgresjust now
512Mi0.5 vCPU
Disk 1 · 25 GB · /data

Auto-loading logs

Scrolling up in the log viewer automatically fetches older entries while preserving your scroll position. No more clicking "load more" — just scroll.

Continuous CPU slider

Set any vCPU value instead of discrete steps — the backend now accepts fractional values like 0.3 or 1.7 vCPU.

Pro plan limits increased

Pro plan services now support up to 8 vCPU and 16 GB memory per service.

Disk usage charts

Services with volumes now show real-time disk usage in the metrics tab, with the volume capacity shown as a labeled reference line.

1H6H7D30D
postgres-a7x
Disk Usage

2.6GB / 10 GB

Static builder

New build option to serve static sites directly with nginx — no Node.js runtime needed.

Pricing interval toggle

Switch between monthly and yearly pricing on the pricing page.

What's Next

GPU support, more templates, and team collaboration features are in the pipeline. Follow this changelog to stay up to date.