diff --git a/agent/agent.go b/agent/agent.go
index 9c85f065ec2b..b37dc62ffbf1 100644
--- a/agent/agent.go
+++ b/agent/agent.go
@@ -1494,7 +1494,10 @@ func newConsulConfig(runtimeCfg *config.RuntimeConfig, logger hclog.Logger) (*co
 	cfg.RequestLimitsReadRate = runtimeCfg.RequestLimitsReadRate
 	cfg.RequestLimitsWriteRate = runtimeCfg.RequestLimitsWriteRate
 
+	cfg.Reporting.License.Enabled = runtimeCfg.Reporting.License.Enabled
+
 	enterpriseConsulConfig(cfg, runtimeCfg)
+
 	return cfg, nil
 }
 
@@ -4185,6 +4188,11 @@ func (a *Agent) reloadConfigInternal(newCfg *config.RuntimeConfig) error {
 		HeartbeatTimeout:      newCfg.ConsulRaftHeartbeatTimeout,
 		ElectionTimeout:       newCfg.ConsulRaftElectionTimeout,
 		RaftTrailingLogs:      newCfg.RaftTrailingLogs,
+		Reporting: consul.Reporting{
+			License: consul.License{
+				Enabled: newCfg.Reporting.License.Enabled,
+			},
+		},
 	}
 	if err := a.delegate.ReloadConfig(cc); err != nil {
 		return err
diff --git a/agent/agent_oss_test.go b/agent/agent_oss_test.go
new file mode 100644
index 000000000000..ceb90beb0634
--- /dev/null
+++ b/agent/agent_oss_test.go
@@ -0,0 +1,46 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build !consulent
+// +build !consulent
+
+package agent
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestAgent_consulConfig_Reporting(t *testing.T) {
+	if testing.Short() {
+		t.Skip("too slow for testing.Short")
+	}
+
+	t.Parallel()
+	hcl := `
+		reporting {
+			license {
+				enabled = true
+			}
+		}
+	`
+	a := NewTestAgent(t, hcl)
+	defer a.Shutdown()
+	require.Equal(t, false, a.consulConfig().Reporting.License.Enabled)
+}
+
+func TestAgent_consulConfig_Reporting_Default(t *testing.T) {
+	if testing.Short() {
+		t.Skip("too slow for testing.Short")
+	}
+
+	t.Parallel()
+	hcl := `
+		reporting {
+		}
+	`
+	a := NewTestAgent(t, hcl)
+	defer a.Shutdown()
+	require.Equal(t, false, a.consulConfig().Reporting.License.Enabled)
+}
diff --git a/agent/config/builder_oss.go b/agent/config/builder_oss.go
index ce6e8d44ce0b..f0fcc30ae4ea 100644
--- a/agent/config/builder_oss.go
+++ b/agent/config/builder_oss.go
@@ -57,6 +57,10 @@ func validateEnterpriseConfigKeys(config *Config) []error {
 		add("license_path")
 		config.LicensePath = nil
 	}
+	if config.Reporting.License.Enabled != nil {
+		add("reporting.license.enabled")
+		config.Reporting.License.Enabled = nil
+	}
 
 	return result
 }
diff --git a/agent/config/builder_oss_test.go b/agent/config/builder_oss_test.go
index 2fd5f50ad7c3..1fdba09e6028 100644
--- a/agent/config/builder_oss_test.go
+++ b/agent/config/builder_oss_test.go
@@ -107,6 +107,19 @@ func TestValidateEnterpriseConfigKeys(t *testing.T) {
 				require.Empty(t, c.LicensePath)
 			},
 		},
+		"reporting.license.enabled": {
+			config: Config{
+				Reporting: Reporting{
+					License: License{
+						Enabled: &boolVal,
+					},
+				},
+			},
+			badKeys: []string{"reporting.license.enabled"},
+			check: func(t *testing.T, c *Config) {
+				require.Nil(t, c.Reporting.License.Enabled)
+			},
+		},
 		"multi": {
 			config: Config{
 				ReadReplica: &boolVal,
diff --git a/agent/config/config.go b/agent/config/config.go
index 6ed4e9616f0e..348dfbaddba8 100644
--- a/agent/config/config.go
+++ b/agent/config/config.go
@@ -291,6 +291,9 @@ type Config struct {
 	LicensePollMaxTime    *string `mapstructure:"license_poll_max_time" json:"-"`
 	LicenseUpdateBaseTime *string `mapstructure:"license_update_base_time" json:"-"`
 	LicenseUpdateMaxTime  *string `mapstructure:"license_update_max_time" json:"-"`
+
+	// license reporting
+	Reporting Reporting `mapstructure:"reporting" json:"-"`
 }
 
 type GossipLANConfig struct {
@@ -943,3 +946,11 @@ type RaftBoltDBConfigRaw struct {
 type RaftWALConfigRaw struct {
 	SegmentSizeMB *int `mapstructure:"segment_size_mb" json:"segment_size_mb,omitempty"`
 }
+
+type License struct {
+	Enabled *bool `mapstructure:"enabled"`
+}
+
+type Reporting struct {
+	License License `mapstructure:"license"`
+}
diff --git a/agent/config/runtime.go b/agent/config/runtime.go
index b0d9cf436e55..24b39507723d 100644
--- a/agent/config/runtime.go
+++ b/agent/config/runtime.go
@@ -1479,9 +1479,19 @@ type RuntimeConfig struct {
 	// here so that tests can use a smaller value.
 	LocalProxyConfigResyncInterval time.Duration
 
+	Reporting ReportingConfig
+
 	EnterpriseRuntimeConfig
 }
 
+type LicenseConfig struct {
+	Enabled bool
+}
+
+type ReportingConfig struct {
+	License LicenseConfig
+}
+
 type AutoConfig struct {
 	Enabled         bool
 	IntroToken      string
diff --git a/agent/config/runtime_oss_test.go b/agent/config/runtime_oss_test.go
index 6274511bc038..8d2e71e1c605 100644
--- a/agent/config/runtime_oss_test.go
+++ b/agent/config/runtime_oss_test.go
@@ -10,6 +10,7 @@ import (
 	"testing"
 
 	"github.com/hashicorp/consul/sdk/testutil"
+	"github.com/stretchr/testify/require"
 )
 
 var testRuntimeConfigSanitizeExpectedFilename = "TestRuntimeConfig_Sanitize.golden"
@@ -28,6 +29,7 @@ var enterpriseConfigKeyWarnings = []string{
 	enterpriseConfigKeyError{key: "acl.msp_disable_bootstrap"}.Error(),
 	enterpriseConfigKeyError{key: "acl.tokens.managed_service_provider"}.Error(),
 	enterpriseConfigKeyError{key: "audit"}.Error(),
+	enterpriseConfigKeyError{key: "reporting.license.enabled"}.Error(),
 }
 
 // OSS-only equivalent of TestConfigFlagsAndEdgecases
@@ -84,3 +86,82 @@ func TestLoad_IntegrationWithFlags_OSS(t *testing.T) {
 		}
 	}
 }
+
+func TestLoad_ReportingConfig(t *testing.T) {
+	dir := testutil.TempDir(t, t.Name())
+
+	t.Run("load from JSON defaults to false", func(t *testing.T) {
+		content := `{
+			"reporting": {}
+		}`
+
+		opts := LoadOpts{
+			FlagValues: FlagValuesTarget{Config: Config{
+				DataDir: &dir,
+			}},
+			Overrides: []Source{
+				FileSource{
+					Name:   "reporting.json",
+					Format: "json",
+					Data:   content,
+				},
+			},
+		}
+		patchLoadOptsShims(&opts)
+		result, err := Load(opts)
+		require.NoError(t, err)
+		require.Len(t, result.Warnings, 0)
+		require.Equal(t, false, result.RuntimeConfig.Reporting.License.Enabled)
+	})
+
+	t.Run("load from HCL defaults to false", func(t *testing.T) {
+		content := `
+		  reporting {}
+		`
+
+		opts := LoadOpts{
+			FlagValues: FlagValuesTarget{Config: Config{
+				DataDir: &dir,
+			}},
+			Overrides: []Source{
+				FileSource{
+					Name:   "reporting.hcl",
+					Format: "hcl",
+					Data:   content,
+				},
+			},
+		}
+		patchLoadOptsShims(&opts)
+		result, err := Load(opts)
+		require.NoError(t, err)
+		require.Len(t, result.Warnings, 0)
+		require.Equal(t, false, result.RuntimeConfig.Reporting.License.Enabled)
+	})
+
+	t.Run("with value set returns warning and defaults to false", func(t *testing.T) {
+		content := `reporting {
+			license {
+			  enabled = true
+			}
+		}`
+
+		opts := LoadOpts{
+			FlagValues: FlagValuesTarget{Config: Config{
+				DataDir: &dir,
+			}},
+			Overrides: []Source{
+				FileSource{
+					Name:   "reporting.hcl",
+					Format: "hcl",
+					Data:   content,
+				},
+			},
+		}
+		patchLoadOptsShims(&opts)
+		result, err := Load(opts)
+		require.NoError(t, err)
+		require.Len(t, result.Warnings, 1)
+		require.Contains(t, result.Warnings[0], "\"reporting.license.enabled\" is a Consul Enterprise configuration and will have no effect")
+		require.Equal(t, false, result.RuntimeConfig.Reporting.License.Enabled)
+	})
+}
diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden
index fff09fa343f6..69d03a564f8d 100644
--- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden
+++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden
@@ -289,6 +289,11 @@
     "ReconnectTimeoutLAN": "0s",
     "ReconnectTimeoutWAN": "0s",
     "RejoinAfterLeave": false,
+    "Reporting": {
+        "License": {
+            "Enabled": false
+        }
+    },
     "RequestLimitsMode": 0,
     "RequestLimitsReadRate": 0,
     "RequestLimitsWriteRate": 0,
diff --git a/agent/config/testdata/full-config.hcl b/agent/config/testdata/full-config.hcl
index dced4781c91e..f08c1a071747 100644
--- a/agent/config/testdata/full-config.hcl
+++ b/agent/config/testdata/full-config.hcl
@@ -372,6 +372,11 @@ reconnect_timeout = "23739s"
 reconnect_timeout_wan = "26694s"
 recursors = [ "63.38.39.58", "92.49.18.18" ]
 rejoin_after_leave = true
+reporting = {
+    license = {
+        enabled = false
+    }
+}
 retry_interval = "8067s"
 retry_interval_wan = "28866s"
 retry_join = [ "pbsSFY7U", "l0qLtWij" ]
diff --git a/agent/config/testdata/full-config.json b/agent/config/testdata/full-config.json
index 7c36981561a7..f98bfe4dab2b 100644
--- a/agent/config/testdata/full-config.json
+++ b/agent/config/testdata/full-config.json
@@ -428,6 +428,11 @@
     "92.49.18.18"
   ],
   "rejoin_after_leave": true,
+  "reporting": {
+    "license": {
+      "enabled": false
+    }
+  },
   "retry_interval": "8067s",
   "retry_interval_wan": "28866s",
   "retry_join": [
diff --git a/agent/consul/config.go b/agent/consul/config.go
index f114dcecfc8a..1721412f5df6 100644
--- a/agent/consul/config.go
+++ b/agent/consul/config.go
@@ -436,6 +436,8 @@ type Config struct {
 
 	PeeringTestAllowPeerRegistrations bool
 
+	Reporting Reporting
+
 	// Embedded Consul Enterprise specific configuration
 	*EnterpriseConfig
 }
@@ -671,6 +673,7 @@ type ReloadableConfig struct {
 	RaftTrailingLogs      int
 	HeartbeatTimeout      time.Duration
 	ElectionTimeout       time.Duration
+	Reporting             Reporting
 }
 
 type RaftLogStoreConfig struct {
@@ -693,3 +696,11 @@ type RaftBoltDBConfig struct {
 type WALConfig struct {
 	SegmentSize int
 }
+
+type License struct {
+	Enabled bool
+}
+
+type Reporting struct {
+	License License
+}
diff --git a/agent/consul/server.go b/agent/consul/server.go
index 5a68e780b415..d2c8c3cfe332 100644
--- a/agent/consul/server.go
+++ b/agent/consul/server.go
@@ -1746,6 +1746,8 @@ func (s *Server) ReloadConfig(config ReloadableConfig) error {
 		return err
 	}
 
+	s.updateReportingConfig(config)
+
 	s.rpcLimiter.Store(rate.NewLimiter(config.RPCRateLimit, config.RPCMaxBurst))
 
 	if config.RequestLimits != nil {
diff --git a/agent/consul/server_oss.go b/agent/consul/server_oss.go
index 4ae524b65c04..67731e450195 100644
--- a/agent/consul/server_oss.go
+++ b/agent/consul/server_oss.go
@@ -174,3 +174,7 @@ func addSerfMetricsLabels(conf *serf.Config, wan bool, segment string, partition
 
 	conf.MetricLabels = append(conf.MetricLabels, networkMetric)
 }
+
+func (s *Server) updateReportingConfig(config ReloadableConfig) {
+	// no-op
+}
diff --git a/agent/consul/server_oss_test.go b/agent/consul/server_oss_test.go
new file mode 100644
index 000000000000..d5a2aff08208
--- /dev/null
+++ b/agent/consul/server_oss_test.go
@@ -0,0 +1,43 @@
+//go:build !consulent
+// +build !consulent
+
+package consul
+
+import (
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/hashicorp/consul/testrpc"
+)
+
+func TestAgent_ReloadConfig_Reporting(t *testing.T) {
+	if testing.Short() {
+		t.Skip("too slow for testing.Short")
+	}
+	t.Parallel()
+
+	dir1, s := testServerWithConfig(t, func(c *Config) {
+		c.Reporting.License.Enabled = false
+	})
+	defer os.RemoveAll(dir1)
+	defer s.Shutdown()
+
+	testrpc.WaitForTestAgent(t, s.RPC, "dc1")
+
+	require.Equal(t, false, s.config.Reporting.License.Enabled)
+
+	rc := ReloadableConfig{
+		Reporting: Reporting{
+			License: License{
+				Enabled: true,
+			},
+		},
+	}
+
+	require.NoError(t, s.ReloadConfig(rc))
+
+	// Check config reload is no-op
+	require.Equal(t, false, s.config.Reporting.License.Enabled)
+}