diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index c393e6a300..b2523cdcce 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -18,6 +18,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
 * BUGFIX: prevent from slow [snapshot creating](https://docs.victoriametrics.com/#how-to-work-with-snapshots) under high data ingestion rate. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3551).
 * BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth.html):  suppress [proxy protocol](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt) parsing errors in case of `EOF`. Usually, the error is caused by health checks and is not a sign of an actual error.
 * BUGFIX: [vmbackup](https://docs.victoriametrics.com/vmbackup.html): fix snapshot not being deleted in case of error during backup. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2055).
+* BUGFIX: allow using dashes and dots in environment variables names referred in config files via `%{ENV-VAR.SYNTAX}`. See [these docs](https://docs.victoriametrics.com/#environment-variables) and [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3999).
 
 ## [v1.87.3](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.87.3)
 
diff --git a/lib/envtemplate/envtemplate.go b/lib/envtemplate/envtemplate.go
index 6ad779d631..393cc44263 100644
--- a/lib/envtemplate/envtemplate.go
+++ b/lib/envtemplate/envtemplate.go
@@ -113,4 +113,7 @@ func isValidEnvVarName(s string) bool {
 	return envVarNameRegex.MatchString(s)
 }
 
-var envVarNameRegex = regexp.MustCompile("^[a-zA-Z0-9_]+$")
+// envVarNameRegex is used for validating environment variable names.
+//
+// Allow dashes and dots in env var names - see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3999
+var envVarNameRegex = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_\-.]*$`)
diff --git a/lib/envtemplate/envtemplate_test.go b/lib/envtemplate/envtemplate_test.go
index cdd7b9ab37..420d679609 100644
--- a/lib/envtemplate/envtemplate_test.go
+++ b/lib/envtemplate/envtemplate_test.go
@@ -24,7 +24,9 @@ func TestExpandTemplates(t *testing.T) {
 	f([]string{"foo=%{bar}", "bar=x"}, []string{"bar=x", "foo=x"})
 	f([]string{"a=x%{b}", "b=y%{c}z%{d}", "c=123", "d=qwe"}, []string{"a=xy123zqwe", "b=y123zqwe", "c=123", "d=qwe"})
 	f([]string{"a=x%{b}y", "b=z%{a}q", "c"}, []string{"a=xzxzxzxz%{a}qyqyqyqy", "b=zxzxzxzx%{b}yqyqyqyq", "c="})
-	f([]string{"a=%{x.y}"}, []string{"a=%{x.y}"})
+	f([]string{"a=%{x.y}", "x.y=test"}, []string{"a=test", "x.y=test"})
+	f([]string{"a=%{x y}"}, []string{"a=%{x y}"})
+	f([]string{"a=%{123}"}, []string{"a=%{123}"})
 }
 
 func TestLookupEnv(t *testing.T) {
@@ -49,7 +51,9 @@ func TestLookupEnv(t *testing.T) {
 
 func TestReplaceSuccess(t *testing.T) {
 	envVars = map[string]string{
-		"foo": "bar",
+		"foo":       "bar",
+		"foo.bar_1": "baz",
+		"foo-bar_2": "test",
 	}
 	f := func(s, resultExpected string) {
 		t.Helper()
@@ -71,7 +75,8 @@ func TestReplaceSuccess(t *testing.T) {
 	f("", "")
 	f("foo", "foo")
 	f("a %{foo}-x", "a bar-x")
-	f("%{foo.bar}", "%{foo.bar}")
+	f("%{foo.bar_1}", "baz")
+	f("qq.%{foo-bar_2}.ww", "qq.test.ww")
 }
 
 func TestReplaceFailure(t *testing.T) {
@@ -85,4 +90,7 @@ func TestReplaceFailure(t *testing.T) {
 		}
 	}
 	f("foo %{bar} %{baz}")
+	f("%{Foo_Foo_1}")
+	f("%{Foo-Bar-2}")
+	f("%{Foo.Baz.3}")
 }