Chroma-native Auth
Chroma offers built in authentication and authorization mechanisms to secure your Chroma instance.
Auth Disabled by Default
By default, Chroma does not require authentication. You must enable it manually. If you are deploying Chroma in a public-facing environment, it is highly recommended to enable authentication.
Auth needs the company of SSL/TLS
Authentication without encryption is insecure. If you are deploying Chroma in a public-facing environment, it is highly recommended that you add (SSL/TLS)[ssl-proxy.md].
Authentication
Chroma supports two types of authentication:
- Basic Auth - RFC 7617 compliant pre-emptive authentication with username and password credentials in Authorization header.
- Token Auth - Standard token-based auth with
Authorization
orX-Chroma-Token
headers.
For each authentication method there are configurations in both client and server.
Basic Authentication
Server
Generate a password file with bcrypt hashed password:
Multiple users
Chroma supports multiple users in the htpasswd file. You can add multiple users by running the command multiple times WITHOUT -c
flag.
Environment variables:
Running the server:
CLIDockerDocker Compose
Create a docker-compose.yaml
with the following content:
networks:
net:
driver: bridge
services:
chromadb:
image: chromadb/chroma:latest
volumes:
- ./chromadb:/chroma/chroma
- ./server.htpasswd:/chroma/server.htpasswd
environment:
- IS_PERSISTENT=TRUE
- PERSIST_DIRECTORY=/chroma/chroma # this is the default path, change it as needed
- ANONYMIZED_TELEMETRY=${ANONYMIZED_TELEMETRY:-TRUE}
- CHROMA_SERVER_AUTHN_CREDENTIALS_FILE=server.htpasswd
- CHROMA_SERVER_AUTHN_PROVIDER=chromadb.auth.basic_authn.BasicAuthenticationServerProvider
ports:
- 8000:8000
networks:
- net
Run the following command to start the Chroma server:
Is my config right?
If you have correctly configured the server you should see the following line in the server logs:
Client
PythonJSGoJava
import chromadb
from chromadb.config import Settings
client = chromadb.HttpClient(
settings=Settings(
chroma_client_auth_provider="chromadb.auth.basic_authn.BasicAuthClientProvider",
chroma_client_auth_credentials="admin:admin")
)
# if everything is correctly configured the below should list all collections
client.list_collections()
package main
import (
"context"
"log"
chroma "github.com/amikos-tech/chroma-go"
"github.com/amikos-tech/chroma-go/types"
)
func main() {
client, err := chroma.NewClient(
chroma.WithBasePath("http://localhost:8000"),
chroma.WithAuth(types.NewBasicAuthCredentialsProvider("admin", "admin")),
)
if err != nil {
log.Fatalf("Error creating client: %s \n", err)
}
_, err = client.ListCollections(context.TODO())
if err != nil {
log.Fatalf("Error calling ListCollections: %s \n", err)
}
}
The below example shows auth with just headers. A more robust authentication mechanism is being implemented.
package tech.amikos;
import tech.amikos.chromadb.*;
import tech.amikos.chromadb.Collection;
import java.util.*;
public class Main {
public static void main(String[] args) {
try {
Client client = new Client(System.getenv("http://localhost:8000"));
client.setDefaultHeaders(new HashMap<>() {{
put("Authorization", "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes()));
}});
// your code here
} catch (Exception e) {
System.out.println(e);
}
}
}
Testing with cURL
Token Authentication
Server
Environment variables:
Auth Headers
Chroma supports two token transport headers:
Authorization
(default) - the clients are expected to passAuthorization: Bearer <token>
headerX-Chroma-Token
- the clients are expected to passX-Chroma-Token: <token>
header
The header can be configured via CHROMA_AUTH_TOKEN_TRANSPORT_HEADER
environment variable.
Running the server:
CLIDockerDocker Compose
Create a docker-compose.yaml
with the following content:
networks:
net:
driver: bridge
services:
chromadb:
image: chromadb/chroma:latest
volumes:
- ./chromadb:/chroma/chroma
- ./server.htpasswd:/chroma/server.htpasswd
environment:
- IS_PERSISTENT=TRUE
- PERSIST_DIRECTORY=/chroma/chroma # this is the default path, change it as needed
- ANONYMIZED_TELEMETRY=${ANONYMIZED_TELEMETRY:-TRUE}
- CHROMA_SERVER_AUTHN_CREDENTIALS="chr0ma-t0k3n"
- CHROMA_AUTH_TOKEN_TRANSPORT_HEADER="Authorization"
- CHROMA_SERVER_AUTHN_PROVIDER=chromadb.auth.token_authn.TokenAuthenticationServerProvider
ports:
- 8000:8000
networks:
- net
Run the following command to start the Chroma server:
Is my config right?
If you have correctly configured the server you should see the following line in the server logs:
Client
PythonJSGoJava
import chromadb
from chromadb.config import Settings
client = chromadb.HttpClient(
settings=Settings(
chroma_client_auth_provider="chromadb.auth.token_authn.TokenAuthClientProvider",
chroma_client_auth_credentials="chr0ma-t0k3n",
chroma_client_auth_token_transport_header="Authorization"
)
)
# if everything is correctly configured the below should list all collections
client.list_collections()
package main
import (
"context"
"log"
chroma "github.com/amikos-tech/chroma-go"
"github.com/amikos-tech/chroma-go/types"
)
func main() {
client, err := chroma.NewClient(
chroma.WithBasePath("http://localhost:8000"),
chroma.WithAuth(types.NewTokenAuthCredentialsProvider("chr0ma-t0k3n", types.AuthorizationTokenHeader)),
)
if err != nil {
log.Fatalf("Error creating client: %s \n", err)
}
_, err = client.ListCollections(context.TODO())
if err != nil {
log.Fatalf("Error calling ListCollections: %s \n", err)
}
}
The example below shows authorization with just headers. A more robust auth mechanism is under implementation.
package tech.amikos;
import tech.amikos.chromadb.*;
import tech.amikos.chromadb.Collection;
import java.util.*;
public class Main {
public static void main(String[] args) {
try {
Client client = new Client(System.getenv("http://localhost:8000"));
client.setDefaultHeaders(new HashMap<>() {{
put("Authorization", "Bearer chr0ma-t0k3n");
}});
// your code here
} catch (Exception e) {
System.out.println(e);
}
}
}
Testing with cURL
Authorization
Coming soon!
September 6, 2024