---
title: "HeliosDB Security Best Practices"
---

# HeliosDB Security Best Practices

This guide covers how to run HeliosDB Full securely with the controls the
`heliosdb-full` server provides: its startup flags and environment variables, SQL
roles, TLS on the PostgreSQL listener, and the infrastructure around it. Every flag is
described in the [Server Configuration Reference](/docs/full/reference/configuration/).

## Table of Contents

1. [Authentication and Access Control](#1-authentication-and-access-control)
2. [Encryption and Key Management](#2-encryption-and-key-management)
3. [Network Security](#3-network-security)
4. [Secure Development](#4-secure-development)
5. [Auditing and Monitoring](#5-auditing-and-monitoring)
6. [Data Protection](#6-data-protection)
7. [Deployment Security](#7-deployment-security)
8. [Incident Response](#8-incident-response)
9. [Compliance Checklists](#9-compliance-checklists)
10. [Quick Reference](#10-quick-reference)

---

## 1. Authentication and Access Control

### Secure defaults

| Default | Effect |
|---------|--------|
| `--bind-addr 127.0.0.1` | Nothing is reachable from the network until you choose an address |
| `--allow-external` required for any other address | An accidental `0.0.0.0` stops startup |
| `--auth-mode scram` | Credentials are required on every listener |
| `trust` refused on non-loopback binds | Password-less access can never be exposed |
| Optional listeners off | MySQL, Oracle, SQL Server, MongoDB, Cassandra and Redis open only with `--enable-<protocol>` |
| Random superuser password when `HELIOSDB_SUPERUSER_PASSWORD` is unset | No well-known default credential |

### The superuser

The built-in superuser is `postgres`. Set its password with
`HELIOSDB_SUPERUSER_PASSWORD` from a secrets store. Use it for administration only;
applications get their own roles.

### Application roles

```sql
CREATE ROLE orders_app LOGIN PASSWORD 'long-random-value' CONNECTION LIMIT 100;
CREATE ROLE reporting LOGIN PASSWORD 'another-long-value' VALID UNTIL '2027-01-01' CONNECTION LIMIT 10;
ALTER ROLE reporting NOLOGIN;      -- disable without dropping
DROP ROLE reporting;
```

Passwords are stored as SCRAM-SHA-256 verifiers. `LOGIN`/`NOLOGIN`, `VALID UNTIL` and
`CONNECTION LIMIT` are enforced at login.

### Authorization and isolation

In the current release every role that can log in has access to all data in the
server: `GRANT`, `REVOKE` and row-level security return SQLSTATE `0A000`. Design for
that:

- Give each application or tenant that needs separation **its own server instance**
  (own data directory, credentials and ports), not just its own role.
- Keep administrative and application credentials separate so they can be rotated
  independently.
- Restrict which hosts can reach each instance at the network layer.

### Other listeners

Configure credentials only for the listeners you enable:

| Listener | Credential |
|----------|------------|
| MySQL, Redis | Roles from the server's role catalog |
| Oracle | `HELIOSDB_ORACLE_NATIVE_PASSWORD` |
| SQL Server | `HELIOSDB_SQLSERVER_USER`, `HELIOSDB_SQLSERVER_PASSWORD` |
| MongoDB | `HELIOSDB_MONGODB_USER`, `HELIOSDB_MONGODB_PASSWORD` |
| Cassandra | `HELIOSDB_CASSANDRA_USER`, `HELIOSDB_CASSANDRA_PASSWORD` |
| HTTP gateway | `HELIOSDB_API_KEY` |

Keep these listeners on loopback or a private segment that only the application hosts
can reach, and leave disabled the ones you do not use.

### Brute force and connection floods

- `--conn-rate-limit` (default 500 new connections per minute per client IP) and
  `--max-connections` (default 10000) are on by default.
- `--query-rate-limit` caps queries per second per client IP on the PostgreSQL and
  HTTP SQL paths.
- `--startup-timeout-secs` (default 30) closes connections that do not finish the
  handshake.

---

## 2. Encryption and Key Management

### In transit

:::caution[TLS: planned]
HeliosDB Full listeners do not terminate TLS; put a TLS-terminating proxy in
front. Native PostgreSQL TLS (with post-quantum key exchange preferred) is
planned; the `--tls-cert`, `--tls-key` and `--tls-require` flags in this section
describe that planned feature.
:::

Enable TLS on the PostgreSQL listener and require it:

```bash
heliosdb-full --tls-cert /etc/heliosdb/tls/server.crt --tls-key /etc/heliosdb/tls/server.key --tls-require
```

```bash
psql "host=db.internal user=orders_app sslmode=verify-full sslrootcert=/etc/ssl/internal-ca.pem"
```

`SHOW CERTIFICATES` reports whether TLS is configured and whether the current
connection is encrypted. The HTTP gateway and the other wire listeners are plaintext:
put the HTTP gateway behind a TLS-terminating proxy, and carry the others over a
private network, a service mesh with mTLS, or a TLS tunnel.

Rotate the certificate by replacing the files and restarting the server (they are
read at startup).

### At rest

Encrypt the volume that holds the data directory: LUKS/dm-crypt on Linux, or the
provider's KMS-backed disk encryption (EBS, Persistent Disk, Managed Disks) in the
cloud. Encrypt backups in their target as well (see
[Backup & Disaster Recovery](/docs/full/deployment/production_deployment_backup/)).
The [Key Management Guide](/docs/full/quick-starts/security/key_management/) covers
the keys involved.

### Secrets

- Pass passwords and keys through the environment from a secrets manager
  (Vault, AWS Secrets Manager, Kubernetes Secrets) or a root-owned file with mode
  `0600` loaded by `EnvironmentFile=`; never as command-line arguments, which other
  local users can read in the process list.
- Do not bake secrets into images or commit them to source control.

---

## 3. Network Security

1. Bind to a private interface (`--bind-addr 10.x.x.x --allow-external`), never to a
   public address.
2. Allow only application hosts to the database ports with a host firewall and
   security groups or NetworkPolicies.
3. Open only the ports of enabled listeners (5432, 8443 and any you enable).
4. In containers, publish ports on the host's private or loopback address
   (`-p 127.0.0.1:5432:5432`), not on all interfaces.

Kubernetes example:

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: heliosdb-allow-app
spec:
  podSelector:
    matchLabels: {app: heliosdb}
  policyTypes: [Ingress]
  ingress:
    - from:
        - podSelector:
            matchLabels: {role: orders-app}
      ports:
        - {protocol: TCP, port: 5432}
```

---

## 4. Secure Development

- Use bind parameters (prepared statements) in every driver; never build SQL by string
  concatenation. The server also screens incoming SQL for common injection patterns,
  but that is a second line of defence.
- Use a dedicated role per application with a strong generated password.
- Set `statement_timeout` for interactive and reporting sessions to bound runaway
  queries.
- Test against a non-production server with its own credentials.

---

## 5. Auditing and Monitoring

- **Server log:** connections, authentication failures, startup configuration and
  errors go to standard output/journald. Ship it to your log platform or SIEM; it is
  the durable record.
- **Slow statements:** statements slower than `--log-min-duration-statement`
  (default 1000 ms) are logged with their text and duration. `SET
  log_min_duration_statement = 0` in a session logs every statement of that session.
- **Live sessions:** `SHOW CONNECTIONS` and `pg_stat_activity` show who is connected
  and what they are running.
- **Recent data changes:** `SHOW CDC EVENTS LIMIT 100` lists recent
  INSERT/UPDATE/DELETE events (kept in memory, cleared on restart).
- **Health:** probe `GET /health` and `GET /ready` on the HTTP gateway.

Alert on repeated authentication failures, connections from unexpected addresses,
and restarts.

---

## 6. Data Protection

- **Backups:** follow [Backup & Disaster Recovery](/docs/full/deployment/production_deployment_backup/);
  encrypt them and test restores.
- **Minimise sensitive data:** store only what you need; hash or tokenise identifiers
  in the application before they reach the database where possible.
- **Masking for non-production:** copy production data to test environments only
  after masking it with your ETL tooling.
- **Durability:** keep `--synchronous-commit on` (the default) for data you cannot
  lose.

---

## 7. Deployment Security

- Run the server as a dedicated unprivileged user (the container image runs as
  `helios`) with ownership of the data directory only.
- systemd hardening: `NoNewPrivileges=yes`, `ProtectSystem=strict`,
  `ReadWritePaths=/var/lib/heliosdb`, `PrivateTmp=yes`.
- Containers: read-only root filesystem with a volume for the data directory, no
  privileged mode, dropped capabilities.
- Keep the server updated: check `heliosdb-full --version` against the release notes.
- Review `heliosdb-full --show-features --all` after upgrades to see what the build
  provides.

---

## 8. Incident Response

See the [Security Incident Response Plan](/docs/full/features/security/incident-response/).
The first steps for a suspected compromise of the database:

1. Restrict network access to the database ports (firewall) to stop further access
   while you keep the server running for evidence.
2. Save the server log and `SHOW CONNECTIONS` output.
3. Rotate `HELIOSDB_SUPERUSER_PASSWORD`, `HELIOSDB_API_KEY` and listener credentials,
   and application role passwords (`ALTER ROLE ... PASSWORD`).
4. Restart the server with the new secrets; restore from a known-good backup if data
   was altered.

---

## 9. Compliance Checklists

How the server's controls map to common requirements (your organisation's control
owners decide what satisfies each):

| Requirement area | Controls |
|------------------|----------|
| Access control | SCRAM-SHA-256 logins, per-application roles, `VALID UNTIL`, `NOLOGIN`, instance-per-tenant isolation |
| Encryption in transit | PostgreSQL TLS with `--tls-require`; TLS proxy or private network for other listeners |
| Encryption at rest | Volume encryption with KMS-managed keys; encrypted backups |
| Logging and monitoring | Server log shipped to SIEM; slow-statement log; session views |
| Availability and recovery | WAL durability, snapshot or cold-copy backups, tested restores |
| Least functionality | Optional listeners off by default; loopback default bind |

---

## 10. Quick Reference

```bash
# Hardened start
heliosdb-full --data-dir /var/lib/heliosdb \
  --bind-addr 10.0.0.12 --allow-external \
  --tls-cert /etc/heliosdb/tls/server.crt --tls-key /etc/heliosdb/tls/server.key --tls-require \
  --max-connections 2000 --conn-rate-limit 300
```

```sql
CREATE ROLE app LOGIN PASSWORD '...' CONNECTION LIMIT 100;
SHOW ROLES;
SHOW CONNECTIONS;
SHOW CERTIFICATES;
```

## 11. Additional Resources

- [Server Configuration Reference](/docs/full/reference/configuration/)
- [Threat Model](/docs/full/features/security/threat-model/)
- [Security Incident Response Plan](/docs/full/features/security/incident-response/)
