first commit
This commit is contained in:
541
docs/deployment-guides/enterprise/on-premise.mdx
Normal file
541
docs/deployment-guides/enterprise/on-premise.mdx
Normal 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
|
||||
Reference in New Issue
Block a user