diff --git a/charts/self-host/README.md b/charts/self-host/README.md index cca4a0a5..9caea178 100644 --- a/charts/self-host/README.md +++ b/charts/self-host/README.md @@ -390,6 +390,8 @@ spec: EOF ``` +Alternatively, you can create the cluster issuer via the `rawManifets.preInstall` section of `my-values.yaml`. + Finally, set the ingress TLS information in `my-values.yaml`: ```yaml @@ -431,6 +433,8 @@ parameters: EOF ``` +Alternatively, you can create the storage class via the `rawManifets.preInstall` section of `my-values.yaml`. + Set the `sharedStorageClassName` value in `my-values.yaml` to match the name provided. ```yaml @@ -528,6 +532,8 @@ spec: EOF ``` +Alternatively, you can create the secrets provider via the `rawManifets.preInstall` section of `my-values.yaml`. + Note the spots in the definition that say `""`. These will need to be updated for your environment. Also note that you will again have the choice between using the SQL Server Pod and an external SQL Server. Those spots that will need to change have been marked with a comment. Finally, you can name the secrets in Azure Key Vault based on your own naming convention. If you do so, you must make certain that to update the objectName properties under `spec.parameters.objects.array` to match the secrets created in Key Vault. The following commands would create these secrts in a Key Vault: @@ -906,3 +912,309 @@ Update the other settings in `my-values.yaml` based on your environment. Follow ```shell helm upgrade bitwarden bitwarden/self-host --install --devel --namespace bitwarden --values my-values.yaml ``` + +## Example Deployment on AWS EKS + +This section will walk through an example of hosting Bitwarden on AWS EKS. This is just one possible way to deploy the chart as there are many ways of handling persistent storage, secrets, and ingress. + +### Create the namespace + +Follow the instructions above for creating the namespace. + +### Setup Nginx ingress + +The ALB ingress is not currently recommended since it does not support path rewrites with path-based routing. This example uses Nginx, but Traefik could also be used here. + +#### Install the Nginx Ingress Controller + +The ingress controller will setup an AWS Network Load Balancer. Below, we define certain annotations that you should consider setting on the ingress controller service. The specific settings will be dependent on your environment. In this example, we are setting the SSL certificate on the loadbalancer instead of using Let's Encrypt. These annotations specify the certificate provided by AWS Certificate Manager using the certificate's ARN in the `aws-load-balancer-ssl-cert` annotation. + +- service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "ssl" +- service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true" +- service.beta.kubernetes.io/aws-load-balancer-type: "external" +- service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance" +- service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing" +- service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:REPLACEME:REPLACEME:certificate/REPLACEME" # ARN for the certificate +- service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" + +You will also want to set the `spec.externalTrafficPolicy` property to "Local" on the service. The following script will install the controller with these settings: + +```shell +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +helm upgrade -i ingress-nginx ingress-nginx/ingress-nginx \ + --namespace kube-system \ + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-backend-protocol'="ssl" \ + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-cross-zone-load-balancing-enabled'="true" \ + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-type'="external" \ + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-nlb-target-type'="instance" \ + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-scheme'="internet-facing" \ + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-ssl-cert'="arn:aws:acm:REPLACEME:REPLACEME:certificate/REPLACEME" \ #Replace with the ARN for your certificate + --set-string controller.service.annotations.'service\.beta\.kubernetes\.io/aws-load-balancer-ssl-ports'="443" \ + --set controller.service.externalTrafficPolicy=Local +``` + +#### Update the ingrees section in my-values.yaml + +The following settings will create an Nginx ingress. These settings are specific to the Nginx ingress controller annotations we detailed earlier. + +```yaml +general: + domain: "REPLACEME.com" + ingress: + enabled: true + className: "nginx" + ## - Annotations to add to the Ingress resource + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/proxy-read-timeout: "300" + nginx.ingress.kubernetes.io/rewrite-target: /$1 + ## - Labels to add to the Ingress resource + labels: {} + # Certificate options + tls: + # TLS certificate secret name + name: # Handled via the NLB defined in the ingress controller + # Cluster cert issuer (ex. Let's Encrypt) name if one exists + clusterIssuer: + paths: + web: + path: /(.*) + pathType: Prefix + attachments: + path: /attachments[/|$](.*) + pathType: Prefix + api: + path: /api[/|$](.*) + pathType: Prefix + icons: + path: /icons[/|$](.*) + pathType: Prefix + notifications: + path: /notifications[/|$](.*) + pathType: Prefix + events: + path: /events[/|$](.*) + pathType: Prefix + sso: + path: /sso[/|$](.*) + pathType: Prefix + identity: + path: /identity[/|$](.*) + pathType: Prefix + admin: + path: /(admin[/|$]?.*) + pathType: Prefix +``` + +### Setup EFS storage class + +To use EFS persistent storage, you will need to setup the Amazon EFS CSI driver. To do so, please follow the [Amazon EFS CSI driver](https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html). After the driver has been setup, you will need to create a storage class. The exact settings on the storage class will be different for every cluster, but an example is provided below. + +```shell +file_system_id="REPLACE ME" + +cat << EOF | kubectl apply -n bitwarden -f - +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: shared-storage +provisioner: efs.csi.aws.com +parameters: + provisioningMode: efs-ap + fileSystemId: $file_system_id + directoryPerms: "777" # Change for your use case + uid: "2000" # Change for your use case + gid: "2000" # Change for your use case + basePath: "/dyn1" + subPathPattern: "\${.PVC.name}" + ensureUniqueDirectory: "false" + reuseAccessPoint: "false" +mountOptions: + - iam + - tls +EOF +``` + +Alternatively, you can create the storage provider via the `rawManifets.preInstall` section of `my-values.yaml`. + +Review the [CSI Driver for Amazon EFS GitHub page](https://github.com/kubernetes-sigs/aws-efs-csi-driver) for further information on thses settings. After the storage class has been created, set the storage class name in `my-values.yaml`: + +```yaml +sharedStorageClassName: shared-storage +``` + +### Setting secrets using AWS Secrets Manager + +We have detailed several secret provider options. For this example, we will use AWS Secrets Manager. + +First, create a secret in AWS Secrets Manager. You will want to create a secret with keys similar to those below. If you use different key names, make sure to update those in the secret provider class we create later. + +- installationid +- installationkey +- smtpusername +- smtpusername +- smtppassword +- yubicoclientid +- yubicoclientid +- yubicokey +- sapassowrd __*OR*__ dbconnectionstring if using external SQL + +Follow [Use AWS Secrets Manager secrets in Amazon Elastic Kubernetes Services](https://docs.aws.amazon.com/secretsmanager/latest/userguide/integrating_csi_driver.html) to setup the driver and permissions. When creating the IAM permissions policy, one similar to the one below will suffice. Replace the "Resource" value with the ARN of your secret in Resource manager. + +```json +{ + "Version": "2012-10-17", + "Statement": { + "Effect": "Allow", + "Action": [ + "secretsmanager:DescribeSecret", + "secretsmanager:GetSecretValue" + ], + "Resource": "arn:aws:secretsmanager:REPLACEME:REPLACEME:secret:REPLACEME" + } +} +``` + +Create a service account, and give it access to your secret using the policy you created: + +```shell +CLUSTER_NAME=replace_me +ACCOUNT_ID=111111111111 # replace with your AWS account ID +ROLE_NAME=replaceme # name of the role that will be created in IAM +POLICY_NAME=replaceme # the name of the policy you created earlier +eksctl create iamserviceaccount \ + --cluster=$CLUSTER_NAME \ + --namespace=bitwarden \ + --name=bitwarden-sa \ + --role-name $ROLE_NAME \ + --attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/$POLICY_NAME \ + --approve +``` + +Next, create the secret provider class. The example below demonstrates how to do so. Make sure to update the region and objectName before deploying. If you used different keys when creating the secret in Secrets Manager, you will want to update the paths for the secrets as well. + +```shell +cat <