# Database networking and access

Source: https://docs.quake.ai/docs/databases/concepts/database-networking-and-access
Markdown: https://docs.quake.ai/docs/databases/concepts/database-networking-and-access.md
> How applications and administrators reach a database on a Quake AI private subnet: private addressing, security group scope, database ports, and bastion paths.

---

# Database networking and access

A database deployed from the [Self-Managed PostgreSQL](/resources/iac-templates/self-managed-postgres) or [MySQL/MariaDB Database](/resources/iac-templates/mysql-database) template has no floating IP. The instance holds a private address on a project subnet, and two kinds of traffic reach it: application connections from inside the project, and administrative sessions from outside it. The two paths have different shapes.

## Application access

An application instance on the same private network connects to the database's private address and the engine's port. Nothing routes through the internet, and no NAT translation happens in between. The connection string carries the private address:

```text
postgresql://appuser@192.168.40.12:5432/appdb
mysql://appuser@192.168.50.12:3306/appdb
```

The templates create the starting database and role from the `db_name`, `db_user`, and `db_password` variables you set at apply time. Additional users and grants are engine-level work you do after the deployment.

## Administrative access

Administrators reach the same private address through a host that already has a route into the subnet: a bastion with a floating IP, a VPN endpoint, or another instance on the network. The SSH `ProxyJump` option carries both interactive sessions and file copies through that host:

```bash
ssh -i YOUR_PRIVATE_KEY_PATH -J ubuntu@JUMP_HOST ubuntu@DB_PRIVATE_IP
```

[SSH bastion access into a private subnet](/docs/network/how-to/ssh-bastion-access) covers the bastion itself: the instance, its floating IP, its security group, and the client configuration that makes `ProxyJump` the default for the subnet.

## Security group scope

Both templates create a security group that allows the database port from the CIDRs you pass in `allowed_cidrs`, and nothing else. The variable has no default, so the access decision is explicit at apply time.

| Engine | Default port | Template variable |
| --- | --- | --- |
| PostgreSQL | `5432` | `allowed_cidrs` |
| MySQL or MariaDB | `3306` | `allowed_cidrs` |

Scope the range to the narrowest set of sources the topology allows. An application tier on its own subnet gives you a `/24` to allow instead of the whole private network. A single application instance gives you a `/32`. Security group rules are stateful, so an allow rule on the inbound port covers the response traffic; see [Security groups](/docs/network/concepts/security-groups) for rule evaluation and [How to create security group rules](/docs/network/how-to/create-security-group-rules) for the procedure.

## Engine-side binding

The security group is one of two gates. The engine has its own listener and authentication configuration, and both gates have to agree before a client connects:

- **PostgreSQL** listens on the addresses named in `listen_addresses` and authenticates per the rules in `pg_hba.conf`. A client that clears the security group still fails if no `pg_hba.conf` line matches its address, user, and database.
- **MySQL and MariaDB** bind per `bind-address`, and each account carries a host pattern. A `appuser@localhost` grant rejects a connection from the application subnet even when port `3306` is open to it.

The MySQL/MariaDB template binds the server to all interfaces and relies on the security group for network scope.

## Exposing a database publicly

Attaching a floating IP to a database instance puts the engine port on the public internet, where it faces continuous credential scanning. When an external client genuinely needs access, prefer a path that keeps the port private: a VPN into the project network, an SSH tunnel through the bastion, or an application-layer API in front of the database. If a public endpoint is unavoidable, restrict `allowed_cidrs` to the specific source addresses and require TLS at the engine.

## Verifying a connection path

Test the path in the order the packet travels: confirm the private address from the instance list, confirm the security group rule allows the source range, then open a client connection from the source host. [How to connect to a database on a private network](/docs/databases/how-to/connect-to-a-private-database) walks the sequence for both engines, including the `psql` and `mysql` commands that confirm a working session.

## Further reading

- [Self-managed relational databases](/docs/databases/concepts/self-managed-relational-databases): the resources a database deployment composes
- [Security groups](/docs/network/concepts/security-groups): stateful rule sets on instance ports
- [Networks](/docs/network/concepts/networks): project networks, subnets, and routers
- [SSH bastion access into a private subnet](/docs/network/how-to/ssh-bastion-access): the administrative path into a private database
- [Site-to-site VPN](/docs/network/how-to/site-to-site-vpn): connecting an office or another cloud to the project network
