diff --git a/cta-dcache/CMakeLists.txt b/cta-dcache/CMakeLists.txt
index db36b4f9810abb779e4f97d469880a88ba2a4e8b..7f35b07873124924dfb1c9582eb87f7023eac23f 100644
--- a/cta-dcache/CMakeLists.txt
+++ b/cta-dcache/CMakeLists.txt
@@ -52,7 +52,7 @@ endforeach(PROTO_SRC)
 include_directories(${CMAKE_BINARY_DIR}/cta-dcache ${CMAKE_BINARY_DIR}/eos_cta
                     ${PROTOBUF3_INCLUDE_DIRS})
 
-add_executable(cta-dcache FrontendGRpcSvc.cpp ${ProtoSourcesCtaDcache} ${ProtoGrpcSourcesCtaDcache})
+add_executable(cta-dcache Main.cpp FrontendGRpcSvc.cpp ${ProtoSourcesCtaDcache} ${ProtoGrpcSourcesCtaDcache})
 
 target_link_libraries(cta-dcache ${PROTOBUF3_LIBRARIES} ${GRPC_GRPC++_LIBRARY}
         ctascheduler ctacommon ctaobjectstore ctacatalogue)
diff --git a/cta-dcache/FrontendGRpcSvc.cpp b/cta-dcache/FrontendGRpcSvc.cpp
index 8b125e4e13fdee53285d3a7625fcdb9835f35003..c3b3f221129196ae7d54995b5a7148c1d2318604 100644
--- a/cta-dcache/FrontendGRpcSvc.cpp
+++ b/cta-dcache/FrontendGRpcSvc.cpp
@@ -16,11 +16,9 @@
  *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include "FrontendGRpcSvc.h"
-#include "version.h"
-#include <getopt.h>
 
-
-static const std::string CTA_DCACHE_VERSION = "cta-dcache-" + std::string(CTA_VERSION);
+#include "common/log/LogLevel.hpp"
+#include <common/checksum/ChecksumBlobSerDeser.hpp>
 
 Status CtaRpcImpl::Version(::grpc::ServerContext *context, const ::google::protobuf::Empty *request,
                            ::cta::admin::Version *response) {
@@ -229,124 +227,3 @@ CtaRpcImpl::CtaRpcImpl(cta::log::Logger *logger, std::unique_ptr<cta::catalogue:
     m_catalogue(std::move(catalogue)), m_scheduler(std::move(scheduler)) {
     m_log = logger;
 }
-
-using namespace cta;
-using namespace cta::common;
-
-std::string help =
-        "Usage: cta-dcache [options]\n"
-        "\n"
-        "where options can be:\n"
-        "\n"
-        "\t--port <port>, -p <port>:\tTCP port number to use, defaults to 17017\n"
-        "\t--log-header, -n         \tadd hostname and timestamp to log outputs, default\n"
-        "\t--no-log-header, -s      \tdon't add hostname and timestamp to log outputs\n"
-        "\t--version, -v            \tprint version and exit.\n"
-        "\t--help, -h               \tprint this help and exit\n";
-
-static struct option long_options[] =
-        {
-                {"port", required_argument, 0, 'p'},
-                {"log-header", no_argument, 0, 'n'},
-                {"no-log-header", no_argument, 0, 's'},
-                {"help", no_argument, 0, 'h'},
-                { "version", no_argument, 0, 'v'},
-                {0, 0, 0, 0}
-        };
-
-void printHelpAndExit(int rc) {
-    std::cout << help << std::endl;
-    exit(rc);
-}
-
-void printVersionAndExit() {
-    std::cout << "cta-dcache version: " << CTA_VERSION << std::endl;
-    exit(0);
-}
-
-int main(const int argc, char *const *const argv) {
-
-    std::string port = "17017";
-
-    char c;
-    bool shortHeader = false;
-    int option_index = 0;
-    const std::string shortHostName = utils::getShortHostname();
-
-    while( (c = getopt_long(argc, argv, "p:nshv", long_options, &option_index)) != EOF) {
-
-        switch(c) {
-            case 'p':
-                port = std::string(optarg);
-                break;
-            case 'n':
-                shortHeader = false;
-                break;
-            case 's':
-                shortHeader = true;
-                break;
-            case 'h':
-                printHelpAndExit(0);
-                break;
-            case 'v':
-                printVersionAndExit();
-                break;
-            default:
-                printHelpAndExit(1);
-        }
-    }
-
-
-    log::StdoutLogger logger(shortHostName, "cta-dcache", shortHeader);
-    log::LogContext lc(logger);
-
-    lc.log(log::INFO, "Starting " + CTA_DCACHE_VERSION);
-
-    // use castor config to avoid dependency on xroot-ssi
-    Configuration config("/etc/cta/cta.conf");
-
-    std::string server_address("0.0.0.0:" + port);
-
-    // Initialise the Catalogue
-    std::string catalogueConfigFile = "/etc/cta/cta-catalogue.conf";
-    const rdbms::Login catalogueLogin = rdbms::Login::parseFile(catalogueConfigFile);
-
-    const uint64_t nbArchiveFileListingConns = 2;
-    auto catalogueFactory = catalogue::CatalogueFactoryFactory::create(logger, catalogueLogin,
-                                                                       10,
-                                                                       nbArchiveFileListingConns);
-    auto catalogue = catalogueFactory->create();
-    try {
-        catalogue->ping();
-        lc.log(log::INFO, "Connected to catalog " + catalogue->getSchemaVersion().getSchemaVersion<std::string>());
-    } catch (cta::exception::Exception &ex) {
-        lc.log(cta::log::CRIT, ex.getMessageValue());
-        exit(1);
-    }
-
-    // Initialise the Scheduler
-    auto backed = config.getConfEntString("ObjectStore", "BackendPath");
-    lc.log(log::INFO, "Using scheduler backend: " + backed);
-
-    auto sInit = cta::make_unique<SchedulerDBInit_t>("Frontend", backed, logger);
-    auto scheddb = sInit->getSchedDB(*catalogue, logger);
-    scheddb->setBottomHalfQueueSize(25000);
-    auto scheduler = cta::make_unique<cta::Scheduler>(*catalogue, *scheddb, 5, 2*1000*1000);
-
-    CtaRpcImpl svc(&logger, catalogue, scheduler);
-
-    // start gRPC service
-
-    ServerBuilder builder;
-    // Listen on the given address without any authentication mechanism.
-    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
-
-    // Register "service" as the instance through which we'll communicate with
-    // clients. In this case it corresponds to an *synchronous* service.
-    builder.RegisterService(&svc);
-
-    std::unique_ptr <Server> server(builder.BuildAndStart());
-
-    lc.log(cta::log::INFO, "Listening on socket address: " + server_address);
-    server->Wait();
-}
diff --git a/cta-dcache/FrontendGRpcSvc.h b/cta-dcache/FrontendGRpcSvc.h
index da033b6c0101f83261f29e7b80c8ef251ea17f4d..3fd112de6ce601955af1f084df570d43bf901103 100644
--- a/cta-dcache/FrontendGRpcSvc.h
+++ b/cta-dcache/FrontendGRpcSvc.h
@@ -1,29 +1,15 @@
 
-#ifndef CTA_FRONTENDGRPCSVC_H
-#define CTA_FRONTENDGRPCSVC_H
-
+#pragma once
 
+#include "version.h"
 #include <grpcpp/grpcpp.h>
 
-#include "catalogue/CatalogueFactoryFactory.hpp"
-#include "rdbms/Login.hpp"
-#include <common/Configuration.hpp>
-#include <common/utils/utils.hpp>
 #include <scheduler/Scheduler.hpp>
-#include <scheduler/OStoreDB/OStoreDBInit.hpp>
-#include "common/log/SyslogLogger.hpp"
-#include "common/log/StdoutLogger.hpp"
-#include "common/log/FileLogger.hpp"
-#include "common/log/LogLevel.hpp"
-#include <common/checksum/ChecksumBlobSerDeser.hpp>
-
+#include "common/log/Logger.hpp"
 #include "cta_dcache.grpc.pb.h"
 
 using cta::Scheduler;
-using cta::SchedulerDBInit_t;
-using cta::SchedulerDB_t;
 using cta::catalogue::Catalogue;
-using cta::rdbms::Login;
 using cta::dcache::rpc::CtaRpc;
 
 using grpc::Server;
@@ -31,6 +17,8 @@ using grpc::ServerBuilder;
 using grpc::ServerContext;
 using grpc::Status;
 
+static const std::string CTA_DCACHE_VERSION = "cta-dcache-" + std::string(CTA_VERSION);
+
 class CtaRpcImpl : public CtaRpc::Service {
 
 private:
@@ -49,4 +37,3 @@ public:
     Status CancelRetrieve(::grpc::ServerContext* context, const ::cta::dcache::rpc::CancelRetrieveRequest* request, ::google::protobuf::Empty* response);
 };
 
-#endif //CTA_FRONTENDGRPCSVC_H
diff --git a/cta-dcache/Main.cpp b/cta-dcache/Main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e43d8533ce013bb19af3fabfbebddd6208ae6b2
--- /dev/null
+++ b/cta-dcache/Main.cpp
@@ -0,0 +1,151 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2021 CERN
+ * @copyright      Copyright(C) 2021 DESY
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "FrontendGRpcSvc.h"
+#include "version.h"
+
+#include "catalogue/CatalogueFactoryFactory.hpp"
+#include <common/Configuration.hpp>
+#include "rdbms/Login.hpp"
+#include "common/log/StdoutLogger.hpp"
+#include "common/log/Logger.hpp"
+#include "common/log/LogLevel.hpp"
+#include "common/make_unique.hpp"
+#include "scheduler/OStoreDB/OStoreDBInit.hpp"
+
+#include <getopt.h>
+
+using namespace cta;
+using namespace cta::common;
+
+std::string help =
+        "Usage: cta-dcache [options]\n"
+        "\n"
+        "where options can be:\n"
+        "\n"
+        "\t--port <port>, -p <port>:\tTCP port number to use, defaults to 17017\n"
+        "\t--log-header, -n         \tadd hostname and timestamp to log outputs, default\n"
+        "\t--no-log-header, -s      \tdon't add hostname and timestamp to log outputs\n"
+        "\t--version, -v            \tprint version and exit.\n"
+        "\t--help, -h               \tprint this help and exit\n";
+
+static struct option long_options[] =
+        {
+                {"port", required_argument, 0, 'p'},
+                {"log-header", no_argument, 0, 'n'},
+                {"no-log-header", no_argument, 0, 's'},
+                {"help", no_argument, 0, 'h'},
+                { "version", no_argument, 0, 'v'},
+                {0, 0, 0, 0}
+        };
+
+void printHelpAndExit(int rc) {
+    std::cout << help << std::endl;
+    exit(rc);
+}
+
+void printVersionAndExit() {
+    std::cout << "cta-dcache version: " << CTA_VERSION << std::endl;
+    exit(0);
+}
+
+int main(const int argc, char *const *const argv) {
+
+    std::string port = "17017";
+
+    char c;
+    bool shortHeader = false;
+    int option_index = 0;
+    const std::string shortHostName = utils::getShortHostname();
+
+    while( (c = getopt_long(argc, argv, "p:nshv", long_options, &option_index)) != EOF) {
+
+        switch(c) {
+            case 'p':
+                port = std::string(optarg);
+                break;
+            case 'n':
+                shortHeader = false;
+                break;
+            case 's':
+                shortHeader = true;
+                break;
+            case 'h':
+                printHelpAndExit(0);
+                break;
+            case 'v':
+                printVersionAndExit();
+                break;
+            default:
+                printHelpAndExit(1);
+        }
+    }
+
+
+    log::StdoutLogger logger(shortHostName, "cta-dcache", shortHeader);
+    log::LogContext lc(logger);
+
+    lc.log(log::INFO, "Starting " + CTA_DCACHE_VERSION);
+
+    // use castor config to avoid dependency on xroot-ssi
+    Configuration config("/etc/cta/cta.conf");
+
+    std::string server_address("0.0.0.0:" + port);
+
+    // Initialise the Catalogue
+    std::string catalogueConfigFile = "/etc/cta/cta-catalogue.conf";
+    const rdbms::Login catalogueLogin = rdbms::Login::parseFile(catalogueConfigFile);
+
+    const uint64_t nbArchiveFileListingConns = 2;
+    auto catalogueFactory = catalogue::CatalogueFactoryFactory::create(logger, catalogueLogin,
+                                                                       10,
+                                                                       nbArchiveFileListingConns);
+    auto catalogue = catalogueFactory->create();
+    try {
+        catalogue->ping();
+        lc.log(log::INFO, "Connected to catalog " + catalogue->getSchemaVersion().getSchemaVersion<std::string>());
+    } catch (cta::exception::Exception &ex) {
+        lc.log(cta::log::CRIT, ex.getMessageValue());
+        exit(1);
+    }
+
+    // Initialise the Scheduler
+    auto backed = config.getConfEntString("ObjectStore", "BackendPath");
+    lc.log(log::INFO, "Using scheduler backend: " + backed);
+
+    auto sInit = cta::make_unique<SchedulerDBInit_t>("Frontend", backed, logger);
+    auto scheddb = sInit->getSchedDB(*catalogue, logger);
+    scheddb->setBottomHalfQueueSize(25000);
+    auto scheduler = cta::make_unique<cta::Scheduler>(*catalogue, *scheddb, 5, 2*1000*1000);
+
+    CtaRpcImpl svc(&logger, catalogue, scheduler);
+
+    // start gRPC service
+
+    ServerBuilder builder;
+    // Listen on the given address without any authentication mechanism.
+    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
+
+    // Register "service" as the instance through which we'll communicate with
+    // clients. In this case it corresponds to an *synchronous* service.
+    builder.RegisterService(&svc);
+
+    std::unique_ptr <Server> server(builder.BuildAndStart());
+
+    lc.log(cta::log::INFO, "Listening on socket address: " + server_address);
+    server->Wait();
+}