--- 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
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 Contact the Bifrost team to receive your Docker username and password credentials. ## 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` | Store credentials securely. Never commit them to version control or expose them in logs. ## 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 ```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 ``` ```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 ``` ```yaml apiVersion: v1 kind: Secret metadata: name: bifrost-pull-secret namespace: bifrost type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: ``` Generate the base64-encoded config: ```bash # Create docker config cat < 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 ``` ### Step 3: Create Bifrost Configuration 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). ```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) ```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 ``` ```yaml apiVersion: v1 kind: Service metadata: name: bifrost-lb namespace: bifrost spec: selector: app: bifrost ports: - port: 80 targetPort: 8080 protocol: TCP type: LoadBalancer ``` ```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 ``` ## 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