diff --git a/changelogs/unreleased/config-create-parent-directories.md b/changelogs/unreleased/config-create-parent-directories.md
new file mode 100644
index 0000000000000000000000000000000000000000..1a6dce974ef4d72f9e2118da5bf9ebfe2c789ce5
--- /dev/null
+++ b/changelogs/unreleased/config-create-parent-directories.md
@@ -0,0 +1,4 @@
+## bugfix/config
+
+* Support parent directories creation for options that accept a directory or a
+  file (gh-8862).
diff --git a/src/box/lua/config/applier/mkdir.lua b/src/box/lua/config/applier/mkdir.lua
index dea8d28b6c21a28e92b58e33fc69ab03a28bf1a4..bac33628f7f06a51c2ea4e33e3efd0c87b633a60 100644
--- a/src/box/lua/config/applier/mkdir.lua
+++ b/src/box/lua/config/applier/mkdir.lua
@@ -7,21 +7,10 @@ local function safe_mkdir(prefix, dir)
 
     if stat == nil then
         log.verbose('%s: create directory: %s', prefix, dir)
-        local _, err = fio.mkdir(dir)
-
-        -- A file can be created by another process in between the
-        -- stat() and the mkdir() calls.
-        --
-        -- In this case mkdir() gives an error. Let's ignore it if
-        -- the created file is a directory, but raise the error
-        -- otherwise.
+        local _, err = fio.mktree(dir)
         if err ~= nil then
-            if fio.path.is_dir(dir) then
-                log.verbose('%s: the directory already exists: %s', prefix, dir)
-            else
-                error(('%s: failed to create directory %s: %s'):format(prefix,
-                    dir, err))
-            end
+            error(('%s: failed to create directory %s: %s'):format(prefix,
+                dir, err))
         end
     else
         if fio.path.is_dir(dir) then
diff --git a/test/config-luatest/mkdir_test.lua b/test/config-luatest/mkdir_test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c2c7806ac134208dde429ad20d2ff08b228ee83f
--- /dev/null
+++ b/test/config-luatest/mkdir_test.lua
@@ -0,0 +1,24 @@
+local t = require('luatest')
+local helpers = require('test.config-luatest.helpers')
+
+local g = helpers.group()
+
+g.test_nested_dirs = function(g)
+    local verify = function()
+        local fio = require('fio')
+
+        for _, dir in ipairs({'a/b', 'd/e/f', 'g/h/i', 'j/k/l'}) do
+            t.assert_equals(fio.path.is_dir(dir), true)
+        end
+    end
+
+    helpers.success_case(g, {
+        options = {
+            ['process.pid_file'] = 'a/b/c.pid',
+            ['vinyl.dir'] = 'd/e/f',
+            ['wal.dir'] = 'g/h/i',
+            ['snapshot.dir'] = 'j/k/l',
+        },
+        verify = verify,
+    })
+end