Skip to main content

Access from outside

A database is private to its environment. Expose it only when something outside the cluster must reach it, such as a desktop client, a BI tool, or an app hosted elsewhere, and take it off the internet again when that is over.

How it works​

The database gets a TCP domain, such as db.example.com. Traefik opens the database's port, such as 5432, on every node. A client connects there with TLS and names the domain in its TLS handshake (SNI), and Traefik sends it to the database that has that domain. Several databases can share one port, each with its own domain.

Traefik only routes connections that start TLS. A client that connects without it is not let through.

The TLS is handled in one of two ways:

Traefik ends TLSTLS passthrough
The certificateThe domain's, obtained and renewed by HivePaaSMounted into the database, which serves it itself
What the database needsNothingIts own TLS turned on
From Traefik to the databaseUnencrypted, on the environment's private networkEncrypted from the client all the way

Traefik ending TLS is the simpler one, and enough for most. Use passthrough when the connection must stay encrypted all the way to the database.

Which databases​

DatabaseTraefik ends TLSTLS passthrough
PostgreSQLYes, any versionYes; a client that starts TLS directly needs PostgreSQL 17 or later
MongoDBYesYes, with TLS turned on in mongod
Redis, ValkeyYes, from a client that sends SNIYes, with TLS turned on in the server
MySQL, MariaDBNoNo: publish its port instead

A database with an HTTP interface, such as ClickHouse's on 8123, CouchDB or Elasticsearch, needs none of this: give that port an ordinary HTTP domain, as for any app. See App domains.

Expose it, Traefik ending TLS​

  1. Point the domain's DNS at your servers, such as db.example.com. A wildcard record for your root domain already covers it.
  2. In the database's Routing Settings, turn on Expose The App To The Internet, and add the domain with:
    • Protocol set to TCP;
    • Container Port set to the database's port, such as 5432;
    • its SSL Certificate, or none, for HivePaaS to find or get one.
  3. Save.
  4. Open the port in your firewall.

The database's App Kind shows where it can be reached, under Public Access: its domains are set in its Routing Settings alone.

Then connect with TLS, to the domain:

# PostgreSQL: libpq sends SNI from version 14
psql "host=db.example.com port=5432 dbname=app user=app sslmode=verify-full sslrootcert=system"

# MongoDB
mongosh "mongodb://app:<password>@db.example.com:27017/app?tls=true&authSource=admin"

# Redis and Valkey: redis-cli sends SNI only when asked
redis-cli -h cache.example.com -p 6379 --tls --sni cache.example.com -a '<password>'

A client that sends no SNI reaches Traefik, but not the database: a Redis client then fails with an error such as Unknown RESP type 72 "H", Traefik's HTTP answer. redis-cli and valkey-cli send it with --sni, and ioredis with tls: { servername: "cache.example.com" }, even for a rediss:// URL.

With Traefik ending TLS, the database itself has no TLS: leave its SSL mode at Disable, for the apps beside it.

Expose it, with TLS passthrough​

The database serves the certificate itself, so it needs it as files, and its TLS turned on.

  1. Add the domain as above, then turn on TLS Passthrough on it, in the database's Routing Settings.
  2. Put the certificate and its key into the database's containers with a setting mount: mount the domain's SSL certificate, its certificate at /tls/tls.crt and its key at /tls/tls.key.
  3. Turn TLS on in the database, reading those files.

For PostgreSQL, the key must belong to the postgres user, and be readable by it alone: in the setting mount, give the key the owner 70 for the Alpine images, or 999 for the Debian ones, and the mode 0600. Then set the database's Command, under Deployment Settings, to:

postgres -c ssl=on -c ssl_cert_file=/tls/tls.crt -c ssl_key_file=/tls/tls.key

The mounted files follow the certificate when it is renewed, but the database reads them when it starts: restart it after a renewal.

With its own TLS on, the database can ask the apps beside it for TLS too: set its SSL mode to Require.

MySQL and MariaDB​

A MySQL or MariaDB server speaks first, before any TLS, so Traefik can neither read a domain from the connection nor pass it on. Publish the database's port instead, in its Networks, such as 3306. It is then on every node, for one database per port, and open to whoever reaches the nodes.

The connection is then as encrypted as the server makes it. MySQL 8.4, and MariaDB from 11.4, turn TLS on by themselves, with a certificate they sign: have the client require it.

mysql -h <node address> -P 3306 -u app -p --ssl-mode=REQUIRED

Keep it safe​

A database on the internet is found and tried within hours.

  • Give it a long, generated password, and connect as its ordinary user, not as postgres or root.
  • Let through only the addresses that need it, in your firewall: the domain's allowed IPs and rate limits apply to HTTP only.
  • Turn Expose The App To The Internet off when it is not needed.