diff --git a/CHANGELOG.md b/CHANGELOG.md
index e90d3fbd86ac45bf2b9042808a30e3ae02285d7a..e434767539f34e0256982a279902650012cd1e17 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,14 +25,15 @@ with the `YY.0M.MICRO` scheme.
 - System table `_pico_replicaset` now has a different format: the field `master_id`
   is replaced with 2 fields `current_master_id` and `target_master_id`.
 
-
-
 ### CLI
 
 - New command `picodata admin` to connect to picodata instance via unix socket under the admin account.
 
 - SQL by default in `picodata connect`. Lua language is deprecated in `picodata connect`.
 
+- Rename `picodata run --console-sock` option to `--admin-sock` and
+  provide a default value `<data_dir>/admin.sock`.
+
 ## [23.12.0] - 2023-12-08
 
 ### Features
diff --git a/src/cli/args.rs b/src/cli/args.rs
index a7b260841c54e8044ef56f006adb8cb558f84bb8..a8b3d820c433cfef8aa90e439a8be3364868b344 100644
--- a/src/cli/args.rs
+++ b/src/cli/args.rs
@@ -135,12 +135,13 @@ pub struct Run {
     /// Enable interactive console
     pub interactive_mode: bool,
 
-    #[clap(long, value_name = "PATH", env = "PICODATA_CONSOLE_SOCK")]
+    #[clap(long, value_name = "PATH", env = "PICODATA_ADMIN_SOCK")]
     /// Unix socket for the interactive console to connect using
-    /// `picodata admin`. Unlike connecting to a
-    /// `--listen` address, console communication occurs in plain text
+    /// `picodata admin`. Unlike connecting via `picodata connect`
+    /// console communication occurs in plain text
     /// and always operates under the admin account.
-    pub console_sock: Option<String>,
+    /// Default value: <data_dir>/admin.sock
+    pub admin_sock: Option<String>,
 
     #[clap(
         long,
@@ -220,6 +221,13 @@ impl Run {
         Ok(args)
     }
 
+    pub fn admin_sock(&self) -> String {
+        match &self.admin_sock {
+            Some(path) => path.clone(),
+            None => self.data_dir.clone() + "/admin.sock",
+        }
+    }
+
     pub fn advertise_address(&self) -> String {
         let Address { host, port, .. } = self.advertise_address.as_ref().unwrap_or(&self.listen);
         format!("{host}:{port}")
diff --git a/src/lib.rs b/src/lib.rs
index 2a03c58e5f36ab8589bfb26fd19bb36fd2e93ad8..5057962c5e57c1108725b7ae35c2a208010ce57c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,7 +15,6 @@ use ::tarantool::{fiber, session};
 use rpc::{join, update_instance};
 use std::cell::OnceCell;
 use std::collections::HashMap;
-use std::io;
 use std::time::Duration;
 use storage::Clusterwide;
 use traft::RaftSpaceAccess;
@@ -31,7 +30,7 @@ use crate::plugin::*;
 use crate::schema::ADMIN_ID;
 use crate::tier::{Tier, DEFAULT_TIER};
 use crate::traft::op;
-use crate::util::{effective_user_id, unwrap_or_terminate, validate_and_complete_unix_socket_path};
+use crate::util::{effective_user_id, listen_admin_console, unwrap_or_terminate};
 
 mod access_control;
 pub mod audit;
@@ -787,31 +786,7 @@ fn postjoin(args: &args::Run, storage: Clusterwide, raft_storage: RaftSpaceAcces
     box_cfg.listen = Some(format!("{}:{}", args.listen.host, args.listen.port));
     tarantool::set_cfg(&box_cfg);
 
-    // Listen interactive console connections on a unix socket
-    if let Some(ref console_sock) = args.console_sock {
-        let l = ::tarantool::lua_state();
-
-        let validated_path = validate_and_complete_unix_socket_path(console_sock);
-
-        if validated_path.is_err() {
-            tlog!(
-                Critical,
-                "failed to listen interactive console on {console_sock:?}: invalid path"
-            );
-            std::process::exit(-1);
-        }
-
-        let console_sock = validated_path.unwrap();
-        if let Err(e) = l.exec_with(r#"require('console').listen(...)"#, &console_sock) {
-            tlog!(Error, "{e}");
-            tlog!(
-                Critical,
-                "failed to listen interactive console on {console_sock:?}: {}",
-                io::Error::last_os_error()
-            );
-            std::process::exit(-1);
-        }
-    }
+    unwrap_or_terminate(listen_admin_console(args));
 
     if let Err(e) =
         tarantool::on_shutdown(move || fiber::block_on(on_shutdown::callback(PluginList::get())))
diff --git a/src/util.rs b/src/util.rs
index 52f66df7e5b77da5c70c75f7ff43839ba035c808..5d0689d62023be5d834dbbef14610eb2f7c18116 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,3 +1,4 @@
+use crate::cli::args;
 use crate::traft::error::Error;
 use nix::sys::termios::{tcgetattr, tcsetattr, LocalFlags, SetArg::TCSADRAIN};
 use std::any::{Any, TypeId};
@@ -509,15 +510,16 @@ pub fn prompt_password(prompt: &str) -> Result<String, std::io::Error> {
 ////////////////////////////////////////////////////////////////////////////////
 /// Validate unix socket uri via lua uri module
 ///
-/// Unix socket uri should start with ./ or ../ so we prepend it manually
+/// Doesn't change path in case of absolute path.
+/// To relative path `./` prepended.
 ///
 /// Return None in case of incorrect path
-/// Return Some(`value`) with `unix/:` and, probably, `./`, `../` prepended to `value`
+/// Return Some(`value`) with `unix/:` and, probably, `./` prepended to `value`
 pub fn validate_and_complete_unix_socket_path(socket_path: &str) -> Result<String, String> {
     let l = ::tarantool::lua_state();
     let path = std::path::Path::new(socket_path);
     let console_sock = match path.components().next() {
-        Some(std::path::Component::Normal(_)) => {
+        Some(std::path::Component::Normal(_)) | Some(std::path::Component::ParentDir) => {
             format!("unix/:./{socket_path}")
         }
         _ => format!("unix/:{socket_path}"),
@@ -533,6 +535,19 @@ pub fn validate_and_complete_unix_socket_path(socket_path: &str) -> Result<Strin
     Ok(console_sock)
 }
 
+////////////////////////////////////////////////////////////////////////////////
+/// Starts admin console.
+///
+/// Returns Err in case of problems with socket path.
+pub fn listen_admin_console(args: &args::Run) -> Result<(), String> {
+    let lua = ::tarantool::lua_state();
+
+    let validated_path = validate_and_complete_unix_socket_path(&args.admin_sock())?;
+
+    lua.exec_with(r#"require('console').listen(...)"#, &validated_path)
+        .map_err(|err| err.to_string())
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 /// Like unwrap(), but instead of a panic it logs
 /// the error in picodata format and calls exit()
diff --git a/test/int/test_cli_connect.py b/test/int/test_cli_connect.py
index 37f2a1f0743005151918969dfadfe318b8f46e46..5b3ab21dc36ea4d4aa278dd3f466018c9001d345 100644
--- a/test/int/test_cli_connect.py
+++ b/test/int/test_cli_connect.py
@@ -233,30 +233,29 @@ def test_admin_empty_path(binary_path: str):
     cli.expect_exact(pexpect.EOF)
 
 
-def test_admin_ok(cluster: Cluster):
+def test_connect_unix_ok_via_default_sock(cluster: Cluster):
     i1 = cluster.add_instance(wait_online=False)
-    i1.env.update({"PICODATA_CONSOLE_SOCK": f"{i1.data_dir}/console.sock"})
     i1.start()
     i1.wait_online()
 
     cli = pexpect.spawn(
         # For some uninvestigated reason, readline trims the propmt in CI
         # Instead of
-        #   unix/:/some/path/to/console.sock>
+        #   unix/:/some/path/to/admin.sock>
         # it prints
-        #   </path/to/console.sock>
+        #   </path/to/admin.sock>
         #
         # We were unable to debug it quickly and used cwd as a workaround
         cwd=i1.data_dir,
         command=i1.binary_path,
-        args=["admin", "./console.sock"],
+        args=["admin", "./admin.sock"],
         encoding="utf-8",
         timeout=1,
     )
     cli.logfile = sys.stdout
 
-    cli.expect_exact("connected to unix/:./console.sock")
-    cli.expect_exact("unix/:./console.sock>")
+    cli.expect_exact("connected to unix/:./admin.sock")
+    cli.expect_exact("unix/:./admin.sock>")
 
     cli.sendline("\\set language lua")
     cli.sendline("box.session.user()")