DQC Logo
|

Connect via DQC Proxy

The DQC Proxy connects your databases to the DQC Platform without opening a single inbound firewall port. It runs as a small service inside your network and establishes an outbound, TLS-encrypted tunnel (WSS over port 443) to the DQC tunnel gateway. All database access from the platform travels through this tunnel — your firewall stays closed.

In one sentence: the DQC Platform reaches your database exclusively through the tunnel that your proxy established from the inside out — and even then only the targets you explicitly allowlisted.


System requirements

  • Linux server or VM (x86_64 or ARM64) — 1 vCPU / 256 MB RAM are plenty

  • Outbound HTTPS (port 443) to gw.shared.app.dqc.ai

  • Network access from the proxy host to the database(s) you want to connect

  • No inbound firewall rules required

Download & installation

Download the archive for your architecture from the DQC Proxy releases page:

Verify the checksum, then install:

sha256sum --check --ignore-missing SHA256SUMS
tar -xzf dqcproxy-linux-<arch>.tar.gz
sudo install -m 0755 dqcproxy /usr/local/bin/dqcproxy

Current checksums (v0.1.0): amd64 e3b8e49004dd771d16c49bcd3027539116cd8fe9469fe0811252c4e0b8e7c76b, arm64 ebf774d7ad2d3d4b2debc488c0c586d0c056743ce8496b36af1d481ddcd5ef78.

Run as a dedicated VM (cloud-init)

If you prefer a dedicated proxy VM in your infrastructure, create a standard Ubuntu 22.04/24.04 minimal VM (1 vCPU / 1 GB RAM / 10 GB disk) and attach our cloud-init.yaml as user-data — fill in your token and allowlist, boot, done. The VM installs the proxy (checksum-verified), hardens the service, and enables unattended OS security updates. For an already-running VM there is an install.sh:

curl -fsSLO https://github.com/dataqcompany/dqcproxy-releases/raw/main/vm/install.sh
sudo bash install.sh --token dqcpx_YOUR_TOKEN --allow "db1.internal.example.com:5432"

The operating system stays under your control and patch policy — the proxy is a single static binary on top.

Run as a container

If you run Docker or Kubernetes, use the public multi-arch image ghcr.io/dataqcompany/dqcproxy instead of a VM:

docker run -d --name dqcproxy --restart always \
  -e DQCPROXY_MODE=client \
  -e DQCPROXY_GATEWAY_URL=wss://gw.shared.app.dqc.ai \
  -e DQCPROXY_TOKEN=dqcpx_YOUR_TOKEN \
  -e DQCPROXY_ALLOW="db1.internal.example.com:5432" \
  ghcr.io/dataqcompany/dqcproxy:latest

No ports are published — the proxy is outbound-only. The image is distroless (no shell, no package manager) and runs as a non-root user.

Start the proxy

You receive a one-time enrollment token (dqcpx_…) from DQC. It identifies your proxy to the gateway — treat it like a password.

dqcproxy --mode=client \
  --gateway wss://gw.shared.app.dqc.ai \
  --token dqcpx_YOUR_TOKEN \
  --allow "db1.internal.example.com:5432,db2.internal.example.com:1433"

On success the log shows:

{"level":"INFO","msg":"tunnel established","gateway":"wss://gw.shared.app.dqc.ai"}

Run as a systemd service (recommended)

/etc/systemd/system/dqcproxy.service:

[Unit]
Description=DQC Proxy (reverse tunnel to the DQC Platform)
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/dqcproxy --mode=client
Environment=DQCPROXY_GATEWAY_URL=wss://gw.shared.app.dqc.ai
EnvironmentFile=/etc/dqcproxy/env
Restart=always
RestartSec=5
DynamicUser=yes
NoNewPrivileges=yes
ProtectSystem=strict

[Install]
WantedBy=multi-user.target

/etc/dqcproxy/env (mode 600, owned by root):

DQCPROXY_TOKEN=dqcpx_YOUR_TOKEN
DQCPROXY_ALLOW=db1.internal.example.com:5432

Enable it with sudo systemctl enable --now dqcproxy.

Configuration reference

Every flag can alternatively be set as an environment variable:

  • --mode / DQCPROXY_MODE — always client in your network

  • --gateway / DQCPROXY_GATEWAY_URL — gateway URL: wss://gw.shared.app.dqc.ai

  • --token / DQCPROXY_TOKEN — your enrollment token (dqcpx_…)

  • --allow / DQCPROXY_ALLOW — allowlist of reachable targets (see below)

Target allowlist

The proxy connects exclusively to targets you allow here — everything else is rejected (default deny). Comma-separated entries, three forms:

  • host:port — exactly this host and port, e.g. db1.internal.example.com:5432

  • *.domain:port — all subdomains, fixed port, e.g. *.sql.example.com:1433

  • host:* — fixed host, any port, e.g. dwh.example.com:*

Blanket patterns like *:5432 are deliberately not accepted.

Security

  • Outbound only: the proxy never opens a listening port. It dials the DQC gateway via WSS (TLS, port 443).

  • No credentials in the proxy: database credentials stay encrypted in the DQC Platform. The proxy relays opaque bytes; with database TLS enabled it only ever sees encrypted traffic.

  • Allowlist in your hands: target restrictions are enforced inside your network. Even a fully compromised cloud counterpart could only reach the host:port targets you listed.

  • Server-authoritative routes: which targets are requested is determined by the connectors configured in the DQC Platform — the tunnel does not transport arbitrary externally chosen addresses.

  • No code execution: the proxy contains no business logic and executes nothing. A single static binary.

Troubleshooting

  • tunnel established never appears — outbound port 443 to gw.shared.app.dqc.ai is blocked (check firewall/web proxy) or the token is invalid. Contact DQC support.

  • The log shows a rejected target — the target host:port is missing from --allow. Add it and restart the service. Note: localhost and 127.0.0.1 are distinct entries.

  • Connection drops — the proxy reconnects automatically with backoff; short interruptions heal themselves. A permanent reconnect loop: contact DQC support.

  • Error “refusing plaintext ws://” — the gateway URL must start with wss:// (TLS). ws:// is only permitted in development setups.

Questions? support@dqc.ai — please include a log excerpt and the release version.

Connect via DQC Proxy | DQC