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:
Verify the password file:
docker run --rm -v ./server.htpasswd:/server.htpasswd --entrypoint htpasswd httpd:2 -vb /server.htpasswd admin password123
Multiple users
Chroma supports multiple users in the htpasswd file. You can add multiple users by running the command multiple
times WITHOUT -c
flag.
Frequently encountered Chroma errors
If you see the following error:
It is likely that you have not used the -B
(bcrypt) flag when creating the password file.
Environment variables:
export CHROMA_SERVER_AUTHN_CREDENTIALS_FILE="server.htpasswd"
export CHROMA_SERVER_AUTHN_PROVIDER="chromadb.auth.basic_authn.BasicAuthenticationServerProvider"
Running the server:
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
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);
}
}
}
Token Authentication¶
Server
Environment variables:
export CHROMA_SERVER_AUTHN_CREDENTIALS="chr0ma-t0k3n"
export CHROMA_SERVER_AUTHN_PROVIDER="chromadb.auth.token_authn.TokenAuthenticationServerProvider"
export CHROMA_AUTH_TOKEN_TRANSPORT_HEADER="Authorization" # or X-Chroma-Token
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:
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
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!