Answerplane Docs
Website Open app
Data teams, administrators 6 min

Connector

Query a private database without exposing it, using an agent that runs in your own network.

Connector

Most databases worth asking questions about are not reachable from the internet. They listen on loopback, sit inside a VPC, or hide behind NAT. The Connector lets you use one anyway, without exposing it.

You run a small agent next to your database. It dials out to Answerplane over TLS and keeps that connection open. Queries travel back down it.

  • No inbound port. No firewall rule, no public database, no allowlist to maintain.
  • Your credentials stay yours. The connection string lives in the agent's configuration, inside your network. Answerplane stores only which connector and which datasource to use.
  • Read-only. The agent refuses writes before they reach your database, on top of the read-only role you give it.

Install

Create the connector in Settings → Connectors, or from the API:

bash
curl -X POST https://api.answerplane.com/api/v1/connectors \
  -H "Authorization: Bearer $ANSWERPLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"production"}'

The response contains a token, shown once. Then run this on any host that can reach your database:

bash
docker run -d --name answerplane-connector --restart unless-stopped \
  -e ANSWERPLANE_TUNNEL_URL=wss://api.answerplane.com/api/v1/connectors/tunnel \
  -e ANSWERPLANE_CONNECTOR_TOKEN=apc_your_token_here \
  -e ANSWERPLANE_DATASOURCES='{"mydb":{"dsn":"postgresql://readonly:password@localhost:5432/mydb"}}' \
  answerplane/connector:latest

That is the whole install. The connector appears as online within a few seconds, and the datasources it advertises become available when you add a database.

The image is published for linux/amd64 and linux/arm64, so it runs on ordinary servers and on Graviton or Ampere instances alike. Pin a version instead of latest if you would rather control upgrades yourself:

bash
docker pull answerplane/connector:1.0.0

Prefer not to run containers? See running without Docker below.

Prepare a read-only user

Give the agent an account that cannot change anything. For PostgreSQL:

sql
CREATE ROLE answerplane LOGIN PASSWORD 'choose-a-strong-password';
GRANT CONNECT ON DATABASE mydb TO answerplane;
GRANT USAGE ON SCHEMA public TO answerplane;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO answerplane;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO answerplane;

MySQL, SQL Server, Oracle, MongoDB and the warehouses follow the same principle: grant read, grant nothing else.

Several databases, one connector

One agent can serve many datasources. Name each one; those names are what you pick from when adding a database.

bash
-e ANSWERPLANE_DATASOURCES='{
  "billing":   {"dsn":"postgresql://readonly:[email protected]:5432/billing"},
  "analytics": {"dsn":"mysql://readonly:[email protected]:3306/analytics"},
  "events":    {"dsn":"mongodb://readonly:[email protected]:27017/events"}
}'

If a password contains characters that are awkward in a URL, pass it separately instead. Explicit fields take precedence over the DSN:

json
{"billing": {"db_type": "postgresql", "host": "10.0.0.5", "database": "billing",
             "username": "readonly", "password": "p@ss/word"}}

Supported databases

Everything Answerplane supports directly also works through a connector: PostgreSQL, MySQL and MariaDB, SQL Server, Oracle, SQLite, MongoDB, Redshift, BigQuery, Snowflake, Databricks and ClickHouse.

Settings

Variable Required Purpose
ANSWERPLANE_TUNNEL_URL yes wss://api.answerplane.com/api/v1/connectors/tunnel
ANSWERPLANE_CONNECTOR_TOKEN yes the token from enrollment
ANSWERPLANE_DATASOURCES yes JSON map of name to connection details
ANSWERPLANE_MAX_ROWS no row ceiling per query, default 50000
ANSWERPLANE_MAX_QUERY_SECONDS no query timeout ceiling, default 120
ANSWERPLANE_MAX_CONCURRENT no concurrent queries, default 8
ANSWERPLANE_LOG_LEVEL no default INFO

The agent shares your database with your own application, so the concurrency and row ceilings are deliberately conservative. Raise them only if you know the headroom is there.

Running without Docker

The agent is a normal Python process, so it runs anywhere Python 3.12+ does.

bash
git clone https://github.com/edihasaj/answerplane.git /opt/answerplane-connector
cd /opt/answerplane-connector
python3 -m venv venv
./venv/bin/pip install websockets structlog pydantic pydantic-settings \
  cryptography aiomysql tenacity asyncpg aiosqlite boto3 aioodbc

Then run ./venv/bin/python -m connector with the same environment variables, under systemd, supervisor, or whatever you already use. That is roughly a 60 MB install, and the agent idles around 40 MB resident.

On Debian and Ubuntu you also need unixodbc, even for a PostgreSQL-only host: the driver package imports the SQL Server driver eagerly, and it will not start without libodbc.so.2.

bash
sudo apt-get install -y unixodbc

If your service unit uses ProtectHome=true, add "ssl_mode": "disable" to any datasource pointing at 127.0.0.1. Otherwise the PostgreSQL client probes ~/.postgresql/ for a client certificate, the sandbox denies it, and the driver reports that as a failed connection.

Operating it

Check status in Settings → Connectors, or:

bash
curl -s https://api.answerplane.com/api/v1/connectors \
  -H "Authorization: Bearer $ANSWERPLANE_API_KEY"

Logs live in the container:

bash
docker logs -f answerplane-connector

If the connection drops, the agent reconnects on its own with backoff. Restarting it is always safe.

To upgrade, pull and recreate:

bash
docker pull answerplane/connector:latest
docker rm -f answerplane-connector
# then re-run the install command above

Revoking

Deleting a connector invalidates its token immediately and closes any live connection. The token cannot be reused; issue a new connector to reconnect.

Troubleshooting

Stays offline. Check the host can reach api.answerplane.com on 443 outbound. The agent logs the reason it could not connect.

Rejected token. Tokens are shown once at enrollment. If it was lost, create a new connector.

Queries fail with a read-only error. Expected: the agent refuses anything that is not plainly a read. If a legitimate query is being caught, rephrase it as a SELECT.

Cannot reach the database. The agent connects from wherever it runs. If it is in a container, localhost means the container, not the host. Use the host's address, or run with --network host.

Start typing to search every guide.