Encryption
Everything Radioso Cloud stores is encrypted at rest, and everything that travels between its parts, and out to the services it calls, is encrypted in transit. This page says what that covers, which keys are involved, and how a self-hosted deployment gets the same.
At rest
On Radioso Cloud, conversations, documents, settings and everything else live in Cloud SQL for PostgreSQL and in a Cloud Storage bucket for uploaded files. Google Cloud encrypts both with AES-256, including database backups and logs, under keys Google manages. Radioso doesn’t offer customer-managed keys.
Credentials get a second layer. Workspace provider API keys, connector and OAuth secrets, and webhook signing secrets are encrypted by the application with AES-256-GCM before they reach the database, under the deployment’s CONNECTOR_ENCRYPTION_KEY. Nobody can read them back through the API, and they stay unreadable in a database copy without that key. Keys it replaces can stay configured to decrypt only, so the key can be replaced without re-entering credentials: Rotate the credential encryption key walks through it.
In transit
- Browsers, embeds and API clients reach Radioso over HTTPS.
- The backend and workers reach Postgres over TLS. Every hosted runtime sets
PGSSLMODE=no-verify. The connection is encrypted, and the client doesn’t check the server’s certificate, because a Cloud SQL private-IP certificate doesn’t name the address clients connect to. The database has no public address and is reachable only from the stack’s private network. - Cloud SQL refuses unencrypted connections on stacks where
db_require_encrypted_connectionsis on. A client that tries plain text fails at connect. - Model providers, email, Slack and the other outside services are called over HTTPS. Data residency lists each one and where it processes data.
Check that database connections are encrypted
Run this as the application’s database user. Each runtime shows up under its own application name:
SELECT a.application_name,
count(*) FILTER (WHERE s.ssl) AS encrypted,
count(*) AS total
FROM pg_stat_activity a
JOIN pg_stat_ssl s USING (pid)
WHERE a.usename = current_user
GROUP BY a.application_name;Every row should show encrypted equal to total. A row where it doesn’t is a runtime still connecting in plain text.
Self-hosted deployments
You own both layers. Disk encryption is whatever your host or volume provides. The default Compose stack runs Postgres on the same private Docker network as the backend and connects without TLS.
To encrypt the database connection, set PGSSLMODE on the backend and worker containers, or put the TLS settings in DATABASE_URL:
PGSSLMODE=no-verifyencrypts without checking the certificate. Use it when the network path to Postgres is already private.DATABASE_URL=postgres://...?sslmode=verify-full&sslrootcert=/etc/ssl/postgres-ca.pemencrypts and checks both the certificate chain and the host name against your CA. Settings inDATABASE_URLtake precedence overPGSSLMODE.
Keep CONNECTOR_ENCRYPTION_KEY out of the database’s backups. A backup and its key stored together protect nothing.
Common failure modes
- A certificate error at startup, such as
self-signed certificate.DATABASE_URLcarriessslmode=requireorsslmode=verify-ca. The Node.js Postgres driver treats both asverify-fulland checks the certificate against the system’s public CAs. UsePGSSLMODE=no-verify, orverify-fullwithsslrootcertpointing at your CA. - A runtime fails to connect right after you turn on
db_require_encrypted_connections. That runtime has noPGSSLMODEand no TLS settings inDATABASE_URL. Run the check above before turning enforcement on.
Read next
- Deployment: turning on encrypted-only connections for a stack.
- Data retention: how long backups and logs keep data after a deletion.
- Data residency: where each outside service processes data.