Add sysprop driven XML tags to default solr.xml (#636)

The default solr.xml now has the necessary plumbing to obey the commonly
used `solr.sharedLib`, `solr.allowPaths`, `enableMetrics` and
`solr.port.advertise` system properties.

---------

Co-authored-by: Houston Putman <houstonputman@gmail.com>
diff --git a/controllers/solrcloud_controller.go b/controllers/solrcloud_controller.go
index af82887..dec0cfd 100644
--- a/controllers/solrcloud_controller.go
+++ b/controllers/solrcloud_controller.go
@@ -225,9 +225,9 @@
 
 			if hasSolrXml {
 				// make sure the user-provided solr.xml is valid
-				if !strings.Contains(solrXml, "${hostPort:") {
+				if !(strings.Contains(solrXml, "${solr.port.advertise:") || strings.Contains(solrXml, "${hostPort:")) {
 					return requeueOrNot,
-						fmt.Errorf("custom solr.xml in ConfigMap %s must contain a placeholder for the 'hostPort' variable, such as <int name=\"hostPort\">${hostPort:80}</int>",
+						fmt.Errorf("custom solr.xml in ConfigMap %s must contain a placeholder for either 'solr.port.advertise', or its deprecated alternative 'hostPort', e.g. <int name=\"hostPort\">${solr.port.advertise:80}</int>",
 							providedConfigMapName)
 				}
 				// stored in the pod spec annotations on the statefulset so that we get a restart when solr.xml changes
diff --git a/controllers/solrcloud_controller_backup_test.go b/controllers/solrcloud_controller_backup_test.go
index 0e8cafd..566b7c7 100644
--- a/controllers/solrcloud_controller_backup_test.go
+++ b/controllers/solrcloud_controller_backup_test.go
@@ -102,11 +102,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			foundEnv := statefulSet.Spec.Template.Spec.Containers[0].Env
 
@@ -150,12 +151,13 @@
 
 				// Env Variable Tests
 				expectedEnvVars := map[string]string{
-					"ZK_HOST":        "host:7271/",
-					"SOLR_HOST":      "$(POD_NAME)." + foundSolrCloud.HeadlessServiceName() + "." + foundSolrCloud.Namespace,
-					"SOLR_PORT":      "8983",
-					"SOLR_NODE_PORT": "8983",
-					"SOLR_LOG_LEVEL": "INFO",
-					"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+					"ZK_HOST":             "host:7271/",
+					"SOLR_HOST":           "$(POD_NAME)." + foundSolrCloud.HeadlessServiceName() + "." + foundSolrCloud.Namespace,
+					"SOLR_PORT":           "8983",
+					"SOLR_NODE_PORT":      "8983",
+					"SOLR_PORT_ADVERTISE": "8983",
+					"SOLR_LOG_LEVEL":      "INFO",
+					"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 				}
 				foundEnv := found.Spec.Template.Spec.Containers[0].Env
 
@@ -204,12 +206,13 @@
 
 				// Env Variable Tests
 				expectedEnvVars := map[string]string{
-					"ZK_HOST":        "host:7271/",
-					"SOLR_HOST":      "$(POD_NAME)." + foundSolrCloud.HeadlessServiceName() + "." + foundSolrCloud.Namespace,
-					"SOLR_PORT":      "8983",
-					"SOLR_NODE_PORT": "8983",
-					"SOLR_LOG_LEVEL": "INFO",
-					"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+					"ZK_HOST":             "host:7271/",
+					"SOLR_HOST":           "$(POD_NAME)." + foundSolrCloud.HeadlessServiceName() + "." + foundSolrCloud.Namespace,
+					"SOLR_PORT":           "8983",
+					"SOLR_NODE_PORT":      "8983",
+					"SOLR_PORT_ADVERTISE": "8983",
+					"SOLR_LOG_LEVEL":      "INFO",
+					"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 				}
 				foundEnv := found.Spec.Template.Spec.Containers[0].Env
 
diff --git a/controllers/solrcloud_controller_externaldns_test.go b/controllers/solrcloud_controller_externaldns_test.go
index b63a1ff..92d7e7e 100644
--- a/controllers/solrcloud_controller_externaldns_test.go
+++ b/controllers/solrcloud_controller_externaldns_test.go
@@ -97,11 +97,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "3000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "3000",
+				"SOLR_PORT_ADVERTISE": "3000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -177,11 +178,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "2000",
-				"SOLR_NODE_PORT": "2000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "2000",
+				"SOLR_NODE_PORT":      "2000",
+				"SOLR_PORT_ADVERTISE": "2000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "2000"}), "Incorrect pre-stop command")
@@ -248,11 +250,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "3000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "3000",
+				"SOLR_PORT_ADVERTISE": "3000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -318,11 +321,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "3000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "3000",
+				"SOLR_PORT_ADVERTISE": "3000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -386,11 +390,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "3000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "3000",
+				"SOLR_PORT_ADVERTISE": "3000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -466,11 +471,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace + ".svc." + testKubeDomain,
-				"SOLR_PORT":      "2000",
-				"SOLR_NODE_PORT": "2000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace + ".svc." + testKubeDomain,
+				"SOLR_PORT":           "2000",
+				"SOLR_NODE_PORT":      "2000",
+				"SOLR_PORT_ADVERTISE": "2000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "2000"}), "Incorrect pre-stop command")
@@ -531,11 +537,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
-				"SOLR_PORT":      "2000",
-				"SOLR_NODE_PORT": "2000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.Namespace + "." + testDomain,
+				"SOLR_PORT":           "2000",
+				"SOLR_NODE_PORT":      "2000",
+				"SOLR_PORT_ADVERTISE": "2000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "2000"}), "Incorrect pre-stop command")
diff --git a/controllers/solrcloud_controller_ingress_test.go b/controllers/solrcloud_controller_ingress_test.go
index f9c61ba..d9ad9bf 100644
--- a/controllers/solrcloud_controller_ingress_test.go
+++ b/controllers/solrcloud_controller_ingress_test.go
@@ -113,11 +113,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "100",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "100",
+				"SOLR_PORT_ADVERTISE": "100",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -213,11 +214,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "3000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "3000",
+				"SOLR_PORT_ADVERTISE": "3000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -292,11 +294,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "100",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "100",
+				"SOLR_PORT_ADVERTISE": "100",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -369,11 +372,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.Namespace,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "100",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.Namespace,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "100",
+				"SOLR_PORT_ADVERTISE": "100",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -446,11 +450,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "100",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "100",
+				"SOLR_PORT_ADVERTISE": "100",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -519,11 +524,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.Namespace + ".svc." + testKubeDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "100",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.Namespace + ".svc." + testKubeDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "100",
+				"SOLR_PORT_ADVERTISE": "100",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
@@ -595,11 +601,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
-				"SOLR_PORT":      "3000",
-				"SOLR_NODE_PORT": "100",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           solrCloud.Namespace + "-$(POD_NAME)." + testDomain,
+				"SOLR_PORT":           "3000",
+				"SOLR_NODE_PORT":      "100",
+				"SOLR_PORT_ADVERTISE": "100",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			Expect(statefulSet.Spec.Template.Spec.Containers[0].Lifecycle.PreStop.Exec.Command).To(Equal([]string{"solr", "stop", "-p", "3000"}), "Incorrect pre-stop command")
diff --git a/controllers/solrcloud_controller_test.go b/controllers/solrcloud_controller_test.go
index 1646013..2c56858 100644
--- a/controllers/solrcloud_controller_test.go
+++ b/controllers/solrcloud_controller_test.go
@@ -117,13 +117,14 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_JAVA_MEM":  "-Xmx4G",
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"SOLR_LOG_LEVEL": "DEBUG",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT) extra-opts",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_JAVA_MEM":       "-Xmx4G",
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"SOLR_LOG_LEVEL":      "DEBUG",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT) extra-opts",
 			}
 			foundEnv := statefulSet.Spec.Template.Spec.Containers[0].Env
 			// Note that this check changes the variable foundEnv, so the values are no longer valid afterwards.
@@ -247,13 +248,14 @@
 
 			Expect(statefulSet.Spec.Template.Spec.Containers).To(HaveLen(1), "Solr StatefulSet requires a container.")
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/test",
-				"SOLR_HOST":      "$(POD_NAME).foo-solrcloud-headless.default",
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"GC_TUNE":        "gc Options",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
-				"SOLR_STOP_WAIT": strconv.FormatInt(testTerminationGracePeriodSeconds-5, 10),
+				"ZK_HOST":             "host:7271/test",
+				"SOLR_HOST":           "$(POD_NAME).foo-solrcloud-headless.default",
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"GC_TUNE":             "gc Options",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
+				"SOLR_STOP_WAIT":      strconv.FormatInt(testTerminationGracePeriodSeconds-5, 10),
 			}
 			expectedStatefulSetLabels := util.MergeLabelsOrAnnotations(solrCloud.SharedLabelsWith(solrCloud.Labels), map[string]string{"technology": util.SolrCloudPVCTechnology})
 			expectedStatefulSetAnnotations := map[string]string{util.SolrZKConnectionStringAnnotation: "host:7271/test"}
@@ -438,11 +440,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace + ".svc." + testKubeDomain,
-				"SOLR_PORT":      "2000",
-				"SOLR_NODE_PORT": "2000",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT)",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace + ".svc." + testKubeDomain,
+				"SOLR_PORT":           "2000",
+				"SOLR_NODE_PORT":      "2000",
+				"SOLR_PORT_ADVERTISE": "2000",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT)",
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 			By("testing the Solr Common Service")
diff --git a/controllers/solrcloud_controller_zk_test.go b/controllers/solrcloud_controller_zk_test.go
index 8fb8a74..57917fb 100644
--- a/controllers/solrcloud_controller_zk_test.go
+++ b/controllers/solrcloud_controller_zk_test.go
@@ -104,11 +104,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
+				"ZK_HOST":             "host:7271/",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
 			}
 			insertExpectedAclEnvVars(expectedEnvVars, false)
 			for _, envVar := range extraVars {
@@ -169,11 +170,12 @@
 
 			// Env Variable Tests
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/a-ch/root",
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
+				"ZK_HOST":             "host:7271/a-ch/root",
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
 			}
 			insertExpectedAclEnvVars(expectedEnvVars, true)
 			for _, envVar := range extraVars {
@@ -449,12 +451,13 @@
 			// Env Variable Tests
 			expectedZKHost := expectedZkConnStr + "/a-ch/root"
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        expectedZKHost,
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"ZK_CHROOT":      "/a-ch/root",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
+				"ZK_HOST":             expectedZKHost,
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"ZK_CHROOT":           "/a-ch/root",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
 			}
 			insertExpectedAclEnvVars(expectedEnvVars, false)
 			for _, envVar := range extraVars {
@@ -525,11 +528,12 @@
 			// Env Variable Tests
 			expectedZKHost := expectedZkConnStr + "/"
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        expectedZKHost,
-				"SOLR_HOST":      "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
+				"ZK_HOST":             expectedZKHost,
+				"SOLR_HOST":           "$(POD_NAME)." + solrCloud.HeadlessServiceName() + "." + solrCloud.Namespace,
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_CREDS_AND_ACLS) -Dextra -Dopts",
 			}
 			insertExpectedAclEnvVars(expectedEnvVars, true)
 			for _, envVar := range extraVars {
@@ -565,13 +569,14 @@
 			statefulSet := expectStatefulSet(ctx, solrCloud, solrCloud.StatefulSetName())
 			Expect(statefulSet.Spec.Template.Spec.Containers).To(HaveLen(1), "Solr StatefulSet requires a container.")
 			expectedEnvVars := map[string]string{
-				"ZK_HOST":        "host:7271/test",
-				"SOLR_HOST":      "$(POD_NAME).foo-solrcloud-headless.default",
-				"SOLR_PORT":      "8983",
-				"SOLR_NODE_PORT": "8983",
-				"SOLR_ZK_OPTS":   testSolrZKOpts,
-				"SOLR_OPTS":      "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_OPTS) " + testSolrOpts,
-				"SOLR_STOP_WAIT": strconv.FormatInt(60-5, 10),
+				"ZK_HOST":             "host:7271/test",
+				"SOLR_HOST":           "$(POD_NAME).foo-solrcloud-headless.default",
+				"SOLR_PORT":           "8983",
+				"SOLR_NODE_PORT":      "8983",
+				"SOLR_PORT_ADVERTISE": "8983",
+				"SOLR_ZK_OPTS":        testSolrZKOpts,
+				"SOLR_OPTS":           "-DhostPort=$(SOLR_NODE_PORT) $(SOLR_ZK_OPTS) " + testSolrOpts,
+				"SOLR_STOP_WAIT":      strconv.FormatInt(60-5, 10),
 			}
 			testPodEnvVariables(expectedEnvVars, statefulSet.Spec.Template.Spec.Containers[0].Env)
 
diff --git a/controllers/util/solr_util.go b/controllers/util/solr_util.go
index b6867dd..62a99c8 100644
--- a/controllers/util/solr_util.go
+++ b/controllers/util/solr_util.go
@@ -61,8 +61,9 @@
 
 	DefaultStatefulSetPodManagementPolicy = appsv1.ParallelPodManagement
 
-	DistLibs    = "/opt/solr/dist"
-	ContribLibs = "/opt/solr/contrib/%s/lib"
+	DistLibs              = "/opt/solr/dist"
+	ContribLibs           = "/opt/solr/contrib/%s/lib"
+	SysPropLibPlaceholder = "${solr.sharedLib:}"
 )
 
 var (
@@ -305,9 +306,15 @@
 		},
 		{
 			// This is the port that the Solr Node will advertise itself as listening on in live_nodes
+			// TODO Remove in 0.9.0 once users have had a chance to switch any custom solr.xml files over to using the `solr.port.advertise` placeholder
 			Name:  "SOLR_NODE_PORT",
 			Value: strconv.Itoa(solrAdressingPort),
 		},
+		{
+			// Supercedes SOLR_NODE_PORT above.  'bin/solr' converts to 'solr.port.advertise' sysprop automatically.
+			Name:  "SOLR_PORT_ADVERTISE",
+			Value: strconv.Itoa(solrAdressingPort),
+		},
 		// POD_HOSTNAME is deprecated and will be removed in a future version. Use POD_NAME instead
 		{
 			Name: "POD_HOSTNAME",
@@ -780,7 +787,7 @@
   %s
   <solrcloud>
     <str name="host">${host:}</str>
-    <int name="hostPort">${hostPort:80}</int>
+    <int name="hostPort">${solr.port.advertise:80}</int>
     <str name="hostContext">${hostContext:solr}</str>
     <bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
     <int name="zkClientTimeout">${zkClientTimeout:30000}</int>
@@ -795,6 +802,8 @@
     <int name="connTimeout">${connTimeout:60000}</int>
   </shardHandlerFactory>
   <int name="maxBooleanClauses">${solr.max.booleanClauses:1024}</int>
+  <str name="allowPaths">${solr.allowPaths:}</str>
+  <metrics enabled="${metricsEnabled:true}"/>
   %s
 </solr>
 `
@@ -840,6 +849,9 @@
 func GenerateAdditionalLibXMLPart(solrModules []string, additionalLibs []string) string {
 	libs := make(map[string]bool, 0)
 
+	// Placeholder for users to specify libs via sysprop
+	libs[SysPropLibPlaceholder] = true
+
 	// Add all module library locations
 	if len(solrModules) > 0 {
 		libs[DistLibs] = true
@@ -853,16 +865,12 @@
 		libs[libPath] = true
 	}
 
-	libXml := ""
-	if len(libs) > 0 {
-		libList := make([]string, 0)
-		for lib := range libs {
-			libList = append(libList, lib)
-		}
-		sort.Strings(libList)
-		libXml = fmt.Sprintf("<str name=\"sharedLib\">%s</str>", strings.Join(libList, ","))
+	libList := make([]string, 0)
+	for lib := range libs {
+		libList = append(libList, lib)
 	}
-	return libXml
+	sort.Strings(libList)
+	return fmt.Sprintf("<str name=\"sharedLib\">%s</str>", strings.Join(libList, ","))
 }
 
 func getAppProtocol(solrCloud *solr.SolrCloud) *string {
diff --git a/controllers/util/solr_util_test.go b/controllers/util/solr_util_test.go
index 0e3f635..b6d6bb4 100644
--- a/controllers/util/solr_util_test.go
+++ b/controllers/util/solr_util_test.go
@@ -116,25 +116,29 @@
 }
 
 func TestGenerateAdditionalLibXMLPart(t *testing.T) {
+	// No specified libs
+	xmlString := GenerateAdditionalLibXMLPart([]string{}, []string{})
+	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">${solr.sharedLib:}</str>", "Wrong sharedLib xml for no specified libs")
+
 	// Just 1 repeated solr module
-	xmlString := GenerateAdditionalLibXMLPart([]string{"gcs-repository", "gcs-repository"}, []string{})
-	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for just 1 repeated solr module")
+	xmlString = GenerateAdditionalLibXMLPart([]string{"gcs-repository", "gcs-repository"}, []string{})
+	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">${solr.sharedLib:},/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for just 1 repeated solr module")
 
 	// Just 2 different solr modules
 	xmlString = GenerateAdditionalLibXMLPart([]string{"gcs-repository", "analytics"}, []string{})
-	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for just 2 different solr modules")
+	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">${solr.sharedLib:},/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for just 2 different solr modules")
 
 	// Just 2 repeated libs
 	xmlString = GenerateAdditionalLibXMLPart([]string{}, []string{"/ext/lib", "/ext/lib"})
-	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">/ext/lib</str>", "Wrong sharedLib xml for just 1 repeated additional lib")
+	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib</str>", "Wrong sharedLib xml for just 1 repeated additional lib")
 
 	// Just 2 different libs
 	xmlString = GenerateAdditionalLibXMLPart([]string{}, []string{"/ext/lib2", "/ext/lib1"})
-	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">/ext/lib1,/ext/lib2</str>", "Wrong sharedLib xml for just 2 different additional libs")
+	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib1,/ext/lib2</str>", "Wrong sharedLib xml for just 2 different additional libs")
 
 	// Combination of everything
 	xmlString = GenerateAdditionalLibXMLPart([]string{"gcs-repository", "analytics", "analytics"}, []string{"/ext/lib2", "/ext/lib2", "/ext/lib1"})
-	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">/ext/lib1,/ext/lib2,/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for mix of additional libs and solr modules")
+	assert.EqualValuesf(t, xmlString, "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib1,/ext/lib2,/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for mix of additional libs and solr modules")
 }
 
 func TestGenerateSolrXMLStringForCloud(t *testing.T) {
@@ -151,7 +155,7 @@
 			SolrModules:    []string{"ltr", "analytics"},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/ext/lib1,/ext/lib2,/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with a backupRepo, additionalLibs and solrModules")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib1,/ext/lib2,/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with a backupRepo, additionalLibs and solrModules")
 
 	// Just SolrModules and AdditionalLibs
 	solrCloud = &solr.SolrCloud{
@@ -160,7 +164,7 @@
 			SolrModules:    []string{"ltr", "analytics"},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/ext/lib1,/ext/lib2,/opt/solr/contrib/analytics/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with additionalLibs and solrModules")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib1,/ext/lib2,/opt/solr/contrib/analytics/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with additionalLibs and solrModules")
 
 	// Just SolrModules and Backups
 	solrCloud = &solr.SolrCloud{
@@ -174,7 +178,7 @@
 			SolrModules: []string{"ltr", "analytics"},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with a backupRepo and solrModules")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/opt/solr/contrib/analytics/lib,/opt/solr/contrib/gcs-repository/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with a backupRepo and solrModules")
 
 	// Just AdditionalLibs and Backups
 	solrCloud = &solr.SolrCloud{
@@ -188,7 +192,7 @@
 			AdditionalLibs: []string{"/ext/lib2", "/ext/lib1"},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/ext/lib1,/ext/lib2,/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with a backupRepo and additionalLibs")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib1,/ext/lib2,/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with a backupRepo and additionalLibs")
 
 	// Just SolrModules
 	solrCloud = &solr.SolrCloud{
@@ -196,7 +200,7 @@
 			SolrModules: []string{"ltr", "analytics"},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/opt/solr/contrib/analytics/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with just solrModules")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/opt/solr/contrib/analytics/lib,/opt/solr/contrib/ltr/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with just solrModules")
 
 	// Just Backups
 	solrCloud = &solr.SolrCloud{
@@ -209,7 +213,7 @@
 			},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with just a backupRepo")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/opt/solr/contrib/gcs-repository/lib,/opt/solr/dist</str>", "Wrong sharedLib xml for a cloud with just a backupRepo")
 
 	// Just AdditionalLibs
 	solrCloud = &solr.SolrCloud{
@@ -217,5 +221,5 @@
 			AdditionalLibs: []string{"/ext/lib2", "/ext/lib1"},
 		},
 	}
-	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">/ext/lib1,/ext/lib2</str>", "Wrong sharedLib xml for a cloud with a just additionalLibs")
+	assert.Containsf(t, GenerateSolrXMLStringForCloud(solrCloud), "<str name=\"sharedLib\">${solr.sharedLib:},/ext/lib1,/ext/lib2</str>", "Wrong sharedLib xml for a cloud with a just additionalLibs")
 }
diff --git a/docs/solr-cloud/solr-cloud-crd.md b/docs/solr-cloud/solr-cloud-crd.md
index d2080d9..b30ea67 100644
--- a/docs/solr-cloud/solr-cloud-crd.md
+++ b/docs/solr-cloud/solr-cloud-crd.md
@@ -338,7 +338,7 @@
       ... CUSTOM CONFIG HERE ...
     </solr>
 ```
-**Important: Your custom `solr.xml` must include `<int name="hostPort">${hostPort:0}</int>` as the operator relies on this element to set the port Solr pods advertise to ZooKeeper. If this element is missing, then your Solr pods will not be created.**
+**Important: Your custom `solr.xml` must include `<int name="hostPort">${solr.port.advertise:0}</int>` as the operator relies on this element to set the port Solr pods advertise to ZooKeeper. If this element is missing, then your Solr pods will not be created.**
 
 You can get the default `solr.xml` from a Solr pod as a starting point for creating a custom config using `kubectl cp` as shown in the example below:
 ```bash
diff --git a/docs/upgrade-notes.md b/docs/upgrade-notes.md
index 6f5ad4a..128be56 100644
--- a/docs/upgrade-notes.md
+++ b/docs/upgrade-notes.md
@@ -130,6 +130,8 @@
 
 - The `POD_HOSTNAME` envVar in SolrCloud Pods has been deprecated. Use `POD_NAME` instead.
 
+- Use of the `hostPort` system property placeholder in custom solr.xml files has been deprecated.  Use `<int name="hostPort">${solr.port.advertise:80}</int>`, the default value used by Solr, instead.
+
 ### v0.7.0
 - **Kubernetes support is now limited to 1.21+.**  
   If you are unable to use a newer version of Kubernetes, please install the `v0.6.0` version of the Solr Operator for use with Kubernetes `1.20` and below.
diff --git a/helm/solr/Chart.yaml b/helm/solr/Chart.yaml
index 44070f5..f265d4b 100644
--- a/helm/solr/Chart.yaml
+++ b/helm/solr/Chart.yaml
@@ -55,6 +55,13 @@
           url: https://github.com/apache/solr-operator/issues/630
         - name: Github PR
           url: https://github.com/apache/solr-operator/pull/631
+    - kind: changed
+      description: The default solr.xml now includes the necessary boilerplate to specify additional `sharedLib` and `allowPath` values (via the `solr.sharedLib` and `solr.allowPaths` system properties respectively).  The `metricsEnabled` system property can also be used to toggle Solr's metrics processing (defaults to `true`).  Lastly, the `solr.port.advertise` property can be used to control the port Solr is advertised under in `/live_nodes` and other cluster state.  Users providing their own `solr.xml` should replace any references to the `hostPort` system property with `solr.port.advertise`, as support for the `hostPort` placeholder will be removed in a future release.
+      links:
+        - name: Github Issue
+          url: https://github.com/apache/solr-operator/issues/635
+        - name: Github PR
+          url: https://github.com/apache/solr-operator/pull/636
   artifacthub.io/containsSecurityUpdates: "false"
   artifacthub.io/recommendations: |
     - url: https://artifacthub.io/packages/helm/apache-solr/solr-operator