# Production security checklist

Verify that an environment is locked down before it takes production traffic.

Before an environment goes live, work through the items below - each one names a security concern and links to the page with the mechanism. For the wider pass over an environment, beyond security alone, see the [production checklist](https://zato.io/docs/admin/production-checklist.html).

## Set your own passwords {#set-your-own-passwords}

A container generates random passwords for everything that you do not set, and nobody knows a generated password. Set your own before the first start:

- `Zato_Dashboard_Password` - the Dashboard's `admin` account
- `Zato_SSH_Password` - the `zato` user's SSH access
- `Zato_IDE_Password` - the `ide_publisher` user for IDE integration

All three, and what they protect, are in the [environment variables reference](https://zato.io/tutorials/devops/env-variables.html). For the accounts themselves, see [security defaults](https://zato.io/docs/admin/security/defaults.html), and to rotate a password later, see [changing passwords](https://zato.io/docs/admin/security/change-password.html).

## Publish the TLS ports only {#publish-the-tls-ports-only}

Every port that takes traffic has a TLS variant, and a production environment publishes only the TLS ports:

- Publish 11224, the load balancer's TLS port - this is how API clients reach you
- Do not publish 11223 or 8183 - the same traffic without TLS
- Publish 8184, the Dashboard's TLS port, only to your own network - a VPN, an office range, a bastion
- Do not publish 22 - `docker exec` and `kubectl exec` do the same job without an open port

The whole table, with what goes over each port, is under [ports and network](https://zato.io/docs/admin/ports.html).

## Serve your own certificate {#serve-your-own-certificate}

A container without a mounted certificate generates a self-signed certificate, which browsers and API clients do not trust. Mount your own `zato.pem` and set the minimum TLS version through `Zato_SSL_Protocols` - the whole subject, including where the files go and how the load balancer serves them, is under [SSL/TLS](https://zato.io/docs/admin/security/ssl/index.html).

## Require client certificates at the handshake {#require-client-certificates-at-the-handshake}

With a client CA mounted, `Zato_SSL_Client_Verify=required` rejects clients without a valid certificate at the handshake - the variable is in the [environment variables reference](https://zato.io/tutorials/devops/env-variables.html) and the certificate side is under [SSL/TLS](https://zato.io/docs/admin/security/ssl/index.html).

## Authenticate every channel {#authenticate-every-channel}

Every channel takes a security definition, and a channel without one is unauthenticated. Assign one of the supported authentication methods to each channel - the types and how to pick one are under [channel security](https://zato.io/docs/admin/security/channel.html), and the credentials that your own outgoing connections present are under [outgoing connections](https://zato.io/docs/admin/security/outgoing.html).

## Limit callers and filter addresses {#limit-callers-and-filter-addresses}

Cap how much traffic any one caller sends and block the address ranges that should never reach you - both are part of [rate limiting and firewall](https://zato.io/docs/admin/guide/rate-limit.html). To reuse one rate-limit plan across many API clients, assign [quota tiers](https://zato.io/docs/admin/guide/quota-tiers.html).

## Protect the metrics endpoint {#protect-the-metrics-endpoint}

The `/metrics` Prometheus endpoint is behind HTTP [Basic Auth](https://zato.io/docs/security/basic-auth.html) whose password is `Zato_Metrics_Password` - set your own, and for the details see the [environment variables reference](https://zato.io/tutorials/devops/env-variables.html) and [monitoring](https://zato.io/docs/monitoring/index.html).

## Cap request sizes {#cap-request-sizes}

`Zato_TCP_Max_Msg_Size` caps the size of a single incoming HTTP message, in megabytes, and the server rejects requests over the limit - the variable is in the [environment variables reference](https://zato.io/tutorials/devops/env-variables.html).

## Keep secrets out of YAML {#keep-secrets-out-of-yaml}

Enmasse never exports passwords, and the way to supply them at import time is environment variables with the `Zato_Enmasse_Env.` prefix - the configuration in git stays free of credentials. For how the references work, see [enmasse](https://zato.io/docs/admin/enmasse.html#environment-variables).

## Allow only the outbound access the platform needs {#allow-only-the-outbound-access-the-platform-needs}

If your firewall blocks outbound traffic by default, allow outbound access for your own outgoing connections, for [health checks](https://zato.io/docs/admin/health-checks.html) and for shipping logs out - the list is under [ports and network](https://zato.io/docs/admin/ports.html#outbound).

## See also {#see-also}

- [Security defaults](https://zato.io/docs/admin/security/defaults.html) - Generated passwords, inactive channels and the audit log
- [Ports and network](https://zato.io/docs/admin/ports.html) - The full port table and the outbound access list
- [Production checklist](https://zato.io/docs/admin/production-checklist.html) - The wider pre-production pass, beyond security

## Learn more {#learn-more}

- [Production checklist](https://zato.io/docs/admin/production-checklist.html) - What to confirm before an environment takes real traffic
- [Audit log](https://zato.io/docs/admin/audit-log/) - Every request, response and error, and what you can do with them afterwards
- [Health checks](https://zato.io/docs/admin/health-checks.html) - Have Zato ping your outgoing connections instead of waiting for traffic to fail
- [Logging](https://zato.io/docs/admin/logging.html) - What is written where, and how to ship it to Splunk, Loki, Elastic or Datadog
- [GitOps with enmasse](https://zato.io/docs/admin/enmasse.html) - Keep the whole environment in git as YAML and import it anywhere
