---
title: "HeliosDB-Lite Security Hardening Guide"
---

# HeliosDB-Lite Security Hardening Guide

---

## Table of Contents

1. [Overview](#overview)
2. [Network Exposure](#network-exposure)
3. [Authentication](#authentication)
4. [Authorization](#authorization)
5. [Encryption](#encryption)
6. [Secrets](#secrets)
7. [Host and Container Hardening](#host-and-container-hardening)
8. [Monitoring](#monitoring)
9. [Security Checklist](#security-checklist)
10. [Planned Controls](#planned-controls)

---

## Overview

`heliosdb-lite start` opens up to three listeners:

| Listener | Default | Notes |
|----------|---------|-------|
| PostgreSQL wire | `127.0.0.1:5432` | SQL access; authentication set by `--auth` |
| HTTP | port `8080` | REST API under `/v1` (JWT bearer tokens), `/health`, `/metrics`, `/version` |
| WAL replication | port `5433` | Only with a replication role |

`heliosdb-lite repl` opens a data directory in-process and listens on no port.

The defaults favour local development: `--auth trust` and a loopback listen address.
Change both before any other host can reach the server.

---

## Network Exposure

- Keep `--listen 127.0.0.1` (the default) unless clients on other hosts must connect.
  When they must, bind to a private interface and allow only known client addresses
  in your firewall or security group.
- Expose the HTTP port only to the clients and monitoring systems that need it.
- Keep the replication port reachable only between database nodes.

```bash
# Kubernetes: only application pods may reach the database pods
kubectl apply -f - <<'YAML'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: heliosdb-ingress
spec:
  podSelector:
    matchLabels:
      app: heliosdb-lite
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: app
      ports:
        - port: 5432
        - port: 8080
YAML
```

---

## Authentication

**PostgreSQL wire protocol:** start the server with SCRAM-SHA-256.

```bash
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"
heliosdb-lite start --data-dir /var/lib/heliosdb \
  --auth scram-sha-256 --password "$HELIOSDB_ADMIN_PASSWORD"
```

`--password` sets the password of the built-in administrator accounts `postgres` and
`helios`. Create one login role per application:

```sql
CREATE ROLE app_rw LOGIN PASSWORD 'a-long-random-password';
```

**REST API:** every `/v1` route requires `Authorization: Bearer <JWT>`, signed with
`HELIOSDB_JWT_SECRET`. The server refuses to start without that secret. API-key
authentication is planned.

See the [SCRAM-SHA-256 Quick Reference](/docs/lite/guides/quickstart/scram_quick_reference/)
and the [JWT Auth Quick Reference](/docs/lite/guides/quickstart/jwt_auth_quick_reference/).

---

## Authorization

- Grant each role only what it needs:

```sql
GRANT SELECT, INSERT, UPDATE ON orders TO app_rw;
REVOKE ALL ON payroll FROM app_rw;
```

- Use [row-level security](/docs/lite/guides/rls_quickstart/) for per-tenant or per-user
  row filtering. Superusers bypass RLS, so connect applications as non-superuser roles.
- Reserve `postgres` and `helios` for administration.

---

## Encryption

**At rest:** enable Transparent Data Encryption (AES-256-GCM) in `config.toml`:

```toml
[encryption]
enabled = true
key_source = { File = "/etc/heliosdb/encryption.key" }
```

See the [Encryption Quick Start](/docs/lite/guides/encryption_quickstart/).

**In transit:** start with `--tls-cert` and `--tls-key`. The server offers TLS to every
client; require it in each client with `sslmode=require` or stricter. See
[PostgreSQL SSL/TLS Configuration](/docs/lite/guides/postgresql_ssl_configuration/).

**Backups:** dump files are not encrypted by the dump command. Encrypt them before they
leave the host:

```bash
heliosdb-lite dump --data-dir /var/lib/heliosdb --output backup.heliodump
gpg --symmetric --cipher-algo AES256 backup.heliodump
```

---

## Secrets

| Secret | Where it is used |
|--------|------------------|
| `HELIOSDB_JWT_SECRET` | Signs REST API tokens; use at least 32 random bytes |
| `--password` | Administrator password for the PostgreSQL port |
| `HELIOSDB_METRICS_KEY` | Unlocks `/metrics` and detailed `/health` output |
| Encryption key | Decrypts the data directory when TDE is on |

Keep secrets in a secret manager or in files readable only by the service user
(`chmod 600`), never in the configuration file, the repository or the shell history.

---

## Host and Container Hardening

```bash
# Dedicated service user and private data directory
useradd -r -s /bin/false heliosdb
chown -R heliosdb:heliosdb /var/lib/heliosdb
chmod 700 /var/lib/heliosdb
chmod 600 /etc/heliosdb/config.toml
```

```bash
# Containers: run as non-root, drop capabilities, read-only root filesystem
docker run --user 1000:1000 --cap-drop ALL --read-only \
  -v heliosdb_data:/data -e HELIOSDB_JWT_SECRET \
  heliosdb-lite start --data-dir /data --listen 0.0.0.0 \
  --auth scram-sha-256 --password "$HELIOSDB_ADMIN_PASSWORD"
```

---

## Monitoring

- Set `HELIOSDB_METRICS_KEY` and scrape `/metrics` with it; without the key the
  endpoint answers 403.
- Alert on repeated authentication failures in the server log (for example more than
  10 per minute), on unexpected connection counts in `pg_stat_activity`, on an error
  rate above 1% and on free disk space below 10%.
- Ship logs to your log platform; set the level with `RUST_LOG` (for example
  `RUST_LOG=info`).

---

## Security Checklist

### Before Deployment
- [ ] `--auth scram-sha-256` with a strong administrator password
- [ ] One login role per application, least privilege, no superuser
- [ ] RLS policies on multi-tenant tables
- [ ] `HELIOSDB_JWT_SECRET` from a secret manager
- [ ] TLS certificates installed; clients use `sslmode=require`
- [ ] TDE enabled and the key backed up separately
- [ ] Listen address and firewall rules reviewed

### After Deployment
- [ ] Restore from a dump to confirm backups work
- [ ] Rotate passwords with `ALTER ROLE ... PASSWORD`
- [ ] Renew TLS certificates before they expire
- [ ] Review roles and grants regularly

---

## Planned Controls

These controls are on the roadmap and are not available in the current release:

- Built-in audit logging (see [Audit Logging](/docs/lite/features/audit_logging/));
  use triggers to record changes meanwhile
- Online encryption key rotation and cloud KMS key sources
- Client-certificate authentication on the PostgreSQL port
- Zero-knowledge encryption for Lite
