diff --git a/charts/pgcat/Chart.yaml b/charts/pgcat/Chart.yaml
index 49df3e11..bf04fbe1 100644
--- a/charts/pgcat/Chart.yaml
+++ b/charts/pgcat/Chart.yaml
@@ -5,4 +5,4 @@ maintainers:
   - name: Wildcard
     email: support@w6d.io
 appVersion: "1.2.0"
-version: 0.2.1
+version: 0.3.0
diff --git a/charts/pgcat/templates/_helpers.tpl b/charts/pgcat/templates/_helpers.tpl
index 07c2d25f..f9a404dc 100644
--- a/charts/pgcat/templates/_helpers.tpl
+++ b/charts/pgcat/templates/_helpers.tpl
@@ -60,3 +60,34 @@ Create the name of the service account to use
 {{- default "default" .Values.serviceAccount.name }}
 {{- end }}
 {{- end }}
+
+{{/*
+Defines a password function which will assign the appropriate password to the supplied key.
+
+It will use the literal value from `.password` if it is present. Otherwise it will fetch the value from the
+specified secret and use that.
+
+If the password is blank, and the secret object does not contain both name and key properties this returns `""`.
+Similarly, if the secret lookup fails, this also returns `""`.
+
+NB: For this lookup to succeed, the secret must already be defined. Notably this means that it's not likely to be
+managed directly by this chart. It also means that changes to the secret require an upgrade of the release, since the
+value of the secret is effectively copied into this manifest.
+
+Args:
+  * password = The plaintext password
+  * secret = An object (key and name) to use as essentially as a secretKeyRef
+*/}}
+{{- define "pgcat.password" -}}
+{{- if .password }}
+{{- .password | quote }}
+{{- else if and .secret.name .secret.key }}
+{{- $secret := (lookup "v1" "Secret" $.Release.Namespace .secret.name) }}
+{{- if $secret }}
+{{- $password := index $secret.data .secret.key | b64dec }}
+{{- $password | quote }}
+{{- else }}
+""
+{{- end }}
+{{- end }}
+{{- end -}}
diff --git a/charts/pgcat/templates/secret.yaml b/charts/pgcat/templates/secret.yaml
index 358f4e97..8d0d2ed5 100644
--- a/charts/pgcat/templates/secret.yaml
+++ b/charts/pgcat/templates/secret.yaml
@@ -31,11 +31,11 @@ stringData:
     tls_private_key = "{{ .Values.configuration.general.tls_private_key }}"
     {{- end }}
     admin_username = {{ .Values.configuration.general.admin_username | quote }}
-    admin_password = {{ .Values.configuration.general.admin_password | quote }}
+    admin_password = {{ include "pgcat.password" (dict "password" .Values.configuration.general.admin_password "secret" .Values.configuration.general.admin_password_secret) }}
     {{- if and .Values.configuration.general.auth_query_user .Values.configuration.general.auth_query_password .Values.configuration.general.auth_query }}
     auth_query = {{ .Values.configuration.general.auth_query | quote }}
     auth_query_user = {{ .Values.configuration.general.auth_query_user | quote }}
-    auth_query_password = {{ .Values.configuration.general.auth_query_password | quote }}
+    auth_query_password = {{ include "pgcat.password" (dict "password" .Values.configuration.general.auth_query_password "secret" .Values.configuration.general.auth_query_password_secret) }}
     {{- end }}
 
     {{- range $pool := .Values.configuration.pools }}
@@ -59,26 +59,20 @@ stringData:
     ##
     [pools.{{ $pool.name | quote }}.users.{{ $index }}]
     username = {{ $user.username | quote }}
-    {{- if $user.password }}
-    password = {{ $user.password | quote }}
-    {{- else if and $user.passwordSecret.name $user.passwordSecret.key }}
-    {{- $secret := (lookup "v1" "Secret" $.Release.Namespace $user.passwordSecret.name) }}
-    {{- if $secret }}
-    {{- $password := index $secret.data $user.passwordSecret.key | b64dec }}
-    password = {{ $password | quote }}
-    {{- end }}
-    {{- end }}
+    password = {{ include "pgcat.password" (dict "password" $user.password "secret" $user.passwordSecret) }}
     pool_size = {{ $user.pool_size }}
     statement_timeout = {{ default 0 $user.statement_timeout }}
     min_pool_size = {{ default 3 $user.min_pool_size }}
     {{- if $user.server_lifetime }}
     server_lifetime = {{ $user.server_lifetime }}
     {{- end }}
-    {{-     if and $user.server_username $user.server_password }}
+    {{- if $user.server_username }}
     server_username = {{ $user.server_username | quote }}
-    server_password = {{ $user.server_password | quote }}
-    {{-     end }}
-    {{-   end }}
+    server_password = {{ include "pgcat.password" (dict "password" $user.server_password "secret" $user.server_password_secret) }}
+    {{- end }}
+
+    {{/* end range users */}}
+    {{- end }}
 
     {{-   range $index, $shard := $pool.shards }}
 
diff --git a/charts/pgcat/values.yaml b/charts/pgcat/values.yaml
index 20a4e27b..a5ef2ca0 100644
--- a/charts/pgcat/values.yaml
+++ b/charts/pgcat/values.yaml
@@ -65,7 +65,8 @@ podAnnotations: {}
 ## @param podSecurityContext.enabled Enabled PgCat pods' Security Context
 ## @param podSecurityContext.fsGroup Set PgCat pod's Security Context fsGroup
 ##
-podSecurityContext: {}
+podSecurityContext:
+  {}
   # fsGroup: 2000
 
 ## PgCat pods' Security Context
@@ -75,7 +76,8 @@ podSecurityContext: {}
 ## @param containerSecurityContext.runAsUser Set PgCat container's Security Context runAsUser
 ## @param containerSecurityContext.runAsNonRoot Set PgCat container's Security Context runAsNonRoot
 ##
-containerSecurityContext: {}
+containerSecurityContext:
+  {}
   # capabilities:
   #   drop:
   #   - ALL
@@ -94,7 +96,8 @@ service:
 ingress:
   enabled: false
   className: ""
-  annotations: {}
+  annotations:
+    {}
     # kubernetes.io/ingress.class: nginx
     # kubernetes.io/tls-acme: "true"
   hosts:
@@ -170,16 +173,16 @@ configuration:
     connect_timeout: 5000
 
     # How long an idle connection with a server is left open (ms).
-    idle_timeout: 30000  # milliseconds
+    idle_timeout: 30000 # milliseconds
 
     # Max connection lifetime before it's closed, even if actively used.
-    server_lifetime: 86400000  # 24 hours
+    server_lifetime: 86400000 # 24 hours
 
     # Whether to use TLS for server connections or not.
     server_tls: false
 
     # How long a client is allowed to be idle while in a transaction (ms).
-    idle_client_in_transaction_timeout: 0  # milliseconds
+    idle_client_in_transaction_timeout: 0 # milliseconds
 
     # @param configuration.general.healthcheck_timeout How much time to give `SELECT 1` health check query to return with a result (ms).
     healthcheck_timeout: 1000
@@ -191,7 +194,7 @@ configuration:
     shutdown_timeout: 60000
 
     # @param configuration.general.ban_time For how long to ban a server if it fails a health check (seconds).
-    ban_time: 60    # seconds
+    ban_time: 60 # seconds
 
     # @param configuration.general.log_client_connections If we should log client connections
     log_client_connections: false
@@ -205,9 +208,15 @@ configuration:
     tls_certificate: "-"
     tls_private_key: "-"
 
-    # Credentials to access the virtual administrative database (pgbouncer or pgcat)
+    # Username used to access the virtual administrative database (pgbouncer or pgcat)
     # Connecting to that database allows running commands like `SHOW POOLS`, `SHOW DATABASES`, etc..
     admin_username: "postgres"
+
+    # Password to be used for administrative queries.
+    #
+    # @param configuration.general.admin_password
+    # @param configuration.general.admin_password_password_secret.name Name of the secret containing the password
+    # @param configuration.general.admin_password_password_secret.key Key in the secret containing the password
     admin_password: "postgres"
 
     # Query to be sent to servers to obtain the hash used for md5 authentication. The connection will be
@@ -227,6 +236,8 @@ configuration:
     # in the pool. This parameter is inherited by every pool and can be redefined in pool configuration.
     #
     # @param configuration.general.auth_query_password
+    # @param configuration.general.auth_query_password_secret.name Name of the secret containing the password
+    # @param configuration.general.auth_query_password_secret.key Key in the secret containing the password
     auth_query_password: null
 
     # Number of seconds of connection idleness to wait before sending a keepalive packet to the server.
@@ -244,14 +255,28 @@ configuration:
   ## For the example below a client can connect using "postgres://sharding_user:sharding_user@pgcat_host:pgcat_port/sharded"
   ## @param [object]
   pools:
-    [{
-      name: "simple", pool_mode: "transaction",
-      users: [{username: "user", password: "pass", pool_size: 5, statement_timeout: 0}],
-      shards: [{
-        servers: [{host: "postgres", port: 5432, role: "primary"}],
-        database: "postgres"
-      }]
-    }]
+    [
+      {
+        name: "simple",
+        pool_mode: "transaction",
+        users:
+          [
+            {
+              username: "user",
+              password: "pass",
+              pool_size: 5,
+              statement_timeout: 0,
+            },
+          ],
+        shards:
+          [
+            {
+              servers: [{ host: "postgres", port: 5432, role: "primary" }],
+              database: "postgres",
+            },
+          ],
+      },
+    ]
     # - ## default values
     #   ##
     #   ##
@@ -322,6 +347,8 @@ configuration:
     #  ## @param users[0].passwordSecret.name Name of the secret containing the password
     #  ## @param users[0].passwordSecret.key Key in the secret containing the password
     #  ## @param users[0].pool_size Maximum number of server connections that can be established for this user
+    #  ## @param users[0].server_password_secret.name Name of the secret containing the server password
+    #  ## @param users[0].server_password_secret.key Key in the secret containing the server password
     #  ## @param users[0].statement_timeout Maximum query duration. Dangerous, but protects against DBs that died in a non-obvious way.
     #  users: []
     #    # - username: "user"