# Production Security Checklist

> Source: https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/production_checklist
> For the complete documentation index, see [llms.txt](https://docs.synthesized.io/llms.txt).

Work through this list before an installation handles production data. Each item links to the page that explains how to do it.

For the security model behind these items, see [Security Overview](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/security_overview).

## Secrets

-  Generate your own `JWT_SECRET`. See [Docker Compose](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/production_setup/dc) or [Helm](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/production_setup/helm).
-  Generate your own 256-bit `CREDENTIALS_ENCRYPTION_KEY`, and keep a copy in your secret store: if it’s lost, the stored data source passwords can’t be recovered.
-  Set a strong `ADMIN_DEFAULT_PASSWORD` for the first administrator, and change it after the first sign-in.
-  Keep these values, and the database passwords, out of version control. With Helm, put them in `api.container.secretConfig`.
-  If you turn on the Assistant, generate your own `AGENT_SECRET_KEY`, and set the same value on Governor’s API and on the Assistant.
-  Consider keeping data source passwords in a [secret manager](https://docs.synthesized.io/tdk/latest/user_guide/070_integrations/secret_management/secret_managers) (AWS, Google Cloud or HashiCorp Vault) instead of in Governor.

## Network and encryption

-  Serve the web UI and the API over HTTPS, with TLS 1.2 or later. See [TLS termination](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/production_setup/dc#_setting_up_tls_termination) for Docker Compose, or the ingress TLS settings for [Helm](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/production_setup/helm).
-  Turn on TLS between workers and Governor: set `WORKER_USEPLAINTEXT=false`, and use mutual TLS where workers run in other networks. See [Worker–Governor mTLS](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/production_setup/worker_mtls).
-  Allow the gRPC port (`50055` by default) only from the networks where your workers run.
-  Put workers in the same network as the databases they process, so database traffic doesn’t cross networks. See [Synthesized Workers](https://docs.synthesized.io/tdk/latest/user_guide/020_guides/advanced_workflows/workers).
-  Use encrypted JDBC connections where your databases support them. See [SSL certificate issues](https://docs.synthesized.io/tdk/latest/user_guide/080_troubleshooting/database_specific/ssl_issues).
-  Set `GOVERNOR_SECURITY_ALLOWEDORIGINPATTERNS` to the address users open Governor on. See [Governor and Worker Settings](https://docs.synthesized.io/tdk/latest/user_guide/040_reference/configuration/advanced_configuration).
-  Limit access to Governor’s health and metrics endpoints to your monitoring systems.
-  Turn on the Assistant only if you’ve approved the LLM endpoint it calls. With the Assistant off, the platform needs no internet access. See [Network connections](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/security_overview#_network_connections).

## Sign-in and roles

-  Connect your identity provider with [SSO](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/authentication/sso) or [LDAP](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/authentication/ldap_activedirectory), so joiners and leavers are managed in one place.
-  With SAML or LDAP, map your groups to roles, so roles follow group membership at each sign-in.
-  Sign in through your identity provider as an administrator before anyone else does: the first user to sign in through SAML or LDAP can become the `OWNER`. See [How roles are assigned](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/rbac/#_how_roles_are_assigned).
-  Keep `GOVERNOR_SECURITY_DEFAULTROLE` at `MEMBER`.
-  Give each team its own [project](https://docs.synthesized.io/tdk/latest/user_guide/010_get_started/projects), with only the data sources its workflows need.
-  Keep the number of Administrators and Owners small, and review them regularly.
-  For pipelines, create [access keys](https://docs.synthesized.io/tdk/latest/user_guide/020_guides/advanced_workflows/public_api_access_keys) as a dedicated user with access to only what the pipeline needs, with the shortest expiry that works.

## Databases

-  Create a dedicated database user for the platform on each database, with the [minimum grants](https://docs.synthesized.io/tdk/latest/user_guide/010_get_started/database_permissions): read on inputs, write on outputs. Use a separate user for each environment, so each can be audited and removed on its own.
-  Mark production data sources **Read-only** in Governor, so no workflow can write to them. See [Data Sources](https://docs.synthesized.io/tdk/latest/user_guide/010_get_started/datasources).
-  Use dedicated output databases: a run can empty or recreate the output’s tables.
-  Limit how many connections the platform’s database users can open.

## Workflows and outputs

-  Keep `safety_mode: STRICT` (the default), so a column no rule matches stops the run instead of being copied.
-  Before you share an output, check what it can contain. See [Data Protection](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/data_protection).
-  Run a [PII scan](https://docs.synthesized.io/tdk/latest/user_guide/030_core_concepts/pii) on new data sources, and review the columns it marks and the ones it can’t recognise.
-  Restrict who can read the output databases, as you would any copy of production data, until you’ve checked them.

## Operations

-  Pin image versions to a release tag, and keep up with releases. See [Updating the Platform](https://docs.synthesized.io/tdk/latest/user_guide/050_deployment_operations/updating_tdk/).
-  Back up Governor’s metadata database, and restrict access to it: it holds the encrypted data source passwords.
-  Keep `SENTRY_DSN` unset unless you want error reports sent to a Sentry project.
-  Forward the logs of the `backend` and `worker` containers to your log platform, and alert on the [security events](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/security_overview#_security_events) in the audit log.
-  Deactivate users who leave, or remove them in your identity provider. See [Joiners, movers and leavers](https://docs.synthesized.io/tdk/latest/user_guide/060_security_compliance/rbac/#_joiners_movers_and_leavers).
