SSL/TLS Proxy

In this section we’ll explore how to secure Chroma with a TLS-terminated HTTPS proxy. Below we’ll give two examples of how to do this using Envoy and Nginx. The certificates are self-signed and generated using OpenSSL, but in the future we’ll also provide examples of how to achieve this with Let’s Encrypt and certbot.

Getting The cert

To manually generate a certificate follow the steps here.

Envoy

The following envoy configuration will create a listener on port 443 that will forward all requests to the chromadb.

  1. static_resources:
  2. listeners:
  3. - name: listener_0
  4. address:
  5. socket_address:
  6. address: 0.0.0.0
  7. port_value: 443
  8. filter_chains:
  9. - filters:
  10. - name: envoy.filters.network.http_connection_manager
  11. typed_config:
  12. "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
  13. stat_prefix: ingress_http
  14. route_config:
  15. name: chroma_route
  16. virtual_hosts:
  17. - name: local_chromadb
  18. domains: [ "*" ]
  19. routes:
  20. - match:
  21. prefix: "/"
  22. route:
  23. cluster: chromadb_service
  24. prefix_rewrite: "/"
  25. http_filters:
  26. - name: envoy.filters.http.router
  27. typed_config:
  28. "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  29. transport_socket:
  30. name: envoy.transport_sockets.tls
  31. typed_config:
  32. "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
  33. common_tls_context:
  34. tls_certificates:
  35. - certificate_chain:
  36. filename: "/etc/envoy/certs/servercert.pem"
  37. private_key:
  38. filename: "/etc/envoy/certs/serverkey.pem"
  39. clusters:
  40. - name: chromadb_service
  41. connect_timeout: 0.25s
  42. type: LOGICAL_DNS
  43. lb_policy: ROUND_ROBIN
  44. load_assignment:
  45. cluster_name: chromadb_service
  46. endpoints:
  47. - lb_endpoints:
  48. - endpoint:
  49. address:
  50. socket_address:
  51. address: chromadb
  52. port_value: 8000

Finally the docker compose to tie things up where we have added a cert-gen step to automatically generate the certificates, prior to starting the envoy and chromadb services.

  1. version: '3'
  2. networks:
  3. net:
  4. driver: bridge
  5. services:
  6. cert-gen:
  7. image: openquantumsafe/openssl3
  8. volumes:
  9. - ./certs:/certs
  10. - ./openssl.cnf:/etc/ssl/openssl.cnf
  11. command: |
  12. sh -c "[ -f /certs/servercert.pem ] || \
  13. openssl req -new -newkey rsa:2048 -sha256 -days 365 -nodes -x509 -keyout /certs/serverkey.pem -out /certs/servercert.pem -subj '/O=Chroma/C=US' -config /etc/ssl/openssl.cnf"
  14. environment:
  15. - CHROMA_DOMAIN=${CHROMA_DOMAIN:-localhost}
  16. envoy:
  17. image: bitnami/envoy
  18. volumes:
  19. - ./envoy.yaml:/opt/bitnami/envoy/conf/envoy.yaml
  20. - ./certs:/etc/envoy/certs
  21. - ./wait-for-certs.sh:/usr/local/bin/wait-for-certs.sh
  22. ports:
  23. - "443:443"
  24. networks:
  25. - net
  26. depends_on:
  27. - cert-gen
  28. entrypoint: |
  29. sh -c "/usr/local/bin/wait-for-certs.sh && \
  30. /opt/bitnami/envoy/bin/envoy -c /opt/bitnami/envoy/conf/envoy.yaml"
  31. chromadb:
  32. image: chromadb/chroma:0.5.5
  33. volumes:
  34. - ./chromadb:/chroma/chroma
  35. environment:
  36. - IS_PERSISTENT=TRUE
  37. - ANONYMIZED_TELEMETRY=${ANONYMIZED_TELEMETRY:-TRUE}
  38. networks:
  39. - net
  40. depends_on:
  41. - envoy

Nginx

Use the following Nginx config (nginx.conf) as a starting point and build from there:

  1. server {
  2. listen 443 ssl;
  3. server_name localhost;
  4. ssl_certificate /etc/nginx/certs/servercert.pem;
  5. ssl_certificate_key /etc/nginx/certs/serverkey.pem;
  6. location / {
  7. proxy_pass http://chromadb:8000;
  8. proxy_set_header Host $host;
  9. proxy_http_version 1.1; # Use HTTP/1.1
  10. proxy_set_header X-Real-IP $remote_addr;
  11. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  12. proxy_set_header X-Forwarded-Proto $scheme;
  13. }
  14. }

Create a docker-compose.yml file with the following content:

Config Files

For the following docker-compose.yaml to operate successfully openssl.cnf and nginx.conf files need to be present in the same directory.

  1. version: '3'
  2. networks:
  3. net:
  4. driver: bridge
  5. services:
  6. cert-gen:
  7. image: openquantumsafe/openssl3
  8. volumes:
  9. - ./certs:/certs
  10. - ./openssl.cnf:/etc/ssl/openssl.cnf
  11. command: |
  12. sh -c "[ -f /certs/servercert.pem ] || \
  13. openssl req -new -newkey rsa:2048 -sha256 -days 365 -nodes -x509 -keyout /certs/serverkey.pem -out /certs/servercert.pem -subj '/O=Chroma/C=US' -config /etc/ssl/openssl.cnf"
  14. environment:
  15. - CHROMA_DOMAIN=${CHROMA_DOMAIN:-localhost}
  16. chromadb:
  17. image: chromadb/chroma:0.5.5
  18. volumes:
  19. - ./chromadb:/chroma/chroma
  20. environment:
  21. - IS_PERSISTENT=TRUE
  22. - ANONYMIZED_TELEMETRY=${ANONYMIZED_TELEMETRY:-TRUE}
  23. ports:
  24. - "8000:8000"
  25. networks:
  26. - net
  27. nginx:
  28. image: nginx:latest
  29. depends_on:
  30. - cert-gen
  31. - chromadb
  32. ports:
  33. - "443:443"
  34. volumes:
  35. - ./nginx.conf:/etc/nginx/conf.d/default.conf
  36. - ./certs:/etc/nginx/certs
  37. networks:
  38. - net

July 31, 2024