RDS through AWS SSM

Your RDS Instance Has No Public Endpoint.
Reach It Through AWS SSM, Without a Bastion.

AgentsRoom opens an AWS Session Manager port-forwarding session to your database and connects its SQL client through it. The session runs aws ssm start-session with the AWS-StartPortForwardingSessionToRemoteHost document, authorized by the AWS profile already configured on your machine.

The database stays in its private subnet, the security group stays closed, and nothing new gets exposed to the internet. What changes is that you can finally query it, and so can an AI coding agent, read-only.

SSM port forwarding
No public endpoint
AgentsRoom
127.0.0.1 : port picked by the OS
aws ssm start-session
AWS-StartPortForwardingSessionToRemoteHost
Managed nodei-0a1b2c3d4e5f
RDS MySQL
private subnet : 3306
Reserving a free loopback port
Loopback only, never the local networkNo inbound SSH, no public endpoint

How AgentsRoom reaches an RDS instance in a private subnet through AWS Systems Manager, without opening anything to the internet.

The setup is common enough to be boring, and painful enough to cost an afternoon. An Amazon RDS instance sits in a private subnet. It has no public endpoint. Its security group accepts traffic from the application, and from nothing else. There is no inbound SSH port anywhere in that VPC, because someone did the right thing and closed it. And now you need to look at three rows to understand a bug.

AWS Systems Manager Session Manager already solves the transport. A managed EC2 node inside the VPC can forward a local port on your machine to a third host it can reach, which is exactly what an RDS instance in a private subnet is. The document that does it is AWS-StartPortForwardingSessionToRemoteHost, and the command is aws ssm start-session. Nothing exotic, nothing to install on the database.

AgentsRoom runs that command for you and puts a SQL client on the other end. You pick the instance, the region and the profile once, you attach a database connection to it, and from then on opening that database is one click. The session is authorized by your own AWS profile or SSO login, so no key and no password are stored for the hop itself.

The Usual Ways Around It All Cost Something

Three answers to the same problem, and what each of them charges you.

A bastion host to maintain

A jump box in a public subnet is a server you patch, monitor, pay for and eventually forget. It carries an inbound SSH port, a list of authorized keys that drifts as people join and leave, and a security group that is one careless edit away from being open to the world. It exists only so someone can reach a database occasionally.

A VPN for a three-row question

A client VPN puts your whole machine inside the network to answer a question about three rows. It has to be provisioned, distributed, renewed and revoked, it fights with the rest of your connectivity, and on a laptop that moves between networks it is the piece that breaks first. Most teams that have one still keep a bastion next to it.

Credentials copied around

The alternative everyone falls back to is worse : the endpoint and the password end up in a chat message, a shared note, a script committed by accident, or a prompt sent to an AI agent. Access spreads to places nobody is tracking, and revoking it later means rotating a credential and hoping every copy is gone.

From a Private RDS Instance to a Result Set

Four steps, done once, then it is one click.

01

Save an AWS SSM connection

In the connections manager, add a connection and set its transport to AWS SSM. You give it the instance ID of a managed EC2 node that can reach the database (i-0123456789abcdef0), your AWS profile and the region. There is no password field and no key field, because the session is authorized by the AWS credentials already on your machine.

02

Add the database and reach it through that connection

Add a MySQL or MariaDB connection with the RDS endpoint as its host, the port, the user and the database. In the Reach through field, pick the AWS SSM connection you just saved instead of Direct connection. That is the entire configuration : the endpoint stays private, the security group stays closed.

03

AgentsRoom opens the session

When you open the connection, AgentsRoom asks the operating system for a free loopback port, then starts aws ssm start-session with the AWS-StartPortForwardingSessionToRemoteHost document, passing the RDS endpoint as host, the database port as portNumber and the reserved port as localPortNumber. It waits until that port actually accepts a TCP connection before declaring the tunnel ready, so the client never connects too early.

04

Query it, or let an agent query it

The SQL console connects to 127.0.0.1 on the forwarded port and behaves like any other connection : schema browser, one statement at a time, capped result sets. An AI coding agent can query the same connection over MCP, read-only, without ever receiving the password. Closing the connection kills the session process with it.

What actually runs

The command AgentsRoom spawns

There is no proprietary protocol here and nothing is reimplemented in JavaScript. AgentsRoom spawns the AWS CLI as a child process, with arguments passed directly rather than through a shell, and reads its output. If you have ever opened a port-forwarding session by hand, this is the line you already know.

aws ssm start-session \
  --target i-0a1b2c3d4e5f \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters host=acme-prod.abc123.eu-west-1.rds.amazonaws.com,\
               portNumber=3306,localPortNumber=54321 \
  --profile acme-prod --region eu-west-1

The instance ID, the endpoint, the region and the profile come from the connection you saved. The local port is chosen by the operating system at open time.

Forwarding to the managed node itself, rather than to a database behind it, is the same document with host=localhost. That is why the same connection type covers both a database in a private subnet and a service running on the instance you are connected to.

Prerequisites

What has to be true before it works

AgentsRoom drives your AWS setup, it does not replace it. Five things have to be in place, and they are the same five Session Manager needs on its own.

  • The AWS CLI on your machine

    AgentsRoom calls the aws binary directly. If aws ssm start-session works in your terminal, it works here.

  • The session-manager-plugin

    Session Manager needs its plugin installed next to the CLI. Without it, the session exits immediately and AgentsRoom shows you the error the CLI printed rather than hanging.

  • A working AWS profile or SSO login

    Authorization comes from your own credentials, passed as --profile and --region. AgentsRoom stores the profile name and the region, never a key, never a secret.

  • A managed node in the VPC

    An EC2 instance registered with Systems Manager, running the SSM Agent, with an instance profile that allows the session. It is the node the traffic passes through, and it needs no inbound port of its own.

  • A path from the node to the database

    The database security group has to accept traffic from the node on the database port, and your IAM policy has to allow ssm:StartSession with that document. Nothing else about the VPC has to change.

What the Tunnel Does, and What It Refuses to Do

The properties that decide whether this is safe to leave configured on a laptop.

Loopback only

The forwarded port is bound to 127.0.0.1 and nothing else. A database reached this way is never republished on the local network, so a coffee shop Wi-Fi does not turn your laptop into an open proxy to production.

A port picked by the OS

AgentsRoom asks the operating system for a free port and hands it to the session. There is no fixed port to guess, nothing to reserve in advance, and no collision with whatever else you are running.

Ready means ready

The tunnel resolves only once the local port actually accepts a TCP connection, and gives up with the error the CLI printed if it never does. No arbitrary sleep, no client connecting to a port that is not listening yet.

No key, no password for the hop

The SSM session is authorized by your AWS profile or SSO session. AgentsRoom stores the instance ID, the profile name and the region, and nothing that could be replayed by anyone who read that configuration.

The database stays read-only

A database connection is read-only when created. A write needs that specific connection made writable and an explicit confirmation, and a connection flagged as production says so loudly in that confirmation.

One statement per call

Each call carries exactly one statement, so nothing hides behind a semicolon, and result sets are capped so a wide query cannot flood a window or an agent context.

Why This Is Less Access, Not More

A tunnel sounds like a hole, and the reflex is right : most ways of reaching a private database do widen the attack surface. This one narrows it. Nothing is opened on the database side, no inbound port is created anywhere in the VPC, and the managed node needs no SSH listener of its own. The traffic goes out from the node to the Systems Manager service, and your machine meets it there.

Authorization stays where your organisation already manages it. The session is granted by your AWS identity, through the profile or the SSO login already configured on the machine, which means it is logged like any other Session Manager session, revoked the day that identity is revoked, and scoped by an IAM policy rather than by who happens to hold a key. AgentsRoom stores the instance ID, the profile name and the region : none of that is a credential.

On the database side the guardrails are the same ones every AgentsRoom connection gets. Read-only by default, one statement per call, capped result sets, and a production flag that hardens the write confirmation. An AI agent querying through MCP gets a result set and never the password, and the tool it queries with refuses anything but a read whatever the connection allows a human to do.

What is not supported

MySQL and MariaDB only, and PostgreSQL is not one of them

The database client speaks the MySQL wire protocol, so the engines that work are MySQL and MariaDB. On RDS that means RDS for MySQL, RDS for MariaDB and Aurora MySQL-compatible editions. RDS for PostgreSQL and Aurora PostgreSQL are not supported, and neither are SQL Server, Oracle, MongoDB or SQLite. You deserve to know that before the download rather than after it.

The SSM transport itself is engine-agnostic, since it forwards a TCP port. What is missing for PostgreSQL is the client on top of it, not the tunnel underneath. Which engine comes next is decided by what people ask for, so if yours is missing, say which one on the public backlog and it gets counted.

Request your database engine
AI agents + private databases

An agent can query it too, read-only

db_listdb_schemadb_querydb_connection_new

Once the connection exists, an AI coding agent can use it through AgentsRoom MCP by naming it. db_list returns the saved connections and their metadata, db_schema walks the schemas, tables and columns without a line of SQL, db_query runs one statement and returns capped rows, and db_connection_new proposes a database that is not saved yet by pre-filling the form you review and save.

AgentsRoom opens the SSM session itself when the agent asks, so the agent never handles an AWS credential, a database password or a port number. What travels back is a result set. db_query is read-only whatever the connection allows, and that rule lives in the desktop app rather than in the MCP process, so it holds even if the agent is talked into asking for something else.

That is the whole point of doing this properly. An agent debugging against a production replica in a private subnet reads the rows that explain the bug, and has no path to change them, no credential to leak into its context, and no way to reach that database once the app is closed.

FAQ

How do I connect to an RDS instance that has no public endpoint?

Through an AWS SSM port-forwarding session. Save an AWS SSM connection pointing at a managed EC2 node that can reach the database, then create the MySQL or MariaDB connection with the RDS endpoint as its host and pick that SSM connection in the Reach through field. AgentsRoom opens the session with aws ssm start-session and connects the SQL client to the forwarded loopback port. The database keeps no public endpoint and its security group is unchanged.

Which SSM document does AgentsRoom use?

AWS-StartPortForwardingSessionToRemoteHost, with host set to the database endpoint, portNumber set to the database port and localPortNumber set to the loopback port reserved on your machine. That document forwards through the managed node to a third host, which is exactly the case of an RDS instance in a private subnet. Forwarding to the node itself is the same document with host=localhost.

Do I still need a bastion host?

No. Session Manager replaces the jump box for this use case : the managed node needs no inbound SSH port and no public IP, the traffic leaves the node towards the Systems Manager service, and your machine joins the session from the outside. There is no key list to maintain and no public subnet to keep an eye on.

What do I need installed on my machine?

The AWS CLI and the session-manager-plugin, plus a working AWS profile or SSO login. AgentsRoom calls the aws binary directly, so if aws ssm start-session works in your terminal it works here. If the plugin is missing, the session exits immediately and AgentsRoom shows you the error the CLI printed instead of hanging on an invisible prompt.

Does AgentsRoom store an AWS key for this?

No. The session is authorized by the AWS credentials already configured on your machine, passed to the CLI as --profile and --region. AgentsRoom stores the instance ID, the profile name and the region, which are not credentials. The database password is a separate thing : it is kept in the vault encrypted through your OS keychain, and it is never returned to an AI agent.

Which local port does the tunnel use, and who can reach it?

The operating system picks a free port at open time, and the tunnel binds it to 127.0.0.1 only. Nothing on the local network can reach it, and there is no fixed port to guess. The tunnel is considered ready only once that port actually accepts a TCP connection, and it is closed with the connection.

Does this work with RDS for PostgreSQL?

No. The database client supports MySQL and MariaDB only, so on RDS that means RDS for MySQL, RDS for MariaDB and Aurora MySQL-compatible editions. RDS for PostgreSQL and Aurora PostgreSQL are not supported today, and neither are SQL Server, Oracle, MongoDB or SQLite. The SSM tunnel itself forwards a TCP port and does not care about the engine : what is missing is the client on top of it. Ask for an engine on the public backlog and it gets counted.

Can I forward to the EC2 instance itself instead of a database?

Yes. It is the same document with host=localhost, so a service listening on the managed node is reachable the same way. The same AWS SSM connection also opens a plain terminal session on that instance, which is how you run an agent CLI on a machine that has no inbound SSH port at all.

Can an AI agent query the database through the tunnel?

Yes, read-only. An agent names a saved connection through AgentsRoom MCP, the app opens the SSM session and runs the statement itself, and only the result set travels back. The agent never receives the AWS profile, the endpoint credentials or the database password, and db_query refuses anything but a read whatever that connection allows a human to do.

You may also like

Query the Database Nobody Can Reach

Download AgentsRoom, save an AWS SSM connection, point a MySQL or MariaDB database at it, and query your private RDS instance without a bastion, a VPN or a shared password.

FreeDownload

Companion app: monitor your agents on the go

Bring your own: Claude, Codex, Antigravity CLI, or other AI provider.

Get the extension
Chrome Web Store

Push bugs and requests straight to your public backlog.

A glimpse of AgentsRoom in action.

Multiple projects
Multi-provider
Multiple agents
Live status
File diff & commit
Mobile companion
Live preview
Agent teams
Browser automation
Backlog-driven dev
Prompt Library
Skills Library
View all features