diff --git a/enterprise/backend/src/metabase_enterprise/advanced_config/models/pulse_channel.clj b/enterprise/backend/src/metabase_enterprise/advanced_config/models/pulse_channel.clj
index 5bc61de21ddc6a85eb9158710588d06204ece77a..addac1ae095bb1861f000fdd1d55085e6fed1d67 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_config/models/pulse_channel.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_config/models/pulse_channel.clj
@@ -8,6 +8,7 @@
 
 (defsetting subscription-allowed-domains
   (deferred-tru "Allowed email address domain(s) for new Dashboard Subscriptions and Alerts. To specify multiple domains, separate each domain with a comma, with no space in between. To allow all domains, leave the field empty. This setting doesn’t affect existing subscriptions.")
+  :encryption :no
   :visibility :public
   :export?    true
   :feature    :email-allow-list
diff --git a/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj b/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj
index cae4a48bc4c5fab80bf81bf8cbf7d8c7ca0f6820..2095616f8ecbfc63b915c8851437bcd05dd988bc 100644
--- a/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj
+++ b/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj
@@ -29,14 +29,16 @@
 ;; TODO - maybe we want to add a csv setting type?
 (defsetting ldap-sync-user-attributes-blacklist
   (deferred-tru "Comma-separated list of user attributes to skip syncing for LDAP users.")
-  :default "userPassword,dn,distinguishedName"
-  :type    :csv
-  :audit   :getter)
+  :encryption :no
+  :default    "userPassword,dn,distinguishedName"
+  :type       :csv
+  :audit      :getter)
 
 (defsetting ldap-group-membership-filter
   (deferred-tru "Group membership lookup filter. The placeholders '{dn}' and '{uid}' will be replaced by the user''s Distinguished Name and UID, respectively.")
-  :default "(member={dn})"
-  :audit   :getter)
+  :encryption :no
+  :default    "(member={dn})"
+  :audit      :getter)
 
 (defn- syncable-user-attributes [m]
   (when (ldap-sync-user-attributes)
diff --git a/enterprise/backend/src/metabase_enterprise/llm/settings.clj b/enterprise/backend/src/metabase_enterprise/llm/settings.clj
index 021e7472f6a8c98caa53198d0532ee12e86e641f..ccf64778262f61cfef090e7fe1e1b389d903dcbc 100644
--- a/enterprise/backend/src/metabase_enterprise/llm/settings.clj
+++ b/enterprise/backend/src/metabase_enterprise/llm/settings.clj
@@ -5,6 +5,7 @@
 
 (defsetting ee-openai-model
   (deferred-tru "The OpenAI Model (e.g. 'gpt-4', 'gpt-3.5-turbo')")
+  :encryption :no
   :visibility :settings-manager
   :default "gpt-4-turbo-preview"
   :export? false
@@ -12,6 +13,7 @@
 
 (defsetting ee-openai-api-key
   (deferred-tru "The OpenAI API Key used in Metabase Enterprise.")
+  :encryption :no
   :visibility :settings-manager
   :export? false
   :doc "This feature is experimental.")
diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
index 7119447eb942849e582604c825c06259f53d5fdc..d20a655efa392644c0bbd8589fdb94565d4eea9b 100644
--- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
+++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj
@@ -54,8 +54,9 @@ don''t have one.")
 (defsetting saml-identity-provider-uri
   (deferred-tru "This is the URL where your users go to log in to your identity provider. Depending on which IdP you''re
 using, this usually looks like `https://your-org-name.example.com` or `https://example.com/app/my_saml_app/abc123/sso/saml`")
-  :feature :sso-saml
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :feature    :sso-saml
+  :audit      :getter)
 
 (mu/defn- validate-saml-idp-cert
   "Validate that an encoded identity provider certificate is valid, or throw an Exception."
@@ -70,33 +71,38 @@ using, this usually looks like `https://your-org-name.example.com` or `https://e
 (defsetting saml-identity-provider-certificate
   (deferred-tru "Encoded certificate for the identity provider. Depending on your IdP, you might need to download this,
 open it in a text editor, then copy and paste the certificate's contents here.")
-  :feature :sso-saml
-  :audit   :no-value
-  :setter  (fn [new-value]
-            ;; when setting the idp cert validate that it's something we
-             (when new-value
-               (validate-saml-idp-cert new-value))
-             (setting/set-value-of-type! :string :saml-identity-provider-certificate new-value)))
+  :feature    :sso-saml
+  :audit      :no-value
+  :encryption :no
+  :setter     (fn [new-value]
+                ;; when setting the idp cert validate that it's something we
+                (when new-value
+                  (validate-saml-idp-cert new-value))
+                (setting/set-value-of-type! :string :saml-identity-provider-certificate new-value)))
 
 (defsetting saml-identity-provider-issuer
   (deferred-tru "This is a unique identifier for the IdP. Often referred to as Entity ID or simply 'Issuer'. Depending
 on your IdP, this usually looks something like `http://www.example.com/141xkex604w0Q5PN724v`")
-  :feature :sso-saml
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :feature    :sso-saml
+  :audit      :getter)
 
 (defsetting saml-application-name
   (deferred-tru "This application name will be used for requests to the Identity Provider")
-  :default "Metabase"
-  :feature :sso-saml
-  :audit   :getter)
+  :default    "Metabase"
+  :feature    :sso-saml
+  :audit      :getter
+  :encryption :when-encryption-key-set)
 
 (defsetting saml-keystore-path
   (deferred-tru "Absolute path to the Keystore file to use for signing SAML requests")
-  :feature :sso-saml
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :feature    :sso-saml
+  :audit      :getter)
 
 (defsetting saml-keystore-password
   (deferred-tru "Password for opening the keystore")
+  :encryption :when-encryption-key-set
   :default    "changeit"
   :sensitive? true
   :feature    :sso-saml
@@ -105,27 +111,31 @@ on your IdP, this usually looks something like `http://www.example.com/141xkex60
 (defsetting saml-keystore-alias
   (deferred-tru "Alias for the key that {0} should use for signing SAML requests"
                 (public-settings/application-name-for-setting-descriptions))
-  :default "metabase"
-  :feature :sso-saml
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :default    "metabase"
+  :feature    :sso-saml
+  :audit      :getter)
 
 (defsetting saml-attribute-email
   (deferred-tru "SAML attribute for the user''s email address")
-  :default "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
-  :feature :sso-saml
-  :audit   :getter)
+  :default    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
+  :feature    :sso-saml
+  :encryption :when-encryption-key-set
+  :audit      :getter)
 
 (defsetting saml-attribute-firstname
   (deferred-tru "SAML attribute for the user''s first name")
-  :default "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
-  :feature :sso-saml
-  :audit   :getter)
+  :default    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
+  :encryption :when-encryption-key-set
+  :feature    :sso-saml
+  :audit      :getter)
 
 (defsetting saml-attribute-lastname
   (deferred-tru "SAML attribute for the user''s last name")
-  :default "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
-  :feature :sso-saml
-  :audit   :getter)
+  :default    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
+  :encryption :when-encryption-key-set
+  :feature    :sso-saml
+  :audit      :getter)
 
 (defsetting saml-group-sync
   (deferred-tru "Enable group membership synchronization with SAML.")
@@ -136,21 +146,23 @@ on your IdP, this usually looks something like `http://www.example.com/141xkex60
 
 (defsetting saml-attribute-group
   (deferred-tru "SAML attribute for group syncing")
-  :default "member_of"
-  :feature :sso-saml
-  :audit   :getter)
+  :default    "member_of"
+  :feature    :sso-saml
+  :audit      :getter
+  :encryption :when-encryption-key-set)
 
 (defsetting saml-group-mappings
   ;; Should be in the form: {"groupName": [1, 2, 3]} where keys are SAML groups and values are lists of MB groups IDs
   (deferred-tru "JSON containing SAML to {0} group mappings."
                 (public-settings/application-name-for-setting-descriptions))
-  :type    :json
-  :cache?  false
-  :default {}
-  :feature :sso-saml
-  :audit   :getter
-  :setter  (comp (partial setting/set-value-of-type! :json :saml-group-mappings)
-                 (partial mu/validate-throw validate-group-mappings)))
+  :encryption :when-encryption-key-set
+  :type       :json
+  :cache?     false
+  :default    {}
+  :feature    :sso-saml
+  :audit      :getter
+  :setter     (comp (partial setting/set-value-of-type! :json :saml-group-mappings)
+                    (partial mu/validate-throw validate-group-mappings)))
 
 (defsetting saml-configured
   (deferred-tru "Are the mandatory SAML settings configured?")
@@ -187,40 +199,46 @@ on your IdP, this usually looks something like `http://www.example.com/141xkex60
 
 (defsetting jwt-identity-provider-uri
   (deferred-tru "URL of JWT based login page")
-  :feature :sso-jwt
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :feature    :sso-jwt
+  :audit      :getter)
 
 (defsetting jwt-shared-secret
   (deferred-tru (str "String used to seed the private key used to validate JWT messages."
                      " "
                      "A hexadecimal-encoded 256-bit key (i.e., a 64-character string) is strongly recommended."))
-  :type    :string
-  :feature :sso-jwt
-  :audit   :no-value)
+  :encryption :when-encryption-key-set
+  :type       :string
+  :feature    :sso-jwt
+  :audit      :no-value)
 
 (defsetting jwt-attribute-email
   (deferred-tru "Key to retrieve the JWT user's email address")
-  :default "email"
-  :feature :sso-jwt
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :default    "email"
+  :feature    :sso-jwt
+  :audit      :getter)
 
 (defsetting jwt-attribute-firstname
   (deferred-tru "Key to retrieve the JWT user's first name")
-  :default "first_name"
-  :feature :sso-jwt
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :default    "first_name"
+  :feature    :sso-jwt
+  :audit      :getter)
 
 (defsetting jwt-attribute-lastname
   (deferred-tru "Key to retrieve the JWT user's last name")
-  :default "last_name"
-  :feature :sso-jwt
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :default    "last_name"
+  :feature    :sso-jwt
+  :audit      :getter)
 
 (defsetting jwt-attribute-groups
   (deferred-tru "Key to retrieve the JWT user's groups")
-  :default "groups"
-  :feature :sso-jwt
-  :audit   :getter)
+  :default    "groups"
+  :feature    :sso-jwt
+  :encryption :when-encryption-key-set
+  :audit      :getter)
 
 (defsetting jwt-group-sync
   (deferred-tru "Enable group membership synchronization with JWT.")
@@ -233,14 +251,15 @@ on your IdP, this usually looks something like `http://www.example.com/141xkex60
   ;; Should be in the form: {"groupName": [1, 2, 3]} where keys are JWT groups and values are lists of MB groups IDs
   (deferred-tru "JSON containing JWT to {0} group mappings."
                 (public-settings/application-name-for-setting-descriptions))
-  :type    :json
-  :cache?  false
-  :default {}
-  :feature :sso-jwt
-  :audit   :getter
-  :setter  (comp (partial setting/set-value-of-type! :json :jwt-group-mappings)
-                 (partial mu/validate-throw validate-group-mappings))
-  :doc "JSON object containing JWT to Metabase group mappings, where keys are JWT groups and values are lists of Metabase groups IDs.")
+  :encryption :when-encryption-key-set
+  :type       :json
+  :cache?     false
+  :default    {}
+  :feature    :sso-jwt
+  :audit      :getter
+  :setter     (comp (partial setting/set-value-of-type! :json :jwt-group-mappings)
+                    (partial mu/validate-throw validate-group-mappings))
+  :doc        "JSON object containing JWT to Metabase group mappings, where keys are JWT groups and values are lists of Metabase groups IDs.")
 
 (defsetting jwt-configured
   (deferred-tru "Are the mandatory JWT settings configured?")
diff --git a/enterprise/backend/test/metabase_enterprise/advanced_config/file/settings_test.clj b/enterprise/backend/test/metabase_enterprise/advanced_config/file/settings_test.clj
index 9ed4550a4f69e9150cb9116d0c85e04078d1a616..1928f868779b9ed6a18bab21d4875a039a5bd663 100644
--- a/enterprise/backend/test/metabase_enterprise/advanced_config/file/settings_test.clj
+++ b/enterprise/backend/test/metabase_enterprise/advanced_config/file/settings_test.clj
@@ -13,7 +13,8 @@
 
 (defsetting config-from-file-settings-test-setting
   "Internal test setting."
-  :visibility :internal)
+  :visibility :internal
+  :encryption :no)
 
 (deftest settings-test
   (testing "Should be able to set settings with config-from-file"
diff --git a/src/metabase/analytics/snowplow.clj b/src/metabase/analytics/snowplow.clj
index 31e6d25358fae887c00a120ea283548474518f4b..e3c478de0a9a88e575519d2b8e0612e04ec0c84b 100644
--- a/src/metabase/analytics/snowplow.clj
+++ b/src/metabase/analytics/snowplow.clj
@@ -62,7 +62,7 @@
   (deferred-tru
    (str "Unique identifier to be used in Snowplow analytics, to identify this instance of Metabase. "
         "This is a public setting since some analytics events are sent prior to initial setup."))
-  :encryption :never
+  :encryption :no
   :visibility :public
   :base       setting/uuid-nonce-base
   :doc        false)
@@ -90,6 +90,7 @@
 
 (defsetting snowplow-url
   (deferred-tru "The URL of the Snowplow collector to send analytics events to.")
+  :encryption :no
   :default    (if config/is-prod?
                 "https://sp.metabase.com"
                 ;; See the iglu-schema-registry repo for instructions on how to run Snowplow Micro locally for development
diff --git a/src/metabase/api/embed/common.clj b/src/metabase/api/embed/common.clj
index 0700d678163acd7bb7f7434065c38afa606a4472..725950d5b57cde163b1ee76a5a2695113ba57b38 100644
--- a/src/metabase/api/embed/common.clj
+++ b/src/metabase/api/embed/common.clj
@@ -336,6 +336,7 @@
 
 (defsetting entity-id-translation-counter
   (deferred-tru "A counter for tracking the number of entity_id -> id translations. Whenever we call [[model->entity-ids->ids]], we increment this counter by the number of translations.")
+  :encryption :no
   :visibility :internal
   :export?    false
   :audit      :never
diff --git a/src/metabase/api/geojson.clj b/src/metabase/api/geojson.clj
index 1a1ab46667a83a156c4ccb595df22d8263a591e6..ead44a8e2d93f495254ce7c83f4b6ebe9cac2ae6 100644
--- a/src/metabase/api/geojson.clj
+++ b/src/metabase/api/geojson.clj
@@ -112,14 +112,15 @@
 
 (defsetting custom-geojson
   (deferred-tru "JSON containing information about custom GeoJSON files for use in map visualizations instead of the default US State or World GeoJSON.")
-  :type    :json
-  :getter  (fn [] (merge (setting/get-value-of-type :json :custom-geojson) (builtin-geojson)))
-  :setter  (fn [new-value]
-             ;; remove the built-in keys you can't override them and we don't want those to be subject to validation.
-             (let [new-value (not-empty (reduce dissoc new-value (keys (builtin-geojson))))]
-               (when new-value
-                 (validate-geojson new-value))
-               (setting/set-value-of-type! :json :custom-geojson new-value)))
+  :encryption :no
+  :type       :json
+  :getter     (fn [] (merge (setting/get-value-of-type :json :custom-geojson) (builtin-geojson)))
+  :setter     (fn [new-value]
+                ;; remove the built-in keys you can't override them and we don't want those to be subject to validation.
+                (let [new-value (not-empty (reduce dissoc new-value (keys (builtin-geojson))))]
+                  (when new-value
+                    (validate-geojson new-value))
+                  (setting/set-value-of-type! :json :custom-geojson new-value)))
   :visibility :public
   :export?    true
   :audit      :raw-value)
diff --git a/src/metabase/driver.clj b/src/metabase/driver.clj
index ae3656917d6369112f488e78f3fa25c7b6132f11..bda48e7741401ebaa607bb9fdc0de31e67888a82 100644
--- a/src/metabase/driver.clj
+++ b/src/metabase/driver.clj
@@ -61,6 +61,7 @@
 
 (defsetting report-timezone
   (deferred-tru "Connection timezone to use when executing queries. Defaults to system timezone.")
+  :encryption :no
   :visibility :settings-manager
   :export?    true
   :audit      :getter
diff --git a/src/metabase/email.clj b/src/metabase/email.clj
index 9fad6f2a1007bb6e1a329500655aaeaedae65dd4..f629273c9c23f4a66185899ee628bd82f6a2274b 100644
--- a/src/metabase/email.clj
+++ b/src/metabase/email.clj
@@ -23,12 +23,14 @@
 
 (defsetting email-from-address
   (deferred-tru "The email address you want to use for the sender of emails.")
+  :encryption :no
   :default    "notifications@metabase.com"
   :visibility :settings-manager
   :audit      :getter)
 
 (defsetting email-from-name
   (deferred-tru "The name you want to use for the sender of emails.")
+  :encryption :no
   :visibility :settings-manager
   :audit      :getter)
 
@@ -46,6 +48,7 @@
 
 (defsetting email-reply-to
   (deferred-tru "The email address you want the replies to go to, if different from the from address.")
+  :encryption :no
   :type       :json
   :visibility :settings-manager
   :audit      :getter
@@ -56,28 +59,33 @@
 
 (defsetting email-smtp-host
   (deferred-tru "The address of the SMTP server that handles your emails.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :audit      :getter)
 
 (defsetting email-smtp-username
   (deferred-tru "SMTP username.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :audit      :getter)
 
 (defsetting email-smtp-password
   (deferred-tru "SMTP password.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :sensitive? true
   :audit      :getter)
 
 (defsetting email-smtp-port
   (deferred-tru "The port your SMTP server uses for outgoing emails.")
+  :encryption :when-encryption-key-set
   :type       :integer
   :visibility :settings-manager
   :audit      :getter)
 
 (defsetting email-smtp-security
   (deferred-tru "SMTP secure connection protocol. (tls, ssl, starttls, or none)")
+  :encryption :when-encryption-key-set
   :type       :keyword
   :default    :none
   :visibility :settings-manager
diff --git a/src/metabase/embed/settings.clj b/src/metabase/embed/settings.clj
index 95daad375c2018d636dc944362ecc64a669b643c..7c228af0f26fd0de388e4d0314b2a502f724e37d 100644
--- a/src/metabase/embed/settings.clj
+++ b/src/metabase/embed/settings.clj
@@ -15,7 +15,8 @@
                 (public-settings/application-name-for-setting-descriptions))
   :feature    :embedding
   :visibility :public
-  :audit      :getter)
+  :audit      :getter
+  :encryption :no)
 
 (defsetting enable-embedding
   (deferred-tru "Allow admins to securely embed questions and dashboards within other applications?")
diff --git a/src/metabase/integrations/common.clj b/src/metabase/integrations/common.clj
index 5e0ea7ad350bf48bd3f1ac8660b1ad5f7da50c64..c349f2659a615b3bfb9bdd6e86600240a60108d2 100644
--- a/src/metabase/integrations/common.clj
+++ b/src/metabase/integrations/common.clj
@@ -61,7 +61,8 @@
   (deferred-tru "Should new email notifications be sent to admins, for all new SSO users?")
   (fn [] (if (premium-features/enable-any-sso?)
            :ee
-           :oss)))
+           :oss))
+  :type :boolean)
 
 (define-multi-setting-impl send-new-sso-user-admin-email? :oss
   :getter (fn [] (constantly true))
diff --git a/src/metabase/integrations/google.clj b/src/metabase/integrations/google.clj
index aa9df64dd9edb2c4412b637f9b05d92a9bd13648..64fcc5bb828f923d668a8930000a3799a53a0c5c 100644
--- a/src/metabase/integrations/google.clj
+++ b/src/metabase/integrations/google.clj
@@ -27,6 +27,7 @@
 
 (defsetting google-auth-client-id
   (deferred-tru "Client ID for Google Sign-In.")
+  :encryption :when-encryption-key-set
   :visibility :public
   :audit      :getter
   :setter     (fn [client-id]
diff --git a/src/metabase/integrations/google/interface.clj b/src/metabase/integrations/google/interface.clj
index dd662e5c01340593fd3e874dcf0c9aded91d6b74..54de44d96be58dea61323976e8abd6b5ff9ac6d9 100644
--- a/src/metabase/integrations/google/interface.clj
+++ b/src/metabase/integrations/google/interface.clj
@@ -7,4 +7,5 @@
 #_{:clj-kondo/ignore [:missing-docstring]}
 (define-multi-setting google-auth-auto-create-accounts-domain
   (deferred-tru "When set, allow users to sign up on their own if their Google account email address is from this domain.")
-  (fn [] (if (premium-features/enable-sso-google?) :ee :oss)))
+  (fn [] (if (premium-features/enable-sso-google?) :ee :oss))
+  :encryption :when-encryption-key-set)
diff --git a/src/metabase/integrations/ldap.clj b/src/metabase/integrations/ldap.clj
index f10219bb3228b11d678b99b32b1b4b82751677a0..df131aefa7e629a57fb35e736358777e746ae44d 100644
--- a/src/metabase/integrations/ldap.clj
+++ b/src/metabase/integrations/ldap.clj
@@ -24,13 +24,15 @@
 
 (defsetting ldap-host
   (deferred-tru "Server hostname.")
+  :encryption :when-encryption-key-set
   :audit :getter)
 
 (defsetting ldap-port
   (deferred-tru "Server port, usually 389 or 636 if SSL is used.")
-  :type    :integer
-  :default 389
-  :audit   :getter)
+  :encryption :when-encryption-key-set
+  :type       :integer
+  :default    389
+  :audit      :getter)
 
 (defsetting ldap-security
   (deferred-tru "Use SSL, TLS or plain text.")
@@ -44,39 +46,46 @@
 
 (defsetting ldap-bind-dn
   (deferred-tru "The Distinguished Name to bind as (if any), this user will be used to lookup information about other users.")
+  :encryption :when-encryption-key-set
   :audit :getter)
 
 (defsetting ldap-password
   (deferred-tru "The password to bind with for the lookup user.")
+  :encryption :when-encryption-key-set
   :sensitive? true
   :audit     :getter)
 
 (defsetting ldap-user-base
   (deferred-tru "Search base for users. (Will be searched recursively)")
-  :audit :getter)
+  :encryption :no
+  :audit      :getter)
 
 (defsetting ldap-user-filter
   (deferred-tru "User lookup filter. The placeholder '{login'} will be replaced by the user supplied login.")
-  :default "(&(objectClass=inetOrgPerson)(|(uid={login})(mail={login})))"
-  :audit   :getter)
+  :default    "(&(objectClass=inetOrgPerson)(|(uid={login})(mail={login})))"
+  :encryption :no
+  :audit      :getter)
 
 (defsetting ldap-attribute-email
   (deferred-tru "Attribute to use for the user''s email. (usually ''mail'', ''email'' or ''userPrincipalName'')")
-  :default "mail"
-  :getter  (fn [] (u/lower-case-en (setting/get-value-of-type :string :ldap-attribute-email)))
-  :audit   :getter)
+  :default    "mail"
+  :encryption :no
+  :getter     (fn [] (u/lower-case-en (setting/get-value-of-type :string :ldap-attribute-email)))
+  :audit      :getter)
 
 (defsetting ldap-attribute-firstname
   (deferred-tru "Attribute to use for the user''s first name. (usually ''givenName'')")
-  :default "givenName"
-  :getter  (fn [] (u/lower-case-en (setting/get-value-of-type :string :ldap-attribute-firstname)))
-  :audit   :getter)
+  :default    "givenName"
+  :getter     (fn [] (u/lower-case-en (setting/get-value-of-type :string :ldap-attribute-firstname)))
+  :encryption :no
+  :audit      :getter)
 
 (defsetting ldap-attribute-lastname
   (deferred-tru "Attribute to use for the user''s last name. (usually ''sn'')")
-  :default "sn"
-  :getter  (fn [] (u/lower-case-en (setting/get-value-of-type :string :ldap-attribute-lastname)))
-  :audit   :getter)
+  :encryption :no
+  :default    "sn"
+  :getter     (fn [] (u/lower-case-en (setting/get-value-of-type :string :ldap-attribute-lastname)))
+  :audit      :getter)
 
 (defsetting ldap-group-sync
   (deferred-tru "Enable group membership synchronization with LDAP.")
@@ -86,28 +95,30 @@
 
 (defsetting ldap-group-base
   (deferred-tru "Search base for groups. Not required for LDAP directories that provide a ''memberOf'' overlay, such as Active Directory. (Will be searched recursively)")
-  :audit   :getter)
+  :audit      :getter
+  :encryption :no)
 
 (defsetting ldap-group-mappings
   ;; Should be in the form: {"cn=Some Group,dc=...": [1, 2, 3]} where keys are LDAP group DNs and values are lists of
   ;; MB groups IDs
   (deferred-tru "JSON containing LDAP to Metabase group mappings.")
-  :type    :json
-  :cache?  false
-  :default {}
-  :audit   :getter
-  :getter  (fn []
-             (json/parse-string (setting/get-value-of-type :string :ldap-group-mappings) #(DN. (str %))))
-  :setter  (fn [new-value]
-             (cond
-               (string? new-value)
-               (recur (json/parse-string new-value))
-
-               (map? new-value)
-               (do (doseq [k (keys new-value)]
-                     (when-not (DN/isValidDN (u/qualified-name k))
-                       (throw (IllegalArgumentException. (tru "{0} is not a valid DN." (u/qualified-name k))))))
-                   (setting/set-value-of-type! :json :ldap-group-mappings new-value)))))
+  :encryption :no
+  :type       :json
+  :cache?     false
+  :default    {}
+  :audit      :getter
+  :getter     (fn []
+                (json/parse-string (setting/get-value-of-type :string :ldap-group-mappings) #(DN. (str %))))
+  :setter     (fn [new-value]
+                (cond
+                  (string? new-value)
+                  (recur (json/parse-string new-value))
+
+                  (map? new-value)
+                  (do (doseq [k (keys new-value)]
+                        (when-not (DN/isValidDN (u/qualified-name k))
+                          (throw (IllegalArgumentException. (tru "{0} is not a valid DN." (u/qualified-name k))))))
+                      (setting/set-value-of-type! :json :ldap-group-mappings new-value)))))
 
 (defsetting ldap-configured?
   (deferred-tru "Have the mandatory LDAP settings (host and user search base) been validated and saved?")
diff --git a/src/metabase/integrations/slack.clj b/src/metabase/integrations/slack.clj
index a367e5dce74d417e928c100fbb15c7e13c7bd300..b9b201d63f684b677e4c816b0748386c9fa37f10 100644
--- a/src/metabase/integrations/slack.clj
+++ b/src/metabase/integrations/slack.clj
@@ -23,6 +23,7 @@
    (str "Deprecated Slack API token for connecting the Metabase Slack bot. "
         "Please use a new Slack app integration instead."))
   :deprecated "0.42.0"
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :doc        false
   :audit      :never)
@@ -31,6 +32,7 @@
   (deferred-tru
    (str "Bot user OAuth token for connecting the Metabase Slack app. "
         "This should be used for all new Slack integrations starting in Metabase v0.42.0."))
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :getter (fn []
             (-> (setting/get-value-of-type :string :slack-app-token)
@@ -57,6 +59,7 @@
 
 (defsetting slack-cached-channels-and-usernames
   "A cache shared between instances for storing an instance's slack channels and users."
+  :encryption :when-encryption-key-set
   :visibility :internal
   :type       :json
   :doc        false
@@ -76,6 +79,7 @@
 (defsetting slack-files-channel
   (deferred-tru "The name of the channel to which Metabase files should be initially uploaded")
   :default "metabase_files"
+  :encryption :no
   :visibility :settings-manager
   :audit      :getter
   :setter (fn [channel-name]
diff --git a/src/metabase/metabot/settings.clj b/src/metabase/metabot/settings.clj
index a7fda854ace10a8372023188879d752208ea813b..62f3270c8120af785eb657205e4d79d882c2cd1f 100644
--- a/src/metabase/metabot/settings.clj
+++ b/src/metabase/metabot/settings.clj
@@ -8,29 +8,35 @@
 
 (defsetting openai-model
   (deferred-tru "The OpenAI Model (e.g. 'gpt-4-turbo-preview', 'gpt-4', 'gpt-3.5-turbo')")
+  :encryption :no
   :visibility :settings-manager
   :default "gpt-4-turbo-preview")
 
 (defsetting openai-api-key
   (deferred-tru "The OpenAI API Key.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager)
 
 (defsetting openai-organization
   (deferred-tru "The OpenAI Organization ID.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager)
 
 (defsetting metabot-default-embedding-model
   (deferred-tru "The default embeddings model to be used for metabot.")
+  :encryption :no
   :visibility :internal
   :default "text-embedding-ada-002")
 
 (defsetting metabot-get-prompt-templates-url
   (deferred-tru "The URL in which metabot versioned prompt templates are stored.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :default "https://stkxezsr2kcnkhusi3fgcc5nqm0ttgfx.lambda-url.us-east-1.on.aws/")
 
 (defsetting metabot-feedback-url
   (deferred-tru "The URL to which metabot feedback is posted.")
+  :encryption :when-encryption-key-set
   :visibility :settings-manager
   :default "https://amtix3l3qvitb2qxstaqtcoqby0monuf.lambda-url.us-east-1.on.aws/")
 
diff --git a/src/metabase/models/cloud_migration.clj b/src/metabase/models/cloud_migration.clj
index 43e7be9f254ae64f1a681dd3b5629da48cc6ddfa..04685651c79fed05d0d2435032f0fa481a7ede70 100644
--- a/src/metabase/models/cloud_migration.clj
+++ b/src/metabase/models/cloud_migration.clj
@@ -43,6 +43,7 @@
 
 (defsetting store-url
   (deferred-tru "Store URL.")
+  :encryption :no
   :visibility :admin ;; should be :internal, but FE doesn't get internal settings
   :default    (str "https://store" (when (store-use-staging) ".staging") ".metabase.com")
   :doc        false
@@ -50,6 +51,7 @@
 
 (defsetting store-api-url
   (deferred-tru "Store API URL.")
+  :encryption :no
   :visibility :internal
   :default    (str "https://store-api" (when (store-use-staging) ".staging") ".metabase.com")
   :doc        false
@@ -57,6 +59,7 @@
 
 (defsetting migration-dump-file
   (deferred-tru "Dump file for migrations.")
+  :encryption :no
   :visibility :internal
   :default    nil
   :doc        false
@@ -64,6 +67,7 @@
 
 (defsetting migration-dump-version
   (deferred-tru "Custom dump version for migrations.")
+  :encryption :no
   :visibility :internal
   ;; Use a known version on staging when there's no real version.
   ;; This will cause the restore to fail on cloud unless you also set `migration-dump-file` to
diff --git a/src/metabase/models/setting.clj b/src/metabase/models/setting.clj
index a698cc69ebc7082cd2f0ad898063d98d29c15bb2..0d394b96f9de9f62b6a1cbd588924c23e3834bae 100644
--- a/src/metabase/models/setting.clj
+++ b/src/metabase/models/setting.clj
@@ -271,9 +271,10 @@
    ;; where this setting should be visible (default: :admin)
    [:visibility Visibility]
 
-   ;; should this setting be encrypted `:never` or `:maybe` (when `MB_ENCRYPTION_SECRET_KEY` is set).
-   ;; Defaults to `:maybe` (except for `:boolean` typed settings, where it defaults to `:never`)
-   [:encryption [:enum :never :maybe]]
+   ;; should this setting be encrypted. Available options are `:no` or `:when-encryption-key-set` (the setting will be
+   ;; encrypted when `MB_ENCRYPTION_SECRET_KEY` is set, otherwise we can't encrypt). This is required for `:timestamp`,
+   ;; `:json`, and `:csv`-typed settings. Defaults to `:no` for all other types.
+   [:encryption [:enum :no :when-encryption-key-set]]
 
    ;; should this setting be serialized?
    [:export? :boolean]
@@ -388,7 +389,7 @@
       (core/get *database-local-values* setting-name))))
 
 (defn- prohibits-encryption? [setting-or-name]
-  (= :never (:encryption (resolve-setting setting-or-name))))
+  (= :no (:encryption (resolve-setting setting-or-name))))
 
 (defn- allows-user-local-values? [setting]
   (#{:only :allowed} (:user-local (resolve-setting setting))))
@@ -953,6 +954,42 @@
     (binding [config/*disable-setting-cache* (not cache?)]
       (set-with-audit-logging! setting new-value bypass-read-only?))))
 
+(defn- extract-encryption-or-default
+  "Encryption is turned off or on according to (in order of preference):
+
+  - the value you specify in `defsetting`,
+
+  - ON for settings marked as `sensitive?`
+
+  - ON for settings with a setter of `:none` (the specific value here doesn't really matter, we just don't want the
+  caller to need to provide a value)
+
+  - OFF for types unlikely to contain secrets. As of this writing, that's booleans, numbers, keywords, and timestamps
+
+  If none of these conditions are met (a non-`:sensitive?` string/json/csv value you're storing in the database, and
+  you didn't provide a value) then we'll throw an exception telling you that you need to provide it. This way, when we
+  add new settings, we'll think about their sensitivity level and make a conscious decision about whether they need to
+  be encrypted or not."
+  [setting]
+  (or
+   (:encryption setting)
+   ;; NOTE: if none of the below conditions is met, users of `defsetting` will be required to
+   ;; provide a value for `:encryption`.
+   ;;
+   ;; if a setting is `:sensitive?`, default to encrypting it
+   (when (:sensitive? setting)
+     :when-encryption-key-set)
+   ;; if a setting isn't stored in the DB, the value doesn't really matter, but provide
+   ;; a default so the caller doesn't have to
+   (when (= (:setter setting) :none)
+     :when-encryption-key-set)
+   ;; if the setting isn't a type likely to contain secrets, default to plaintext
+   (when (contains? #{:boolean :integer :positive-integer :double :keyword :timestamp} (:type setting))
+     :no)
+
+   (throw (ex-info (trs "`:encryption` is a required option for setting {0}" (:name setting))
+                   {:setting setting}))))
+
 ;;; +----------------------------------------------------------------------------------------------------------------+
 ;;; |                                               register-setting!                                                |
 ;;; +----------------------------------------------------------------------------------------------------------------+
@@ -977,7 +1014,7 @@
                  :init           nil
                  :tag            (default-tag-for-type setting-type)
                  :visibility     :admin
-                 :encryption     (if (= setting-type :boolean) :never :maybe)
+                 :encryption     (extract-encryption-or-default setting)
                  :export?        false
                  :sensitive?     false
                  :cache?         true
diff --git a/src/metabase/models/user.clj b/src/metabase/models/user.clj
index d80a08a2457a3c8e8f989d91fec4e69615bcd201..b2fcb921c70e9848d0cb0feae3512a8051c575f2 100644
--- a/src/metabase/models/user.clj
+++ b/src/metabase/models/user.clj
@@ -454,6 +454,7 @@
 
 (defsetting last-acknowledged-version
   (deferred-tru "The last version for which a user dismissed the 'What's new?' modal.")
+  :encryption :no
   :user-local :only
   :type :string)
 
diff --git a/src/metabase/public_settings.clj b/src/metabase/public_settings.clj
index 541331ab282d2e22334dea71743f75f0a106ca07..8b167a5cc4ea6acae032b7c7a3d6916f8cbdb90c 100644
--- a/src/metabase/public_settings.clj
+++ b/src/metabase/public_settings.clj
@@ -26,6 +26,7 @@
 
 (defsetting application-name
   (deferred-tru "Replace the word “Metabase” wherever it appears.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -74,6 +75,7 @@
   ;; Don't i18n this docstring because it's not user-facing! :)
   "Unique identifier used for this instance of {0}. This is set once and only once the first time it is fetched via
   its magic getter. Nice!"
+  :encryption :no
   :visibility :authenticated
   :base       setting/uuid-nonce-base
   :doc        false)
@@ -118,14 +120,15 @@
 
 (defsetting version-info
   (deferred-tru "Information about available versions of Metabase.")
-  :type    :json
-  :audit   :never
-  :default {}
-  :doc     false
-  :getter  (fn []
-             (let [raw-vi (setting/get-value-of-type :json :version-info)
-                   current-major (config/current-major-version)]
-               (version-info* raw-vi {:current-major current-major :upgrade-threshold-value (upgrade-threshold)}))))
+  :encryption :no
+  :type       :json
+  :audit      :never
+  :default    {}
+  :doc        false
+  :getter     (fn []
+                (let [raw-vi (setting/get-value-of-type :json :version-info)
+                      current-major (config/current-major-version)]
+                  (version-info* raw-vi {:current-major current-major :upgrade-threshold-value (upgrade-threshold)}))))
 
 (defsetting version-info-last-checked
   (deferred-tru "Indicates when Metabase last checked for new versions.")
@@ -146,6 +149,7 @@
 (defsetting site-name
   (deferred-tru "The name used for this instance of {0}."
                 (application-name-for-setting-descriptions))
+  :encryption :no
   :default    "Metabase"
   :audit      :getter
   :visibility :settings-manager
@@ -153,6 +157,7 @@
 
 (defsetting custom-homepage
   (deferred-tru "Pick one of your dashboards to serve as homepage. Users without dashboard access will be directed to the default homepage.")
+  :encryption :no
   :default    false
   :type       :boolean
   :audit      :getter
@@ -160,6 +165,7 @@
 
 (defsetting custom-homepage-dashboard
   (deferred-tru "ID of dashboard to use as a homepage")
+  :encryption :no
   :type       :integer
   :visibility :public
   :audit      :getter)
@@ -171,6 +177,7 @@
   in [[metabase.public-settings.premium-features/fetch-token-status]]. (`site-uuid` is used for anonymous
   analytics/stats and if we sent it along with the premium features token check API request it would no longer be
   anonymous.)"
+  :encryption :when-encryption-key-set
   :visibility :internal
   :base       setting/uuid-nonce-base
   :doc        false)
@@ -178,12 +185,14 @@
 (defsetting site-uuid-for-version-info-fetching
   "A *different* site-wide UUID that we use for the version info fetching API calls. Do not use this for any other
   applications. (See [[site-uuid-for-premium-features-token-checks]] for more reasoning.)"
+  :encryption :when-encryption-key-set
   :visibility :internal
   :base       setting/uuid-nonce-base)
 
 (defsetting site-uuid-for-unsubscribing-url
   "UUID that we use for generating urls users to unsubscribe from alerts. The hash is generated by
   hash(secret_uuid + email + subscription_id) = url. Do not use this for any other applications. (See #29955)"
+  :encryption :when-encryption-key-set
   :visibility :internal
   :base       setting/uuid-nonce-base)
 
@@ -207,6 +216,7 @@
   (deferred-tru
    (str "This URL is used for things like creating links in emails, auth redirects, and in some embedding scenarios, "
         "so changing it could break functionality or get you locked out of this instance."))
+  :encryption :when-encryption-key-set
   :visibility :public
   :audit      :getter
   :getter     (fn []
@@ -234,7 +244,7 @@
   :visibility :public
   :export?    true
   :audit      :getter
-  :encryption :never
+  :encryption :no
   :getter     (fn []
                 (let [value (setting/get-value-of-type :string :site-locale)]
                   (when (i18n/available-locale? value)
@@ -248,6 +258,7 @@
 (defsetting admin-email
   (deferred-tru "The email address users should be referred to if they encounter a problem.")
   :visibility :authenticated
+  :encryption :when-encryption-key-set
   :audit      :getter)
 
 (defsetting anon-tracking-enabled
@@ -260,6 +271,7 @@
 
 (defsetting map-tile-server-url
   (deferred-tru "The map tile server URL template used in map visualizations, for example from OpenStreetMaps or MapBox.")
+  :encryption :no
   :default    "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
   :visibility :public
   :audit      :getter)
@@ -276,6 +288,7 @@
 
 (defsetting landing-page
   (deferred-tru "Enter a URL of the landing page to show the user. This overrides the custom homepage setting above.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -325,6 +338,7 @@
 
 (defsetting persisted-model-refresh-cron-schedule
   (deferred-tru "cron syntax string to schedule refreshing persisted models.")
+  :encryption :no
   :type       :string
   :default    "0 0 0/6 * * ? *"
   :visibility :admin
@@ -366,6 +380,7 @@
 
 (defsetting notification-link-base-url
   (deferred-tru "By default \"Site Url\" is used in notification links, but can be overridden.")
+  :encryption :no
   :visibility :internal
   :type       :string
   :feature    :whitelabel
@@ -375,12 +390,14 @@
 
 (defsetting deprecation-notice-version
   (deferred-tru "Metabase version for which a notice about usage of deprecated features has been shown.")
+  :encryption :no
   :visibility :admin
   :doc        false
   :audit      :never)
 
 (defsetting loading-message
   (deferred-tru "Choose the message to show while a query is running.")
+  :encryption :no
   :visibility :public
   :export?    true
   :feature    :whitelabel
@@ -390,6 +407,7 @@
 
 (defsetting application-colors
   (deferred-tru "Choose the colors used in the user interface throughout Metabase and others specifically for the charts. You need to refresh your browser to see your changes take effect.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :json
@@ -423,6 +441,7 @@ To change the chart colors:
 
 (defsetting application-font
   (deferred-tru "Replace “Lato” as the font family.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -437,6 +456,7 @@ To change the chart colors:
 
 (defsetting application-font-files
   (deferred-tru "Tell us where to find the file for each font weight. You don’t need to include all of them, but it’ll look better if you do.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :json
@@ -473,6 +493,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting application-logo-url
   (deferred-tru "Upload a file to replace the Metabase logo on the top bar.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -483,6 +504,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting application-favicon-url
   (deferred-tru "Upload a file to use as the favicon.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -501,6 +523,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting login-page-illustration
   (deferred-tru "Options for displaying the illustration on the login page.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -510,6 +533,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting login-page-illustration-custom
   (deferred-tru "The custom illustration for the login page.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -518,6 +542,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting landing-page-illustration
   (deferred-tru "Options for displaying the illustration on the landing page.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -527,6 +552,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting landing-page-illustration-custom
   (deferred-tru "The custom illustration for the landing page.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -535,6 +561,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting no-data-illustration
   (deferred-tru "Options for displaying the illustration when there are no results after running a question.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -544,6 +571,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting no-data-illustration-custom
   (deferred-tru "The custom illustration for when there are no results after running a question.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -552,6 +580,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting no-object-illustration
   (deferred-tru "Options for displaying the illustration when there are no results after searching.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -561,6 +590,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting no-object-illustration-custom
   (deferred-tru "The custom illustration for when there are no results after searching.")
+  :encryption :no
   :visibility :public
   :export?    true
   :type       :string
@@ -602,6 +632,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting help-link-custom-destination
   (deferred-tru "Custom URL for the help link.")
+  :encryption :no
   :visibility :public
   :type       :string
   :audit      :getter
@@ -654,6 +685,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting custom-formatting
   (deferred-tru "Object keyed by type, containing formatting settings")
+  :encryption :no
   :type       :json
   :export?    true
   :default    {}
@@ -701,6 +733,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting source-address-header
   (deferred-tru "Identify the source of HTTP requests by this header's value, instead of its remote address.")
+  :encryption :no
   :default "X-Forwarded-For"
   :export? true
   :audit   :getter
@@ -742,6 +775,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting has-sample-database?
   "Whether this instance has a Sample Database database"
+  :type       :boolean
   :visibility :authenticated
   :setter     :none
   :getter     (fn [] (t2/exists? :model/Database, :is_sample true))
@@ -873,6 +907,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting uploads-settings
   (deferred-tru "Upload settings")
+  :encryption :when-encryption-key-set ; this doesn't really have an effect as this setting is not stored as a setting model
   :visibility :authenticated
   :export?    false ; the data is exported with a database export, so we don't need to export a setting
   :type       :json
@@ -979,6 +1014,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 (defsetting uploads-schema-name
   (deferred-tru "Schema name for uploads")
   :deprecated "0.50.0"
+  :encryption :no
   :visibility :internal
   :export?    false
   :type       :string
@@ -987,6 +1023,7 @@ See [fonts](../configuring-metabase/fonts.md).")
 
 (defsetting uploads-table-prefix
   (deferred-tru "Prefix for upload table names")
+  :encryption :no
   :deprecated "0.50.0"
   :visibility :internal
   :export?    false
diff --git a/src/metabase/server/middleware/auth.clj b/src/metabase/server/middleware/auth.clj
index cc04fc517ddf965112bacca68d471cfb96dd08df..3d6ee714da92f4e9830c33b028f6a9ab73394b59 100644
--- a/src/metabase/server/middleware/auth.clj
+++ b/src/metabase/server/middleware/auth.clj
@@ -33,6 +33,7 @@
 
 (defsetting api-key
   "When set, this API key is required for all API requests."
+  :encryption :when-encryption-key-set
   :visibility :internal
   :doc "Middleware that enforces validation of the client via the request header X-Metabase-Apikey.
         If the header is available, then it’s validated against MB_API_KEY.
diff --git a/src/metabase/server/middleware/session.clj b/src/metabase/server/middleware/session.clj
index 7bc41fabaf67f9286a319148e69ea532a06be1cf..77cd908d1e92e3634e8c795e889b977ad86f6658 100644
--- a/src/metabase/server/middleware/session.clj
+++ b/src/metabase/server/middleware/session.clj
@@ -509,24 +509,25 @@
   ;; Should be in the form "{\"amount\":60,\"unit\":\"minutes\"}" where the unit is one of "seconds", "minutes" or "hours".
   ;; The amount is nillable.
   (deferred-tru "Time before inactive users are logged out. By default, sessions last indefinitely.")
-  :type    :json
-  :default nil
-  :getter  (fn []
-             (let [value (setting/get-value-of-type :json :session-timeout)]
-               (if-let [error-key (check-session-timeout value)]
-                 (do (log/warn (case error-key
-                                 :amount-must-be-positive            "Session timeout amount must be positive."
-                                 :amount-must-be-less-than-100-years "Session timeout must be less than 100 years."))
-                     nil)
-                 value)))
-  :setter  (fn [new-value]
-             (when-let [error-key (check-session-timeout new-value)]
-               (throw (ex-info (case error-key
-                                 :amount-must-be-positive            "Session timeout amount must be positive."
-                                 :amount-must-be-less-than-100-years "Session timeout must be less than 100 years.")
-                               {:status-code 400})))
-             (setting/set-value-of-type! :json :session-timeout new-value))
-  :doc "Has to be in the JSON format `\"{\"amount\":120,\"unit\":\"minutes\"}\"` where the unit is one of \"seconds\", \"minutes\" or \"hours\".")
+  :encryption :no
+  :type       :json
+  :default    nil
+  :getter     (fn []
+                (let [value (setting/get-value-of-type :json :session-timeout)]
+                  (if-let [error-key (check-session-timeout value)]
+                    (do (log/warn (case error-key
+                                    :amount-must-be-positive            "Session timeout amount must be positive."
+                                    :amount-must-be-less-than-100-years "Session timeout must be less than 100 years."))
+                        nil)
+                    value)))
+  :setter     (fn [new-value]
+                (when-let [error-key (check-session-timeout new-value)]
+                  (throw (ex-info (case error-key
+                                    :amount-must-be-positive            "Session timeout amount must be positive."
+                                    :amount-must-be-less-than-100-years "Session timeout must be less than 100 years.")
+                                  {:status-code 400})))
+                (setting/set-value-of-type! :json :session-timeout new-value))
+  :doc        "Has to be in the JSON format `\"{\"amount\":120,\"unit\":\"minutes\"}\"` where the unit is one of \"seconds\", \"minutes\" or \"hours\".")
 
 (defn session-timeout->seconds
   "Convert the session-timeout setting value to seconds."
diff --git a/src/metabase/util/embed.clj b/src/metabase/util/embed.clj
index 9ff0f5cbf731b2352cdad99106db3e4755f0ce9c..7a74ebe99dca93f4b34082039e378eedd68c8ef5 100644
--- a/src/metabase/util/embed.clj
+++ b/src/metabase/util/embed.clj
@@ -58,6 +58,7 @@
 
 (defsetting embedding-secret-key
   (deferred-tru "Secret key used to sign JSON Web Tokens for requests to `/api/embed` endpoints.")
+  :encryption :when-encryption-key-set
   :visibility :admin
   :audit :no-value
   :setter (fn [new-value]
diff --git a/test/metabase/api/session_test.clj b/test/metabase/api/session_test.clj
index 1a29e151c0135ccab8aa85305ed2092b6fd5f745..0dd6391f11483be50f5d9285c6aff81c568b3658 100644
--- a/test/metabase/api/session_test.clj
+++ b/test/metabase/api/session_test.clj
@@ -453,6 +453,7 @@
     (testing "Includes user-local settings"
       (defsetting test-session-api-setting
         "test setting"
+        :encryption :no
         :user-local :only
         :type       :string
         :default    "FOO")
diff --git a/test/metabase/api/setting_test.clj b/test/metabase/api/setting_test.clj
index 03ae6f14886faa5b7b72e4c93a3da9d73b7da251..cf29dd9f6d578c35be75cd858a4ce49e2576ce14 100644
--- a/test/metabase/api/setting_test.clj
+++ b/test/metabase/api/setting_test.clj
@@ -32,7 +32,8 @@
 
 (defsetting test-settings-manager-visibility
   (deferred-tru "Setting to test the `:settings-manager` visibility level. This only shows up in dev.")
-  :visibility :settings-manager)
+  :visibility :settings-manager
+  :encryption :when-encryption-key-set)
 
 ;; ## Helper Fns
 (defn- fetch-test-settings
diff --git a/test/metabase/models/setting/multi_setting_test.clj b/test/metabase/models/setting/multi_setting_test.clj
index 12a5fc209fcf8b7eb3a52f1e17cc6f2a20ae66b0..b69ceabc8e34e460ddf811a9ca21c660dd1b90f3 100644
--- a/test/metabase/models/setting/multi_setting_test.clj
+++ b/test/metabase/models/setting/multi_setting_test.clj
@@ -12,7 +12,8 @@
 (multi-setting/define-multi-setting ^:private multi-setting-test-bird-name
   "A test Setting."
   (fn [] *parakeet*)
-  :visibility :internal)
+  :visibility :internal
+  :encryption :no)
 
 (multi-setting/define-multi-setting-impl multi-setting-test-bird-name :green-friend
   :getter (constantly "Green Friend")
diff --git a/test/metabase/models/setting_test.clj b/test/metabase/models/setting_test.clj
index 8742605554173dfd2cd5600d02ccd3e30d80b3ff..cabd53da09ec2f0d630a60e9e5ff1f126b77d9ff 100644
--- a/test/metabase/models/setting_test.clj
+++ b/test/metabase/models/setting_test.clj
@@ -27,15 +27,18 @@
 ;; ## TEST SETTINGS DEFINITIONS
 
 (defsetting test-setting-1
-  "Test setting - this only shows up in dev (1)")
+  "Test setting - this only shows up in dev (1)"
+  :encryption :when-encryption-key-set)
 
 (defsetting test-setting-2
   "Test setting - this only shows up in dev (2)"
-  :default "[Default Value]")
+  :default "[Default Value]"
+  :encryption :when-encryption-key-set)
 
 (defsetting test-setting-3
   "Test setting - this only shows up in dev (3)"
-  :visibility :internal)
+  :visibility :internal
+  :encryption :when-encryption-key-set)
 
 (defsetting test-boolean-setting
   "Test setting - this only shows up in dev (3)"
@@ -44,26 +47,31 @@
 
 (defsetting test-json-setting
   "Test setting - this only shows up in dev (4)"
-  :type :json)
+  :type :json
+  :encryption :when-encryption-key-set)
 
 (defsetting test-csv-setting
   "Test setting - this only shows up in dev (5)"
   :visibility :internal
-  :type :csv)
+  :type :csv
+  :encryption :when-encryption-key-set)
 
 (defsetting ^:private test-csv-setting-with-default
   "Test setting - this only shows up in dev (6)"
   :visibility :internal
   :type :csv
-  :default ["A" "B" "C"])
+  :default ["A" "B" "C"]
+  :encryption :when-encryption-key-set)
 
 (defsetting test-env-setting
   "Test setting - this only shows up in dev (7)"
-  :visibility :internal)
+  :visibility :internal
+  :encryption :when-encryption-key-set)
 
 (defsetting toucan-name
   "Name for the Metabase Toucan mascot."
-  :visibility :internal)
+  :visibility :internal
+  :encryption :when-encryption-key-set)
 
 (defsetting test-setting-calculated-getter
   "Test setting - this only shows up in dev (8)"
@@ -74,7 +82,8 @@
 (defsetting test-setting-custom-init
   "Test setting - this only shows up in dev (0)"
   :type       :string
-  :init       (comp str random-uuid))
+  :init       (comp str random-uuid)
+  :encryption :when-encryption-key-set)
 
 (def ^:private ^:dynamic *enabled?* false)
 
@@ -82,34 +91,37 @@
   "Setting to test the `:enabled?` property of settings. This only shows up in dev."
   :visibility :internal
   :type       :string
-  :enabled?   (fn [] *enabled?*))
+  :enabled?   (fn [] *enabled?*)
+  :encryption :when-encryption-key-set)
 
 (defsetting test-enabled-setting-default
   "Setting to test the `:enabled?` property of settings. This only shows up in dev."
   :visibility :internal
   :type       :string
   :default    "setting-default"
-  :enabled?   (fn [] *enabled?*))
+  :enabled?   (fn [] *enabled?*)
+  :encryption :when-encryption-key-set)
 
 (defsetting test-feature-setting
   "Setting to test the `:feature` property of settings. This only shows up in dev."
   :visibility :internal
   :type       :string
   :default    "setting-default"
-  :feature    :test-feature)
+  :feature    :test-feature
+  :encryption :when-encryption-key-set)
 
 (defsetting test-never-encrypted-setting
   "Setting to test the `:encryption` property of settings. This only shows up in dev."
   :visibility :internal
   :type       :string
-  :encryption :never
+  :encryption :no
   :feature    :test-feature)
 
 (defsetting test-boolean-encrypted-setting
   "Setting to test that a boolean setting can be encrypted, even though the default is not to. This only shows up in dev."
   :visibility :internal
   :type       :boolean
-  :encryption :maybe
+  :encryption :when-encryption-key-set
   :feature    :test-feature)
 
 ;; ## HELPER FUNCTIONS
@@ -222,13 +234,15 @@
 (defsetting test-no-default-with-base-setting
   "Setting to test the `:base` property of settings. This only shows up in dev."
   :visibility :internal
-  :base       base-options)
+  :base       base-options
+  :encryption :when-encryption-key-set)
 
 (defsetting test-default-with-base-setting
   "Setting to test the `:base` property of settings. This only shows up in dev."
   :visibility :internal
   :base       base-options
-  :default    "fully-bespoke")
+  :default    "fully-bespoke"
+  :encryption :when-encryption-key-set)
 
 (deftest ^:parallel defsetting-with-base-test
   (testing "A setting which specifies some base options"
@@ -426,7 +440,8 @@
                  setting)))))))
 
 (defsetting test-i18n-setting
-  (deferred-tru "Test setting - with i18n"))
+  (deferred-tru "Test setting - with i18n")
+  :encryption :when-encryption-key-set)
 
 (deftest validate-description-test
   (testing "Validate setting description with i18n string"
@@ -444,7 +459,8 @@
                    (description)))))))))
 
 (defsetting test-dynamic-i18n-setting
-  (deferred-tru "Test setting - with i18n: {0}" (test-i18n-setting)))
+  (deferred-tru "Test setting - with i18n: {0}" (test-i18n-setting))
+  :encryption :when-encryption-key-set)
 
 (deftest dynamic-description-test
   (testing "Descriptions with i18n string should update if it depends on another setting's value."
@@ -645,7 +661,8 @@
 (defsetting uncached-setting
   "A test setting that should *not* be cached."
   :visibility :internal
-  :cache? false)
+  :cache? false
+  :encryption :when-encryption-key-set)
 
 (deftest uncached-settings-test
   (encryption-test/with-secret-key nil
@@ -724,23 +741,28 @@
 
 (defsetting test-internal-setting
   "test Setting"
-  :visibility :internal)
+  :visibility :internal
+  :encryption :when-encryption-key-set)
 
 (defsetting test-public-setting
   (deferred-tru "test Setting")
-  :visibility :public)
+  :visibility :public
+  :encryption :when-encryption-key-set)
 
 (defsetting test-authenticated-setting
   (deferred-tru "test Setting")
-  :visibility :authenticated)
+  :visibility :authenticated
+  :encryption :when-encryption-key-set)
 
 (defsetting test-settings-manager-setting
   (deferred-tru "test Setting")
-  :visibility :settings-manager)
+  :visibility :settings-manager
+  :encryption :when-encryption-key-set)
 
 (defsetting test-admin-setting
   (deferred-tru "test Setting")
-  :visibility :admin)
+  :visibility :admin
+  :encryption :when-encryption-key-set)
 
 (deftest can-read-setting-test
   (testing "no authenticated user"
@@ -783,18 +805,21 @@
   "test Setting"
   :visibility     :internal
   :type           :integer
-  :database-local :only)
+  :database-local :only
+  :encryption :when-encryption-key-set)
 
 (defsetting ^:private test-database-local-allowed-setting
   (deferred-tru "test Setting")
   :visibility     :authenticated
   :type           :integer
-  :database-local :allowed)
+  :database-local :allowed
+  :encryption :when-encryption-key-set)
 
 (defsetting ^:private test-database-local-never-setting
   "test Setting"
   :visibility :internal
-  :type       :integer) ; `:never` should be the default
+  :type       :integer
+  :encryption :when-encryption-key-set) ; `:no` should be the default for `:database-local`
 
 (deftest database-local-settings-test
   (doseq [[database-local-type {:keys [setting-name setting-getter-fn setting-setter-fn returns]}]
@@ -883,7 +908,8 @@
   (deferred-tru "test Setting")
   :visibility     :authenticated
   :database-local :only
-  :default        "DEFAULT")
+  :default        "DEFAULT"
+  :encryption     :when-encryption-key-set)
 
 (deftest database-local-only-settings-test
   (testing "Disallow setting Database-local-only Settings"
@@ -926,16 +952,19 @@
 (defsetting test-user-local-only-setting
   (deferred-tru  "test Setting")
   :visibility :authenticated
-  :user-local :only)
+  :user-local :only
+  :encryption :when-encryption-key-set)
 
 (defsetting test-user-local-allowed-setting
   (deferred-tru "test Setting")
   :visibility :authenticated
-  :user-local :allowed)
+  :user-local :allowed
+  :encryption :when-encryption-key-set)
 
 (defsetting ^:private test-user-local-never-setting
   (deferred-tru "test Setting")
-  :visibility :internal) ; `:never` should be the default
+  :visibility :internal
+  :encryption :when-encryption-key-set) ; `:no` should be the default for `:user-local`
 
 (deftest user-local-settings-test
   (testing "Reading and writing a user-local-only setting in the context of a user uses the user-local value"
@@ -989,7 +1018,8 @@
          (defsetting test-user-local-and-db-local-setting
            (deferred-tru "test Setting")
            :user-local     :allowed
-           :database-local :allowed)))))
+           :database-local :allowed
+           :encryption     :when-encryption-key-set)))))
 
 (deftest identity-hash-test
   (testing "Settings are hashed based on the key"
@@ -1045,7 +1075,8 @@
            :type       :string
            :default    "setting-default"
            :enabled?   (fn [] false)
-           :feature    :test-feature)))))
+           :feature    :test-feature
+           :encryption :when-encryption-key-set)))))
 
 ;;; ------------------------------------------------- Misc tests -------------------------------------------------------
 
@@ -1069,7 +1100,8 @@
 (defsetting ^:private test-integer-setting
   "test Setting"
   :visibility :internal
-  :type       :integer)
+  :type       :integer
+  :encryption :when-encryption-key-set)
 
 (deftest integer-setting-test
   (testing "Should be able to set integer setting with a string"
@@ -1085,15 +1117,15 @@
   (testing "Should not be able to define a setting with a retired name"
     (with-redefs [setting/retired-setting-names #{"retired-setting"}]
       (try
-        (defsetting retired-setting (deferred-tru "A retired setting name"))
+        (defsetting retired-setting (deferred-tru "A retired setting name") :encryption :when-encryption-key-set)
         (catch Exception e
           (is (= "Setting name 'retired-setting' is retired; use a different name instead"
                  (ex-message e))))))))
 
 (deftest duplicated-setting-name
   (testing "can re-register a setting in the same ns (redefining or reloading ns)"
-    (is (defsetting foo (deferred-tru "A testing setting") :visibility :public))
-    (is (defsetting foo (deferred-tru "A testing setting") :visibility :public)))
+    (is (defsetting foo (deferred-tru "A testing setting") :visibility :public :encryption :when-encryption-key-set))
+    (is (defsetting foo (deferred-tru "A testing setting") :visibility :public :encryption :when-encryption-key-set)))
   (testing "if attempt to register in a different ns throws an error"
     (let [current-ns (ns-name *ns*)]
       (try
@@ -1101,7 +1133,7 @@
           (:require
            [metabase.models.setting :refer [defsetting]]
            [metabase.util.i18n :as i18n :refer [deferred-tru]]))
-        (defsetting foo (deferred-tru "A testing setting") :visibility :public)
+        (defsetting foo (deferred-tru "A testing setting") :visibility :public :encryption :when-encryption-key-set)
         (catch Exception e
           (is (=? {:existing-setting
                    {:description (deferred-tru "A testing setting")
@@ -1119,7 +1151,8 @@
 
 (defsetting test-setting-with-question-mark?
   "Test setting - this only shows up in dev (6)"
-  :visibility :internal)
+  :visibility :internal
+  :encryption :when-encryption-key-set)
 
 (deftest munged-setting-name-test
   (testing "Only valid characters used for environment lookup"
@@ -1138,29 +1171,34 @@
            (m/map-vals #(select-keys % [:name :munged-name])
                        (try (defsetting test-setting-with-question-mark????
                               "Test setting - this only shows up in dev (6)"
-                              :visibility :internal)
+                              :visibility :internal
+                              :encryption :when-encryption-key-set)
                             (catch Exception e (ex-data e)))))))
   (testing "Munge collision on first definition"
     (defsetting test-setting-normal
       "Test setting - this only shows up in dev (6)"
-      :visibility :internal)
+      :visibility :internal
+      :encryption :when-encryption-key-set)
     (is (= {:existing-setting {:name :test-setting-normal, :munged-name "test-setting-normal"},
             :new-setting {:name :test-setting-normal??, :munged-name "test-setting-normal"}}
            (m/map-vals #(select-keys % [:name :munged-name])
                        (try (defsetting test-setting-normal??
                               "Test setting - this only shows up in dev (6)"
-                              :visibility :internal)
+                              :visibility :internal
+                              :encryption :when-encryption-key-set)
                             (catch Exception e (ex-data e)))))))
   (testing "Munge collision on second definition"
     (defsetting test-setting-normal-1??
       "Test setting - this only shows up in dev (6)"
-      :visibility :internal)
+      :visibility :internal
+      :encryption :when-encryption-key-set)
     (is (= {:new-setting {:munged-name "test-setting-normal-1", :name :test-setting-normal-1},
             :existing-setting {:munged-name "test-setting-normal-1", :name :test-setting-normal-1??}}
            (m/map-vals #(select-keys % [:name :munged-name])
                        (try (defsetting test-setting-normal-1
                               "Test setting - this only shows up in dev (6)"
-                              :visibility :internal)
+                              :visibility :internal
+                              :encryption :when-encryption-key-set)
                             (catch Exception e (ex-data e)))))))
   (testing "Removes characters not-compliant with shells"
     (is (= "aa1aa-b2b_cc3c"
@@ -1210,14 +1248,16 @@
       (try
         (walk/macroexpand-all
          `(defsetting ~'test-asdf-asdf-asdf
-            "untranslated description"))
+            "untranslated description"
+            :encryption :when-encryption-key-set))
         (catch Exception e
           (is (re-matches #"defsetting docstrings must be a \*deferred\* i18n form.*"
                           (:cause (Throwable->map e)))))))))
 
 (defsetting test-setting-audit-never
   "Test setting with no auditing"
-  :audit :never)
+  :audit :never
+  :encryption :when-encryption-key-set)
 
 (defsetting test-setting-audit-raw-value
   "Test setting with auditing raw values"
@@ -1226,15 +1266,17 @@
 
 (defsetting test-setting-audit-getter
   "Test setting with auditing values returned from getter"
-  :type   :string
-  :getter (constantly "GETTER VALUE")
-  :audit  :getter)
+  :type       :string
+  :getter     (constantly "GETTER VALUE")
+  :audit      :getter
+  :encryption :when-encryption-key-set)
 
 (defsetting test-sensitive-setting-audit
   "Test that a sensitive setting has its value obfuscated before being audited"
   :type       :string
   :sensitive? true
-  :audit      :getter)
+  :audit      :getter
+  :encryption :when-encryption-key-set)
 
 (deftest setting-audit-test
   (mt/with-premium-features #{:audit-app}
@@ -1293,6 +1335,7 @@
   (deferred-tru  "Audited user-local setting")
   :visibility :authenticated
   :user-local :only
+  :encryption :when-encryption-key-set
   :audit      :raw-value)
 
 (deftest user-local-settings-audit-test
@@ -1319,11 +1362,13 @@
 (defsetting exported-setting
   "This setting would be serialized"
   :export? true
+  :encryption :when-encryption-key-set
   ;; make sure it's internal so it doesn't interfere with export test
   :visibility :internal)
 
 (defsetting non-exported-setting
   "This setting would not be serialized"
+  :encryption :when-encryption-key-set
   :export? false)
 
 (deftest export?-test
@@ -1354,7 +1399,8 @@
 (defmacro define-setting-for-type [format]
   `(defsetting ~(validation-setting-symbol format)
      "Setting to test validation of this format - this only shows up in dev"
-     :type ~(keyword (name format))))
+     :type ~(keyword (name format))
+     :encryption :when-encryption-key-set))
 
 (defmacro get-parse-exception [format raw-value]
   `(mt/with-temp-env-var-value! [~(symbol (str "mb-" (validation-setting-symbol format))) ~raw-value]
@@ -1554,6 +1600,6 @@
 
 (deftest boolean-settings-default-to-never-encrypted
   (testing "Boolean settings default to never encrypted"
-    (is (= :never (:encryption (setting/resolve-setting :test-boolean-setting)))))
+    (is (= :no (:encryption (setting/resolve-setting :test-boolean-setting)))))
   (testing "Boolean settings can be encrypted"
-    (is (= :maybe (:encryption (setting/resolve-setting :test-boolean-encrypted-setting))))))
+    (is (= :when-encryption-key-set (:encryption (setting/resolve-setting :test-boolean-encrypted-setting))))))
diff --git a/test/metabase/test/data/interface.clj b/test/metabase/test/data/interface.clj
index 30805fd67964410b2d74ad8cdd8febab32718048..99de1584098173327cd3366d900e685521399c9e 100644
--- a/test/metabase/test/data/interface.clj
+++ b/test/metabase/test/data/interface.clj
@@ -40,6 +40,7 @@
 
 (defsetting database-source-dataset-name
   "The name of the test dataset this Database was created from, if any."
+  :encryption     :no
   :visibility     :internal
   :type           :string
   :database-local :only)
diff --git a/test/metabase/test/util_test.clj b/test/metabase/test/util_test.clj
index 5b806fad98e195543f1126e3cec801b7b8299f02..5903e61f32445de523202909d5373c8bd2f95c11 100644
--- a/test/metabase/test/util_test.clj
+++ b/test/metabase/test/util_test.clj
@@ -35,7 +35,8 @@
   "Another internal test setting"
   :visibility :internal
   :default    ["A" "B" "C"]
-  :type       :csv)
+  :type       :csv
+  :encryption :no)
 
 (deftest with-temporary-setting-values-test
   (testing "`with-temporary-setting-values` should do its thing"