On-Premise Data Gateway

The on-premise gateway lets the SQL Database Reader query your database without exposing a database port to the internet, and without Qlar storing your database credentials.

You run a small open-source program next to your database. It makes outbound HTTPS calls to Qlar asking whether there is a query to run, runs it read-only, and sends the rows back. Nothing connects in.


Direct connection vs. on-premise gateway

You choose between the two on the first step of the plugin setup. Both answer the same questions with the same data; they differ in what your network has to allow and in what Qlar ends up holding.

Direct connectionOn-premise gateway
Database port reachable from QlarRequiredNot required
Inbound firewall ruleRequiredNone
Public DNS name or TLS certificate on your sideSometimesNone
Database credentials held by QlarYesNo โ€” they stay on your machine
Record of every query in your own systemsNoYes โ€” local audit log
Table allow-list under your controlIn the Qlar UIAlso in your own config file
Setup effortLowerOne program to install and keep running

Choose the gateway when your security team will not open a database port, or when credentials leaving your environment is the objection. Choose direct when neither is a concern โ€” it is fewer moving parts.


What the gateway protects, and what it does not

Worth being precise about, because an overstated control is worse than none.

It does protect:

  • Network exposure. No inbound rule, no listening socket, nothing of yours reachable from the internet.
  • Your credentials. They live only in the gateway's own configuration file. Qlar never receives them and has no way to read them.
  • What may be executed. The gateway parses every statement and accepts exactly one read, refuses the file, shell and network escape hatches its dialect offers, and runs everything in a read-only transaction enforced by your database.
  • Visibility. Every statement is written to a local audit log with the agent, user and conversation that caused it. The file is yours and nothing in the protocol can switch it off.

It does not protect:

  • Query results still reach Qlar and the AI model. That is what the feature is for. Columns that must never leave your environment should not be in the allow-list.
  • Anything an approved gateway is allowed to read, if Qlar itself were compromised. Your allow-list bounds that; your audit log reveals it.
  • Access to the machine. Anyone who can read the gateway's .env has your database credentials, exactly as with any application config.

Before you start

  • A machine on your network that can reach the database and make outbound HTTPS calls.
  • Docker, or Python 3.11+.
  • A database account with SELECT on the tables the agent needs, and nothing more. The gateway always opens read-only transactions, but a read-only account is the guarantee that does not depend on software being correct.

Setting it up

1. Choose the gateway

In the plugin setup, on How should Qlar reach your database?, pick On-premise gateway. The Connection step is replaced by a Gateway step, which never asks for a host, username or password.

2. Get a one-time enrolment code

Click Connect a new gateway. Qlar shows a code such as K7P4-9WQX-2MTD, together with the commands to run โ€” including the two lines that tell the gateway where to send that code.

The code is single use and expires after 15 minutes. Qlar stores only a hash of it, so it cannot be shown again โ€” copy it before you leave the page. If you lose it, create a new one.

3. Install and configure

Download the gateway from github.com/pusakaai/data-gateway and create a .env next to it:

# Both of these come from the panel that showed you the code. QLAR_BASE_URL is the API
# endpoint, which is not the address of the Qlar web interface: that one serves a website,
# and a gateway pointed at it fails to enrol.
QLAR_BASE_URL=https://your-qlar-endpoint/api/data-gateway
QLAR_ENROLLMENT_CODE=K7P4-9WQX-2MTD

DB_PROVIDER=postgresql
DB_HOST=db.internal
DB_PORT=5432
DB_NAME=warehouse
DB_USER=qlar_readonly
DB_PASSWORD=...

Check the database before involving Qlar at all:

docker run --rm --env-file .env -v "$PWD/state:/state" \
  ghcr.io/pusakaai/data-gateway:0.2.0 test-db

4. Start it

One command. enroll registers this machine, waits to be approved, and then starts serving โ€” there is nothing to come back and run afterwards.

docker run -d --name qlar-gateway --restart unless-stopped \
  --env-file .env -v "$PWD/state:/state" \
  ghcr.io/pusakaai/data-gateway:0.2.0 enroll

docker logs -f qlar-gateway

The gateway generates its own key pair โ€” the private half is written to gateway-key.pem and never leaves your machine โ€” registers only the public half, and prints a fingerprint to the log:

3A:7F:19:C4:...:C2

enrolled, waiting for approval in Qlar. Compare the key fingerprint above with the one
the CMS shows and click Approve; this starts working on its own, nothing else to run here.

Stopping docker logs does not stop the gateway, and running that same docker run line again after a restart re-uses the enrolment it already has rather than trying to redeem a code that was spent the first time.

5. Approve the fingerprint

Qlar now shows a card with the hostname that registered and the same fingerprint. Compare the two strings character for character, and approve only if they match.

This is the step that matters. Enrolling grants nothing on its own: until a person approves the fingerprint, the gateway receives no queries at all. It is what makes a leaked enrolment code useless โ€” whoever stole it would also have to get you to approve a fingerprint you have never seen.

If the fingerprint does not match what your machine printed, do not approve it. Cancel and issue a new code.

There is no step 6. Within a few seconds of the click the log says approved. Serving queries for ..., the gateway shows as online in Qlar, and you continue to configuring tables and columns exactly as with a direct connection.

Notice that no command on this page publishes a port. That is the point.


Set TABLE_ALLOWLIST in the gateway's .env to the tables the agent may read:

TABLE_ALLOWLIST=public.shipment_order,public.hub,public.customer

This list lives on your premises, so no change on Qlar's side can widen it. A query touching anything else is refused before the database sees it, and the refusal is recorded in your audit log.


Running it

TaskWhat to do
Check it is aliveThe gateway shows Connected / Online in the plugin's Gateway step.
See what has runtail -f audit/queries.jsonl on the gateway machine.
Stop access immediatelyRevoke in Qlar. The gateway stops itself on its next poll โ€” nothing to redeploy.
UpgradePull a newer image and restart. Upgrades are on your schedule; Qlar keeps accepting the published protocol version.
Move it to another machineCopy gateway-key.pem and .env. Without the key the fingerprint changes and you must enrol and approve again.

Back up gateway-key.pem. It is the gateway's identity.

Restarting Qlar does not disconnect anything: there is no session to lose. A poll that fails is simply retried, and enrolment and approval are stored server-side.


Troubleshooting

SymptomCauseFix
Qlar rejected the enrolment codeCodes are single use and expire after 15 minutesGenerate a fresh one
Stays Waiting for your approvalNobody approved the fingerprint yetClick the card, or Review fingerprint on it, compare, and click Approve. This works even if the page that issued the code was closed.
Every request fails with 401Clock skew beyond ยฑ2 minutes โ€” by far the most common causeFix NTP on the gateway machine
this gateway has been revoked, then it exitsRevoked in QlarDelete gateway-state.json and enrol again
Questions fail with the data source is offlineThe gateway is not running, or cannot reach QlarStart it; allow outbound 443 to your Qlar endpoint
A query is refused as not allowedWorking as designedAdd the table to TABLE_ALLOWLIST, or clear the list
Fingerprint changed after a redeployThe key file was not persistedMount the state volume, then enrol and approve again

The gateway's own install guide covers systemd and Kubernetes, and the protocol specification documents the wire contract in full โ€” it is published so you can audit it, or write your own gateway in another language.