<!-- # hard line break macro for HTML -->

<a id="enterprise-installation"></a>

# FiftyOne Enterprise Installation

FiftyOne Enterprise deployments come with a centralized FiftyOne Enterprise App
and database that allows your entire team to collaborate securely on the same
datasets. FiftyOne Enterprise is deployed entirely into your environment, either
on-premises or in a private cloud. Your data never leaves your environment.

FiftyOne Enterprise can be deployed on a wide variety of infrastructure
solutions, including Kubernetes and Docker.

#### NOTE
Detailed instructions for the initial FiftyOne Enterprise deployment, along
with all necessary components, are made available by your Voxel51 support
team during the onboarding process.

<a id="enterprise-python-sdk"></a>

## Python SDK

While the [FiftyOne Enterprise App](app.md#enterprise-app) allows for countless new
App-centric workflows, any existing Python-based workflows that you’ve fallen
in love with in the open-source version of FiftyOne are still directly
applicable!

FiftyOne Enterprise requires an updated Python SDK, which is a wrapper around the
open-source FiftyOne package that adds new functionality like support for
cloud-backed media.

You can find the installation instructions under the “Install FiftyOne” section
of the Enterprise App by clicking on your user icon in the upper right corner:

![install-enterprise](images/enterprise/install_fiftyone.png)

There you’ll see instructions for installing a `fiftyone` package from the
private PyPI server as shown below:

```shell
pip install --index-url https://${TOKEN}@pypi.fiftyone.ai fiftyone
```

#### NOTE
See [Installation with Poetry](#enterprise-installation-poetry) if you use
`poetry` instead of `pip`.

#### NOTE
The Enterprise Python package is named `fiftyone` and has the same module
structure as [fiftyone](../api/fiftyone.md), so any existing scripts you
built using open source will continue to run after you upgrade!

### Next steps

After installing the Enterprise Python SDK in your virtual environment, you’ll need
to configure two things:

* Your team’s [API connection](api_connection.md#enterprise-api-connection) or
  [MongoDB connection](../user_guide/config.md#configuring-mongodb-connection)
* The [cloud credentials](#enterprise-cloud-credentials) to access your
  cloud-backed media

That’s it! Any operations you perform will be stored in a centralized location
and will be available to all users with access to the same datasets in the
Enterprise App or their Python workflows.

<a id="enterprise-installation-poetry"></a>

### Installation with Poetry

If you  are using [poetry](https://python-poetry.org/) to install your
dependencies rather than `pip`, you will need to follow instructions in
[the docs for installing from a private repository.](https://python-poetry.org/docs/repositories/#installing-from-private-package-sources)
The two key points are specifying the additional private source and declaring
that the `fiftyone` module should be found there and not the default PyPI
location.

#### Add source

In poetry v1.5, it is recommended to use an
[explicit package source.](https://python-poetry.org/docs/repositories/#explicit-package-sources)

```shell
poetry source add --priority=explicit fiftyone-enterprise https://pypi.fiftyone.ai/simple/
```

Prior to v1.5, you should use the deprecated
[secondary package source.](https://python-poetry.org/docs/1.4/repositories/#secondary-package-sources)

```shell
poetry source add --secondary fiftyone-enterprise https://pypi.fiftyone.ai/simple/
```

#### Configure credentials

```shell
poetry config http-basic.fiftyone-enterprise ${TOKEN} ""
```

Alternatively, you can specify the credentials in environment variables.

```shell
export POETRY_HTTP_BASIC_FIFTYONE_ENTERPRISE_USERNAME="${TOKEN}"
export POETRY_HTTP_BASIC_FIFTYONE_ENTERPRISE_PASSWORD=""
```

If you have trouble configuring the credentials, see
[more in the poetry docs here.](https://python-poetry.org/docs/repositories/#configuring-credentials)

#### Add fiftyone dependency

Replace `X.Y.Z` with the proper version

```default
poetry add --source fiftyone-enterprise fiftyone==X.Y.Z
```

You should then see snippets in the `pyproject.toml` file like the following
(the `priority` line will be different for `poetry<v1.5`):

```toml
[[tool.poetry.source]]
name = "fiftyone-enterprise"
url = "https://pypi.fiftyone.ai"
priority = "explicit"
```

```toml
[tool.poetry.dependencies]
fiftyone = {version = "X.Y.Z", source = "fiftyone-enterprise"}
```

<a id="enterprise-cloud-credentials"></a>

## Cloud credentials

In order to utilize cloud-backed media functionality of FiftyOne Enterprise, at
least one cloud source must be configured with proper credentials. Below are
instructions for configuring each supported cloud provider for local SDK use
or directly to the Enterprise containers. An admin can also [configure
credentials for use by all app users](#enterprise-cloud-storage-page).

<a id="enterprise-cors"></a>

### Cross-origin resource sharing (CORS)

We strongly recommend configuring cross-origin resource sharing (CORS) on your
cloud storage buckets/containers. Most media renders in the App via standard `<img>`/`<video>`
elements that do not require CORS, but any media that the App fetches and
decodes directly in the browser **requires** it, including cloud-backed
[point clouds](../user_guide/using_datasets.md#point-cloud-datasets),
[segmentation maps](../user_guide/using_datasets.md#semantic-segmentation), in-App annotation, and
multimodal (MCAP) datasets. Without CORS, these assets fail to load with a
`No 'Access-Control-Allow-Origin' header is present on the requested resource`
browser error, even when other media displays correctly in the App.

When configuring CORS, set the allowed origin(s) to the URL(s) from which your
users access the FiftyOne Enterprise App, and allow the `GET` and `HEAD`
methods. For media that is read in byte ranges (such as MCAP), also allow the
`Range` request header and expose the `Content-Range`, `Content-Length`,
and `Accept-Ranges` response headers. Details are provided below for each
cloud platform.

### Browser caching

If your datasets include cloud-backed media, we strongly recommend configuring your data
sources to allow for built in browser caching. This will cache signed URL responses
so you don’t need to reload assets from your cloud storage between sessions.
Details are provided below for each cloud platform.

<a id="enterprise-amazon-s3"></a>

### Amazon S3

To work with FiftyOne datasets whose media are stored in Amazon S3, you simply
need to provide
[AWS credentials](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#using-a-configuration-file)
to your Enterprise client with read access to the relevant objects and buckets.

You can do this in any of the following ways:

1. Configure/provide AWS credentials in any format supported by the
[boto3 library](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials).
For example, here are two of the supported methods:

```shell
# Access key
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=... # if applicable
export AWS_DEFAULT_REGION=...
```

```shell
# Web identity provider
export AWS_ROLE_ARN=...
export AWS_WEB_IDENTITY_TOKEN_FILE=...
export AWS_ROLE_SESSION_NAME... #if applicable
export AWS_DEFAULT_REGION=...
```

2. Provide AWS credentials on a per-session basis by setting one of the
following sets of environment variables to point to your AWS credentials on
disk:

```shell
# AWS config file
export AWS_CONFIG_FILE="/path/to/aws-config.ini"
export AWS_PROFILE=default  # optional
```

```shell
# Shared credentials file
export AWS_SHARED_CREDENTIALS_FILE="/path/to/aws-credentials.ini"
export AWS_PROFILE=default  # optional
```

In the above, the config file should use
[this syntax](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#using-a-configuration-file)
and the shared credentials file should use
[this syntax](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#shared-credentials-file).

#### NOTE
FiftyOne Enterprise requires either the `s3:ListBucket` or
`s3:GetBucketLocation` permission in order to access objects in S3 buckets.

If you wish to use multi-account credentials, your credentials must have
the `s3:ListBucket` permission, as `s3:GetBucketLocation` does not support
this.

3. Permanently register AWS credentials on a particular machine by adding the
following keys to your [media cache config](cloud_media.md#enterprise-media-cache-config):

```json
{
    "aws_config_file": "/path/to/aws-config.ini",
    "aws_profile": "default"  # optional
}
```

If you need to [configure CORS on your AWS buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html),
here is an example configuration:

```json
[
    {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["GET", "HEAD"],
        "AllowedOrigins": ["https://fiftyone-enterprise-deployment.yourcompany.com"],
        "ExposeHeaders": ["Content-Range", "Content-Length", "Accept-Ranges"],
        "MaxAgeSeconds": 86400
    }
]
```

If you would like to take advantage of browser caching you can
[specify cache-control headers on S3 objects](https://docs.aws.amazon.com/whitepapers/latest/build-static-websites-aws/controlling-how-long-amazon-s3-content-is-cached-by-amazon-cloudfront.html#specify-cache-control-headers).
By default S3 does not provide cache-control headers so it will be up to your browser’s
heuristics engine to determine how long to cache the object.

<a id="enterprise-google-cloud"></a>

### Google Cloud Storage

To work with FiftyOne datasets whose media are stored in Google Cloud Storage,
you simply need to provide [credentials](https://cloud.google.com/docs/authentication)
to your Enterprise client with read access to the relevant objects and buckets.

You can do this in any of the following ways:

1. Configure
[application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials)
in a manner supported by Google Cloud, such as:

- [Using the gcloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
- [Attaching a service account to your Google Cloud resource](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)

2. Provide GCS credentials on a per-session basis by setting the following
environment variables to point to your GCS credentials on disk:

```shell
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/gcp-credentials.json"
```

3. Permanently register GCS credentials on a particular machine by adding the
following keys to your [media cache config](cloud_media.md#enterprise-media-cache-config):

```json
{
    "google_application_credentials": "/path/to/gcp-credentials.json"
}
```

In the above, the credentials file can contain any format supported by
[google.auth.load_credentials_from_file()](https://google-auth.readthedocs.io/en/master/reference/google.auth.html#google.auth.load_credentials_from_file),
which includes a service account key, stored authorized user credentials, or
external account credentials.

If you need to [configure CORS on your GCP buckets](https://cloud.google.com/storage/docs/using-cors),
here is an example configuration:

```json
[
    {
        "origin": ["https://fiftyone-enterprise-deployment.yourcompany.com"],
        "method": ["GET", "HEAD"],
        "responseHeader": ["Content-Range", "Content-Length", "Accept-Ranges"],
        "maxAgeSeconds": 3600
    }
]
```

If you would like to take advantage of browser caching you can
[specify cache-control headers on GCP content](https://cloud.google.com/storage/docs/metadata#cache-control).
By default GCP sets the max-age=0 seconds meaning no caching will occur.

<a id="enterprise-azure"></a>

### Microsoft Azure


<div class="available-in">
    <div class="available-in-row">
        <span class="available-in-label">Available in:</span>
        <span class="available-in-pill available-in-pill--enterprise">Enterprise</span>
    </div>
    <div class="available-in-row">
        <span class="available-in-versions">Introduced in <a href="../release-notes.html#fiftyone-enterprise-1-2-1">FiftyOne Enterprise 1.2.1</a></span>
    </div>
    
    <div class="available-in-cta">
        <a href="https://voxel51.com/book-a-demo" class="available-in-cta-link" rel="noopener noreferrer" target="_blank">
            Schedule a demo to get started with FiftyOne Enterprise
        </a>
    </div>

</div>

To work with FiftyOne datasets whose media are stored in Azure Storage, you
simply need to provide
[Azure credentials](https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-data-operations-cli)
to your Enterprise client with read access to the relevant objects and containers.

You can do this in any of the following ways:

1. Provide your Azure credentials in any manner recognized by
[azure.identity.DefaultAzureCredential](https://learn.microsoft.com/en-us/python/api/azure-identity/azure.identity.defaultazurecredential?view=azure-python)

2. Provide your Azure credentials on a per-session basis by setting any group
of environment variables shown below:

```shell
# Option 1
export AZURE_STORAGE_CONNECTION_STRING=...
export AZURE_ALIAS=...  # optional
```

```shell
# Option 2
export AZURE_STORAGE_ACCOUNT=...
export AZURE_STORAGE_KEY=...
export AZURE_ALIAS=...  # optional
```

```shell
# Option 3
export AZURE_STORAGE_ACCOUNT=...
export AZURE_CLIENT_ID=...
export AZURE_CLIENT_SECRET=...
export AZURE_TENANT_ID=...
export AZURE_ALIAS=...  # optional
```

3. Provide Azure credentials on a per-session basis by setting the following
environment variables to point to your Azure credentials on disk:

```shell
export AZURE_CREDENTIALS_FILE=/path/to/azure-credentials.ini
export AZURE_PROFILE=default  # optional
```

4. Permanently register Azure credentials on a particular machine by adding the
following keys to your [media cache config](cloud_media.md#enterprise-media-cache-config):

```json
{
    "azure_credentials_file": "/path/to/azure-credentials.ini",
    "azure_profile": "default"  # optional
}
```

In the options above, the `.ini` file should have syntax similar to one of
the following:

```shell
[default]
conn_str = ...
alias = ...  # optional
```

```shell
[default]
account_name = ...
account_key = ...
alias = ...  # optional
```

```shell
[default]
account_name = ...
sas_token = ...
alias = ...  # optional
```

```shell
[default]
account_name = ...
client_id = ...
secret = ...
tenant = ...
alias = ...  # optional
```

#### NOTE
File based cloud credentials support interpolation so make sure to escape
any special characters if you want their literal version to be used.
For example, sas_tokens often contain `%` characters that should be escaped as
`%%` in the .ini file.

When populating samples with Azure Storage filepaths, you can either specify
paths by their full URL:

```python
filepath = "https://${account_name}.blob.core.windows.net/container/path/to/object.ext"

# For example
filepath = "https://voxel51.blob.core.windows.net/test-container/image.jpg"
```

or, if you have defined an alias in your config, you may instead prefix the
alias:

```python
filepath = "${alias}://container/path/to/object.ext"

# For example
filepath = "az://test-container/image.jpg"
```

#### NOTE
If you use a
[custom Azure domain](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-custom-domain-name?tabs=azure-portal),
you can provide it by setting the
`AZURE_STORAGE_ACCOUNT_URL` environment variable or by including the
`account_url` key in your credentials `.ini` file.

If you need to configure CORS on your Azure Blob storage account, you can do so
at the storage-account level (Blob service) via the Azure portal
(**Settings > Resource sharing (CORS)**) or the Azure CLI:

```shell
az storage cors add \
    --services b \
    --methods GET HEAD \
    --origins "https://fiftyone-enterprise-deployment.yourcompany.com" \
    --allowed-headers "*" \
    --exposed-headers "Content-Range" "Content-Length" "Accept-Ranges" \
    --max-age 3600 \
    --account-name "<account-name>"
```

See the
[Azure Storage CORS documentation](https://learn.microsoft.com/en-us/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services)
for more details.

If you would like to take advantage of browser caching you can
[specify cache-control headers on Azure blobs](https://learn.microsoft.com/en-us/azure/cdn/cdn-manage-expiration-of-blob-content#setting-cache-control-headers-by-using-azure-powershell).
By default Azure does not provide cache-control headers so it will be up to your browser’s
heuristics engine to determine how long to cache the object.

<a id="enterprise-minio"></a>

### MinIO

To work with FiftyOne datasets whose media are stored in
[MinIO](https://min.io/), you simply need to provide the credentials to your
Enterprise client with read access to the relevant objects and buckets.

You can do this in any of the following ways:

1. Provide your MinIO credentials on a per-session basis by setting the
individual environment variables shown below:

```shell
export MINIO_ACCESS_KEY=...
export MINIO_SECRET_ACCESS_KEY=...
export MINIO_ENDPOINT_URL=...
export MINIO_ALIAS=...  # optional
export MINIO_REGION=...  # if applicable
```

2. Provide MinIO credentials on a per-session basis by setting the following
environment variables to point to your MinIO credentials on disk:

```shell
export MINIO_CONFIG_FILE=/path/to/minio-config.ini
export MINIO_PROFILE=default  # optional
```

3. Permanently register MinIO credentials on a particular machine by adding the
following keys to your [media cache config](cloud_media.md#enterprise-media-cache-config):

```json
{
    "minio_config_file": "/path/to/minio-config.ini",
    "minio_profile": "default"  # optional
}
```

In the options above, the `.ini` file should have syntax similar the following:

```shell
[default]
access_key = ...
secret_access_key = ...
endpoint_url = ...
alias = ...  # optional
region = ...  # if applicable
```

When populating samples with MinIO filepaths, you can either specify paths by
prefixing your MinIO endpoint URL:

```python
filepath = "${endpoint_url}/bucket/path/to/object.ext"

# For example
filepath = "https://voxel51.min.io/test-bucket/image.jpg"
```

or, if you have defined an alias in your config, you may instead prefix the
alias:

```python
filepath = "${alias}://bucket/path/to/object.ext"

# For example
filepath = "minio://test-bucket/image.jpg"
```

If you would like to take advantage of browser caching you can
[specify cache-control headers on MinIO content using the metadata field of the put_object API](https://min.io/docs/minio/linux/developers/python/API.html).
By default Minio does not provide cache-control headers so it will be up to your browser’s
heuristics engine to determine how long to cache the object.

<a id="enterprise-extra-kwargs"></a>

### Extra client arguments

Configuring credentials following the instructions above is almost always
sufficient for FiftyOne Enterprise to properly utilize them. In rare cases where the
cloud provider client needs non-default configuration, you can add extra client
kwargs via the [media cache config](cloud_media.md#enterprise-media-cache-config):

```json
{
    "extra_client_kwargs": {
        "azure": {"extra_kwarg": "value"},
        "gcs": {"extra_kwarg": "value"},
        "minio": {"extra_kwarg": "value"},
        "s3": {"extra_kwarg": "value"}
    }
}
```

Provider names and the class that extra kwargs are passed to:

<ul class="simple">
    <li> <strong>azure</strong>: <code class="docutils literal notranslate> <span class="pre">azure.identity.DefaultAzureCredential</span></code> </li>
    <li> <strong>gcs</strong>: <code class="docutils literal notranslate> <span class="pre">google.cloud.storage.Client</span></code> </li>
    <li> <strong>minio</strong>: <code class="docutils literal notranslate> <span class="pre">botocore.config.Config</span></code> </li>
    <li> <strong>s3</strong>: <code class="docutils literal notranslate> <span class="pre">botocore.config.Config</span></code> </li>
</ul>

<a id="enterprise-cloud-storage-page"></a>

## Managed cloud credentials

Cloud provider credentials can be managed directly on the Enterprise server.
Managed credentials are automatically loaded for all matching media requests
(App, local SDK, Delegated Operators, etc.) and stored encrypted in the
Enterprise database, eliminating the need for environment variable configuration
in your deployment.

Managed credentials can be scoped to be a specific user or user group, or be
available globally to all users. Any user can configure credentials for their
own use, while only admins can configure group specific or global credentials.

A managed credential can optionally be restricted to a specific list of bucket(s):

* If one or more buckets are provided, the credentials are
  **bucket-specific credentials** that will only be used to read/write media
  within the specified bucket(s)
* If no buckets are provided, the credentials are **default credentials**
  that will be used whenever trying to read/write any media for the provider
  that does not belong to a bucket with bucket-specific credentials

#### NOTE
Bucket-specific credentials are useful in situations where you cannot or
do not wish to provide a single set of credentials to cover all buckets
that your team plans to use within a given cloud storage provider.

When providing bucket-specific credentials, you may either provide bucket
names like `my-bucket`, or you can provide fully-qualified buckets like
`s3://my-bucket` and
`https://voxel51.blob.core.windows.net/my-container`.

#### NOTE
Only one **default credential** can exist per provider and scope. Adding
another default credential for the same provider at the same scope
**replaces** the existing one.

To use multiple credentials for the same provider and scope — for example, two
Azure storage accounts, or two AWS accounts — each credential must be
made bucket-specific by listing its buckets/containers. In particular,
for Azure the storage account name embedded in the credential is **not**
used to route requests; provide fully-qualified containers instead, e.g.
`https://account1.blob.core.windows.net/container1`.

Managed credentials are considered unique based on the scope (user, group,
or global), cloud provider, and the optional bucket(s) they are associated
with. The system will look for credentials in the following default order,
stopping once the first credential is found:

1. If the current user has any bucket-specific credentials that match the
   bucket of the media being accessed, those credentials will be used
2. If the current user belongs to any groups that have bucket-specific
   credentials that match the bucket of the media being accessed, those
   credentials will be used
3. If any global bucket-specific credentials match the bucket of the media
   being accessed, those credentials will be used
4. If the current user has any default credentials for the provider of the
   media being accessed, those credentials will be used
5. If the current user belongs to any groups that have default credentials
   for the provider of the media being accessed, those credentials will be
   used
6. If any global default credentials for the provider of the media being
   accessed exist, those credentials will be used

### Setting managed credentials

Admins can configure cloud credentials via the Settings > Cloud storage page.

To upload a new credential, click the `Add credential` button:

![cloud-creds-add-credentials-button](images/enterprise/cloud_creds_add_btn.png)

This will open a modal that you can use to add a credential for any of the
available providers:

![blank-cloud-creds-modal](images/enterprise/cloud_creds_modal_blank.png)

#### NOTE
Any credentials configured via environment variables in your deployment
will not be displayed in this page.

After the appropriate files or fields are populated, click `Save credential`
to store the (encrypted) credential.

Alternatively, credentials can be updated programmatically with the
[`add_cloud_credentials()`](management_sdk.md#fiftyone.management.cloud_credentials.add_cloud_credentials)
method in the Management SDK.

Any cloud credentials uploaded via this method will automatically be used by
the Enterprise UI when any user attempts to load media associated with the
appropriate provider or specific bucket.

#### NOTE
By default, Enterprise servers refresh their credentials every 120 seconds, so
you may need to wait up to two minutes after modifying your credentials via
this page in order for the changes to take effect.

#### NOTE
Users cannot access stored credentials directly, either via the Enterprise UI or
by using the Enterprise SDK locally. The credentials are only decrypted and
used internally by the Enterprise servers.

<a id="enterprise-cloud-creds-origin-preference"></a>

### Cloud credentials origin preference

If credentials are configured both on the local machine and remotely via the
Enterprise server, the behavior is for the Enterprise SDK to use the first
matching set of credentials found.

* When running the Enterprise SDK locally, the default is to use local
  credentials, if any exist, and otherwise to use managed credentials returned
  by the Enterprise server.
* However, if the Enterprise SDK is being used in an Internal Service (App
  server, delegated operator, etc.) the default is to prefer managed
  credentials returned by the Enterprise server.

This can be manually controlled by setting the
`FIFTYONE_CLOUD_CREDS_ORIGIN_PREFERENCE` environment variable on the machine to
either `local` or `remote`. Regardless of the preference, credentials from both
sources will be considered if the default location has none that match. So if
credentials from the preferred source have no matches for a given request,
credentials from the other source will be attempted before giving up.

<a id="enterprise-cloud-creds-local-download"></a>

### Cloud credentials local download

By default, users must set up local credentials when using the Enterprise SDK
with an API connection. This is to prevent downloading credentials from the
Enterprise server to that user’s local machine. However, you can change this
default, so that local SDK usage will download credentials from the Enterprise
server, and there is no need to configure credentials locally. To enable
downloading of credentials to machines, set the environment variable
`FEATURE_FLAG_ENABLE_CREDS_LOCAL_USE` to `True` in the `teams-api` container.

<a id="enterprise-ai-model-weights"></a>

## AI model weights


<div class="available-in">
    <div class="available-in-row">
        <span class="available-in-label">Available in:</span>
        <span class="available-in-pill available-in-pill--enterprise">Enterprise</span>
    </div>
    <div class="available-in-row">
        <span class="available-in-versions">Introduced in <a href="../release-notes.html#fiftyone-enterprise-2-19-0">FiftyOne Enterprise 2.19.0</a></span>
    </div>
    
    <div class="available-in-cta">
        <a href="https://voxel51.com/book-a-demo" class="available-in-cta-link" rel="noopener noreferrer" target="_blank">
            Schedule a demo to get started with FiftyOne Enterprise
        </a>
    </div>

</div>

The FiftyOne Enterprise App ships with AI-assisted mask segmentation for annotation
workflows. By default, the required model weights are served from Voxel51’s
CDN and no configuration is required.

Deployments that prefer to serve the weights from their own infrastructure
can set the optional `FIFTYONE_MODEL_WEIGHTS_BASE_SAM2` environment
variable on the `fiftyone-app` container. The value is a base URL or
cloud path that hosts the weights. The App appends the specific weight
file to it at request time.

The base location must host the two files that the App fetches:

* `encoder.with_runtime_opt.ort`
* `decoder.onnx`

The SAM2 tiny variant is recommended for optimal user experience. The
simplest way to populate your own location is to mirror the files Voxel51
serves from its CDN, which are the canonical artifacts that the App is
built against:

```shell
curl -sSL -o encoder.with_runtime_opt.ort \
    https://models-cdn.voxel51.com/sam2/encoder.with_runtime_opt.ort
curl -sSL -o decoder.onnx \
    https://models-cdn.voxel51.com/sam2/decoder.onnx
```

Then upload both files to the location referenced by
`FIFTYONE_MODEL_WEIGHTS_BASE_SAM2`.

```shell
# Private GCS bucket
FIFTYONE_MODEL_WEIGHTS_BASE_SAM2=gs://my-bucket/sam2

# Private S3 bucket
FIFTYONE_MODEL_WEIGHTS_BASE_SAM2=s3://my-bucket/sam2

# Private HTTPS endpoint
FIFTYONE_MODEL_WEIGHTS_BASE_SAM2=https://cdn.internal.example.com/sam2
```

When a cloud path is used, URLs are signed automatically using the
deployment’s [cloud credentials](#enterprise-cloud-credentials), so
the `fiftyone-app` container must have read access to the bucket.
