diff --git a/src/args.rs b/src/args.rs
index 6fd1d2428af603ae91bc495283a9912dd3d53b18..8366751a408864ecafe45bf3a219ada1caa4b878 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -3,6 +3,7 @@ use std::{
     borrow::Cow,
     ffi::{CStr, CString},
 };
+use tarantool::log::SayLevel;
 use tarantool::tlua::{self, c_str};
 use thiserror::Error;
 
@@ -82,6 +83,39 @@ pub struct Run {
     #[clap(long, value_name = "name", env = "PICODATA_REPLICASET_ID")]
     /// Name of the replicaset
     pub replicaset_id: Option<String>,
+
+    #[clap(long, arg_enum, default_value = "info", env = "PICODATA_LOG_LEVEL")]
+    /// Log level
+    log_level: LogLevel,
+}
+
+// Copy enum because clap:ArgEnum can't be derived for the foreign SayLevel.
+#[derive(Debug, Copy, Clone, tlua::Push, PartialEq, clap::ArgEnum)]
+#[clap(rename_all = "lower")]
+enum LogLevel {
+    Fatal,
+    System,
+    Error,
+    Crit,
+    Warn,
+    Info,
+    Verbose,
+    Debug,
+}
+
+impl From<LogLevel> for SayLevel {
+    fn from(l: LogLevel) -> SayLevel {
+        match l {
+            LogLevel::Fatal => SayLevel::Fatal,
+            LogLevel::System => SayLevel::System,
+            LogLevel::Error => SayLevel::Error,
+            LogLevel::Crit => SayLevel::Crit,
+            LogLevel::Warn => SayLevel::Warn,
+            LogLevel::Info => SayLevel::Info,
+            LogLevel::Verbose => SayLevel::Verbose,
+            LogLevel::Debug => SayLevel::Debug,
+        }
+    }
 }
 
 impl Run {
@@ -102,6 +136,10 @@ impl Run {
             None => self.listen.clone(),
         }
     }
+
+    pub fn log_level(&self) -> SayLevel {
+        self.log_level.into()
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -275,4 +313,21 @@ mod tests {
             assert_eq!(parsed.advertise_address(), "advertise-from-args:3301");
         }
     }
+
+    #[test]
+    fn test_log_level() {
+        let _env_dump = EnvDump::new();
+        std::env::set_var("PICODATA_INSTANCE_ID", "test-log-level");
+        std::env::set_var("PICODATA_PEER", "test-log-level");
+
+        let parsed = parse![Run,];
+        assert_eq!(parsed.log_level(), SayLevel::Info);
+
+        std::env::set_var("PICODATA_LOG_LEVEL", "verbose");
+        let parsed = parse![Run,];
+        assert_eq!(parsed.log_level(), SayLevel::Verbose);
+
+        let parsed = parse![Run, "--log-level", "warn"];
+        assert_eq!(parsed.log_level(), SayLevel::Warn);
+    }
 }
diff --git a/src/main.rs b/src/main.rs
index 5f1f7ab9dee26ffd268fd1624c80915b05681a60..2c8033ef85e071ccaefbd6145ad5f0c8ecc764df 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -356,6 +356,7 @@ fn start_discover(args: &args::Run, to_supervisor: ipc::Sender<IpcMessage>) {
         read_only: false,
         wal_dir: args.data_dir.clone(),
         memtx_dir: args.data_dir.clone(),
+        log_level: args.log_level() as u8,
         ..Default::default()
     };
 
@@ -476,6 +477,7 @@ fn start_join(args: &args::Run, leader_address: String) {
         replication: resp.box_replication.clone(),
         wal_dir: args.data_dir.clone(),
         memtx_dir: args.data_dir.clone(),
+        log_level: args.log_level() as u8,
         ..Default::default()
     };