diff --git a/packages/documentation/astro.config.mjs b/packages/documentation/astro.config.mjs index f2299475a2..fcb9b0c7b4 100644 --- a/packages/documentation/astro.config.mjs +++ b/packages/documentation/astro.config.mjs @@ -172,8 +172,30 @@ export default defineConfig({ link: '/integration/deployment/docker-compose' }, { - label: 'Helm and Kubernetes', - link: '/integration/deployment/helm-k8s' + label: 'Helm & Kubernetes', + collapsed: true, + items: [ + { + label: 'Get Started', + link: '/integration/deployment/helm-k8s/getting-started' + }, + { + label: 'Peered Rafiki Instances Example', + link: '/integration/deployment/helm-k8s/peered-rafiki-architecture' + }, + { + label: 'Deploy ASE A', + link: '/integration/deployment/helm-k8s/ase-a-test-wallet' + }, + { + label: 'Deploy ASE B', + link: '/integration/deployment/helm-k8s/ase-b-interledger-app' + }, + { + label: 'Peer the ASEs', + link: '/integration/deployment/helm-k8s/ase-peering' + } + ] } ] }, diff --git a/packages/documentation/public/img/rafiki-peering-diagram.png b/packages/documentation/public/img/rafiki-peering-diagram.png new file mode 100644 index 0000000000..350a58ac48 Binary files /dev/null and b/packages/documentation/public/img/rafiki-peering-diagram.png differ diff --git a/packages/documentation/src/content/docs/es/overview/concepts/accounting.mdx b/packages/documentation/src/content/docs/es/overview/concepts/accounting.mdx index f2a783c92c..3e74d54604 100644 --- a/packages/documentation/src/content/docs/es/overview/concepts/accounting.mdx +++ b/packages/documentation/src/content/docs/es/overview/concepts/accounting.mdx @@ -207,7 +207,7 @@ Now, your peer liquidity account's balance is \$9,900 and your USD settlement ac TigerBeetle is a high-performance distributed financial accounting database used by Rafiki’s [backend service](/es/integration/deployment/services/backend-service) to store account balance data. Both liquidity and settlement accounts in Rafiki correspond to TigerBeetle credit and debit accounts, respectively. -TigerBeetle only holds balance data without any additional ILP packet metadata. For detailed information on TigerBeetle, including its consensus mechanism and its limitations, visit the official TigerBeetle documentation and blog. For more information about TigerBeetle in a production Rafiki environment, see [Running Rafiki in production](/es/integration/deployment/helm-k8s). +TigerBeetle only holds balance data without any additional ILP packet metadata. For detailed information on TigerBeetle, including its consensus mechanism and its limitations, visit the official TigerBeetle documentation and blog. For more information about TigerBeetle in a production Rafiki environment, see [Running Rafiki in production](/es/integration/deployment/helm-k8s/getting-started). ### Postgres diff --git a/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-a-test-wallet.mdx b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-a-test-wallet.mdx new file mode 100644 index 0000000000..cdc0daacb5 --- /dev/null +++ b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-a-test-wallet.mdx @@ -0,0 +1,480 @@ +--- +title: Deploy ASE A using Test Wallet +description: Step-by-step guide to deploy a Rafiki instance and the Test Wallet app (ASE A) on a Kubernetes cluster using the public Interledger Helm charts. +--- + +import { LinkOut } from '@interledger/docs-design-system' + +This guide shows how Account Servicing Entity A (**ASE A**) can deploy: + +- A **Rafiki** instance (auth, backend, frontend) +- The **Test Wallet** app from github.com/interledger/testnet + +to a **Kubernetes cluster** (on any cloud provider) using the **public Interledger Helm charts**. + +For the overall system design, refer to the [Peered Rafiki Instances Architecture](/integration/deployment/helm-k8s/peered-rafiki-architecture). + +## 1. Prerequisites + +- Access to a **cloud provider account** (AWS, Google Cloud, Azure) or on-premises infrastructure with permissions to create a Kubernetes cluster. +- Permissions to create: + - Kubernetes clusters, + - Kubernetes namespaces, + - Load balancers / ingress resources, + - DNS records for your domain. +- Local tooling: + - kubectl installed + and configured to access your cluster + - Helm 3+ installed + +Source code and charts (for reference and customization): + +- Rafiki: github.com/interledger/rafiki +- Test Wallet: github.com/interledger/testnet +- Helm charts: github.com/interledger/charts + +## 2. Create the Kubernetes cluster for ASE A + +Create a Kubernetes cluster on your preferred cloud provider or on-premises. The exact commands vary by provider: + +**Example for Google Cloud Platform (GKE):** + +```bash +gcloud container clusters create ase-a-cluster \ + --num-nodes=3 \ + --machine-type=e2-standard-4 +gcloud container clusters get-credentials ase-a-cluster +``` + +Choose a cluster name appropriate for your environment, for example: + +- **Cluster name**: `ase-a-cluster` +- **Region**: Choose a region suitable for your deployment + +Verify cluster access: + +```bash +kubectl get nodes +``` + +## 3. Prepare Kubernetes namespaces and Helm repository + +Create Kubernetes namespaces: + +```bash +kubectl create namespace rafiki-ase-a +kubectl create namespace wallet-ase-a +``` + +Add the Interledger Helm repository (if not already added): + +```bash +helm repo add interledger-helm https://interledger.github.io/charts/interledger +helm repo update +``` + +Charts used: + +- `interledger-helm/rafiki` for the Rafiki instance +- `interledger-helm/testnet-wallet` for the Test Wallet app + +## 4. Deploy infrastructure for Rafiki + +### 4.1 Deploy PostgreSQL, Redis, and TigerBeetle + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo add tigerbeetle https://tigerbeetle.github.io/helm-charts +helm repo update + +helm install rafiki-ase-a-postgres bitnami/postgresql \ + --namespace rafiki-ase-a \ + --set auth.username=rafiki_backend \ + --set auth.password=CHOOSE_STRONG_PASSWORD \ + --set auth.database=rafiki_backend + +helm install rafiki-ase-a-redis bitnami/redis \ + --namespace rafiki-ase-a \ + --set auth.enabled=false + +helm install rafiki-ase-a-tigerbeetle tigerbeetle/tigerbeetle \ + --namespace rafiki-ase-a \ + --set replicaCount=3 \ + --set persistence.size=20Gi +``` + +:::caution +Replace all `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique passwords. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +## 5. Deploy Rafiki for ASE A + +Rafiki is deployed using the `rafiki` chart. You configure it via a Helm values file referencing your ingress domain names and database/Redis/TigerBeetle services. + +### 5.1 Choose domain names + +Decide on domain names and later create DNS records pointing to your ingress IP or load balancer: + +- **Rafiki backend**: `rafiki.ase-a.example.com` +- **Rafiki auth**: `auth.ase-a.example.com` +- **Rafiki admin UI**: `rafiki-admin.ase-a.example.com` + +### 5.2 Create Rafiki values file + +Create `rafiki-ase-a.values.yaml`: + +```yaml +fullnameOverride: 'rafiki-ase-a' + +imageOverride: + repository: ghcr.io/interledger + +config: + frontend: + logLevel: info + nodeEnv: production + port: 3010 + signatureVersion: '1' + serviceUrls: + GRAPHQL_URL: >- + http://rafiki-ase-a-backend-service.rafiki-ase-a:3001/graphql + OPEN_PAYMENTS_URL: https://rafiki.ase-a.example.com + + auth: + shouldCreateSecrets: true + nodeEnv: production + logLevel: info + redisUrl: + value: >- + redis://rafiki-ase-a-redis-master.rafiki-ase-a:6379 + databaseUrl: + value: >- + postgresql://rafiki_auth:CHOOSE_STRONG_PASSWORD@ + rafiki-ase-a-postgres.rafiki-ase-a:5432/rafiki_auth + authServerUrl: 'https://auth.ase-a.example.com' + identityServer: + domain: 'https://wallet.ase-a.example.com/idp' + serverSecret: + value: 'REPLACE_ME_ASE_A_IDP_SERVER_SECRET' + cookieKey: + value: 'REPLACE_ME_ASE_A_AUTH_COOKIE_KEY' + tenancy: + tenant_id: 'ase-a-tenant' + admin: + apiSecret: + value: 'REPLACE_ME_ASE_A_AUTH_ADMIN_API_SECRET' + signatureVersion: '1' + + backend: + shouldCreateSecrets: true + nodeEnv: production + logLevel: info + instanceName: 'rafiki-ase-a-instance' + useTigerbeetle: true + tigerbeetle: + clusterId: 0 + replicaAddresses: >- + rafiki-ase-a-tigerbeetle.rafiki-ase-a:4342 + auth: + grantUrl: 'https://auth.ase-a.example.com/gnap' + introspectionUrl: 'https://auth.ase-a.example.com/introspect' + serviceApiUrl: 'https://auth.ase-a.example.com/admin' + rates: + url: '' # optional FX service + webhook: + url: >- + http://wallet-ase-a-backend-service.wallet-ase-a:4003/ + webhooks/rafiki + timeout: 200 + redisUrl: + value: >- + redis://rafiki-ase-a-redis-master.rafiki-ase-a:6379 + databaseUrl: + value: >- + postgresql://rafiki_backend:CHOOSE_STRONG_PASSWORD@ + rafiki-ase-a-postgres.rafiki-ase-a:5432/rafiki_backend + trustProxy: 'true' + ilp: + host: 'https://rafiki.ase-a.example.com' + address: 'test.ase-a' + connector: >- + http://rafiki-ase-a-backend-service.rafiki-ase-a:3002 + streamSecret: + value: 'REPLACE_ME_ASE_A_STREAM_SECRET_BASE64' + slippage: 0.01 + key: + id: 'rafiki-ase-a-key' + pvk: '' # let the chart generate, or provide base64-encoded key + mount: '/mnt/keys/pvk.pem' + webhookSignatureSecret: + value: 'REPLACE_ME_ASE_A_WEBHOOK_SIGNATURE_SECRET' + telemetry: + enabled: 'false' + livenet: 'false' + autoPeering: + enabled: 'true' + tenancy: + tenant_id: 'ase-a-tenant' + admin: + apiSecret: + value: 'REPLACE_ME_ASE_A_BACKEND_ADMIN_API_SECRET' + signatureVersion: '1' + +ingress: + backend: + enabled: true + className: nginx + hosts: + - host: rafiki.ase-a.example.com + paths: + - path: / + pathType: Prefix + service: + name: rafiki-ase-a-backend-service + port: 3000 + - path: /ilp + pathType: Prefix + service: + name: rafiki-ase-a-backend-service + port: 3002 + auth: + enabled: true + className: nginx + hosts: + - host: auth.ase-a.example.com + paths: + - path: / + pathType: Prefix + service: + name: rafiki-ase-a-auth-service + port: 3006 + frontend: + enabled: true + className: nginx + hosts: + - host: rafiki-admin.ase-a.example.com + paths: + - path: / + pathType: Prefix + service: + name: rafiki-ase-a-frontend-service + port: 3010 +``` + +:::caution +Replace all `REPLACE_ME_...` and `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique secrets. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +### 5.3 Install ingress controller (if needed) + +If your cluster does not already have an ingress controller, install one. For example, using NGINX Ingress Controller: + +```bash +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update + +helm install nginx-ingress ingress-nginx/ingress-nginx \ + --namespace ingress-nginx \ + --create-namespace \ + --set controller.publishService.enabled=true +``` + +:::note +Different cloud providers may have their own ingress controllers (for example, AWS Application Load Balancer Controller, Azure Application Gateway Ingress Controller). Adjust the ingress configuration accordingly. +::: + +### 5.4 Install Rafiki + +```bash +helm install rafiki-ase-a interledger-helm/rafiki \ + --namespace rafiki-ase-a \ + -f rafiki-ase-a.values.yaml + +kubectl get pods -n rafiki-ase-a +kubectl get svc -n rafiki-ase-a +kubectl get ingress -n rafiki-ase-a +``` + +Get the external IP or hostname: + +```bash +kubectl get ingress -n rafiki-ase-a +``` + +Configure DNS for: + +- `rafiki.ase-a.example.com` +- `auth.ase-a.example.com` +- `rafiki-admin.ase-a.example.com` + +pointing to your ingress controller's external IP or load balancer hostname. + +## 6. Deploy Test Wallet for ASE A + +ASE A deploys the **Test Wallet** app from github.com/interledger/testnet using the `testnet-wallet` Helm chart. The Test Wallet integrates with Rafiki via Open Payments APIs. + +### 6.1 Deploy PostgreSQL and Redis for Test Wallet + +```bash +helm install wallet-ase-a-postgres bitnami/postgresql \ + --namespace wallet-ase-a \ + --set auth.username=testnet_wallet \ + --set auth.password=CHOOSE_STRONG_PASSWORD \ + --set auth.database=testnet_wallet + +helm install wallet-ase-a-redis bitnami/redis \ + --namespace wallet-ase-a \ + --set auth.enabled=false +``` + +:::caution +Replace all `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique passwords. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +### 6.2 Create Test Wallet values file + +Create `testnet-wallet-ase-a.values.yaml`: + +```yaml +fullnameOverride: 'wallet-ase-a' + +imageOverride: + repository: ghcr.io/interledger + +config: + frontend: + logLevel: info + nodeEnv: production + port: 4003 + urls: + backend: 'https://api.ase-a.example.com' + openPaymentsHost: 'https://rafiki.ase-a.example.com' + authHost: 'https://auth.ase-a.example.com' + cookie: + name: 'ase-a.cookie' + features: + useTestKycData: true + + backend: + shouldCreateSecrets: true + nodeEnv: production + logLevel: info + port: 4003 + cookie: + name: 'ase-a.cookie' + password: 'REPLACE_ME_ASE_A_WALLET_COOKIE_PASSWORD' + ttl: 2630000 + hosts: + openPayments: 'https://rafiki.ase-a.example.com' + graphqlEndpoint: >- + http://rafiki-ase-a-backend-service.rafiki-ase-a:3001/graphql + authGraphqlEndpoint: >- + http://rafiki-ase-a-auth-service.rafiki-ase-a:3003/graphql + frontend: 'https://wallet.ase-a.example.com' + auth: 'https://auth.ase-a.example.com' + database: + url: >- + postgres://testnet_wallet:CHOOSE_STRONG_PASSWORD@ + wallet-ase-a-postgres.wallet-ase-a:5432/testnet_wallet + redis: + url: >- + redis://wallet-ase-a-redis-master.wallet-ase-a:6379 + identity: + serverSecret: 'REPLACE_ME_ASE_A_WALLET_IDP_SECRET' + webhook: + signatureSecret: 'REPLACE_ME_ASE_A_WALLET_WEBHOOK_SIGNATURE' + interaction: + cookieSameSite: 'lax' + email: + send: false + from: 'tech@interledger.org' + sendgridKey: '' + paymentPointer: '' # optional default wallet address + rafiki: + operatorId: 'ase-a-tenant' + apiSignatureVersion: '1' +``` + +:::caution +Replace all `REPLACE_ME_...` and `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique secrets. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +### 6.3 Create ingress for Test Wallet + +Decide on Test Wallet domain names: + +- **Test Wallet UI**: `wallet.ase-a.example.com` +- **Test Wallet API**: `api.ase-a.example.com` + +Create `testnet-wallet-ase-a.ingress.yaml`: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: wallet-ase-a + namespace: wallet-ase-a + annotations: + kubernetes.io/ingress.class: 'nginx' +spec: + rules: + - host: wallet.ase-a.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: wallet-ase-a-frontend-service + port: + number: 4003 + - host: api.ase-a.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: wallet-ase-a-backend-service + port: + number: 4003 +``` + +### 6.4 Install the Test Wallet chart + +```bash +helm install wallet-ase-a interledger-helm/testnet-wallet \ + --namespace wallet-ase-a \ + -f testnet-wallet-ase-a.values.yaml + +kubectl apply -f testnet-wallet-ase-a.ingress.yaml + +kubectl get pods -n wallet-ase-a +kubectl get svc -n wallet-ase-a +kubectl get ingress -n wallet-ase-a +``` + +### 6.5 Verify ASE A services + +Get the external IP or hostname: + +```bash +kubectl get ingress -n wallet-ase-a +``` + +Update DNS so that `wallet.ase-a.example.com` and `api.ase-a.example.com` resolve to your ingress controller's external IP or load balancer hostname. + +## 7. Test ASE A + +Once DNS and TLS are configured: + +1. Visit `https://wallet.ase-a.example.com` and create a test user. +2. Use Rafiki Admin at `https://rafiki-admin.ase-a.example.com` to: + - Create an asset (for example, USD with appropriate scale). + - Create a tenant (if not auto-created from configuration). + - Create one or more wallet addresses for the user. +3. From the Test Wallet UI, fund the account using test flows and perform a payment between two ASE A users to verify the deployment. + +When the deployment of ASE A is complete, proceed to deploying ASE B: + +- [Deploy ASE B using Interledger App Wallet](/integration/deployment/helm-k8s/ase-b-interledger-app) diff --git a/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-b-interledger-app.mdx b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-b-interledger-app.mdx new file mode 100644 index 0000000000..d61c0b87b2 --- /dev/null +++ b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-b-interledger-app.mdx @@ -0,0 +1,481 @@ +--- +title: Deploy ASE B using Interledger App Wallet +description: Step-by-step guide to deploy a Rafiki instance and the Interledger App Wallet application (ASE B) on a Kubernetes cluster using the public Interledger Helm charts. +--- + +import { LinkOut } from '@interledger/docs-design-system' + +This guide shows how Account Servicing Entity B (**ASE B**) can deploy: + +- A **Rafiki** instance (auth, backend, frontend) +- The **Interledger App Wallet** (container images are available from `ghcr.io/interledger`) + +to a **Kubernetes cluster** (on any cloud provider) using the **public Interledger Helm charts**. + +For the overall system design, refer to the [Peered Rafiki Instances Architecture](/integration/deployment/helm-k8s/peered-rafiki-architecture). + +## 1. Prerequisites + +- Access to a **cloud provider account** (AWS, Google Cloud, Azure) or on-premises infrastructure with permissions to create a Kubernetes cluster. +- Permissions to create: + - Kubernetes clusters, + - Kubernetes namespaces, + - Load balancers / ingress resources, + - DNS records for your domain. +- Local tooling: + - kubectl installed + and configured to access your cluster + - Helm 3+ installed + +Source code and charts (for reference and customization): + +- Rafiki: github.com/interledger/rafiki +- Interledger App Wallet: Container images are available from `ghcr.io/interledger` +- Helm charts: github.com/interledger/charts + +## 2. Create the Kubernetes cluster for ASE B + +Create a Kubernetes cluster on your preferred cloud provider or on-premises. The exact commands vary by provider: + +**Example for Google Cloud Platform (GKE):** + +```bash +gcloud container clusters create ase-b-cluster \ + --num-nodes=3 \ + --machine-type=e2-standard-4 +gcloud container clusters get-credentials ase-b-cluster +``` + +Choose a cluster name appropriate for your environment, for example: + +- **Cluster name**: `ase-b-cluster` +- **Region**: Choose a region suitable for your deployment + +Verify cluster access: + +```bash +kubectl get nodes +``` + +## 3. Prepare Kubernetes namespaces and Helm repository + +Create Kubernetes namespaces: + +```bash +kubectl create namespace rafiki-ase-b +kubectl create namespace wallet-ase-b +``` + +Add the Interledger Helm repository (if not already added): + +```bash +helm repo add interledger-helm https://interledger.github.io/charts/interledger +helm repo update +``` + +Charts used: + +- `interledger-helm/rafiki` for the Rafiki instance +- `interledger-helm/ilf-wallet-backend` for the Interledger App Wallet backend +- `interledger-helm/ilf-wallet-frontend` for the Interledger App Wallet frontend +- `interledger-helm/ilf-wallet-admin` for the Interledger App Wallet admin (optional) + +## 4. Deploy infrastructure for Rafiki + +### 4.1 Deploy PostgreSQL, Redis, and TigerBeetle + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo add tigerbeetle https://tigerbeetle.github.io/helm-charts +helm repo update + +helm install rafiki-ase-b-postgres bitnami/postgresql \ + --namespace rafiki-ase-b \ + --set auth.username=rafiki_backend \ + --set auth.password=CHOOSE_STRONG_PASSWORD \ + --set auth.database=rafiki_backend + +helm install rafiki-ase-b-redis bitnami/redis \ + --namespace rafiki-ase-b \ + --set auth.enabled=false + +helm install rafiki-ase-b-tigerbeetle tigerbeetle/tigerbeetle \ + --namespace rafiki-ase-b \ + --set replicaCount=3 \ + --set persistence.size=20Gi +``` + +:::caution +Replace all `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique passwords. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +## 5. Deploy Rafiki for ASE B + +Rafiki is deployed using the `rafiki` chart. You configure it via a Helm values file referencing your ingress domain names and database/Redis/TigerBeetle services. + +### 5.1 Choose domain names + +Decide on domain names and later create DNS records pointing to your ingress IP or load balancer: + +- **Rafiki backend**: `rafiki.ase-b.example.com` +- **Rafiki auth**: `auth.ase-b.example.com` +- **Rafiki admin UI**: `rafiki-admin.ase-b.example.com` + +### 5.2 Create Rafiki values file + +Create `rafiki-ase-b.values.yaml`: + +```yaml +fullnameOverride: 'rafiki-ase-b' + +imageOverride: + repository: ghcr.io/interledger + +config: + frontend: + logLevel: info + nodeEnv: production + port: 3010 + signatureVersion: '1' + serviceUrls: + GRAPHQL_URL: >- + http://rafiki-ase-b-backend-service.rafiki-ase-b:3001/graphql + OPEN_PAYMENTS_URL: https://rafiki.ase-b.example.com + + auth: + shouldCreateSecrets: true + nodeEnv: production + logLevel: info + redisUrl: + value: >- + redis://rafiki-ase-b-redis-master.rafiki-ase-b:6379 + databaseUrl: + value: >- + postgresql://rafiki_auth:CHOOSE_STRONG_PASSWORD@ + rafiki-ase-b-postgres.rafiki-ase-b:5432/rafiki_auth + authServerUrl: 'https://auth.ase-b.example.com' + identityServer: + domain: 'https://wallet.ase-b.example.com/idp' + serverSecret: + value: 'REPLACE_ME_ASE_B_IDP_SERVER_SECRET' + cookieKey: + value: 'REPLACE_ME_ASE_B_AUTH_COOKIE_KEY' + tenancy: + tenant_id: 'ase-b-tenant' + admin: + apiSecret: + value: 'REPLACE_ME_ASE_B_AUTH_ADMIN_API_SECRET' + signatureVersion: '1' + + backend: + shouldCreateSecrets: true + nodeEnv: production + logLevel: info + instanceName: 'rafiki-ase-b-instance' + useTigerbeetle: true + tigerbeetle: + clusterId: 0 + replicaAddresses: >- + rafiki-ase-b-tigerbeetle.rafiki-ase-b:4342 + auth: + grantUrl: 'https://auth.ase-b.example.com/gnap' + introspectionUrl: 'https://auth.ase-b.example.com/introspect' + serviceApiUrl: 'https://auth.ase-b.example.com/admin' + rates: + url: '' # optional currency exchange service + webhook: + url: >- + http://wallet-ase-b-backend-service.wallet-ase-b:8080/ + webhooks/rafiki + timeout: 200 + redisUrl: + value: >- + redis://rafiki-ase-b-redis-master.rafiki-ase-b:6379 + databaseUrl: + value: >- + postgresql://rafiki_backend:CHOOSE_STRONG_PASSWORD@ + rafiki-ase-b-postgres.rafiki-ase-b:5432/rafiki_backend + trustProxy: 'true' + ilp: + host: 'https://rafiki.ase-b.example.com' + address: 'test.ase-b' + connector: >- + http://rafiki-ase-b-backend-service.rafiki-ase-b:3002 + streamSecret: + value: 'REPLACE_ME_ASE_B_STREAM_SECRET_BASE64' + slippage: 0.01 + key: + id: 'rafiki-ase-b-key' + pvk: '' # or base64 private key + mount: '/mnt/keys/pvk.pem' + webhookSignatureSecret: + value: 'REPLACE_ME_ASE_B_WEBHOOK_SIGNATURE_SECRET' + telemetry: + enabled: 'false' + livenet: 'false' + autoPeering: + enabled: 'true' + tenancy: + tenant_id: 'ase-b-tenant' + admin: + apiSecret: + value: 'REPLACE_ME_ASE_B_BACKEND_ADMIN_API_SECRET' + signatureVersion: '1' + +ingress: + backend: + enabled: true + className: nginx + hosts: + - host: rafiki.ase-b.example.com + paths: + - path: / + pathType: Prefix + service: + name: rafiki-ase-b-backend-service + port: 3000 + - path: /ilp + pathType: Prefix + service: + name: rafiki-ase-b-backend-service + port: 3002 + auth: + enabled: true + className: nginx + hosts: + - host: auth.ase-b.example.com + paths: + - path: / + pathType: Prefix + service: + name: rafiki-ase-b-auth-service + port: 3006 + frontend: + enabled: true + className: nginx + hosts: + - host: rafiki-admin.ase-b.example.com + paths: + - path: / + pathType: Prefix + service: + name: rafiki-ase-b-frontend-service + port: 3010 +``` + +:::caution +Replace all `REPLACE_ME_...` and `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique secrets. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +### 5.3 Install ingress controller (if needed) + +If your cluster does not yet have an ingress controller, install one. For example, using NGINX Ingress Controller: + +```bash +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update + +helm install nginx-ingress ingress-nginx/ingress-nginx \ + --namespace ingress-nginx \ + --create-namespace \ + --set controller.publishService.enabled=true +``` + +:::note +Different cloud providers may have their own ingress controllers (for example, AWS Application Load Balancer Controller, Azure Application Gateway Ingress Controller). Adjust the ingress configuration accordingly. +::: + +### 5.4 Install Rafiki + +```bash +helm install rafiki-ase-b interledger-helm/rafiki \ + --namespace rafiki-ase-b \ + -f rafiki-ase-b.values.yaml + +kubectl get pods -n rafiki-ase-b +kubectl get svc -n rafiki-ase-b +kubectl get ingress -n rafiki-ase-b +``` + +Get the external IP or hostname: + +```bash +kubectl get ingress -n rafiki-ase-b +``` + +Configure DNS for: + +- `rafiki.ase-b.example.com` +- `auth.ase-b.example.com` +- `rafiki-admin.ase-b.example.com` + +pointing to your ingress controller's external IP or load balancer hostname. + +## 6. Deploy Interledger App Wallet for ASE B + +ASE B deploys the **Interledger App Wallet** using the `ilf-wallet-*` Helm charts. Container images are available from `ghcr.io/interledger`. The Interledger App Wallet integrates with Rafiki via Open Payments APIs. + +The Interledger App Wallet is deployed as separate charts: + +- `ilf-wallet-backend` – Backend service +- `ilf-wallet-frontend` – User-facing frontend +- `ilf-wallet-admin` – Admin interface (optional) + +### 6.1 Deploy PostgreSQL and Redis for Interledger App Wallet + +```bash +helm install wallet-ase-b-postgres bitnami/postgresql \ + --namespace wallet-ase-b \ + --set auth.username=ilf_wallet \ + --set auth.password=CHOOSE_STRONG_PASSWORD \ + --set auth.database=ilf_wallet + +helm install wallet-ase-b-redis bitnami/redis \ + --namespace wallet-ase-b \ + --set auth.enabled=false +``` + +:::caution +Replace all `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique passwords. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +### 6.2 Backend values + +Create `interledger-app-wallet-ase-b-backend.values.yaml` based on the chart's `values.yaml` (adjusting for your environment). At a minimum: + +- Point the Interledger App Wallet backend to: + - Its own database and Redis instances. + - The Rafiki ASE B URLs for Open Payments and auth. + - Any webhook or currency exchange endpoints you require. + +Example (schematic, adapt to the actual schema in the chart's `values.yaml`): + +```yaml +fullnameOverride: 'wallet-ase-b-backend' + +config: + database: + url: >- + postgres://ilf_wallet:CHOOSE_STRONG_PASSWORD@ + wallet-ase-b-postgres.wallet-ase-b:5432/ilf_wallet + redis: + url: >- + redis://wallet-ase-b-redis-master.wallet-ase-b:6379 + rafiki: + backendUrl: 'https://rafiki.ase-b.example.com' + authUrl: 'https://auth.ase-b.example.com' + http: + port: 8080 + ingress: + enabled: false # frontend ingress will expose the public UI; backend may be private +``` + +:::caution +Replace all `CHOOSE_STRONG_PASSWORD` placeholders with strong, unique secrets. For production, store these in your cloud provider's secret management service (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, etc.) and surface them via Kubernetes secrets rather than inline values. +::: + +Install the Interledger App Wallet backend: + +```bash +helm install wallet-ase-b-backend interledger-helm/ilf-wallet-backend \ + --namespace wallet-ase-b \ + -f interledger-app-wallet-ase-b-backend.values.yaml +``` + +### 6.3 Frontend values + +Create `interledger-app-wallet-ase-b-frontend.values.yaml`: + +```yaml +fullnameOverride: 'wallet-ase-b-frontend' + +config: + backend: + url: 'http://wallet-ase-b-backend.wallet-ase-b:8080' + port: 3000 + +ingress: + enabled: true + className: nginx + hosts: + - host: wallet.ase-b.example.com + paths: + - path: / + pathType: Prefix + service: + name: wallet-ase-b-frontend + port: 3000 +``` + +Install the Interledger App Wallet frontend: + +```bash +helm install wallet-ase-b-frontend interledger-helm/ilf-wallet-frontend \ + --namespace wallet-ase-b \ + -f interledger-app-wallet-ase-b-frontend.values.yaml +``` + +### 6.4 Admin values + +Create `interledger-app-wallet-ase-b-admin.values.yaml`: + +```yaml +fullnameOverride: 'wallet-ase-b-admin' + +config: + backend: + url: 'http://wallet-ase-b-backend.wallet-ase-b:8080' + port: 3001 + +ingress: + enabled: true + className: nginx + hosts: + - host: admin.ase-b.example.com + paths: + - path: / + pathType: Prefix + service: + name: wallet-ase-b-admin + port: 3001 +``` + +Install the Interledger App Wallet admin service: + +```bash +helm install wallet-ase-b-admin interledger-helm/ilf-wallet-admin \ + --namespace wallet-ase-b \ + -f interledger-app-wallet-ase-b-admin.values.yaml +``` + +### 6.5 Verify ASE B services + +```bash +kubectl get pods -n wallet-ase-b +kubectl get svc -n wallet-ase-b +kubectl get ingress -n wallet-ase-b +``` + +Get the external IP or hostname: + +```bash +kubectl get ingress -n wallet-ase-b +``` + +Update DNS so that `wallet.ase-b.example.com` and `admin.ase-b.example.com` (if enabled) resolve to your ingress controller's external IP or load balancer hostname. + +## 7. Test ASE B + +Once DNS and TLS are configured: + +1. Visit `https://wallet.ase-b.example.com` and create a test user. +2. Use Rafiki Admin at `https://rafiki-admin.ase-b.example.com` to: + - Create an asset (for example, USD with appropriate scale). + - Create a tenant (if not auto-created from configuration). + - Create one or more wallet addresses for the user. +3. (Optional) Use `https://admin.ase-b.example.com` (if enabled) to inspect accounts and configuration. +4. From the Interledger App Wallet UI, fund the account and perform a payment between two ASE B users to verify the deployment. + +When both ASE A and ASE B deployments are running, proceed to: + +- [Peer ASE A and ASE B](/integration/deployment/helm-k8s/ase-peering) diff --git a/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-peering.mdx b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-peering.mdx new file mode 100644 index 0000000000..5c82df7e6d --- /dev/null +++ b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/ase-peering.mdx @@ -0,0 +1,562 @@ +--- +title: Peer ASE A and ASE B Rafiki instances +description: Guide to peering two Rafiki instances (ASE A with Test Wallet and ASE B with Interledger App Wallet) to enable Interledger payments between them. +next: Production requirements and checklist +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components' +import { LinkOut } from '@interledger/docs-design-system' + +With **ASE A** (using Test Wallet) and **ASE B** (using Interledger App Wallet) deployed on their own Kubernetes clusters, this guide explains how to: + +- **Expose the Rafiki connector endpoints** on each side. +- **Create assets, peers, and accounts** in both Rafiki instances. +- **Enable Interledger payments** between the two wallets. + +## 1. Assumptions and endpoints + +This guide assumes: + +- ASE A deployment is complete: + - Rafiki Admin: `https://rafiki-admin.ase-a.example.com` + - Rafiki backend (Open Payments): `https://rafiki.ase-a.example.com` + - ILP address (example): `test.ase-a` +- ASE B deployment is complete: + - Rafiki Admin: `https://rafiki-admin.ase-b.example.com` + - Rafiki backend (Open Payments): `https://rafiki.ase-b.example.com` + - ILP address (example): `test.ase-b` + +The Rafiki backend services expose an **ILP connector port** (default `3002`). In both `rafiki-*.values.yaml` files, this is typically configured as: + +```yaml +backend: + ilp: + connector: 'http://.:3002' +``` + +For peering, each Rafiki must be able to reach the **other** Rafiki's connector endpoint over HTTP(S). + +## 2. Expose connector endpoints + +In many cases, you will expose the ILP connector alongside the Open Payments API via Kubernetes `Service` and `Ingress`. Ensure that: + +- The backend service includes port `3002` (connector). +- The ingress route forwards ILP traffic to that port. + +### 2.1 Example backend service (ASE A) + +Your Rafiki Helm chart should already create a backend service with ports: + +- `3000` – Open Payments +- `3001` – Admin / GraphQL +- `3002` – ILP connector + +Confirm: + +```bash +kubectl get svc rafiki-ase-a-backend-service -n rafiki-ase-a -o yaml +``` + +You should see a port named `connector` (or similar) on `3002`. Repeat for ASE B: + +```bash +kubectl get svc rafiki-ase-b-backend-service -n rafiki-ase-b -o yaml +``` + +### 2.2 Example ingress paths + +If you expose ILP over HTTPS under `/ilp`, your ingress for the backend might look like: + +```yaml +spec: + rules: + - host: rafiki.ase-a.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: rafiki-ase-a-backend-service + port: + number: 3000 + - path: /ilp + pathType: Prefix + backend: + service: + name: rafiki-ase-a-backend-service + port: + number: 3002 +``` + +Do the same for ASE B (`rafiki.ase-b.example.com`). This should result in connector URLs like: + +- ASE A connector: `https://rafiki.ase-a.example.com/ilp` +- ASE B connector: `https://rafiki.ase-b.example.com/ilp` + +## 3. Configure assets and peers in Rafiki + +This section shows how to configure **matching assets** and **peer relationships** on both Rafiki instances using the [Admin GraphQL API](/apis/graphql/backend). All requests must be authenticated using the tenant's `ADMIN_API_SECRET` and include a `tenant-id` header. Refer to [Backend service authentication](/integration/deployment/services/backend-service#authentication-and-authorization) for details. + +### 3.1 Decide on assets and ILP addresses + +For a simple demo: + +- **Asset** (both sides): `USD`, scale `2` +- **ILP addresses**: + - ASE A: `test.ase-a` + - ASE B: `test.ase-b` +- **HTTP auth tokens** (shared secrets): + - `ase-a-to-ase-b-token`: Token ASE A uses when sending packets to ASE B (ASE B's incoming token). + - `ase-b-to-ase-a-token`: Token ASE B uses when sending packets to ASE A (ASE A's incoming token). + +:::caution +HTTP auth tokens and ILP addresses must be **consistent and symmetric** across both peers. Mismatched tokens or ILP addresses will cause peering failures. +::: + +### 3.2 ASE A – create asset + +First, create the USD asset on ASE A. Send the following GraphQL mutation to `https://rafiki.ase-a.example.com/graphql`: + + + + ```graphql + mutation CreateAsset($input: CreateAssetInput!) { + createAsset(input: $input) { + code + success + message + asset { + id + code + scale + tenantId + } + } + } + ``` + + + ```json + { + "input": { + "code": "USD", + "scale": 2 + } + } + ``` + + + ```json + { + "data": { + "createAsset": { + "code": "200", + "success": true, + "message": "Created Asset", + "asset": { + "id": "b3dffeda-1e0e-47d4-82a3-69b1a622eeb9", + "code": "USD", + "scale": 2, + "tenantId": "ase-a-tenant" + } + } + } + } + ``` + + + +:::note[Authentication] +All requests to the [Backend Admin API](/apis/graphql/backend) must include a `tenant-id` header and be signed using the tenant's API secret. Refer to [Backend service authentication](/integration/deployment/services/backend-service#authentication-and-authorization) for details. +::: + +Save the `asset.id` from the response. You'll need it when creating the peer. + +### 3.3 ASE A – create peer + +Create a peer representing ASE B. Use the asset ID from the previous step: + + + + ```graphql + mutation CreatePeer($input: CreatePeerInput!) { + createPeer(input: $input) { + code + success + message + peer { + id + name + staticIlpAddress + asset { + code + scale + } + liquidity + liquidityThreshold + } + } + } + ``` + + + ```json + { + "input": { + "name": "ase-b-peer", + "staticIlpAddress": "test.ase-b", + "http": { + "incoming": { + "authTokens": ["ase-b-to-ase-a-token"] + }, + "outgoing": { + "endpoint": "https://rafiki.ase-b.example.com/ilp", + "authToken": "ase-a-to-ase-b-token" + } + }, + "assetId": "b3dffeda-1e0e-47d4-82a3-69b1a622eeb9", + "initialLiquidity": 1000000, + "liquidityThreshold": 100000, + "maxPacketAmount": 1000000 + } + } + ``` + + + ```json + { + "data": { + "createPeer": { + "code": "200", + "success": true, + "message": "Created ILP Peer", + "peer": { + "id": "480ef339-7842-4501-a905-923fc1339cef", + "name": "ase-b-peer", + "staticIlpAddress": "test.ase-b", + "asset": { + "code": "USD", + "scale": 2 + }, + "liquidity": 1000000, + "liquidityThreshold": 100000 + } + } + } + } + ``` + + + +### 3.4 ASE B – create asset + +Create the USD asset on ASE B. Send the following GraphQL mutation to `https://rafiki.ase-b.example.com/graphql`: + + + + ```graphql + mutation CreateAsset($input: CreateAssetInput!) { + createAsset(input: $input) { + code + success + message + asset { + id + code + scale + tenantId + } + } + } + ``` + + + ```json + { + "input": { + "code": "USD", + "scale": 2 + } + } + ``` + + + ```json + { + "data": { + "createAsset": { + "code": "200", + "success": true, + "message": "Created Asset", + "asset": { + "id": "a4efffeb-2f1f-58e5-93b4-7ac2b7330fca", + "code": "USD", + "scale": 2, + "tenantId": "ase-b-tenant" + } + } + } + } + ``` + + + +Save the `asset.id` from the response for the next step. + +### 3.5 ASE B – create peer + +Create a peer representing ASE A. Use the asset ID from the previous step and ensure the HTTP auth tokens are **symmetric** with ASE A's configuration: + + + + ```graphql + mutation CreatePeer($input: CreatePeerInput!) { + createPeer(input: $input) { + code + success + message + peer { + id + name + staticIlpAddress + asset { + code + scale + } + liquidity + liquidityThreshold + } + } + } + ``` + + + ```json + { + "input": { + "name": "ase-a-peer", + "staticIlpAddress": "test.ase-a", + "http": { + "incoming": { + "authTokens": ["ase-a-to-ase-b-token"] + }, + "outgoing": { + "endpoint": "https://rafiki.ase-a.example.com/ilp", + "authToken": "ase-b-to-ase-a-token" + } + }, + "assetId": "a4efffeb-2f1f-58e5-93b4-7ac2b7330fca", + "initialLiquidity": 1000000, + "liquidityThreshold": 100000, + "maxPacketAmount": 1000000 + } + } + ``` + + + ```json + { + "data": { + "createPeer": { + "code": "200", + "success": true, + "message": "Created ILP Peer", + "peer": { + "id": "591fg44a-8953-5612-b016-034gd2440dfg", + "name": "ase-a-peer", + "staticIlpAddress": "test.ase-a", + "asset": { + "code": "USD", + "scale": 2 + }, + "liquidity": 1000000, + "liquidityThreshold": 100000 + } + } + } + } + ``` + + + +:::caution[Token symmetry] +Note that: + +- ASE B's **incoming** token (`ase-a-to-ase-b-token`) matches ASE A's **outgoing** token. +- ASE B's **outgoing** token (`ase-b-to-ase-a-token`) matches ASE A's **incoming** token. + +This symmetry is required for successful peering. +::: + +## 4. Verify peer health + +Use GraphQL queries to verify that both peers are configured correctly and healthy. + +### 4.1 Query peers on ASE A + +Query all peers on ASE A to verify the peer was created: + + + + ```graphql + query GetPeers { + peers { + edges { + cursor + node { + id + name + staticIlpAddress + asset { + code + scale + } + liquidity + liquidityThreshold + http { + outgoing { + endpoint + } + } + } + } + } + } + ``` + + + ```json + { + "data": { + "peers": { + "edges": [ + { + "cursor": "cursor1", + "node": { + "id": "480ef339-7842-4501-a905-923fc1339cef", + "name": "ase-b-peer", + "staticIlpAddress": "test.ase-b", + "asset": { + "code": "USD", + "scale": 2 + }, + "liquidity": 1000000, + "liquidityThreshold": 100000, + "http": { + "outgoing": { + "endpoint": "https://rafiki.ase-b.example.com/ilp" + } + } + } + } + ] + } + } + } + ``` + + + +### 4.2 Query peers on ASE B + +Query all peers on ASE B to verify the peer was created: + + + + ```graphql + query GetPeers { + peers { + edges { + cursor + node { + id + name + staticIlpAddress + asset { + code + scale + } + liquidity + liquidityThreshold + http { + outgoing { + endpoint + } + } + } + } + } + } + ``` + + + ```json + { + "data": { + "peers": { + "edges": [ + { + "cursor": "cursor1", + "node": { + "id": "591fg44a-8953-5612-b016-034gd2440dfg", + "name": "ase-a-peer", + "staticIlpAddress": "test.ase-a", + "asset": { + "code": "USD", + "scale": 2 + }, + "liquidity": 1000000, + "liquidityThreshold": 100000, + "http": { + "outgoing": { + "endpoint": "https://rafiki.ase-a.example.com/ilp" + } + } + } + } + ] + } + } + } + ``` + + + +### 4.3 Verify peer connectivity + +After creating peers on both sides, verify that: + +- Each Rafiki instance has a USD asset with matching code and scale. +- Each Rafiki instance has a peer pointing to the other Rafiki's ILP address. +- The connector endpoints are reachable (check network connectivity). +- HTTP auth tokens are symmetric between both peers. + +You can also check peer health using the Rafiki Admin UI at: + +- `https://rafiki-admin.ase-a.example.com` (ASE A) +- `https://rafiki-admin.ase-b.example.com` (ASE B) + +Navigate to **Peers** and verify that peer status shows **READY** or **HEALTHY**. + +## 5. Interledger payments + +Once peering has been set up and verified, Interledger payments should be possible between users of ASE A (Test Wallet) and ASE B (Interledger App Wallet). Users can send payments between the two wallets using their wallet addresses, and the payments will flow through the peered Rafiki instances. + +## 6. Troubleshooting + +- **Peer not healthy**: + - Double-check connector URLs and that the ILP connector port (`3002`) is accessible via Ingress. + - Verify HTTP auth tokens and ILP addresses match on both sides. + - Check Rafiki backend logs for connection or authentication errors. +- **Payments failing or stuck**: + - Ensure assets, peers, and accounts are correctly linked. + - Confirm sufficient liquidity / limits on both peers and accounts. + - Check wallet logs for any issues constructing Open Payments requests. +- **TLS / DNS issues**: + - Verify DNS records point to the correct ingress IPs. + - Confirm TLS certificates are valid and that Rafiki is configured to trust any intermediate proxies (`trustProxy: "true"` where required). + +:::note[Next steps] +You have completed an example deployment and peering setup. The next section, [Production requirements and checklist](/integration/requirements/overview), covers the requirements and checklist for deploying Rafiki to a production environment, including regulatory requirements, asset setup, wallet addresses, webhooks, and other integration requirements. +::: diff --git a/packages/documentation/src/content/docs/integration/deployment/helm-k8s.mdx b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/getting-started.mdx similarity index 96% rename from packages/documentation/src/content/docs/integration/deployment/helm-k8s.mdx rename to packages/documentation/src/content/docs/integration/deployment/helm-k8s/getting-started.mdx index b1e7518742..0c6f87d8dc 100644 --- a/packages/documentation/src/content/docs/integration/deployment/helm-k8s.mdx +++ b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/getting-started.mdx @@ -1,5 +1,5 @@ --- -title: Helm & Kubernetes +title: Get Started --- import { LinkOut } from '@interledger/docs-design-system' @@ -9,6 +9,13 @@ import FrontEnv from '/src/partials/frontend-variables-helm.mdx' This guide explains how to deploy Rafiki using Helm charts on a Kubernetes cluster. Helm is a package manager for Kubernetes that allows you to define, install, and upgrade complex Kubernetes applications through Helm charts. +This section provides an overview of deploying Rafiki with Helm and Kubernetes. For a deployment example, refer to the subsequent pages: + +- [Peered Rafiki instances overview and architecture](/integration/deployment/helm-k8s/peered-rafiki-architecture) +- [Deploy ASE A using the Test Wallet](/integration/deployment/helm-k8s/ase-a-test-wallet) +- [Deploy ASE B using the Interledger Wallet](/integration/deployment/helm-k8s/ase-b-interledger-app) +- [Peer the ASEs](/integration/deployment/helm-k8s/ase-peering) + Rafiki uses the following key infrastructure components: - **PostgreSQL**: Used for storing application data, grants, and Open Payments resources @@ -308,7 +315,7 @@ The Rafiki `backend` service handles the core Open Payments functionality and bu **Ports exposed:** - `3000` (openPayments) - Open Payments resource server API -- `3001` (admin) - Backend Admin API and GraphQL endpoint +- `3001` (admin) - [Backend Admin API](/apis/graphql/backend) and GraphQL endpoint - `3002` (connector) - ILP connector for sending and receiving packets - `3005` (autoPeering) - Auto-peering service (when enabled) @@ -322,7 +329,7 @@ TigerBeetle is strongly recommended for production deployments due to its high-p
Frontend service -The Rafiki `frontend` service provides an administrative web interface for managing your Rafiki instance. It offers a user-friendly dashboard for monitoring and managing wallet addresses, payments, peers, and other Open Payments resources. The frontend communicates with the Backend Admin API to perform administrative operations. +The Rafiki `frontend` service provides an administrative web interface for managing your Rafiki instance. It offers a user-friendly dashboard for monitoring and managing wallet addresses, payments, peers, and other Open Payments resources. The frontend communicates with the [Backend Admin API](/apis/graphql/backend) to perform administrative operations. **Ports exposed:** diff --git a/packages/documentation/src/content/docs/integration/deployment/helm-k8s/peered-rafiki-architecture.mdx b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/peered-rafiki-architecture.mdx new file mode 100644 index 0000000000..bb81d4d777 --- /dev/null +++ b/packages/documentation/src/content/docs/integration/deployment/helm-k8s/peered-rafiki-architecture.mdx @@ -0,0 +1,91 @@ +--- +title: Peered Rafiki Instances Architecture +description: High-level architecture for deploying two Rafiki-powered Account Servicing Entities (ASE A and ASE B) on Kubernetes using Interledger Helm charts. +--- + +import { LinkOut, LargeImg } from '@interledger/docs-design-system' + +This guide provides an **architectural overview** of a reference deployment where: + +- Account Servicing Entity A (**ASE A**) runs the **Test Wallet** from github.com/interledger/testnet and its own Rafiki instance. +- Account Servicing Entity B (**ASE B**) runs the **Interledger App Wallet** (container images are available from `ghcr.io/interledger`) and its own Rafiki instance. +- Both ASEs deploy to Kubernetes clusters (on any cloud provider) using the public Interledger Helm charts served from `https://interledger.github.io/charts/interledger`. +- The two Rafiki instances are peered, enabling their users to send Interledger payments between ASE A and ASE B. + +## Components + +Each ASE deployment consists of: + +- **Rafiki Layer**: + - `auth` – Open Payments authorization server. + - `backend` – Open Payments resource server and ILP connector. + - `frontend` – Rafiki Admin UI. +- **Wallet (Integrator) Layer**: + - Wallet backend – Integrates with Rafiki via Open Payments APIs. + - Wallet frontend – User-facing web app. +- **Data stores**: + - **PostgreSQL** – Open Payments resources and wallet addresses database. + - **Redis** – Caching and session management. + - **TigerBeetle** – High-performance accounting database for Rafiki. +- **Ingress / DNS**: + - Kubernetes Ingress exposes Rafiki and wallet HTTP endpoints with TLS. + - Public DNS records point to the ingress IPs or load balancer hostnames. + +## High-level topology + +The deployment uses **two independent Kubernetes clusters**, one per ASE. Each cluster can be deployed on any cloud provider (AWS EKS, Google GKE, Azure AKS) or on-premises: + +- **Kubernetes Cluster A** (for example, `ase-a-cluster`): + - Namespace `rafiki-ase-a` (Rafiki Layer) + - Namespace `wallet-ase-a` (Test Wallet Layer) +- **Kubernetes Cluster B** (for example, `ase-b-cluster`): + - Namespace `rafiki-ase-b` (Rafiki Layer) + - Namespace `wallet-ase-b` (Interledger App Wallet Layer) + +Each cluster has: + +- A **Rafiki instance** fronted by an HTTPS ingress (Open Payments + Admin + Auth endpoints). +- A **wallet app** fronted by an HTTPS ingress (user-facing web app + API). +- **Private services** for databases, Redis, and Rafiki connector endpoints. +- **ILP Peering** connection between the two Rafiki backend connectors. + +## Architecture diagram + +The following diagram shows the major components and how they interact: + + + +## Helm charts and Git repositories + +- Public Helm repository: + + ```bash + helm repo add interledger-helm https://interledger.github.io/charts/interledger + helm repo update + ``` + + Charts used: + + - `interledger-helm/rafiki` – Rafiki instance (auth, backend, frontend) + - `interledger-helm/testnet-wallet` – Example wallet implementation + - `interledger-helm/ilf-wallet-backend` – Interledger App wallet backend + - `interledger-helm/ilf-wallet-frontend` – Interledger App wallet frontend + - `interledger-helm/ilf-wallet-admin` – Interledger App wallet admin + +- Git repositories: + - Rafiki: github.com/interledger/rafiki + - Testnet Wallet: github.com/interledger/testnet + - Helm charts: github.com/interledger/charts + +:::note +The Interledger App Wallet git repository is not publicly accessible. Integrators should obtain the referenced Helm charts from `https://interledger.github.io/charts/interledger` where they are publicly served from. +::: + +## Next steps + +- **Deploy ASE A** (Rafiki + Test Wallet): refer to [Deploy ASE A using Test Wallet](/integration/deployment/helm-k8s/ase-a-test-wallet). +- **Deploy ASE B** (Rafiki + Interledger App Wallet): refer to [Deploy ASE B using Interledger App Wallet](/integration/deployment/helm-k8s/ase-b-interledger-app). +- **Peer the Rafiki instances** to enable Interledger payments: refer to [Peer ASE A and ASE B](/integration/deployment/helm-k8s/ase-peering). diff --git a/packages/documentation/src/content/docs/overview/concepts/accounting.mdx b/packages/documentation/src/content/docs/overview/concepts/accounting.mdx index d93f99317a..651141d2dc 100644 --- a/packages/documentation/src/content/docs/overview/concepts/accounting.mdx +++ b/packages/documentation/src/content/docs/overview/concepts/accounting.mdx @@ -207,7 +207,7 @@ Now, your peer liquidity account's balance is \$9,900 and your USD settlement ac TigerBeetle is a high-performance distributed financial accounting database used by Rafiki’s [backend service](/integration/deployment/services/backend-service) to store account balance data. Both liquidity and settlement accounts in Rafiki correspond to TigerBeetle credit and debit accounts, respectively. -TigerBeetle only holds balance data without any additional ILP packet metadata. For detailed information on TigerBeetle, including its consensus mechanism and its limitations, visit the official TigerBeetle documentation and blog. For more information about TigerBeetle in a production Rafiki environment, see [Running Rafiki in production](/integration/deployment/helm-k8s). +TigerBeetle only holds balance data without any additional ILP packet metadata. For detailed information on TigerBeetle, including its consensus mechanism and its limitations, visit the official TigerBeetle documentation and blog. For more information about TigerBeetle in a production Rafiki environment, see [Running Rafiki in production](/integration/deployment/helm-k8s/getting-started). ### Postgres