$ aoox

DocsStacks & databases

Managed database

Create a PostgreSQL, MySQL, MariaDB, Redis, Valkey, or MongoDB database per project and connect it to an application.

Engines
PostgreSQL · MySQL · MariaDB · Redis · Valkey · MongoDB
Shape
One container + volume per database
Connect
${{database.<slug>.url}} in the application's env

Supported engines

EngineImage (default tag)PortInternal URL shape
PostgreSQLpostgres:16-alpine5432postgresql://app:pass@host:5432/<db>
MySQLmysql:83306mysql://app:pass@host:3306/<db>
MariaDBmariadb:113306mysql://app:pass@host:3306/<db>
Redisredis:7-alpine6379redis://:pass@host:6379/0
Valkeyvalkey/valkey:8-alpine6379redis://:pass@host:6379/0
MongoDBmongo:727017mongodb://app:pass@host:27017/<db>?authSource=admin

The container follows the official Docker Hub image's env vars (POSTGRES_*, MYSQL_*, MARIADB_*, --requirepass). The SQL username is always app; the database name is the slug with - replaced by _. The password is random and stored encrypted.

Valkey is a Redis drop-in (a Linux Foundation fork) — same protocol, commands, and persistence format (AOF). Backup, the data browser, and the connection URL all use the exact same path as Redis (redis:// scheme, any Redis client is compatible).
MongoDB has no CREATE DATABASE — a new database only "exists" once it holds data. aoox writes a single placeholder document (collection _aoox_init) right after the container is ready, so the primary database shows up in the collection list (Data tab) immediately instead of only after the application's first write.

PostgreSQL variants

When creating a database with Engine PostgreSQL, pick a Variant for an image with an extension preinstalled — the protocol, credentials, backups, and env references stay exactly the same as plain PostgreSQL (only the image and default tag differ). The extension is activated automatically (CREATE EXTENSION IF NOT EXISTS) as soon as the container accepts connections.

VariantImage (default tag)Use case
pgvectorpgvector/pgvector:pg16Vector similarity search for embeddings (AI/ML).
PostGISpostgis/postgis:16-3.4Geographic/spatial data types and queries.
TimescaleDBtimescale/timescaledb:latest-pg16Time-series data: hypertables, continuous aggregates.
  • No variant (default) = the plain postgres image, no extra extension.
  • Changing the variant after creation isn't supported from the dashboard — delete it and create a new one (optionally restore from a backup into the new database).
  • PostGIS and TimescaleDB already activate their own extension the first time the image starts; aoox still calls CREATE EXTENSION IF NOT EXISTS as a safety net (safe to repeat, doesn't error).

Creating a database

  1. Project page → New database

    FieldNotes
    NameBecomes a unique slug (global, not per project). Container aoox-db-<slug>, volume aoox_db_<slug>.
    EnginePick one of the cards: PostgreSQL / MySQL / MariaDB / Redis / Valkey / MongoDB. For PostgreSQL, also pick a Variant (optional): Plain / pgvector / PostGIS / TimescaleDB.
    Version (image tag)A Docker Hub tag. Blank = the default for the chosen engine and variant (shown under the field and in the table above). Examples: 17, 8.4, 7.2.
    Host portOptional. Fill it in only if you need a connection from outside Docker (a laptop, a remote server). Applications on the aoox host don't need it.
    Listens onDefaults to This server only (127.0.0.1): the database is then not reachable from the internet and you connect through an SSH tunnel (ssh -L 5432:127.0.0.1:5432 user@server). Choose Public only when it must be reachable from other machines, and close it in the provider firewall for everyone else: Docker-published ports are not filtered by ufw. It is chosen at creation and cannot be changed later (recreate the database).
    CPU / memory limitOptional; can be changed later.
  2. Wait for the running status

    1. 01creatingpull the image, create the volume & container, wait until the engine accepts a login (up to 2 minutes; changing mounts, limits or backups answers "still starting" meanwhile)
    2. 02runningready to use; credentials available
    3. 03stoppedcontainer stopped, data kept
    4. 04errorprovisioning failed — check the message

    Provisioning runs in the background (the image pull can take a while); the page refreshes automatically while it's creating.

  3. Connect it to an application

    In the application's env (same project), reference it — don't copy the password:

    Application env
    DATABASE_URL=${{database.app-db.url}}

    Deploy (or roll back) so the new application container picks up the value. Other forms (host, port, username, …) are covered in Environment variables.

No automatic injection
Creating a database doesn't automatically add env to any application. References only work for applications/stacks in the same project.

Connections

TypeHostWho can use it
Internal connectionaoox-db-<slug>Containers on the aoox network: applications, compose stacks joined to that network, jobs.
External connection<server-ip>:<host port> (only if a host port is set)Laptops, GUI clients, applications on a remote server. With "This server only" the address is 127.0.0.1 and only the server itself (or an SSH tunnel) can use it; with "Public", secure it with the provider firewall.

The Overview tab shows both, along with credentials (masked, copyable) and a ready-to-paste DATABASE_URL. Project viewers see the host, port, database, and user but never the password or the URL, and the Data tab shows table and column names without rows (Redis and Valkey: nothing, the keys are data).

Extra databases on the same server

A single PostgreSQL/MySQL/MariaDB/MongoDB container can hold several databases. On the Overview tab, next to the Connection for database selector, an owner/admin can click Add database to create a new database named [A-Za-z_][A-Za-z0-9_]*, and drop an extra database with the trash icon beside the selector (a confirmation dialog appears; everything in it is lost permanently). The one created at provisioning time is the primary one and can't be deleted. The Data tab keeps its own database selector for browsing.

Referencing an extra database from env
REPORTS_DB_URL=${{database.app-db.url:reports}}
  • The host, user, and password are the same — only the database name part differs.
  • The Overview tab shows a Connection for database per name when there's more than one. The add/drop buttons only show while the database is running.
  • Backups have an option to include every database on the server (see Backup).
  • Redis/Valkey don't have this feature (use the DB number in the URL if needed).
  • MongoDB: a new database is immediately populated with a placeholder document, same as the primary one.

Operations

ActionWhereNotes
Stop / StartDatabase panelContainer stops; data on the volume is kept. Connected applications will error until it's started again.
Resource limitsResource limits cardApplies immediately; removing a limit recreates the container (a brief restart).
Change version (tag)—Not available from the UI yet. Create a new database and restore a backup into it.
Engine configurationMount tabMount a file at a config path; the container is re-provisioned.
DeleteDatabase panelWith or without deleting the volume. The backup list is deleted too. With the volume (Delete with data) the volumes of its mounts (including stored config files) and the backup files on the server and their S3 copies are deleted as well; without it they are kept in the backups volume, no longer listed.

Other tabs

  • Data → Data browser: tables, queries, extra databases.
  • Backup → Backup & restore: manual, schedule, retention, S3.
  • Jobs → scheduled commands in the database container or a separate container from the engine image with DB_* env — Scheduled jobs.
  • Mount → engine config files (my.cnf, redis.conf) or extra volumes — Mounts.
  • CPU/RAM metrics (15-second samples) at the top of the panel.

Common pitfalls

SymptomCause & fix
Application: connection refused / ENOTFOUNDIt's using the external/localhost URL from inside a container. Use the internal URL (container name) via a reference.
400 when saving env: no database "x"The slug is wrong, or the database is in a different project.
Error status when creatingThe image tag doesn't exist on Docker Hub, or the host port is already in use. Delete and recreate.
An application on a remote server can't connectThe database always runs on the aoox host. Fill in a host port + firewall, then use the external connection in the env (without a reference).
Data missing after deletingIt was deleted with the volume purged. Restore from a downloaded/S3 backup into a new database.
Not available yet
Changing the engine version (or the PostgreSQL variant) from the UI after creation; replicas/HA; databases on a remote server; automatic env injection. For MongoDB: the query box only supports <collection>.find({...}) (read-only — no insert/update/delete/aggregate from the query box yet; use a backup restore or the application itself to write), no Structure tab/create-collection/edit-delete row yet, and extended-JSON operators like {"$oid":"..."} aren't specially interpreted in filters yet.

Next steps

Found a mistake? Edit this page on GitHub ↗