first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,378 @@
---
title: "AWS Deployment"
description: "Deploy Bifrost Enterprise on AWS using ECR with IRSA or IAM Task Roles"
icon: "aws"
---
Bifrost Enterprise images for AWS customers are distributed through AWS ECR, enabling native IAM integration for secure, credential-less authentication.
## Architecture
```mermaid
flowchart LR
subgraph AWS[AWS Account]
subgraph EKS[EKS Cluster]
Pod[Bifrost Pod]
KSA[K8s ServiceAccount]
end
IAMRole[IAM Role]
ECR[AWS ECR<br/>Bifrost Images]
end
KSA -->|Annotated with| IAMRole
Pod -->|Assumes| IAMRole
IAMRole -->|Pull Permission| ECR
ECR -->|Image| Pod
```
## Prerequisites
- EKS cluster (v1.23+) or ECS cluster
- AWS CLI configured with appropriate permissions
- `kubectl` configured for your EKS cluster
- Your AWS Account ID allowlisted by Bifrost team
<Note>
Contact the Bifrost team to get your AWS account ID and IAM role ARN allowlisted for ECR access.
</Note>
## IRSA (Recommended)
IAM Roles for Service Accounts (IRSA) provides the most secure authentication method for EKS deployments.
### Step 1: Create IAM Policy
Create an IAM policy that grants ECR pull access to the Bifrost repository.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ECRAuth",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Sid": "ECRPullFromBifrost",
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchCheckLayerAvailability"
],
"Resource": "arn:aws:ecr:us-east-1:BIFROST_ACCOUNT_ID:repository/YOUR_HUB_SLUG"
}
]
}
```
<Warning>
Replace `BIFROST_ACCOUNT_ID` and `YOUR_HUB_SLUG` with the values provided by the Bifrost team.
</Warning>
Save this policy as `bifrost-ecr-pull-policy.json` and create it:
```bash
aws iam create-policy \
--policy-name BifrostECRPullPolicy \
--policy-document file://bifrost-ecr-pull-policy.json
```
### Step 2: Create IAM Role with OIDC Trust
Create an IAM role that can be assumed by your Kubernetes ServiceAccount.
First, get your OIDC provider URL:
```bash
aws eks describe-cluster \
--name YOUR_CLUSTER_NAME \
--query "cluster.identity.oidc.issuer" \
--output text
```
Create the trust policy (`trust-policy.json`):
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::YOUR_ACCOUNT_ID:oidc-provider/oidc.eks.REGION.amazonaws.com/id/OIDC_ID"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.REGION.amazonaws.com/id/OIDC_ID:aud": "sts.amazonaws.com",
"oidc.eks.REGION.amazonaws.com/id/OIDC_ID:sub": "system:serviceaccount:NAMESPACE:bifrost-sa"
}
}
}
]
}
```
Create the role and attach the policy:
```bash
# Create the role
aws iam create-role \
--role-name BifrostECRPullRole \
--assume-role-policy-document file://trust-policy.json
# Attach the policy
aws iam attach-role-policy \
--role-name BifrostECRPullRole \
--policy-arn arn:aws:iam::YOUR_ACCOUNT_ID:policy/BifrostECRPullPolicy
```
### Step 3: Provide Role ARN to Bifrost
Send your IAM role ARN to the Bifrost team for allowlisting:
```
arn:aws:iam::YOUR_ACCOUNT_ID:role/BifrostECRPullRole
```
### Step 4: Create Namespace and ServiceAccount
```bash
kubectl create namespace bifrost
```
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: bifrost-sa
namespace: bifrost
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::YOUR_ACCOUNT_ID:role/BifrostECRPullRole
```
### Step 5: Deploy Bifrost
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: bifrost
namespace: bifrost
spec:
replicas: 2
selector:
matchLabels:
app: bifrost
template:
metadata:
labels:
app: bifrost
spec:
serviceAccountName: bifrost-sa
containers:
- name: bifrost
image: BIFROST_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/YOUR_HUB_SLUG:latest
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "2Gi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /app/data/config.json
subPath: config.json
volumes:
- name: config
secret:
secretName: bifrost-config
---
apiVersion: v1
kind: Service
metadata:
name: bifrost
namespace: bifrost
spec:
selector:
app: bifrost
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: ClusterIP
```
## ECS Task Roles
For ECS deployments, use IAM Task Roles for authentication.
### Step 1: Create Task Execution Role
The task execution role allows ECS to pull images from ECR.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "arn:aws:ecr:us-east-1:BIFROST_ACCOUNT_ID:repository/YOUR_HUB_SLUG"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
```
### Step 2: Create ECS Task Definition
```json
{
"family": "bifrost",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::YOUR_ACCOUNT_ID:role/BifrostECSExecutionRole",
"containerDefinitions": [
{
"name": "bifrost",
"image": "BIFROST_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/YOUR_HUB_SLUG:latest",
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/bifrost",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "bifrost"
}
}
}
]
}
```
### Step 3: Create ECS Service
```bash
aws ecs create-service \
--cluster your-cluster \
--service-name bifrost \
--task-definition bifrost \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-xxx],securityGroups=[sg-xxx],assignPublicIp=ENABLED}"
```
## Verifying Access
### Test ECR Authentication
```bash
# Get ECR login token
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
BIFROST_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
# Pull test
docker pull BIFROST_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/YOUR_HUB_SLUG:latest
```
### Verify IRSA Configuration
```bash
# Check ServiceAccount annotation
kubectl get sa bifrost-sa -n bifrost -o yaml
# Verify pod can assume role
kubectl exec -it deployment/bifrost -n bifrost -- \
aws sts get-caller-identity
```
## Troubleshooting
### ImagePullBackOff Errors
1. **Check IAM Role trust policy**: Ensure the OIDC provider and ServiceAccount match
2. **Verify ECR permissions**: Confirm the role has `ecr:BatchGetImage` permission
3. **Check allowlisting**: Ensure your role ARN is allowlisted by Bifrost team
```bash
# Check pod events
kubectl describe pod -l app=bifrost -n bifrost
# Check IRSA token
kubectl exec -it deployment/bifrost -n bifrost -- \
cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token
```
### Authentication Errors
```bash
# Verify OIDC provider is configured
aws iam list-open-id-connect-providers
# Check role assumption
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::YOUR_ACCOUNT_ID:role/BifrostECRPullRole \
--role-session-name test \
--web-identity-token file:///path/to/token
```
## Next Steps
- Configure [Bifrost settings](/quickstart/gateway/setting-up) for your use case
- Set up [observability](/features/observability/default) for monitoring
- Enable [clustering](/enterprise/clustering) for high availability

View File

@@ -0,0 +1,451 @@
---
title: "Azure Deployment"
description: "Deploy Bifrost Enterprise on Azure AKS using Workload Identity Federation to GCP Artifact Registry"
icon: "microsoft"
---
Bifrost Enterprise images for Azure customers are distributed through GCP Artifact Registry, using Azure Workload Identity Federation for secure, credential-less authentication.
## Architecture
```mermaid
flowchart LR
subgraph Azure[Azure Subscription]
subgraph AKS[AKS Cluster]
Pod[Bifrost Pod]
KSA[K8s ServiceAccount]
end
MI[Managed Identity]
end
subgraph GCP[GCP Project]
WIF[Workload Identity<br/>Federation Pool]
GSA[GCP Service Account]
AR[Artifact Registry<br/>Bifrost Images]
end
KSA -->|Federated| MI
MI -->|OIDC Token| WIF
WIF -->|Exchange| GSA
GSA -->|Pull Permission| AR
AR -->|Image| Pod
```
## How It Works
Azure Workload Identity Federation allows Azure Managed Identities to authenticate to GCP without exchanging credentials:
1. **AKS Pod** requests a token using its Kubernetes ServiceAccount
2. **Azure AD** issues an OIDC token for the Managed Identity
3. **GCP Workload Identity Federation** validates the Azure token
4. **GCP STS** exchanges it for a GCP access token
5. **Pod** uses the GCP token to pull images from Artifact Registry
## Prerequisites
- AKS cluster (v1.24+) with Workload Identity enabled
- Azure CLI configured with appropriate permissions
- `kubectl` configured for your AKS cluster
- Your Azure Tenant ID and Managed Identity Client ID provided to Bifrost team
<Note>
Contact the Bifrost team with your Azure Tenant ID and Managed Identity Client IDs to get access configured.
</Note>
## Step 1: Enable Workload Identity on AKS
If not already enabled, enable Workload Identity on your AKS cluster:
```bash
# For existing cluster
az aks update \
--resource-group YOUR_RESOURCE_GROUP \
--name YOUR_CLUSTER_NAME \
--enable-oidc-issuer \
--enable-workload-identity
# Get the OIDC issuer URL
az aks show \
--resource-group YOUR_RESOURCE_GROUP \
--name YOUR_CLUSTER_NAME \
--query "oidcIssuerProfile.issuerUrl" -o tsv
```
## Step 2: Create Azure Managed Identity
```bash
# Create Managed Identity
az identity create \
--name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP \
--location YOUR_LOCATION
# Get the Client ID
CLIENT_ID=$(az identity show \
--name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP \
--query clientId -o tsv)
echo "Client ID: $CLIENT_ID"
```
## Step 3: Create Federated Credential
Link the Kubernetes ServiceAccount to the Azure Managed Identity:
```bash
# Get AKS OIDC issuer
AKS_OIDC_ISSUER=$(az aks show \
--resource-group YOUR_RESOURCE_GROUP \
--name YOUR_CLUSTER_NAME \
--query "oidcIssuerProfile.issuerUrl" -o tsv)
# Create federated credential
az identity federated-credential create \
--name bifrost-federated-credential \
--identity-name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP \
--issuer "$AKS_OIDC_ISSUER" \
--subject "system:serviceaccount:bifrost:bifrost-sa" \
--audience "api://AzureADTokenExchange"
```
## Step 4: Provide Details to Bifrost Team
Send the following information to the Bifrost team:
```bash
# Get Tenant ID
az account show --query tenantId -o tsv
# Get Client ID
az identity show \
--name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP \
--query clientId -o tsv
```
The Bifrost team will configure GCP Workload Identity Federation to trust your Azure Managed Identity.
## Step 5: Store GCP Credential Configuration
After the Bifrost team configures access, they will provide a credential configuration. Store it as a ConfigMap:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: gcp-credential-config
namespace: bifrost
data:
credential-config.json: |
{
"type": "external_account",
"audience": "//iam.googleapis.com/projects/BIFROST_PROJECT_NUMBER/locations/global/workloadIdentityPools/YOUR_HUB_SLUG-azure-pool/providers/YOUR_HUB_SLUG-azure-provider",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/BIFROST_SA@BIFROST_PROJECT.iam.gserviceaccount.com:generateAccessToken",
"token_url": "https://sts.googleapis.com/v1/token",
"credential_source": {
"file": "/var/run/secrets/azure/tokens/azure-identity-token",
"format": {
"type": "text"
}
}
}
```
<Warning>
The Bifrost team will provide the exact values for `BIFROST_PROJECT_NUMBER`, `YOUR_HUB_SLUG`, and `BIFROST_SA`.
</Warning>
## Step 6: Create Kubernetes ServiceAccount
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: bifrost-sa
namespace: bifrost
annotations:
azure.workload.identity/client-id: YOUR_MANAGED_IDENTITY_CLIENT_ID
labels:
azure.workload.identity/use: "true"
```
## Step 7: Create Image Pull Secret with Token Refresh
Create a CronJob to refresh the imagePullSecret using the federated identity:
```yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: refresh-ar-secret
namespace: bifrost
spec:
schedule: "*/30 * * * *" # Every 30 minutes
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
metadata:
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: bifrost-sa
containers:
- name: token-refresh
image: google/cloud-sdk:slim
command: ["/bin/bash", "-c"]
args:
- |
set -e
# Set GCP credential config
export GOOGLE_APPLICATION_CREDENTIALS=/etc/gcp/credential-config.json
# Get GCP access token via federation
TOKEN=$(gcloud auth print-access-token)
# Delete existing secret if it exists
kubectl delete secret ar-pull-secret --ignore-not-found -n bifrost
# Create new imagePullSecret
kubectl create secret docker-registry ar-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=oauth2accesstoken \
--docker-password="$TOKEN" \
-n bifrost
echo "Secret refreshed at $(date)"
volumeMounts:
- name: gcp-credential-config
mountPath: /etc/gcp
readOnly: true
- name: azure-identity-token
mountPath: /var/run/secrets/azure/tokens
readOnly: true
volumes:
- name: gcp-credential-config
configMap:
name: gcp-credential-config
- name: azure-identity-token
projected:
sources:
- serviceAccountToken:
path: azure-identity-token
expirationSeconds: 3600
audience: api://AzureADTokenExchange
restartPolicy: OnFailure
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-manager
namespace: bifrost
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secret-manager-binding
namespace: bifrost
subjects:
- kind: ServiceAccount
name: bifrost-sa
namespace: bifrost
roleRef:
kind: Role
name: secret-manager
apiGroup: rbac.authorization.k8s.io
```
## Step 8: Deploy Bifrost
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: bifrost
namespace: bifrost
spec:
replicas: 2
selector:
matchLabels:
app: bifrost
template:
metadata:
labels:
app: bifrost
azure.workload.identity/use: "true"
spec:
serviceAccountName: bifrost-sa
imagePullSecrets:
- name: ar-pull-secret
containers:
- name: bifrost
image: REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "2Gi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /app/data/config.json
subPath: config.json
volumes:
- name: config
secret:
secretName: bifrost-config
---
apiVersion: v1
kind: Service
metadata:
name: bifrost
namespace: bifrost
spec:
selector:
app: bifrost
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: ClusterIP
```
## Bootstrap: Initial Secret Creation
Before the first deployment, manually trigger the CronJob or create the secret:
```bash
# Create namespace
kubectl create namespace bifrost
# Apply all configurations
kubectl apply -f configmap.yaml
kubectl apply -f serviceaccount.yaml
kubectl apply -f cronjob.yaml
# Manually trigger the CronJob
kubectl create job --from=cronjob/refresh-ar-secret initial-refresh -n bifrost
# Wait for completion
kubectl wait --for=condition=complete job/initial-refresh -n bifrost --timeout=120s
# Verify secret was created
kubectl get secret ar-pull-secret -n bifrost
```
## Verifying Access
### Check Workload Identity Configuration
```bash
# Verify AKS has Workload Identity enabled
az aks show \
--resource-group YOUR_RESOURCE_GROUP \
--name YOUR_CLUSTER_NAME \
--query "oidcIssuerProfile.enabled" -o tsv
# Check federated credential
az identity federated-credential show \
--name bifrost-federated-credential \
--identity-name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP
```
### Verify Token Exchange
```bash
# Check CronJob ran successfully
kubectl get jobs -n bifrost
# View CronJob logs
kubectl logs -l job-name=refresh-ar-secret -n bifrost
# Verify imagePullSecret exists
kubectl get secret ar-pull-secret -n bifrost -o yaml
```
## Troubleshooting
### ImagePullBackOff Errors
1. **Check imagePullSecret exists**: `kubectl get secret ar-pull-secret -n bifrost`
2. **Verify CronJob succeeded**: `kubectl get jobs -n bifrost`
3. **Check Azure Workload Identity**: Ensure labels are set correctly
```bash
# Check pod events
kubectl describe pod -l app=bifrost -n bifrost
# Check ServiceAccount has correct annotations
kubectl get sa bifrost-sa -n bifrost -o yaml
```
### Token Exchange Failures
```bash
# Check CronJob logs for errors
kubectl logs -l job-name=refresh-ar-secret -n bifrost
# Common issues:
# - "audience mismatch": Check credential-config.json audience field
# - "subject mismatch": Verify federated credential subject matches SA
# - "permission denied": Contact Bifrost team to verify WIF configuration
```
### Azure Workload Identity Issues
```bash
# Verify Managed Identity exists
az identity show \
--name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP
# Check federated credentials
az identity federated-credential list \
--identity-name bifrost-pull-identity \
--resource-group YOUR_RESOURCE_GROUP
# Verify pod has identity token mounted
kubectl exec -it deployment/bifrost -n bifrost -- \
ls -la /var/run/secrets/azure/tokens/
```
## Summary
| Component | Value |
|-----------|-------|
| Registry | GCP Artifact Registry |
| Authentication | Azure WIF -> GCP WIF -> GCP SA |
| Token Lifetime | 60 minutes (auto-refreshed every 30 min) |
| Secret Name | `ar-pull-secret` |
## Next Steps
- Configure [Bifrost settings](/quickstart/gateway/setting-up) for your use case
- Set up [observability](/features/observability/default) for monitoring
- Enable [clustering](/enterprise/clustering) for high availability

View File

@@ -0,0 +1,386 @@
---
title: "GCP Deployment"
description: "Deploy Bifrost Enterprise on GCP using Artifact Registry with Workload Identity"
icon: "google"
---
Bifrost Enterprise images for GCP customers are distributed through GCP Artifact Registry, enabling native Workload Identity for secure, keyless authentication.
## Architecture
```mermaid
flowchart LR
subgraph GCP[GCP Project]
subgraph GKE[GKE Cluster]
Pod[Bifrost Pod]
KSA[K8s ServiceAccount]
end
GSA[GCP Service Account]
AR[Artifact Registry<br/>Bifrost Images]
end
KSA -->|Workload Identity| GSA
Pod -->|Impersonates| GSA
GSA -->|Pull Permission| AR
AR -->|Image| Pod
```
## Prerequisites
- GKE cluster (v1.24+) with Workload Identity enabled
- `gcloud` CLI configured with appropriate permissions
- `kubectl` configured for your GKE cluster
- Your GCP project allowlisted by Bifrost team
<Note>
Contact the Bifrost team with your GCP project ID and service account email to get access configured.
</Note>
## Workload Identity (Recommended)
Workload Identity provides the most secure authentication method for GKE deployments by eliminating the need for service account keys.
### Step 1: Enable Workload Identity on GKE
If not already enabled, enable Workload Identity on your cluster:
```bash
# For existing cluster
gcloud container clusters update YOUR_CLUSTER_NAME \
--region=YOUR_REGION \
--workload-pool=YOUR_PROJECT_ID.svc.id.goog
# Verify Workload Identity is enabled
gcloud container clusters describe YOUR_CLUSTER_NAME \
--region=YOUR_REGION \
--format="value(workloadIdentityConfig.workloadPool)"
```
### Step 2: Create GCP Service Account
Create a service account that will be used to pull images:
```bash
# Create service account
gcloud iam service-accounts create bifrost-pull-sa \
--display-name="Bifrost Image Pull SA" \
--project=YOUR_PROJECT_ID
```
### Step 3: Request Access from Bifrost Team
Provide the following to the Bifrost team:
- Your GCP project ID
- Service account email: `bifrost-pull-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com`
The Bifrost team will grant the necessary permissions to pull images from the registry.
### Step 4: Create Namespace and ServiceAccount
```bash
kubectl create namespace bifrost
```
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: bifrost-sa
namespace: bifrost
annotations:
iam.gke.io/gcp-service-account: bifrost-pull-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
```
### Step 5: Bind Kubernetes SA to GCP SA
Allow the Kubernetes ServiceAccount to impersonate the GCP Service Account:
```bash
gcloud iam service-accounts add-iam-policy-binding \
bifrost-pull-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="serviceAccount:YOUR_PROJECT_ID.svc.id.goog[bifrost/bifrost-sa]"
```
### Step 6: Create Image Pull Secret with Token Refresh
Artifact Registry tokens expire after 60 minutes. Use a CronJob to refresh the imagePullSecret:
```yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: refresh-ar-secret
namespace: bifrost
spec:
schedule: "*/30 * * * *" # Every 30 minutes
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
serviceAccountName: bifrost-sa
containers:
- name: token-refresh
image: google/cloud-sdk:slim
command: ["/bin/bash", "-c"]
args:
- |
set -e
# Get access token using Workload Identity
TOKEN=$(gcloud auth print-access-token)
# Delete existing secret if it exists
kubectl delete secret ar-pull-secret --ignore-not-found -n bifrost
# Create new imagePullSecret
kubectl create secret docker-registry ar-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=oauth2accesstoken \
--docker-password="$TOKEN" \
-n bifrost
echo "Secret refreshed at $(date)"
restartPolicy: OnFailure
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-manager
namespace: bifrost
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secret-manager-binding
namespace: bifrost
subjects:
- kind: ServiceAccount
name: bifrost-sa
namespace: bifrost
roleRef:
kind: Role
name: secret-manager
apiGroup: rbac.authorization.k8s.io
```
<Warning>
Replace `REGION` with your Artifact Registry region (e.g., `us-central1`).
</Warning>
### Step 7: Deploy Bifrost
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: bifrost
namespace: bifrost
spec:
replicas: 2
selector:
matchLabels:
app: bifrost
template:
metadata:
labels:
app: bifrost
spec:
serviceAccountName: bifrost-sa
imagePullSecrets:
- name: ar-pull-secret
containers:
- name: bifrost
image: REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "2Gi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /app/data/config.json
subPath: config.json
volumes:
- name: config
secret:
secretName: bifrost-config
---
apiVersion: v1
kind: Service
metadata:
name: bifrost
namespace: bifrost
spec:
selector:
app: bifrost
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: ClusterIP
```
### Bootstrap: Initial Secret Creation
Before the first deployment, manually create the initial imagePullSecret:
```bash
# Authenticate gcloud
gcloud auth login
# Create initial secret
kubectl create secret docker-registry ar-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=oauth2accesstoken \
--docker-password="$(gcloud auth print-access-token)" \
-n bifrost
```
## Service Account Impersonation
For cross-project deployments or when you need to use an existing service account:
### Configure Impersonation
```bash
# Grant impersonation permission
gcloud iam service-accounts add-iam-policy-binding \
BIFROST_PROVIDED_SA@BIFROST_PROJECT.iam.gserviceaccount.com \
--role=roles/iam.serviceAccountTokenCreator \
--member="serviceAccount:bifrost-pull-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com"
```
### Token Refresh with Impersonation
Update the CronJob to use impersonation:
```yaml
args:
- |
set -e
# Get access token by impersonating the Bifrost SA
TOKEN=$(gcloud auth print-access-token \
--impersonate-service-account=BIFROST_PROVIDED_SA@BIFROST_PROJECT.iam.gserviceaccount.com)
kubectl delete secret ar-pull-secret --ignore-not-found -n bifrost
kubectl create secret docker-registry ar-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=oauth2accesstoken \
--docker-password="$TOKEN" \
-n bifrost
```
## Service Account Key (Legacy)
<Warning>
Service account keys are not recommended for production. Use Workload Identity instead.
</Warning>
For environments that cannot use Workload Identity:
```bash
# Create key (provided by Bifrost team)
# Store key securely
# Create imagePullSecret
kubectl create secret docker-registry ar-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=_json_key \
--docker-password="$(cat sa-key.json)" \
-n bifrost
```
## Verifying Access
### Test Artifact Registry Authentication
```bash
# Configure docker for Artifact Registry
gcloud auth configure-docker REGION-docker.pkg.dev
# Pull test (requires impersonation or direct access)
docker pull REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
```
### Verify Workload Identity Configuration
```bash
# Check ServiceAccount annotation
kubectl get sa bifrost-sa -n bifrost -o yaml
# Verify pod can authenticate
kubectl exec -it deployment/bifrost -n bifrost -- \
gcloud auth print-access-token
# Check token refresh CronJob
kubectl get cronjob refresh-ar-secret -n bifrost
kubectl get jobs -n bifrost
```
## Troubleshooting
### ImagePullBackOff Errors
1. **Check imagePullSecret exists**: `kubectl get secret ar-pull-secret -n bifrost`
2. **Verify token is valid**: Check if CronJob ran successfully
3. **Check Workload Identity binding**: Ensure GCP SA is bound to K8s SA
```bash
# Check pod events
kubectl describe pod -l app=bifrost -n bifrost
# Manually refresh token
kubectl create job --from=cronjob/refresh-ar-secret manual-refresh -n bifrost
```
### Workload Identity Issues
```bash
# Verify Workload Identity pool
gcloud container clusters describe YOUR_CLUSTER_NAME \
--region=YOUR_REGION \
--format="value(workloadIdentityConfig.workloadPool)"
# Check IAM binding
gcloud iam service-accounts get-iam-policy \
bifrost-pull-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
```
### Token Expiration
If pods fail to pull images after 60 minutes:
1. Verify CronJob is running: `kubectl get cronjob -n bifrost`
2. Check CronJob logs: `kubectl logs -l job-name=refresh-ar-secret -n bifrost`
3. Manually trigger refresh: `kubectl create job --from=cronjob/refresh-ar-secret manual-refresh -n bifrost`
## Next Steps
- Configure [Bifrost settings](/quickstart/gateway/setting-up) for your use case
- Set up [observability](/features/observability/default) for monitoring
- Enable [clustering](/enterprise/clustering) for high availability

View File

@@ -0,0 +1,541 @@
---
title: "On-Premise Deployment"
description: "Deploy Bifrost Enterprise in on-premise or air-gapped environments using Docker credentials"
icon: "server"
---
Bifrost Enterprise supports on-premise deployments for environments that cannot use cloud-native identity federation. Images are pulled from GCP Artifact Registry using username/password authentication.
## Architecture
```mermaid
flowchart LR
subgraph OnPrem[On-Premise Environment]
subgraph K8s[Kubernetes Cluster]
Pod[Bifrost Pod]
Secret[imagePullSecret]
end
Docker[Docker Daemon]
end
subgraph GCP[GCP]
AR[Artifact Registry<br/>Bifrost Images]
end
Secret -->|Credentials| Pod
Pod -->|Pull| AR
Docker -->|Pull| AR
AR -->|Image| Pod
AR -->|Image| Docker
```
## Prerequisites
- Kubernetes cluster (v1.23+) or Docker runtime
- Network access to `us-central1-docker.pkg.dev` (or your designated region)
- Docker credentials provided by Bifrost team
<Note>
Contact the Bifrost team to receive your Docker username and password credentials.
</Note>
## Credentials
The Bifrost team will provide you with:
| Credential | Description |
|------------|-------------|
| **Username** | `_json_key` (fixed value for GCP Artifact Registry) |
| **Password** | Service account JSON key (base64 encoded or raw JSON) |
| **Registry** | `REGION-docker.pkg.dev` (e.g., `us-central1-docker.pkg.dev`) |
| **Repository** | `REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG` |
<Warning>
Store credentials securely. Never commit them to version control or expose them in logs.
</Warning>
## Docker Deployment
### Step 1: Login to Registry
```bash
# Using the JSON key file
cat bifrost-credentials.json | docker login -u _json_key --password-stdin https://REGION-docker.pkg.dev
# Or using the password directly
docker login -u _json_key -p "$(cat bifrost-credentials.json)" https://REGION-docker.pkg.dev
```
### Step 2: Pull the Image
```bash
docker pull REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
```
### Step 3: Run Bifrost
```bash
docker run -d \
--name bifrost \
-p 8080:8080 \
-v /path/to/config.json:/app/data/config.json:ro \
-v /path/to/data:/app/data \
REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
```
## Kubernetes Deployment
### Step 1: Create Namespace
```bash
kubectl create namespace bifrost
```
### Step 2: Create imagePullSecret
<Tabs>
<Tab title="From JSON Key File">
```bash
kubectl create secret docker-registry bifrost-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=_json_key \
--docker-password="$(cat bifrost-credentials.json)" \
--namespace=bifrost
```
</Tab>
<Tab title="From Base64 Key">
```bash
# If you received a base64-encoded key
kubectl create secret docker-registry bifrost-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=_json_key \
--docker-password="$(echo 'BASE64_ENCODED_KEY' | base64 -d)" \
--namespace=bifrost
```
</Tab>
<Tab title="Using YAML">
```yaml
apiVersion: v1
kind: Secret
metadata:
name: bifrost-pull-secret
namespace: bifrost
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <BASE64_ENCODED_DOCKER_CONFIG>
```
Generate the base64-encoded config:
```bash
# Create docker config
cat <<EOF > docker-config.json
{
"auths": {
"REGION-docker.pkg.dev": {
"username": "_json_key",
"password": "$(cat bifrost-credentials.json | tr -d '\n')",
"auth": "$(echo -n '_json_key:'$(cat bifrost-credentials.json | tr -d '\n') | base64 -w 0)"
}
}
}
EOF
# Base64 encode for secret
cat docker-config.json | base64 -w 0
```
</Tab>
</Tabs>
### Step 3: Create Bifrost Configuration
<Note>
If you use PostgreSQL for `config_store` or `logs_store`, ensure the target database is UTF8 encoded. See [PostgreSQL UTF8 Requirement](../../quickstart/gateway/setting-up#postgresql-utf8-requirement).
</Note>
```yaml
apiVersion: v1
kind: Secret
metadata:
name: bifrost-config
namespace: bifrost
type: Opaque
stringData:
config.json: |
{
"config_store": {
"enabled": true,
"type": "postgres",
"config": {
"host": "postgres.bifrost.svc.cluster.local",
"port": "5432",
"user": "bifrost",
"password": "YOUR_PASSWORD",
"db_name": "bifrost",
"ssl_mode": "disable"
}
},
"logs_store": {
"enabled": true,
"type": "postgres",
"config": {
"host": "postgres.bifrost.svc.cluster.local",
"port": "5432",
"user": "bifrost",
"password": "YOUR_PASSWORD",
"db_name": "bifrost",
"ssl_mode": "disable"
}
}
}
```
### Step 4: Deploy Bifrost
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: bifrost
namespace: bifrost
spec:
replicas: 2
selector:
matchLabels:
app: bifrost
template:
metadata:
labels:
app: bifrost
spec:
imagePullSecrets:
- name: bifrost-pull-secret
containers:
- name: bifrost
image: REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "2Gi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /app/data/config.json
subPath: config.json
- name: data
mountPath: /app/data
volumes:
- name: config
secret:
secretName: bifrost-config
- name: data
persistentVolumeClaim:
claimName: bifrost-data
---
apiVersion: v1
kind: Service
metadata:
name: bifrost
namespace: bifrost
spec:
selector:
app: bifrost
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: bifrost-data
namespace: bifrost
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
```
### Step 5: Expose Bifrost (Optional)
<Tabs>
<Tab title="Ingress">
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bifrost
namespace: bifrost
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
spec:
ingressClassName: nginx
rules:
- host: bifrost.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bifrost
port:
number: 80
tls:
- hosts:
- bifrost.your-domain.com
secretName: bifrost-tls
```
</Tab>
<Tab title="LoadBalancer">
```yaml
apiVersion: v1
kind: Service
metadata:
name: bifrost-lb
namespace: bifrost
spec:
selector:
app: bifrost
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: LoadBalancer
```
</Tab>
<Tab title="NodePort">
```yaml
apiVersion: v1
kind: Service
metadata:
name: bifrost-nodeport
namespace: bifrost
spec:
selector:
app: bifrost
ports:
- port: 80
targetPort: 8080
nodePort: 30080
protocol: TCP
type: NodePort
```
</Tab>
</Tabs>
## Docker Compose Deployment
For simpler deployments without Kubernetes:
```yaml
version: '3.8'
services:
bifrost:
image: REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
container_name: bifrost
ports:
- "8080:8080"
volumes:
- ./config.json:/app/data/config.json:ro
- bifrost-data:/app/data
environment:
- BIFROST_LOG_LEVEL=info
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
postgres:
image: postgres:15-alpine
container_name: bifrost-postgres
environment:
- POSTGRES_USER=bifrost
- POSTGRES_PASSWORD=YOUR_PASSWORD
- POSTGRES_DB=bifrost
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U bifrost"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
bifrost-data:
postgres-data:
```
Login to registry before running:
```bash
cat bifrost-credentials.json | docker login -u _json_key --password-stdin https://REGION-docker.pkg.dev
docker compose up -d
```
## Air-Gapped Environments
For environments without internet access, you can mirror the image to your internal registry.
### Step 1: Pull Image (Internet-Connected Machine)
```bash
# Login and pull
cat bifrost-credentials.json | docker login -u _json_key --password-stdin https://REGION-docker.pkg.dev
docker pull REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
# Save to tar file
docker save REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest > bifrost-image.tar
```
### Step 2: Transfer and Load (Air-Gapped Machine)
```bash
# Load image
docker load < bifrost-image.tar
# Tag for internal registry
docker tag REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest \
internal-registry.company.com/bifrost:latest
# Push to internal registry
docker push internal-registry.company.com/bifrost:latest
```
### Step 3: Update Kubernetes Manifests
Update the image reference in your deployment:
```yaml
containers:
- name: bifrost
image: internal-registry.company.com/bifrost:latest
```
## Credential Rotation
When the Bifrost team rotates your credentials:
### Update Docker Login
```bash
cat new-credentials.json | docker login -u _json_key --password-stdin https://REGION-docker.pkg.dev
```
### Update Kubernetes Secret
```bash
# Delete old secret
kubectl delete secret bifrost-pull-secret -n bifrost
# Create new secret
kubectl create secret docker-registry bifrost-pull-secret \
--docker-server=REGION-docker.pkg.dev \
--docker-username=_json_key \
--docker-password="$(cat new-credentials.json)" \
--namespace=bifrost
# Restart deployment to pick up new secret
kubectl rollout restart deployment/bifrost -n bifrost
```
## Verifying Access
### Test Docker Authentication
```bash
# Verify login
docker login -u _json_key -p "$(cat bifrost-credentials.json)" https://REGION-docker.pkg.dev
# Test pull
docker pull REGION-docker.pkg.dev/BIFROST_PROJECT/YOUR_HUB_SLUG/bifrost:latest
```
### Verify Kubernetes Secret
```bash
# Check secret exists
kubectl get secret bifrost-pull-secret -n bifrost
# Verify secret content (base64 encoded)
kubectl get secret bifrost-pull-secret -n bifrost -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d
```
## Troubleshooting
### ImagePullBackOff Errors
```bash
# Check pod events
kubectl describe pod -l app=bifrost -n bifrost
# Common issues:
# - "unauthorized": Invalid credentials - check username/password
# - "not found": Wrong repository path - verify with Bifrost team
# - "connection refused": Network issue - check firewall rules
```
### Network Connectivity
```bash
# Test DNS resolution
nslookup REGION-docker.pkg.dev
# Test HTTPS connectivity
curl -v https://REGION-docker.pkg.dev/v2/
# Required outbound access:
# - REGION-docker.pkg.dev:443
# - oauth2.googleapis.com:443 (for token refresh)
```
### Credential Issues
```bash
# Verify JSON key format
cat bifrost-credentials.json | jq .
# Check key hasn't expired
cat bifrost-credentials.json | jq '.private_key_id'
# Contact Bifrost team if credentials are invalid
```
## Security Best Practices
1. **Store credentials securely**: Use a secrets manager (Vault, AWS Secrets Manager) for credential storage
2. **Limit access**: Only grant imagePullSecret access to required namespaces
3. **Rotate regularly**: Request credential rotation from Bifrost team periodically
4. **Audit access**: Monitor image pull logs for unauthorized access attempts
5. **Network isolation**: Restrict outbound access to only required registry endpoints
## Next Steps
- Configure [Bifrost settings](/quickstart/gateway/setting-up) for your use case
- Set up [observability](/features/observability/default) for monitoring
- Enable [clustering](/enterprise/clustering) for high availability

View File

@@ -0,0 +1,141 @@
---
title: "Overview"
description: "Deploy Bifrost Enterprise in your cloud environment with secure, private container image distribution"
icon: "info-circle"
---
Bifrost Enterprise provides private container image distribution through dedicated registries, enabling secure deployments in AWS, GCP, Azure, and on-premise environments.
## Architecture
Bifrost uses a hub-and-spoke model with two container registries optimized for each cloud platform:
```mermaid
flowchart TB
subgraph BifrostInfra[Bifrost Infrastructure]
CICD[CI/CD Pipeline]
GCR[GCP Artifact Registry]
ECR[AWS ECR]
end
subgraph Customers[Customer Environments]
subgraph AWSCustomer[AWS Customers]
EKS[EKS Cluster]
ECS[ECS Service]
end
subgraph GCPCustomer[GCP Customers]
GKE[GKE Cluster]
end
subgraph AzureCustomer[Azure Customers]
AKS[AKS Cluster]
end
subgraph OnPrem[On-Premise]
K8S[Kubernetes]
Docker[Docker]
end
end
CICD -->|Push| GCR
CICD -->|Push| ECR
ECR -->|IRSA| EKS
ECR -->|Task Role| ECS
GCR -->|Workload Identity| GKE
GCR -->|Azure WIF| AKS
GCR -->|Basic Auth| OnPrem
```
### Registry Distribution
| Customer Cloud | Registry Source | Why |
|----------------|-----------------|-----|
| AWS | AWS ECR | Native IAM integration, lowest latency within AWS |
| GCP | GCP Artifact Registry | Native Workload Identity, lowest latency within GCP |
| Azure | GCP Artifact Registry | Workload Identity Federation from Azure to GCP |
| On-Premise | GCP Artifact Registry | Basic auth with username/password credentials |
## Authentication Methods
Choose the authentication method based on your deployment environment:
| Environment | Method | Security Level | Setup Complexity |
|-------------|--------|----------------|------------------|
| AWS EKS | [IRSA](/deployment-guides/enterprise/aws#irsa-recommended) | High | Medium |
| AWS ECS | [IAM Task Roles](/deployment-guides/enterprise/aws#ecs-task-roles) | High | Low |
| GCP GKE | [Workload Identity](/deployment-guides/enterprise/gcp#workload-identity-recommended) | High | Low |
| Azure AKS | [Azure WIF](/deployment-guides/enterprise/azure) | High | Medium |
| On-Premise | [Basic Auth](/deployment-guides/enterprise/on-premise) | Medium | Low |
<Note>
Cloud-native identity federation (IRSA, Workload Identity, Azure WIF) is recommended over static credentials for production deployments.
</Note>
## Security Features
### Encryption
- **In-Transit**: All registry communication uses TLS 1.3
- **At-Rest**: Images encrypted using cloud-native encryption (AWS KMS, GCP CMEK)
### Access Control
- **IAM-based**: Fine-grained permissions using cloud IAM policies
- **Audit Logging**: All image pull operations are logged for compliance
- **IP Restrictions**: Optional VPC Service Controls (GCP) or VPC endpoints (AWS)
### Image Security
- **Vulnerability Scanning**: Automatic scanning on push
- **Immutable Tags**: Optional tag immutability to prevent overwrites
- **Signed Images**: Container image signatures for verification
## Prerequisites
Before deploying Bifrost Enterprise, ensure you have:
<Tabs>
<Tab title="AWS">
- AWS account with ECR access
- EKS cluster (v1.23+) or ECS cluster
- IAM permissions to create roles and policies
- `kubectl` and `aws` CLI configured
</Tab>
<Tab title="GCP">
- GCP project with Artifact Registry API enabled
- GKE cluster (v1.24+) with Workload Identity enabled
- IAM permissions for service account management
- `kubectl` and `gcloud` CLI configured
</Tab>
<Tab title="Azure">
- Azure subscription with AKS
- AKS cluster (v1.24+) with Workload Identity enabled
- Permissions to create Managed Identities
- `kubectl` and `az` CLI configured
</Tab>
<Tab title="On-Premise">
- Kubernetes cluster (v1.23+) or Docker runtime
- Network access to `us-central1-docker.pkg.dev`
- Docker credentials provided by Bifrost team
</Tab>
</Tabs>
## Getting Started
<CardGroup cols={2}>
<Card title="AWS Deployment" icon="aws" href="/deployment-guides/enterprise/aws">
Deploy on EKS or ECS with IRSA authentication
</Card>
<Card title="GCP Deployment" icon="google" href="/deployment-guides/enterprise/gcp">
Deploy on GKE with Workload Identity
</Card>
<Card title="Azure Deployment" icon="microsoft" href="/deployment-guides/enterprise/azure">
Deploy on AKS with Azure Workload Identity Federation
</Card>
<Card title="On-Premise" icon="server" href="/deployment-guides/enterprise/on-premise">
Deploy anywhere with Docker credentials
</Card>
</CardGroup>
## Support
For enterprise deployment assistance:
- **Email**: [contact@getmaxim.ai](mailto:contact@getmaxim.ai)
- **Slack**: Connect via Slack Connect for real-time support
- **Documentation**: Platform-specific guides linked above