diff --git a/kubernetes/kolabctl b/kubernetes/kolabctl new file mode 100755 index 00000000..7c5abc5d --- /dev/null +++ b/kubernetes/kolabctl @@ -0,0 +1,534 @@ +#!/bin/bash + +# shellcheck disable=SC2068 +# shellcheck disable=SC2086 + +HOST=${HOST:-kolab.local} +NAMESPACE=${NAMESPACE:-kolab} +CHART_VERSION=${CHART_VERSION:-"0.1.0"} +CHART_URL=${CHART_URL:-"oci://quay.io/apheleiait/kolab/kolab"} + +### ========== Implementation Details ============ + +#Ensure we are connected to the correct cluster (localhost only for now) +__ensure_server() { + if ! grep server: ~/.kube/config | grep 127.0.0.1; then + echo "Connected to the wrong server!" + exit + fi +} + +__helm_upgrade() { + if [[ -f values.yaml ]]; then + ARGS="-f values.yaml" + fi + time helm upgrade -i kolab --wait --wait-for-jobs --timeout 30m0s --create-namespace $ARGS $@ --namespace "$NAMESPACE" "$CHART_URL" --version "$CHART_VERSION" +} + +__helm_template() { + if [[ -f values.yaml ]]; then + ARGS="-f values.yaml" + fi + command helm template kolab --namespace "$NAMESPACE" "$CHART_URL" $ARGS $@ --version "$CHART_VERSION" +} + +__k3s_login() { + # Copy k3s config + mkdir -p "$HOME/.kube" + sudo cp /etc/rancher/k3s/k3s.yaml "$HOME/.kube/config" + sudo chown $(id -i):$(id -g) "$HOME/.kube/config" + chmod 600 "$HOME/.kube/config" + + echo "Export this: export KUBECONFIG=$HOME/.kube/config" +} + + +# Pull images as defined in helm chart. +# Pass in username and password for registry +# This currently only pulls the kolab images (for the rest we'd have to figure out where to pull from) +__k3s_pull() { + # Figure out which images to pull + images=$(__helm_template | grep "image: " | grep -v "#" | grep -oP "(?<=image: ).*" | sed 's/\"//g' | uniq | grep "kolab") + for image in $images; do + echo "Pulling $image" + # For the quay.io/apheleiait images we need to pass in the credentials + if [[ $image == *"quay.io/apheleiait"* ]]; then + if [[ -z $1 || -z $2 ]]; then + echo "You need to specify the quay.io/apheleiait username and password" + exit 1 + fi + sudo k3s ctr images pull --user "$1:$2" "$image" + else + #TODO Support non apheleiait images? + sudo k3s ctr images pull "$image" + fi + done +} + + +__k3s_install() { + # TURN OFF firewalld if you're seeing any networking issues. + + # Install K3S + + sudo mkdir -p /etc/rancher/k3s/ + + curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server" sh -s - --disable traefik + sudo chmod 644 /etc/rancher/k3s/k3s.yaml + + curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + + __k3s_login + + # Check K3S + kubectl get pods -n kube-system + + # Install certmanager + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.crds.yaml + + helm repo add jetstack https://charts.jetstack.io + helm repo add haproxytech https://haproxytech.github.io/helm-charts + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update + + helm install cert-manager jetstack/cert-manager \ + --wait \ + --namespace cert-manager \ + --create-namespace \ + --version v1.13.3 + + helm install haproxy-ingress haproxytech/kubernetes-ingress \ + --wait \ + --namespace haproxy-controller \ + --create-namespace \ + --set controller.config.ssl-certificate=kolab/kolab-cert \ + --set controller.kind=DaemonSet \ + --set controller.daemonset.useHostPort=true \ + --version 1.38.5 + + helm install kube-state-metrics prometheus-community/kube-state-metrics \ + --wait \ + --namespace default \ + --version 3.0.0 +} + +__sum_memory_requests() { + res=$(kubectl get pods -o=jsonpath='{.items[*]..resources.requests.memory}' -n "$NAMESPACE") + let tot=0 + for i in $res; do + if [[ $i =~ "Mi" ]]; then + i=$(echo $i | sed 's/[^0-9]*//g') + tot=$(( tot + i )) + elif [[ $i =~ "Gi" ]]; then + i=$(echo $i | sed 's/[^0-9]*//g') + tot=$(( tot + i * 1000 )) + fi + done + echo $tot +} + +__sum_cpu_requests() { + res=$(kubectl get pods -o=jsonpath='{.items[*]..resources.requests.cpu}' -n "$NAMESPACE") + let tot=0 + for i in $res; do + if [[ $i =~ "m" ]]; then + i=$(echo $i | sed 's/[^0-9]*//g') + tot=$(( tot + i )) + else + tot=$(( tot + i*1000 )) + fi + done + echo $tot +} + +__replace_multiline() { + # Echo content, indent by the passed in spaces, insert before matching line + echo -n "$2" | sed -e "s/^/$4/" | sed -i "/$1/e cat /dev/stdin;echo" $3 + # delete the matching line + sed -i "/$1/d" $3 +} + + +### ========== End of Implementation ============ +# +### ========== Commands ============ + +# Cluster admin commands +kolab__deploy() { + if [[ ! -f values.yaml ]]; then + echo "Missing a values.yaml file, run configure first." + exit 1 + fi + if [[ "$1" == "--k3s" ]]; then + shift + __k3s_install + __k3s_pull $1 $2 + if [[ -n $1 && -n $2 ]]; then + helm registry login quay.io/apheleiait -u "$1" -p "$2" + fi + fi + __ensure_server + echo "This is going to take a while (timeout after 30 minutes)" + __helm_upgrade +} + +kolab__uninstall() { + command helm uninstall kolab --wait --timeout 10m0s --debug $ARGS $@ --namespace "$NAMESPACE" +} + +kolab__update() { + __helm_upgrade $@ +} + +kolab__template() { + __helm_template $@ +} + +# Update the kolabctl script from the latest tarball +kolab__selfupdate() { + wget https://mirror.apheleia-it.ch/pub/kolab-kubernetes-latest.tar.gz -O /tmp/kolab-kubernetes-latest.tar.gz + tar -zxvf /tmp/kolab-kubernetes-latest.tar.gz kolabctl +} + +# kolab__backup() { +# command bin/backup.sh +# } + +# kolab__restore() { +# command bin/restore.sh +# } + +# Render a values.yaml file from a template in docs +kolab__configure() { + TEMPLATE="docs/k3s.values.yaml" + if [[ -f values.yaml ]]; then + echo "values.yaml already exists"; + exit 1 + fi + + if [[ -z $DOMAIN ]]; then + echo "Please enter your domain:" + read -r DOMAIN + fi + + if [[ -z $ADMIN_PASSWORD ]]; then + echo "Please enter your new admin password for the admin@$DOMAIN user:" + read -r ADMIN_PASSWORD + fi + + if [[ -z $PULL_SECRET ]]; then + echo "Please enter your registry access secret:" + read -r PULL_SECRET + fi + + if [[ -z $PUBLIC_IP ]]; then + echo "Please enter your public ip:" + read -r PUBLIC_IP + fi + + TEST_PASSWORD=$(openssl rand -base64 24) + APP_KEY=$(openssl rand -base64 32); + APP_KEY="base64:${APP_KEY}" + + COTURN_STATIC_SECRET=$(openssl rand -hex 32); + PASSPORT_PROXY_OAUTH_CLIENT_ID=$(uuidgen); + PASSPORT_PROXY_OAUTH_CLIENT_SECRET=$(openssl rand -base64 32) + PASSPORT_PRIVATE_KEY=$(openssl genrsa 4096); + PASSPORT_PUBLIC_KEY=$(echo "$PASSPORT_PRIVATE_KEY" | openssl rsa -pubout 2>/dev/null) + MEET_WEBHOOK_TOKEN=$(openssl rand -hex 32) + MEET_SERVER_TOKEN=$(openssl rand -hex 32) + DB_ROOT_PASSWORD=simple123 + DB_KOLAB_PASSWORD=simple123 + DB_LEGACY_PASSWORD=simple123 + DB_ROUNDCUBE_PASSWORD=simple123 + REDIS_PASSWORD=simple123 + MAIL_NOREPLY_PASSWORD=simple123 + MINIO_ROOT_PASSWORD=simple123 + IMAP_ADMIN_PASSWORD=simple123 + + ROUNDCUBE_DES_KEY=$(openssl rand -base64 24); + + DKIM_IDENTIFIER="dkim20240318" + DKIM_KEY=$(openssl genrsa 2048); + + cp "$TEMPLATE" values.yaml + + # / can appear in base64, but | not + sed -i \ + -e "s|DOMAIN|${DOMAIN}|g" \ + -e "s|TEST_PASSWORD|${TEST_PASSWORD}|g" \ + -e "s|IMAP_ADMIN_PASSWORD|${IMAP_ADMIN_PASSWORD}|g" \ + -e "s|APP_KEY|${APP_KEY}|g" \ + -e "s|PULL_SECRET|${PULL_SECRET}|g" \ + -e "s|PASSPORT_PROXY_OAUTH_CLIENT_ID|${PASSPORT_PROXY_OAUTH_CLIENT_ID}|g" \ + -e "s|PASSPORT_PROXY_OAUTH_CLIENT_SECRET|${PASSPORT_PROXY_OAUTH_CLIENT_SECRET}|g" \ + -e "s|PASSPORT_PROXY_OAUTH_CLIENT_SECRET|${PASSPORT_PROXY_OAUTH_CLIENT_SECRET}|g" \ + -e "s|ROUNDCUBE_DES_KEY|${ROUNDCUBE_DES_KEY}|g" \ + -e "s|MEET_WEBHOOK_TOKEN|${MEET_WEBHOOK_TOKEN}|g" \ + -e "s|MEET_SERVER_TOKEN|${MEET_SERVER_TOKEN}|g" \ + -e "s|COTURN_STATIC_SECRET|${COTURN_STATIC_SECRET}|g" \ + -e "s|DB_ROOT_PASSWORD|${DB_ROOT_PASSWORD}|g" \ + -e "s|DB_KOLAB_PASSWORD|${DB_KOLAB_PASSWORD}|g" \ + -e "s|DB_LEGACY_PASSWORD|${DB_LEGACY_PASSWORD}|g" \ + -e "s|DB_ROUNDCUBE_PASSWORD|${DB_ROUNDCUBE_PASSWORD}|g" \ + -e "s|REDIS_PASSWORD|${REDIS_PASSWORD}|g" \ + -e "s|MAIL_NOREPLY_PASSWORD|${MAIL_NOREPLY_PASSWORD}|g" \ + -e "s|MINIO_ROOT_PASSWORD|${MINIO_ROOT_PASSWORD}|g" \ + -e "s|DKIM_IDENTIFIER|${DKIM_IDENTIFIER}|g" \ + -e "s|ADMIN_PASSWORD|${ADMIN_PASSWORD}|g" \ + -e "s|PUBLIC_IP|${PUBLIC_IP}|g" \ + values.yaml + + __replace_multiline PASSPORT_PRIVATE_KEY "$PASSPORT_PRIVATE_KEY" values.yaml " " + __replace_multiline PASSPORT_PUBLIC_KEY "$PASSPORT_PUBLIC_KEY" values.yaml " " + __replace_multiline DKIM_KEY "$DKIM_KEY" values.yaml " " +} + +kolab__registry_login() { + helm registry login quay.io/apheleiait -u "$1" -p "$2" +} + +kolab__selfcheck() { + set -e + + if command kubectl -n $NAMESPACE describe secret/kolab-cert-static --request-timeout "5s" &> /dev/null; then + echo "Found static tls secret" + elif command kubectl -n $NAMESPACE describe secret/kolab-cert-letsencrypt --request-timeout "5s" &> /dev/null; then + echo "Found letsencrypt secret" + else + echo "TLS secret not found" + exit 1 + fi + # Wait for all rollouts to complete + command kubectl -n $NAMESPACE rollout status deployment + + command kubectl exec --stdin --tty -n "$NAMESPACE" deployment/imap -- bash -c "testsaslauthd -u \$IMAP_ADMIN_LOGIN -p \$IMAP_ADMIN_PASSWORD" + command kubectl exec --stdin --tty -n "$NAMESPACE" deployment/horizon -- ./artisan status:health --check=Redis --check=IMAP + command kubectl exec --stdin --tty -n "$NAMESPACE" deployment/roundcube -- ./checkconnections.sh + + + echo "All tests passed" +} + +kolab__stop() { + command /usr/local/bin/k3s-killall.sh +} + +kolab__start() { + command systemctl start k3s +} + +kolab__status() { + echo "# Cluster info" + command kubectl cluster-info + echo "# Helm status" + command helm status kolab -n "$NAMESPACE" + echo "# Events" + command kubectl get events --sort-by=.metadata.creationTimestamp +} + +kolab__shell() { + if [[ $1 == "" ]]; then + # command kubectl run kolab -ti --rm -n "$NAMESPACE" --image localhost:5000/webapp:latest -- /bin/bash + command kubectl run utils -ti --rm -n "$NAMESPACE" --image quay.io/apheleiait/kolab/utils:latest -- /bin/bash + else + command kubectl exec --stdin --tty -n "$NAMESPACE" "deployment/$1" -- /bin/bash + fi +} + +kolab__logs() { + deployment="$1" + shift + command kubectl -n "$NAMESPACE" logs "deployment/$deployment" $@ +} + +# Tail the logs via logcli +# --pod=: wildcard match on the pod_name label +# --search=: Run a fulltext query match on the record +# -f: Stream the log +# --full: Full output including the entire record +kolab__tail() { + if [[ "$*" =~ "--pod" ]]; then + ARGUMENT=$(echo "$*" | grep -o -e "--pod=.*" | cut -d ' ' -f 1) + POD_NAME=$(echo "$ARGUMENT" | cut -d '=' -f 2) + POD_FILTER=",pod_name=~\"$POD_NAME.*\"" + set -- "$(echo "$*" | sed "s|$ARGUMENT *||")" + fi + + if [[ "$*" =~ "--search" ]]; then + ARGUMENT=$(echo "$*" | grep -o -e "--search=.*" | cut -d ' ' -f 1) + SEARCH_STRING=$(echo "$ARGUMENT" | cut -d '=' -f 2) + FULLTEXT_FILTER=" |~ \"$SEARCH_STRING\"" + set -- "$(echo "$*" | sed "s|$ARGUMENT *||")" + fi + + if [[ "$*" =~ "--full" ]]; then + set -- "$(echo "$*" | sed "s|--full *||")" + else + OUTPUT="--output=raw" + fi + echo "$*" + + if [[ "$*" =~ "-f" ]]; then + FOLLOW="--follow" + fi + + # The format is --from=2024-02-22T08:30:24Z --to=2024-02-23T12:30:24Z + if [[ "$*" =~ "--from" ]]; then + # Can't have --from without --to + FROM=$(echo "$*" | grep -o -e "--from=.*" | cut -d ' ' -f 1) + TO=$(echo "$*" | grep -o -e "--to=.*" | cut -d ' ' -f 1) + #beware of --limit (it will continue to apply, so you may get partial results) + + # Can't follow with a time range + FOLLOW="" + fi + + QUERY="{namespace_name=\"$NAMESPACE\"$POD_FILTER} $FULLTEXT_FILTER | json log | line_format \"{{ __timestamp__ }} \t {{.pod_name | trunc 10}} \t{{.log}}\"" + + echo "Running query: $QUERY" + env LOKI_ADDR="http://$HOST/" logcli query "$QUERY" $OUTPUT $FOLLOW $FROM $TO +} + +kolab__describe() { + deployment="$1" + shift + command kubectl -n "$NAMESPACE" describe "deployment/$deployment" $@ +} + +kolab__restart() { + command kubectl -n "$NAMESPACE" rollout restart deployment +} + +kolab__ps() { + command kubectl -n "$NAMESPACE" get pods +} + +kolab__get() { + command kubectl -n "$NAMESPACE" get $@ +} + +kolab__volumes() { + command kubectl -n "$NAMESPACE" get persistentvolumeclaims $@ +} + +kolab__build() { + command env REGISTRY="localhost:5000" build/build.sh --nochecks +} + +kolab__top() { + command kubectl top pods -n "$NAMESPACE" --sum=true + + command kubectl get pods -n "$NAMESPACE" -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t\t"}{..resources.requests.memory}{end}' + echo + echo + + echo "Total memory requests: $(__sum_memory_requests) Mi" + echo "Total cpu requests: $(__sum_cpu_requests) m" + +} + +kolab__metrics() { + command kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods | jq + command kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes | jq + # # Get the metrics for node + # kubectl get --raw /apis/metrics.k8s.io/v1beta1/ | jq '.' + # # Get the metrics for pode + # kubectl get --raw /apis/metrics.k8s.io/v1beta1/ | jq '.' +} + +kolab__reset() { + if [[ "$1" == "--force" ]]; then + REPLY="y" + else + read -p "Are you sure? This will delete the k3s cluster including all data" -n 1 -r + echo + fi + if [[ "$REPLY" =~ ^[Yy]$ ]]; + then + /usr/local/bin/k3s-uninstall.sh + fi +} + +kolab__login() { + if [[ "$1" == "--k3s" ]]; then + command bin/k3slogin.sh + else + echo "Configure kubectl manually, login is not implemented" + fi + command kubectl cluster-info +} + +kolab__exec() { + container=$1 + shift + command kubectl exec --stdin --tty -n "$NAMESPACE" "deployment/$container" -- $@ +} + + +# Administration commands + +kolab__cyradm() { + # FIXME grep credentials from files + command kubectl exec --stdin --tty -n "$NAMESPACE" deployment/imap -- cyradm --auth PLAIN -u admin@kolab.local -w simple123 --port 11143 localhost +} + +kolab__reseed() { + read -p "Are you sure? This will delete all data" -n 1 -r + echo + if [[ "$REPLY" =~ ^[Yy]$ ]]; + then + kolab__exec horizon ./artisan migrate:fresh --seed + fi +} + +kolab__users() { + kolab__exec horizon ./artisan users --attr=email +} + +kolab__password() { + kolab__exec horizon ./artisan user:password $@ +} + +kolab__db() { + kolab__exec mariadb mysql -p +} + +kolab__build() { + command env REGISTRY="localhost:5000" build/publish.sh +} + + +kolab__help() { + cat </dev/null 2>&1; then + "kolab__$cmdname" "${@:1}" +else + echo "Function $cmdname not recognized" >&2 + kolab__help + exit 1 +fi + + diff --git a/kubernetes/values.yaml b/kubernetes/values.yaml new file mode 100644 index 00000000..c6a2ff05 --- /dev/null +++ b/kubernetes/values.yaml @@ -0,0 +1,274 @@ + +# Default values for kolab. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +domainName: "kolab.local" + +# The admin user is always admin@domainName +adminPassword: "simple123" + +# migrate:status is required to make sure we don't try to run commands before the db is ready +# TODO integrate this into the seeder I guess? +initCommands: [ + "./artisan db:ping --wait", + "./artisan migrate:status", + #FIXME wait for seeding to complete + "./artisan user:password admin@kolab.local simple123", + "./artisan user:create test1@kolab.local --password=simple123 || :", + "./artisan user:create test2@kolab.local --password=simple123 || :", +] + +# Created above +testUser: "test1@kolab.local" +testPassword: "simple123" + +appKey: "base64:FG6ECzyAMSmyX+eYwO/FW3bwnarbKkBhqtO65vlMb1E" + +image: + pullPolicy: Always + +certManager: + letsencrypt: + enabled: false + email: "admin@kolab.local" + +# Deploy a fixed certificate +cert: + enabled: true + crt: | + -----BEGIN CERTIFICATE----- + MIIDUzCCAjugAwIBAgIUOd6enK80Ohcw5kX1xYot+ncVxEwwDQYJKoZIhvcNAQEL + BQAwKzETMBEGA1UECgwKRXhhbXBsZSBDQTEUMBIGA1UEAwwLa29sYWIubG9jYWww + HhcNMjMxMjI2MTA0MjUxWhcNMjQxMjI1MTA0MjUxWjArMRMwEQYDVQQKDApFeGFt + cGxlIENBMRQwEgYDVQQDDAtrb2xhYi5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQAD + ggEPADCCAQoCggEBAIr/sBVZxD8jIF9w6WbZ7ivu8P6Grh0yMmd/fOi7T8rloE87 + Zi7CtOVyH/axS6I0dtlKYBmqZz7EoXvKMRirf55Hux3IXIRnSW9H8xXhzDHenwGV + eRyxavka++sWPe7tIhx2seJosfOGHRlWpdPwSvMO4tbVJjUtWrMGYdRwrsvcFVIY + hvD/aCreepmvnbR+YKTY6e8qVeTeMXFhb9Gk86H5cwrltIsO6uo1fx1JazXhEe5b + mqPhIKHNQcv8Mfb+JufhPmdq83ZoNygcrh+YG0K8Mz1t3+eLi5ij1QFR7c51Lnaf + deqaJgDKbiNGtrZEenDUZ4OGnuaWZ818jfAQ+RUCAwEAAaNvMG0wHQYDVR0OBBYE + FGNADX2V1X6/om7P38fmz3YHfbqgMB8GA1UdIwQYMBaAFGNADX2V1X6/om7P38fm + z3YHfbqgMA8GA1UdEwEB/wQFMAMBAf8wGgYJYIZIAYb4QgENBA0WC1NlbGYgU2ln + bmVkMA0GCSqGSIb3DQEBCwUAA4IBAQCHx0kaw1Zs9zwaU93BcQLLtwesIvnyWnzN + QrzNzUB88iGnzMraPa5uvyaVkKm3omyNn+B0qy3e9jBSCgVFe9rg66VPIUgGyNuj + La6LBYDlG5iRKHpY99BF4frS8e5pslp3H42waiGIyVYFWeyHSyHbFH/BIRkGhMa2 + 9Wtnvg5FS20/7NkG3QKui9QuzLaPpPN3yLRHpH6eIwkTV1UvvStRx9a6JQZ5crPW + aileFbysEN+CdJJAHCwreYuJD+UbdDP+3Cp9qaTRyY2nNwoyQxUPySWW8UbsljP9 + V6Of5+sYQ+o6n2E6hQOVEGqVP5kf4GoYBmfJTcbGfIFQYqk85vaA + -----END CERTIFICATE----- + key: | + -----BEGIN PRIVATE KEY----- + MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCK/7AVWcQ/IyBf + cOlm2e4r7vD+hq4dMjJnf3zou0/K5aBPO2YuwrTlch/2sUuiNHbZSmAZqmc+xKF7 + yjEYq3+eR7sdyFyEZ0lvR/MV4cwx3p8BlXkcsWr5GvvrFj3u7SIcdrHiaLHzhh0Z + VqXT8ErzDuLW1SY1LVqzBmHUcK7L3BVSGIbw/2gq3nqZr520fmCk2OnvKlXk3jFx + YW/RpPOh+XMK5bSLDurqNX8dSWs14RHuW5qj4SChzUHL/DH2/ibn4T5navN2aDco + HK4fmBtCvDM9bd/ni4uYo9UBUe3OdS52n3XqmiYAym4jRra2RHpw1GeDhp7mlmfN + fI3wEPkVAgMBAAECggEALA4BHas/X3F/K7DKUR5mdgc727gNDFTiE9qc2NixYBHq + fuJJLy3oDsbeqZ4k5iqxtonzrn7LTWId+nGpoPOONbjvbe+YnyBrbnlD6t4PjYjN + Jb/dzIHQ8VYjnS2GAKmpA5N9KtDbAd+yblr/oQ5KewHvVH7nJriSxCYUMLRsOlE1 + xhhGZpynTg/CmT6xVwSlBIVDCPIfQEKiCBtpUEUwSMhcjETVfAXeNAtluXII3YnG + uhErY4P97ON98CrbcsiWM4GO+nC0pLi3j9oEvkFVGPLFX7aj5WawaJHWjqdUcrG8 + 2R62Ob8Inyg2R9hK3pwEEYH8pwB7cLjfAexxPzF7qwKBgQDEcyZjL6lmPNOosmU5 + ZO84uh/+ppQH1zObVH+Cv4Cj5/SX8i0QbjDopbMoZou0lHJUfBU8JcZYzhN4fGFt + TEpHwHT7gcyDddoSlADB6SRcysFMuRhPOHAfdS99ItZtna+9/uS/TA6cJOlmBPIW + 6/Znb2MexS8SkBxKKxZ3FjbuhwKBgQC1IjzKKb/HMcVspp0gLYsmZh/5/Yjf9ZkO + poFxrlytXoBB/izx62qqn1ihCHGUpQkoVuKA60VjKuLcM9u5Ny2AzuX9ywUrApQE + qcfmElo9eFIUn5VuBttpMJIpNugRE/XTOe7kMKGbd+dyil+Coz5e22IvQBGgGpmx + 1XQ3oGRGgwKBgAJxaCXNnu6tjPhJF6cqESuEbQdurOKYE4U3/Mn0dbYUGV+WXGca + 57LM9Lho5g3d1rokPONdmOTb0zQpX9DLJRVVWF8UUyXDXm3it0uyCYi54MOCfcHm + csaBX5DP0RjV4CydsdyLJpdcgiaJozUTxCGvKe1lCFvTvPZTKNlcRlybAoGAfoA8 + yEvD/g/Ke4kZL0Hfbp/gMS1aDF9v14V93bESVJotJOmo5gOt6R+EPGKzQEbKUHvt + kG+/c/Sdn4AwMfhRNSZKBadmIpWYXnFchFfI4ilH2dNh/weW8K3VRidsh5DTHAPX + zVIRa4yf/aSZ85iilIjO14T9Sj2JnWMf2UGRBpUCgYBd17muOTXJ0BzD34K+vAeH + 9c7S9PZZNuAfF/WWskIuBGhCNuIHFO7ot5IBAoTkudDTVieQXxBo/jTyidr87gUZ + 7kI4YjFMYkH9rAolrUutVo1aKpEHcC2+1ciz8ztiyk9cUZ0s10X+h2Svsnp/HvS9 + R4X5reaQgGrUYaU6SccGoQ== + -----END PRIVATE KEY----- + +passport: + # PASSPORT_PROXY_OAUTH_CLIENT_ID=$(uuidgen); + proxyOauthClientId: "942edef5-3dbd-4a14-8e3e-d5d59b727bee" + proxyOauthClientSecret: "L6L0n56ecvjjK0cJMjeeV1pPAeffUBO0YSSH63wf" + # PASSPORT_PRIVATE_KEY=$(openssl genrsa 4096); + privateKey: | + -----BEGIN PRIVATE KEY----- + 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 + ML8s2QtAD92q3i6X+kLlZ1DxgD3h0rw= + -----END PRIVATE KEY----- + # PASSPORT_PUBLIC_KEY=$(echo "$PASSPORT_PRIVATE_KEY" | openssl rsa -pubout 2>/dev/null) + publicKey: | + -----BEGIN PUBLIC KEY----- + MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzOlrgs3/7CSz/gtXOM6v + WKTpRMdhCKNalUOmXHz7g+aXFe9EAGF1QBTZXUc6FF95rOSVFWyUEJPFVVF/a7EB + J8BQXkA50O2fIp+GjaAb7Ws/xdO/57na9LPxG7+U77Bj5ZHPzMflv6RsccmMyc3S + c1ZcY/j7Zer8ojKqcVcJcYEZ+fJ96vfi9FOI0GalozNZ6YoHI7sXolxH9UT8JNzs + fDBfOmwi8BsKtrcAjg17Rk2OI+kZwPxfpYuq4vzjxkec/wodk2yElJWQLkzXpQCb + Zs2+LvZ4qjKsmrHoMzUCCsO7XeU8on8cneTV5zh9ttG5Xj4tDpwXU1x11Si4qV5S + J9NsKGgS5uzKykpcQG2TN8ihTpGHE5O8BmGAXxVOTfRGE+JqrKFcKwAUtKxgBMWQ + CC7IgA1KGvLnsNpvqOz/Njdo2Ai+hCRe60W1tkzXJ8jrTDX0c+XhTUtCDzyP3fRn + vamOmtESmu2/iq24bEwjyg9u0+EcIu+PPUKeub60+5a+MACsalaje0usCN9bXy8Z + 3fAkrt0uPWqr+aXBJrHPRML4cGKolMnVjK7Awa5TSzIa8I6bZQzFvv35+EhrB3a+ + hERQRBUYyPby4qPlvxHPCgizVH2XRZiRBKNZMsRbs2pnzs2T5AdMYMCtDwIzvj46 + Y18k93qRHecv+ABI4B6f+wcCAwEAAQ== + -----END PUBLIC KEY----- + +kolab: + resources: + limits: + memory: 1000Mi + requests: + memory: 100Mi + +horizon: + resources: + limits: + memory: 500Mi + requests: + memory: 200Mi + +meet: + webhookToken: "simple123" + serverToken: "simple123" + resources: + limits: + memory: 500Mi + +coturn: + resources: + limits: + memory: 30Mi + +collabora: + resources: + requests: + memory: 400Mi + +imap: + tlsSecretName: kolab-cert + adminLogin: "cyrus-admin" + adminPassword: "simple123" + resources: + limits: + memory: 500Mi + requests: + memory: 60Mi + volumes: + spool: + storageClassName: local-path + capacity: 100Mi + lib: + storageClassName: local-path + capacity: 100Mi + +roundcube: + resources: + limits: + memory: 500Mi + requests: + memory: 500Mi + +mariadb: + rootPassword: "VzNsY29tMzJAcGgzbGlh" + # Used by kolab to access the roundcube mfa db + mfaDsn: "mysql://roundcube:simple123@mariadb/roundcube" + kolabPassword: "simple123" + kolabLegacyPassword: "simple123" + roundcubePassword: "simple123" + volumes: + data: + storageClassName: local-path + capacity: 100Mi + resources: + limits: + memory: 500Mi + requests: + memory: 120Mi + +redis: + password: "VzNsY29tMzJAcGgzbGlh" + resources: + limits: + memory: 500Mi + requests: + memory: 20Mi + +postfix: + volumes: + spool: + storageClassName: local-path + capacity: 100Mi + lib: + storageClassName: local-path + capacity: 100Mi + resources: + limits: + memory: 500Mi + requests: + memory: 20Mi + +mail: + # Used for the noreply@domainName sender + noreplyPassword: "simple123" + +minio: + rootUser: "admin" + rootPassword: "simple123" + volumes: + data: + storageClassName: local-path + capacity: 100Mi + +openshift: false + +prometheus: + clusterMonitoring: true