> ## Documentation Index
> Fetch the complete documentation index at: https://orbit.nckrtl.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# database

> Run MySQL servers, create databases on them, and register, inspect, update, and destroy the mysql, pgsql, sqlite, and redis connections that Instances can attach.

A Database connection is a Gateway record with an encrypted password. The `database` family manages the records and inspects a registered database. `database:server` runs a MySQL server as a Docker Node Process and keeps its root password in the Gateway. [Database servers](/docs/reference/database-servers) describes the servers.

[Database connections](/docs/reference/database-connections) describes the driver fields, the API, inspection, and the keys that an attachment writes. Attach a connection to an Instance with [`instance:database:add`](/docs/cli/instance#orbit-instancedatabaseadd).

## Commands

| Command | Result |
| - | - |
| [`database:create`](#orbit-databasecreate) | Register an existing database, or create one on a server. |
| [`database:list`](#orbit-databaselist) | List registered connections. |
| [`database:show`](#orbit-databaseshow) | Show one connection. |
| [`database:update`](#orbit-databaseupdate) | Replace the supplied fields on one connection. |
| [`database:server:create`](#orbit-databaseservercreate) | Run a MySQL server as a Docker Node Process. |
| [`database:server:list`](#orbit-databaseserverlist) | List the servers. |
| [`database:server:show`](#orbit-databaseservershow) | Show one server. |
| [`database:server:destroy`](#orbit-databaseserverdestroy) | Remove a server that no connection uses. |
| [`database:user:create`](#orbit-databaseusercreate) | Add a user to a database on a server. |
| [`database:user:list`](#orbit-databaseuserlist) | List the users Orbit created for a connection. |
| [`database:destroy`](#orbit-databasedestroy) | Destroy one connection record. |
| [`database:query`](#orbit-databasequery) | Run one SQL statement against a registered connection. |
| [`database:tables`](#orbit-databasetables) | List tables on a registered connection. |
| [`database:schema`](#orbit-databaseschema) | Show columns for every table on a registered connection. |
| [`database:describe`](#orbit-databasedescribe) | Show columns for one table on a registered connection. |

Every command accepts `--json`, and every result includes the request ID. No output contains a password; `has_password` shows whether one is stored. `database:destroy` asks for confirmation, and the default is No. JSON and piped calls need `--force`.

## orbit database:create

Register an existing database, or create a new one on a [Database server](/docs/reference/database-servers#create-a-database-on-a-server). The Gateway encrypts the password before it writes the row.

```bash theme={"dark"}
orbit database:create <slug> --driver=DRIVER [options]
orbit database:create <slug> --server=SERVER [--instance=INSTANCE]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Lowercase kebab name of at most 63 characters. |

| Option | Meaning |
| - | - |
| `--driver=DRIVER` | `mysql`, `pgsql`, `sqlite`, or `redis`. |
| `--node=NODE` | Numeric Node ID or registered Node name to associate. The `database` role is not required. |
| `--host=HOST` | Hostname or IP address for mysql, pgsql, and redis, without userinfo or port. |
| `--port=PORT` | TCP port for mysql, pgsql, and redis. Defaults to `3306` for mysql, `5432` for pgsql, and `6379` for redis. |
| `--database=NAME` | Database name for mysql and pgsql, or the numeric database index for redis. |
| `--path=PATH` | Unix absolute sqlite path of at most 1024 characters. |
| `--username=USER` | Username. Required for mysql and pgsql. Optional for redis; omit it when the server has none. |
| `--password=SECRET` | Password. Required for mysql and pgsql. Optional for redis. |
| `--server=SERVER` | Server slug. Creates a MySQL database and user on that server. Excludes every other option except `--instance`. |
| `--instance=INSTANCE` | Numeric Instance ID. With `--server`, attaches the new database to the Instance under prefix `DB`, creates its test database, and makes the Instance its owner. |

| Driver | Required fields | Optional fields |
| - | - | - |
| `mysql` | `--host`, `--database`, `--username`, `--password` | `--node`, `--port` |
| `pgsql` | `--host`, `--database`, `--username`, `--password` | `--node`, `--port` |
| `sqlite` | `--path` | `--node`, `--username`, `--password` |
| `redis` | `--host` | `--node`, `--port`, `--database`, `--username`, `--password` |

```bash theme={"dark"}
orbit database:create app --driver=mysql --host=db.example.test --database=app --username=app --password=secret
orbit database:create local --driver=sqlite --path=/var/lib/app/database.sqlite
orbit database:create postgres --driver=pgsql --node=beast --host=10.44.0.7 --database=app --username=app --password=secret
orbit database:create cache --driver=redis --host=127.0.0.1 --database=0
orbit database:create dlf-leden --server=beast-mysql --instance=60
```

The Gateway answers `validation.failed` when a mysql, pgsql, or redis record includes `--path`, when a sqlite record includes `--host`, `--port`, or `--database`, when a redis record omits `--host`, or when the request includes an unsupported field. A duplicate slug returns `database.slug_conflict` and leaves the existing record unchanged.

Query, tables, schema, and describe refuse a redis connection with `database.driver_unsupported`. An Instance gets the stored `--host` and `--port` unchanged, also on the `--node` Node. Use an address that every Instance can reach, such as the database Node's WireGuard address.

## orbit database:list

List every registered connection ordered by slug.

```bash theme={"dark"}
orbit database:list [--json]
```

## orbit database:show

Show one connection with its driver, Node association, host, port, database, path, username, `has_password`, and the recorded user count.

```bash theme={"dark"}
orbit database:show <slug> [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug. |

## orbit database:update

Replace the supplied fields on one connection. The command requires at least one field option and accepts the same field options as `database:create`.

```bash theme={"dark"}
orbit database:update <slug> [options]
```

| Option | Meaning |
| - | - |
| `--driver=DRIVER` | `mysql`, `pgsql`, `sqlite`, or `redis`. |
| `--node=NODE` | Node ID or registered name. An empty value, `--node=`, clears the association. |
| `--host=HOST` | Hostname or IP for mysql, pgsql, and redis. |
| `--port=PORT` | TCP port for mysql, pgsql, and redis. |
| `--database=NAME` | Database name for mysql and pgsql, or the numeric database index for redis. |
| `--path=PATH` | Unix absolute sqlite path. |
| `--username=USER` | Username. |
| `--password=SECRET` | Password. |

```bash theme={"dark"}
orbit database:update app --password=rotated-secret
orbit database:update app --node=
```

Updating a record does not rewrite the keys already stored on attached Instances. Run `instance:database:add` again with the same prefix to re-project them, then `env:sync` to install them.

## orbit database:server:create

Run a MySQL server as a Docker Node Process. Orbit generates the root password and keeps it only in the Gateway.

```bash theme={"dark"}
orbit database:server:create <slug> --node=NODE [--tag=TAG] [--port=PORT] [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Lowercase kebab name of at most 63 characters. |

| Option | Meaning |
| - | - |
| `--node=NODE` | Numeric Node ID or Node name. Required. |
| `--tag=TAG` | MySQL image tag. The image is `mysql:<tag>`. Defaults to `8.4`. |
| `--port=PORT` | Port to publish on the Node's WireGuard address. Defaults to `3306`. |

```bash theme={"dark"}
orbit database:server:create beast-mysql --node=beast
```

[Database servers](/docs/reference/database-servers#create-a-server) describes the steps, retry, and errors.

## orbit database:server:list

List the servers with their slug, Node, tag, port, status, and number of databases.

```bash theme={"dark"}
orbit database:server:list [--json]
```

## orbit database:server:show

Show one server and the databases on it.

```bash theme={"dark"}
orbit database:server:show <slug> [--json]
```

## orbit database:server:destroy

Remove a server. The Gateway refuses with `database.server_in_use` while a connection points to it. It keeps the data volume.

```bash theme={"dark"}
orbit database:server:destroy <slug> [--force] [--json]
```

| Option | Meaning |
| - | - |
| `--force` | Confirm without prompting. Interactive confirmation defaults to No. A JSON or non-interactive call without `--force` returns `database.confirmation_required`. |

## orbit database:user:create

Add a user to a database on a [server](/docs/reference/database-servers#add-a-user), for example a read-only user in production.

```bash theme={"dark"}
orbit database:user:create <slug> --username=USER --password=SECRET [--read-only] [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug of a database on a server. |

| Option | Meaning |
| - | - |
| `--username=USER` | Username. A 1-32 character identifier. |
| `--password=SECRET` | Password for the new user. |
| `--read-only` | Grant only `SELECT`. Without it, the user gets all privileges on the database. |

```bash theme={"dark"}
orbit database:user:create dlf-leden --username=reporting --password=secret --read-only
```

A connection without a server returns `database.server_required`. The user of a connection on the same server returns `database.name_conflict`. Creating the same user again sets its password and privileges. The Gateway stores the password encrypted, so it can [publish it to Vaultwarden](/docs/reference/vaultwarden#database-user-passwords). No response returns it.

## orbit database:user:list

List the users Orbit created for a connection, each with its privileges and who created it.

```bash theme={"dark"}
orbit database:user:list <slug> [--json]
```

The table shows Username, Privileges, Created by, and Created. `Created by` is the calling Node's name, since the Gateway authorizes every command as a Node.

## orbit database:destroy

Destroy one connection record.

```bash theme={"dark"}
orbit database:destroy <slug> [--force] [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug. |

| Option | Meaning |
| - | - |
| `--force` | Confirm destruction without prompting. Interactive confirmation defaults to No. A JSON or non-interactive call without `--force` returns `database.confirmation_required`. Interactive decline, Ctrl-C, and EOF cancel with `input.cancelled`. |

```bash theme={"dark"}
orbit database:destroy app --force
```

<Warning>
  The Gateway answers `database.connection_attached` while any Instance still attaches the connection. Remove those attachments with `instance:database:remove` first. Destroying the record of a database on a server also drops that database and its user.
</Warning>

## orbit database:query

Run one SQL statement against a registered connection. Without `--write`, the Gateway refuses a statement whose leading verb writes. That check reads only the leading verb; see [Inspect a registered connection](/docs/reference/database-connections#inspect-a-registered-connection). The Gateway refuses SQL that is not sent against a stored slug.

```bash theme={"dark"}
orbit database:query <slug> <sql> [--write] [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug. |
| `sql` | yes | One SQL statement of at most 16384 characters. |

| Option | Meaning |
| - | - |
| `--write` | Allow a write statement. Omission returns `database.write_required` for write SQL. |

A stacked statement returns `database.sql_multiple_statements`. SQLite runs on the linked Node and returns `database.sqlite_node_required` without one. The Gateway returns at most 500 rows and sets `truncated` when more exist. `--write` is permission, not proof that rows changed.

Human output shows the write permission, the reported row count, and a truncation warning after the rows. It shows SQL null as `NULL` and an empty string as `""`. JSON keeps `write`, `row_count`, `truncated`, and the exact cell values.

```bash theme={"dark"}
orbit database:query app "SELECT id, email FROM users"
orbit database:query app "DELETE FROM users WHERE id = 1" --write
```

## orbit database:tables

List tables on a registered connection.

```bash theme={"dark"}
orbit database:tables <slug> [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug. |

```bash theme={"dark"}
orbit database:tables app
```

## orbit database:schema

Show columns for every table on a registered connection.

```bash theme={"dark"}
orbit database:schema <slug> [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug. |

```bash theme={"dark"}
orbit database:schema app
```

## orbit database:describe

Show columns for one table on a registered connection. An unknown table returns `database.table_missing`.

```bash theme={"dark"}
orbit database:describe <slug> <table> [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `slug` | yes | Connection slug. |
| `table` | yes | Table name of letters, digits, and underscores, at most 64 characters. |

```bash theme={"dark"}
orbit database:describe app users
```

## Related

* [`instance:database:add`](/docs/cli/instance#orbit-instancedatabaseadd) and [`instance:database:remove`](/docs/cli/instance#orbit-instancedatabaseremove) attach and detach a connection on one Instance.
* [Database servers](/docs/reference/database-servers) explains how a server keeps its root password.
* [`doctor --family=database_connection`](/docs/cli/doctor) reports missing, unhealthy, or mismatched attachments.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.