OpenProject: Helm chart and application config

Change-Id: Ic3e963e72ed4fd7f3d8550feb55ed468dc561884
diff --git a/charts/openproject/values.yaml b/charts/openproject/values.yaml
new file mode 100644
index 0000000..d650bfe
--- /dev/null
+++ b/charts/openproject/values.yaml
@@ -0,0 +1,705 @@
+# Default values for openproject.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+## Enable development mode.
+##
+## Set this to true if you want are working on the charts locally using
+## local clusters such as minikube or kind.
+##
+## This will set `OPENPROJECT_HTTPS` to `false` and avoid using volumes for
+## tmp folders as (permissions for) these don't work correctly in local clusters.
+develop: false
+
+global:
+  ## Credentials to fetch images from private registry.
+  ##
+  ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+  ##
+  ## imagePullSecrets:
+  ##   - myRegistryKeySecretName
+  #
+  imagePullSecrets: []
+
+## Affinity for pod assignment.
+##
+## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
+#
+affinity: {}
+
+## Define additional environment variables.
+##
+## You can get a list of all environment variables when executing:
+## "RAILS_ENV=production bundle exec rake setting:available_envs"
+##
+## environment:
+##   OPENPROJECT_ATTACHMENT__MAX__SIZE: 5120
+#
+environment: {}
+
+## Provide a name to substitute for the full names of resources.
+#
+fullnameOverride: ""
+
+##
+# Override the cluster domain name used in templating
+clusterDomain: "cluster.local"
+
+## Define settings for wait-for-db init-container
+#
+initdb:
+  image:
+    ## Define docker registry address.
+    #
+    registry: "docker.io"
+
+    ## Define repository string.
+    #
+    repository: "postgres"
+
+    # Postgres version to use
+    tag: 13
+
+    ## Define a imagePullPolicy.
+    ##
+    ## Ref.: https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy
+    ##
+    ## "IfNotPresent" => The image is pulled only if it is not already present locally.
+    ## "Always" => Every time the kubelet launches a container, the kubelet queries the container image registry to
+    ##             resolve the name to an image digest. If the kubelet has a container image with that exact digest cached
+    ##             locally, the kubelet uses its cached image; otherwise, the kubelet pulls the image with the resolved
+    ##             digest, and uses that image to launch the container.
+    ## "Never" => The kubelet does not try fetching the image. If the image is somehow already present locally, the
+    ##            kubelet attempts to start the container; otherwise, startup fails
+    #
+    imagePullPolicy: "Always"
+
+  resources:
+    limits:
+      memory: "200Mi"
+    requests:
+      memory: "200Mi"
+
+## Define and create Kubernetes Service.
+##
+## Ref.: https://kubernetes.io/docs/concepts/services-networking/ingress/
+#
+ingress:
+  ## Whether to enable session affinity or not. It is required by ingress.
+  #
+  enabled: true
+
+  ## Define the name of the ingress class.
+  ##
+  ## If left empty, the cluster default is used.
+  ## Set this if you need a specific class, for instance `nginx`.
+  #
+  ingressClassName:
+
+  ## Define custom ingress annotations:
+  ##
+  ## Example:
+  ## annotations:
+  ##   nginx.ingress.kubernetes.io/rewrite-target: /
+  annotations: {}
+
+  ## Define the Fully Qualified Domain Name (FQDN) where OpenProject should be reachable.
+  #
+  host: "openproject.example.com"
+
+  ## Define the path for OpenProject on your host.
+  #
+  path: /
+
+  ## Each path in an Ingress is required to have a corresponding path type. Paths that do not include an explicit
+  ## pathType will fail validation. There are three supported path types:
+  ##
+  ## "ImplementationSpecific" => With this path type, matching is up to the IngressClass. Implementations can treat this
+  ##                             as a separate pathType or treat it identically to Prefix or Exact path types.
+  ## "Exact" => Matches the URL path exactly and with case sensitivity.
+  ## "Prefix" => Matches based on a URL path prefix split by /.
+  ##
+  ## Ref.: https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types
+  #
+  pathType: "Prefix"
+
+  ## You can secure an Ingress by specifying a Secret that contains a TLS private key and certificate.
+  ##
+  ## Ref.: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls
+  #
+  tls:
+    ## Whether to enable tls or not.
+    #
+    enabled: true
+
+    ## The name of the kubernetes secret which contains a TLS private key and certificate.
+    ## Hint: This secret is not created by this chart and must be provided.
+    ##
+    #
+    secretName: ""
+
+egress:
+  tls:
+    rootCA:
+      configMap: ""
+      fileName: ""
+
+## Define image setting
+#
+image:
+  ## Define docker registry address.
+  #
+  registry: "docker.io"
+
+  ## Define repository string.
+  #
+  repository: "openproject/community"
+
+  ## Define a imagePullPolicy.
+  ##
+  ## Ref.: https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy
+  ##
+  ## "IfNotPresent" => The image is pulled only if it is not already present locally.
+  ## "Always" => Every time the kubelet launches a container, the kubelet queries the container image registry to
+  ##             resolve the name to an image digest. If the kubelet has a container image with that exact digest cached
+  ##             locally, the kubelet uses its cached image; otherwise, the kubelet pulls the image with the resolved
+  ##             digest, and uses that image to launch the container.
+  ## "Never" => The kubelet does not try fetching the image. If the image is somehow already present locally, the
+  ##            kubelet attempts to start the container; otherwise, startup fails
+  #
+  imagePullPolicy: "Always"
+
+  ## Define image tag.
+  ## For the helm chart, use the `-slim` variants as the all-in-one container is not compatible
+  ## with some of the options (non-root execution, password splitting, etc.) and is inefficient for using in helm
+  ## due to embedded a number of services.
+  tag: "13-slim"
+
+  ## Define image sha256 - mutual exclusive with image tag.
+  ## The sha256 has a higher precedence than
+  # sha256:
+
+## Credentials to fetch images from private registry.
+##
+## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
+##
+## imagePullSecrets:
+##   - myRegistryKeySecretName
+#
+imagePullSecrets: []
+
+## Configure memcached settings.
+#
+memcached:
+  ## When set to true, a memcached will be deployed into current namespace, when false you have to provide your own
+  ## memcached instance.
+  #
+  bundled: true
+
+  global:
+    containerSecurityContext:
+      enabled: true
+      allowPrivilegeEscalation: false
+      capabilities:
+        drop:
+          - "ALL"
+      seccompProfile:
+        type: "RuntimeDefault"
+      readOnlyRootFilesystem: true
+      runAsNonRoot: true
+
+  ## When "bundled" is set to false, you need to define the memcached connection details.
+  #
+  connection:
+    host:
+    port:
+
+## String to partially override release name.
+#
+nameOverride: ""
+
+## Node labels for pod assignment.
+##
+## Ref: https://kubernetes.io/docs/user-guide/node-selection/
+#
+nodeSelector: {}
+
+## Deployment strategy
+##
+## Ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
+#
+strategy:
+  ## Re-create pod during deployments by default since a writable volume is mounted.
+  ## Should your cluster support WriteMany volumes, you can change this
+  ## to `RollingUpdate`.
+  type: "Recreate"
+
+# Define the workers to run, their queues, replicas, strategy, and resources
+workers:
+  default:
+    queues: ""
+    replicas: 1
+    strategy:
+      type: "Recreate"
+    resources:
+      requests:
+        memory: "512Mi"
+        cpu: "250m"
+      limits:
+        memory: "4Gi"
+        cpu: "4"
+
+## OpenProject related settings.
+##
+## Ref.: https://www.openproject.org/docs/installation-and-operations/configuration/environment/#supported-environment-variables
+#
+openproject:
+  ## Enable https in backend response.
+  #
+  https: true
+
+  ## Define the host, defaults to value of "ingress.host".
+  #
+  host:
+
+  ## Enable HSTS.
+  #
+  hsts: true
+
+  ## Define Cache settings.
+  #
+  cache:
+    store: "memcache"
+
+  extraEnvVarsSecret: ""
+
+  ## Define the language to seed the instance in
+  #
+  seed_locale: "en"
+
+  ##
+  # Let OpenProject run in a subdirectory,
+  # e.g., https://exameple.com/openproject
+  # specify with leading slash, but without trailing slash
+  # e.g., /openproject
+  railsRelativeUrlRoot:
+
+  ## Define admin user details
+  # only applicable on first installation
+  # Note: Only applicable for versions >= 13.0
+  admin_user:
+    password: "admin"
+    password_reset: "true"
+    name: "OpenProject Admin"
+    mail: "admin@example.net"
+
+  ## Define OpenID Connect providers
+  oidc:
+    enabled: false
+    provider: "Keycloak"
+    displayName: "Keycloak"
+    host: ""
+    identifier: ""
+    secret: ""
+    authorizationEndpoint: ""
+    tokenEndpoint: ""
+    userinfoEndpoint: ""
+    endSessionEndpoint: ""
+    scope: "[openid]"
+
+    # Optional attribute mappings from the id token
+    attribute_map: {}
+
+    ## To avoid having sensitive credentials in your values.yaml, the preferred way is to
+    ## use an existing secret containing the OIDC compatible access credentials.
+    ## Specify the name of this existing secret here.
+    existingSecret:
+
+    ## In case your secret does not use the default keys in the secret, you can adjust them here.
+    secretKeys:
+      identifier: "clientId"
+      secret: "clientSecret"
+
+    # Allows usage of sealed-secret for `identifier` and `secret` values.
+    # Special use case for use in setups where heml template `lookup` function is not available.
+    # Ref: https://github.com/argoproj/argo-cd/issues/5202
+    #
+    extraOidcSealedSecret:
+
+  ## Modify PostgreSQL statement timout.
+  ## Increase in case you get errors such as "ERROR: canceling statement due to statement timeout".
+  ##
+  ## Ref.: https://www.openproject.org/docs/installation-and-operations/configuration/environment/#postgresql-statement_timeout
+  #
+  postgresStatementTimeout: 120s
+
+  ## Whether or not to use ephemeral volumes for /app/tmp and /tmp.
+  ## Falls back to a sensible default if undefined.
+  #
+  useTmpVolumes:
+
+  ## customize the tmp storage mount sizes
+  tmpVolumesStorage: "5Gi"
+
+## Whether to allocate persistent volume disk for the data directory.
+## In case of node failure, the node data directory will still persist.
+##
+## Ref.: https://kubernetes.io/docs/concepts/storage/persistent-volumes/
+#
+persistence:
+  enabled: true
+
+  ## Define the volume access modes:
+  ##
+  ## "ReadWriteOnce" => The volume can be mounted as read-write by a single node. ReadWriteOnce access mode still can
+  ##                    allow multiple pods to access the volume when the pods are running on the same node.
+  ## "ReadOnlyMany" => The volume can be mounted as read-only by many nodes.
+  ## "ReadWriteMany" => The volume can be mounted as read-write by many nodes.
+  ## "ReadWriteOncePod" => The volume can be mounted as read-write by a single Pod. Use ReadWriteOncePod access mode if
+  ##                       you want to ensure that only one pod across whole cluster can read that PVC or write to it.
+  #
+  accessModes:
+    - "ReadWriteMany"
+
+  ## Define custom storage (PVC) annotations:
+  ##
+  annotations: {}
+
+  ## Define the volume size.
+  #
+  size: "1Gi"
+
+  ## Define the class of PV.
+  storageClassName:
+
+## Whether to use an S3-compatible object storage to store OpenProject attachments.
+## If this is enabled, files will NOT be stored in the mounted volume configured in `persistence` above.
+## The volume will not be used at all, so it `persistence.enabled` should be set to `false` in this case.
+##
+## Ref.: https://www.openproject.org/docs/installation-and-operations/configuration/#attachments-storage
+#
+s3:
+  enabled: false
+
+  auth:
+    # Provide the accessKeyId and secret in plain values
+    # We recommend to use the existing
+    Secret option instead
+    accessKeyId:
+    secretAccessKey:
+
+    ## To avoid having sensitive credentials in your values.yaml, the preferred way is to
+    ## use an existing secret containing the S3 compatible access credentials.
+    ## Specify the name of this existing secret here.
+    existingSecret:
+
+    ## In case your secret does not use the default keys in the secret, you can adjust them here.
+    secretKeys:
+      accessKeyId: "accessKeyId"
+      secretAccessKey: "secretAccessKey"
+
+  region:
+  bucketName:
+
+  ## Remove or leave empty to use default AWS S3 endpoint
+  #
+  endpoint:
+  host:
+  port:
+  pathStyle: false
+  signatureVersion: 4
+  useIamProfile: false
+  # Some providers do not properly support signature v4 streaming (e.g. Scaleway)
+  enableSignatureV4Streaming: true
+
+  ## If enabled, upload files directly to S3 from the browser instead of going through OpenProject.
+  ## May not be supported by providers other than AWS S3 itself.
+  ##
+  ## Ref.: https://www.openproject.org/docs/installation-and-operations/configuration/#direct-uploads
+  #
+  directUploads: true
+
+  ## You can always override these options via the environment, for instance:
+  ##
+  ## environment:
+  ##   OPENPROJECT_FOG_CREDENTIALS_REGION: 'us-east-1'
+  ##
+  ## Ref.: https://www.openproject.org/docs/installation-and-operations/configuration/#attachments-storage
+
+## Define custom pod annotations.
+#
+podAnnotations: {}
+
+## Pod Security Context.
+##
+## We use the default value of `1000` for `fsGroup` since that
+## is the app user's group ID and if the user wants to be able to
+## write to `/var/openproject/assets` the mounted folder needs to
+## have a matching gid.
+##
+## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+#
+podSecurityContext:
+  enabled: true
+  fsGroup: 1000
+
+## Container security context using as a default best practice values
+## granting minimum privileges.
+##
+## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+#
+containerSecurityContext:
+  enabled: true
+  runAsUser: 1000
+  runAsGroup: 1000
+  allowPrivilegeEscalation: false
+  capabilities:
+    drop:
+      - "ALL"
+  seccompProfile:
+    type: "RuntimeDefault"
+  readOnlyRootFilesystem: true
+  runAsNonRoot: true
+
+## Configure PostgreSQL settings.
+#
+postgresql:
+  ## When set to true, a postgres server will be deployed into current namespace, when false you have to provide your
+  ## own database instance.
+  #
+  bundled: true
+
+  global:
+    containerSecurityContext:
+      enabled: true
+      allowPrivilegeEscalation: false
+      capabilities:
+        drop:
+          - "ALL"
+      seccompProfile:
+        type: "RuntimeDefault"
+      readOnlyRootFilesystem: true
+      runAsNonRoot: true
+
+  ## When "bundled" is set to false, you need to define the database connection details.
+  #
+  connection:
+    host:
+    port:
+
+  ## Database auth details.
+  #
+  auth:
+    ## To avoid having sensitive credentials in your values.yaml, the preferred way to provide a password
+    ## is to use an existing secret containing the PostgreSQL credentials.
+    ## Specify the name of this existing secret here.
+    ##
+    ## If neither an existing secret nor passwords are defined, a secret is generated automatically.
+    ##
+    ## The postgresql chart will create this secret (the name of which ends with `-postgresql` by default)
+    ## with generated user and admin passwords.
+    ## If you want to see the base64 encoded passwords you can output the secret like this:
+    ##
+    ## ```
+    ## kubectl get secret -n <namespace> openproject-postgresql -o yaml | grep password
+    ## ```
+    #
+    existingSecret: ""
+
+    ## In case your secret does not use the default keys in the secret, you can adjust them here.
+    ##
+    ## secretKeys:
+    ##   adminPasswordKey: "postgres-password"
+    ##   userPasswordKey: "password"
+
+    ## Database username.
+    #
+    username: "openproject"
+
+    ## Database name.
+    #
+    database: "openproject"
+
+    ## If you are not using a Kubernetes secret to store your postgresql credentials,
+    ## you can specify them here if you really must. Please handle with care!
+
+    ## Database password.
+    #
+    password: ""
+
+    ## Database root password.
+    #
+    postgresPassword: ""
+
+  ## When using the "bundled" postgresql chart, you can configure the storageClass and other settings similar to this
+  ## Ref: https://github.com/bitnami/charts/blob/main/bitnami/postgresql/values.yaml
+  #
+  # global:
+  #  storageClass: my-storage-class-name
+
+## Configure liveness and readiness probes.
+##
+## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
+#
+probes:
+  ## Configure liveness probe.
+  ##
+  ## If the liveness probe fails, the container will be restarted.
+  #
+  liveness:
+    ## Whether to enable liveness probes.
+    #
+    enabled: true
+
+    ## Number of seconds after the container has started before startup, liveness or readiness probes are initiated.
+    ## Defaults to 0 seconds. Minimum value is 0.
+    #
+    initialDelaySeconds: 120
+
+    ## Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1.
+    #
+    timeoutSeconds: 3
+
+    ## How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.
+    #
+    periodSeconds: 30
+
+    ## When a probe fails, Kubernetes will try failureThreshold times before giving up. Giving up in case of liveness
+    ## probe means restarting the container. In case of readiness probe the Pod will be marked Unready. Defaults to 3.
+    ## Minimum value is 1.
+    #
+    failureThreshold: 3
+
+    ## Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1.
+    ## Must be 1 for liveness and startup Probes. Minimum value is 1.
+    #
+    successThreshold: 1
+
+  ## Configure readiness probe.
+  ##
+  ## If the readiness probe failes, no traffic will be routed to the container.
+  #
+  readiness:
+    ## Whether to enable liveness probes.
+    #
+    enabled: true
+
+    ## Number of seconds after the container has started before startup, liveness or readiness probes are initiated.
+    ## Defaults to 0 seconds. Minimum value is 0.
+    #
+    initialDelaySeconds: 30
+
+    ## Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1.
+    #
+    timeoutSeconds: 3
+
+    ## How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.
+    #
+    periodSeconds: 15
+
+    ## When a probe fails, Kubernetes will try failureThreshold times before giving up. Giving up in case of liveness
+    ## probe means restarting the container. In case of readiness probe the Pod will be marked Unready. Defaults to 3.
+    ## Minimum value is 1.
+    #
+    failureThreshold: 30
+
+    ## Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1.
+    ## Must be 1 for liveness and startup Probes. Minimum value is 1.
+    #
+    successThreshold: 1
+
+## Number of OpenProject web process replicas.
+#
+replicaCount: 1
+
+## Number of OpenProject background worker process replicas.
+#
+backgroundReplicaCount: 1
+
+## Configure resource requests and limits.
+##
+## http://kubernetes.io/docs/user-guide/compute-resources/
+#
+resources:
+  requests:
+    memory: "512Mi"
+    cpu: "250m"
+  limits:
+    memory: "4Gi"
+    cpu: "4"
+
+## Define and create Kubernetes Service.
+##
+## Ref.: https://kubernetes.io/docs/concepts/services-networking/service
+#
+service:
+  ## Whether to enable session affinity or not. It is required by ingress.
+  #
+  enabled: true
+
+  ## Choose the kind of Service:
+  ##
+  ## "ClusterIP" => Exposes the Service on a cluster-internal IP. Choosing this value makes the Service only reachable
+  ##                from within the cluster. This is the default that is used if you don't explicitly specify a type for
+  ##                a Service.
+  ## "NodePort" => Exposes the Service on each Node's IP at a static port (the NodePort). To make the node port
+  ##               available, Kubernetes sets up a cluster IP address, the same as if you had requested a Service of
+  ##               type: ClusterIP.
+  ## "LoadBalancer" => Exposes the Service externally using a cloud provider's load balancer.
+  ##
+  ## Ref.: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
+  #
+  type: "ClusterIP"
+
+  ## Define the ports of Service.
+  ## You can set the port value to an arbitrary value, it will map the container port by name.
+  ##
+  ## Custom NodePort example:
+  ## ports:
+  ##   http:
+  ##     port: 8080
+  ##     protocol: "TCP"
+  ##     nodePort: "38080"
+  #
+  ports:
+    http:
+      containerPort: 8080
+      port: 8080
+      protocol: "TCP"
+
+  ## Configure session affinity for to hit the same backend for the period specified in `timeoutSeconds`.
+  ##
+  ## Ref.: https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity
+  #
+  sessionAffinity:
+    ## Whether to enable session affinity or not.
+    #
+    enabled: false
+    ## The session duration in seconds.
+    #
+    timeoutSeconds: 10800
+
+## Define Service Accounts for Pods.
+##
+## Ref.: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
+#
+serviceAccount:
+  ## Whether to create service account.
+  #
+  create: true
+
+  ## Define custom service account annotations.
+  #
+  annotations: {}
+
+# Options for the seeder job
+seederJob:
+  ## Define custom seeder job annotations.
+  #
+  annotations: {}
+
+## Tolerations for pod assignment.
+##
+## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
+#
+tolerations: []