542 lines
12 KiB
Plaintext
542 lines
12 KiB
Plaintext
---
|
|
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
|