diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/DerivationFrameworkNCB/test/test_data23cosNCB1.sh b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/DerivationFrameworkNCB/test/test_data23cosNCB1.sh
new file mode 100755
index 0000000000000000000000000000000000000000..791341e0b84d92e7046fa5cf6a4f36326f79a920
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/DerivationFrameworkNCB/test/test_data23cosNCB1.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# art-include: main/Athena
+# art-description: DAOD building NCB1 data23cos
+# art-type: grid
+# art-output: *.pool.root
+# art-output: checkFile*.txt
+# art-output: checkxAOD*.txt
+# art-output: checkIndexRefs*.txt
+
+set -e
+
+Derivation_tf.py \
+--CA True \
+--inputAODFile /cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/CampaignInputs/data23_cos/AOD/data23_cos.00459152.physics_CosmicMuons.merge.AOD.f1383_m2195/data23_cos.00459152.physics_CosmicMuons.merge.AOD.f1383_m2195._lb0124-lb0126._0001.1 \
+--outputDAODFile art.pool.root \
+--formats NCB1 \
+--maxEvents 2000 \
+
+echo "art-result: $? reco"
+
+checkFile.py DAOD_NCB1.art.pool.root > checkFile_NCB1.txt
+
+echo "art-result: $?  checkfile"
+
+checkxAOD.py DAOD_NCB1.art.pool.root > checkxAOD_NCB1.txt
+
+echo "art-result: $?  checkxAOD"
+
+checkIndexRefs.py DAOD_NCB1.art.pool.root > checkIndexRefs_NCB1.txt 2>&1
+
+echo "art-result: $?  checkIndexRefs"
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/makeARTScripts.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/makeARTScripts.py
index 42bbf4cd0fe3d7db06310f1943ef3cad1122149a..f64364df0440f0b408736083fe17a643f21dd68a 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/makeARTScripts.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkART/makeARTScripts.py
@@ -33,6 +33,7 @@ mc21File = com_dir+"mc21/AOD/mc21_13p6TeV.601229.PhPy8EG_A14_ttbar_hdamp258p75_S
 truthFile = com_dir+"mc21/EVNT/mc21_13p6TeV.601229.PhPy8EG_A14_ttbar_hdamp258p75_SingleLep.evgen.EVNT.e8453/EVNT.29328277._003902.pool.root.1"
 data18File = com_dir+"data18/AOD/data18_13TeV.00357772.physics_Main.merge.AOD.r13286_p4910/1000events.AOD.27655096._000455.pool.root.1"
 data22File = com_dir+"data22/AOD/data22_13p6TeV.00431906.physics_Main.merge.AOD.r13928_p5279/1000events.AOD.30220215._001367.pool.root.1"
+data23CosFile = com_dir+"data23_cos/AOD/data23_cos.00459152.physics_CosmicMuons.merge.AOD.f1383_m2195/data23_cos.00459152.physics_CosmicMuons.merge.AOD.f1383_m2195._lb0124-lb0126._0001.1"
 
 # pre/postExec
 preExec = "\'from AthenaCommon.DetFlags import DetFlags; DetFlags.detdescr.all_setOff(); DetFlags.BField_setOn(); DetFlags.digitize.all_setOff(); DetFlags.detdescr.Calo_setOn(); DetFlags.simulate.all_setOff(); DetFlags.pileup.all_setOff(); DetFlags.overlay.all_setOff(); DetFlags.detdescr.Muon_setOn();\'"
@@ -161,6 +162,7 @@ if (makeDataDAODs or makeMCDAODs):
       if makeMCDAODs:
          generateText(formatName,"mc20",mc20File,False,True,"-1",useLegacy)
          generateText(formatName,"mc21",mc21File,False,True,"-1",useLegacy)
+      generateText("NCB1","data23cos",data23CosFile,False,False,"-1",useLegacy)
 if makeTruthDAODs:
    for formatName in truthFormatList:
       generateText(formatName,"mc21",truthFile,True,False,"1000",useLegacy)
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/DerivationConfigList.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/DerivationConfigList.py
index 8e40e3ac17cbda5a70cd3fcda07331301f8de7bc..72e3827b12c757bb877b5741947f3dfffe0bc35c 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/DerivationConfigList.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/DerivationConfigList.py
@@ -128,6 +128,9 @@ from DerivationFrameworkMuons.MUON5 import MUON5Cfg
 from DerivationFrameworkTLA.TLA0 import TLA0Cfg
 from DerivationFrameworkTLA.TLA1 import TLA1Cfg
 
+# NCB derivation running on AODs (for cosmic and BIB studies)
+from DerivationFrameworkNCB.NCB1 import NCB1Cfg
+
 
 # Avoids compilation warnings from Flake8
 __all__ = ['TEST1Cfg','TEST2Cfg','TEST3Cfg','TEST4Cfg','TEST5Cfg','TEST6Cfg',
@@ -152,4 +155,5 @@ __all__ = ['TEST1Cfg','TEST2Cfg','TEST3Cfg','TEST4Cfg','TEST5Cfg','TEST6Cfg',
            'TRIG8Cfg','L1CALO1Cfg',
            'MUON1Cfg','MUON5Cfg',
            'TLA0Cfg', 'TLA1Cfg',
+           'NCB1Cfg'
            ]
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/__init__.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/__init__.py
index d1241fe76062f29fb9697a77fb759e45d56c3af3..98e91540df2208a7f113aeba48881f18f691b7e5 100644
--- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/__init__.py
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkConfiguration/python/__init__.py
@@ -1 +1 @@
-# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/CMakeLists.txt b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2fc84eaa6bbd5e1f3e1f3c61c205be0967814246
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/CMakeLists.txt
@@ -0,0 +1,7 @@
+# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+
+# Declare the package name:
+atlas_subdir( DerivationFrameworkNCB )
+
+# Install files from the package:
+atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/README.md b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..915335226398cb1545955e6ab4192cf20d881b4b
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/README.md
@@ -0,0 +1,11 @@
+# DerivationFrameworkNCB
+
+This package contains the configuration files for the Non-Collision Background (NCB) derivations used for cosmic rays and Beam Induced Background (BIB) studies.
+
+The package contains the following files:
+
+* `NCB1.py`: the configuration of the `NCB1` data type. As well as setting up the driving algorithm ("kernel") for the jobs, these files mainly configure directly the slimming (branch-wise content) but not the common physics content which is configured elsewhere (see below).    
+* `NCBCommonConfig.py`: the configuration of the common physics content. This file pulls in the config fragments from all of the reconstruction domains plus truth and trigger matching (in the case of upgrade samples). 
+
+For more details please refer to [the manual](https://twiki.cern.ch/twiki/bin/view/AtlasProtected/DerivationFramework)
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/NCB1.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/NCB1.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec2c615d9ae22a865c81ab7070ebb0fe38805848
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/NCB1.py
@@ -0,0 +1,103 @@
+# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+#!/usr/bin/env python
+#====================================================================
+# DAOD_NCB1.py
+# This defines DAOD_NCB1, an unskimmed DAOD format for Run 3.
+# It contains the variables and objects needed for cosmic ray and BIB studies
+# done by the NCB group
+# It requires the flag NCB1 in Derivation_tf.py   
+#====================================================================
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from AthenaConfiguration.Enums import MetadataCategory
+
+# Main algorithm config
+def NCB1KernelCfg(ConfigFlags, name='NCB1Kernel', **kwargs):
+    """Configure the derivation framework driving algorithm (kernel) for NCB1"""
+    acc = ComponentAccumulator()
+
+    # Common augmentations
+    from DerivationFrameworkNCB.NCBCommonConfig import NCBCommonAugmentationsCfg
+    acc.merge(NCBCommonAugmentationsCfg(ConfigFlags, TriggerListsHelper = kwargs['TriggerListsHelper']))
+
+    # The kernel algorithm itself
+    DerivationKernel = CompFactory.DerivationFramework.DerivationKernel
+    acc.addEventAlgo(DerivationKernel(name))   
+
+    return acc
+
+
+def NCB1Cfg(ConfigFlags):
+
+    from AthenaCommon.Logging import logging
+    logNCB1 = logging.getLogger('NCB1')
+    logNCB1.info('****************** STARTING NCB1 *****************')
+
+    acc = ComponentAccumulator()
+
+    from DerivationFrameworkPhys.TriggerListsHelper import TriggerListsHelper
+    NCB1TriggerListsHelper = TriggerListsHelper(ConfigFlags)
+
+    acc.merge(NCB1KernelCfg(ConfigFlags, name='NCB1Kernel', StreamName = 'StreamDAOD_NCB1', TriggerListsHelper = NCB1TriggerListsHelper))
+    
+        
+    # ============================
+    # Define contents of the format
+    # =============================
+    
+    from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+    from xAODMetaDataCnv.InfileMetaDataConfig import SetupMetaDataForStreamCfg
+    from DerivationFrameworkCore.SlimmingHelper import SlimmingHelper
+       
+    NCB1SlimmingHelper = SlimmingHelper("NCB1SlimmingHelper", NamesAndTypes = ConfigFlags.Input.TypedCollections, ConfigFlags = ConfigFlags)
+
+    NCB1SlimmingHelper.SmartCollections = [
+        "MET_Baseline_AntiKt4EMTopo",
+        "Electrons",
+        "Photons"
+    ]    
+
+    NCB1SlimmingHelper.AllVariables = [
+        "EventInfo",
+        "InDetTrackParticles",
+        "CombinedMuonTrackParticles",
+        "AntiKt4EMTopoJets",
+        "CaloCalTopoClusters",
+        "Muons",
+        "MuonSegments",
+        "MuonSpectrometerTrackParticles",
+        "ExtrapolatedMuonTrackParticles",
+        "NCB_MuonSegments",
+    ]
+
+       
+    # Truth extra content
+    if ConfigFlags.Input.isMC:
+        from DerivationFrameworkMCTruth.MCTruthCommonConfig import addTruth3ContentToSlimmerTool
+        addTruth3ContentToSlimmerTool(NCB1SlimmingHelper)
+        NCB1SlimmingHelper.AllVariables += [
+            "TruthEvents",
+            "TruthVertices",
+            "TruthParticles",
+            "MET_Truth"
+        ]
+   
+    # Trigger content
+    NCB1SlimmingHelper.IncludeTriggerNavigation = False
+    NCB1SlimmingHelper.IncludeJetTriggerContent = False
+    NCB1SlimmingHelper.IncludeMuonTriggerContent = False
+    NCB1SlimmingHelper.IncludeEGammaTriggerContent = False
+    NCB1SlimmingHelper.IncludeJetTauEtMissTriggerContent = False
+    NCB1SlimmingHelper.IncludeTauTriggerContent = False
+    NCB1SlimmingHelper.IncludeEtMissTriggerContent = False
+    NCB1SlimmingHelper.IncludeBJetTriggerContent = False
+    NCB1SlimmingHelper.IncludeBPhysTriggerContent = False
+    NCB1SlimmingHelper.IncludeMinBiasTriggerContent = False
+
+    # Output stream    
+    NCB1ItemList = NCB1SlimmingHelper.GetItemList()
+    acc.merge(OutputStreamCfg(ConfigFlags, "DAOD_NCB1", ItemList=NCB1ItemList, AcceptAlgs=["NCB1Kernel"]))
+    acc.merge(SetupMetaDataForStreamCfg(ConfigFlags, "DAOD_NCB1", AcceptAlgs=["NCB1Kernel"], createMetadata=[MetadataCategory.CutFlowMetaData]))
+
+    return acc
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/NCBCommonConfig.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/NCBCommonConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..9fc172fd072031e46f2fa34b97e1783b4d10c5e8
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/NCBCommonConfig.py
@@ -0,0 +1,131 @@
+# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+
+# NCBCommonConfig
+# Contains the configuration for the common physics containers/decorations used in analysis DAODs
+# Actual configuration is subcontracted to other config files since some of them are very long
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+
+
+def StandardJetsInDerivCfg(flags):
+    """Jet reconstruction needed for NCB1"""
+
+    from JetRecConfig.StandardSmallRJets import AntiKt4EMTopo
+    from JetRecConfig.JetRecConfig import JetRecCfg
+    from JetRecConfig.JetConfigFlags import jetInternalFlags
+
+    acc = ComponentAccumulator()
+
+    AntiKt4EMTopo_deriv = AntiKt4EMTopo.clone(
+        modifiers = AntiKt4EMTopo.modifiers+("JetPtAssociation","QGTagging")
+    )
+
+    jetList = [AntiKt4EMTopo_deriv]
+
+    jetInternalFlags.isRecoJob = True
+
+    for jd in jetList:
+        acc.merge(JetRecCfg(flags,jd))
+
+    return acc
+
+
+def NCBCommonAugmentationsCfg(flags,**kwargs):
+    """Configure the common augmentation"""
+    acc = ComponentAccumulator()
+
+    # MC truth
+    if flags.Input.isMC:
+        from DerivationFrameworkMCTruth.MCTruthCommonConfig import (
+            AddStandardTruthContentsCfg,
+            AddHFAndDownstreamParticlesCfg,
+            AddMiniTruthCollectionLinksCfg,
+            AddPVCollectionCfg,
+            AddTruthCollectionNavigationDecorationsCfg)
+        from DerivationFrameworkMCTruth.TruthDerivationToolsConfig import TruthCollectionMakerCfg
+        NCBCommonTruthCharmTool = acc.getPrimaryAndMerge(TruthCollectionMakerCfg(
+            flags,
+            name                    = "NCBCommonTruthCharmTool",
+            NewCollectionName       = "TruthCharm",
+            KeepNavigationInfo      = False,
+            ParticleSelectionString = "(abs(TruthParticles.pdgId) == 4)",
+            Do_Compress             = True)) 
+        CommonAugmentation = CompFactory.DerivationFramework.CommonAugmentation
+        acc.addEventAlgo(CommonAugmentation("NCBCommonTruthCharmKernel",AugmentationTools=[NCBCommonTruthCharmTool]))
+        acc.merge(AddHFAndDownstreamParticlesCfg(flags))
+        acc.merge(AddStandardTruthContentsCfg(flags))
+        acc.merge(AddTruthCollectionNavigationDecorationsCfg(
+            flags,
+            TruthCollections=["TruthElectrons", 
+                              "TruthMuons", 
+                              "TruthPhotons", 
+                              "TruthTaus", 
+                              "TruthNeutrinos", 
+                              "TruthBSM", 
+                              "TruthBottom", 
+                              "TruthTop", 
+                              "TruthBoson",
+                              "TruthCharm",
+                              "TruthHFWithDecayParticles"],
+            prefix = 'NCB_'))
+        # Re-point links on reco objects
+        acc.merge(AddMiniTruthCollectionLinksCfg(flags))
+        acc.merge(AddPVCollectionCfg(flags))
+
+    # InDet, Muon, Egamma common augmentations
+    from DerivationFrameworkMuons.MuonsCommonConfig import MuonsCommonCfg
+    acc.merge(MuonsCommonCfg(flags))
+    # TODO: need to find the new flags equivalent for the missing settings below, then we can
+    # drop these kwargs and do everything via the flags
+    from DerivationFrameworkInDet.InDetCommonConfig import InDetCommonCfg
+    acc.merge(InDetCommonCfg(flags,
+                             DoVertexFinding = flags.Tracking.doVertexFinding,
+                             AddPseudoTracks = flags.Tracking.doPseudoTracking,
+                             DecoLRTTTVA = False,
+                             DoR3LargeD0 = flags.Tracking.doLargeD0,
+                             StoreSeparateLargeD0Container = flags.Tracking.storeSeparateLargeD0Container,
+                             MergeLRT = False)) 
+    # Jets, di-taus, tau decorations, flavour tagging, MET association
+    from DerivationFrameworkJetEtMiss.METCommonConfig import METCommonCfg
+    acc.merge(METCommonCfg(flags))
+    acc.merge(StandardJetsInDerivCfg(flags))
+
+    # Trigger matching
+    if flags.Reco.EnableTrigger or flags.Trigger.triggerConfig == 'INFILE':
+        from DerivationFrameworkPhys.TriggerMatchingCommonConfig import TriggerMatchingCommonRun2Cfg
+        from DerivationFrameworkPhys.TriggerMatchingCommonConfig import TriggerMatchingCommonRun2ToRun3Cfg
+        from DerivationFrameworkPhys.TriggerMatchingCommonConfig import TriggerMatchingCommonRun3Cfg
+        # requires some wrangling due to the difference between run 2 and 3
+        triggerListsHelper = kwargs['TriggerListsHelper']
+        if flags.Trigger.EDMVersion == 2:
+            # NOTE: Once Run-2 -> Run-3 trigger navigation is validated and doEDMVersionConversion is on by default, we will only want to do ONE of
+            # TriggerMatchingCommonRun2Cfg(s) OR TriggerMatchingCommonRun2ToRun3Cfg
+            # Otherwise we are doubling up on the analysis trigger data in both the Run-2 and Run-3 formats.
+
+            # This sets up the Run-2 style matching during the derivation process
+            acc.merge(TriggerMatchingCommonRun2Cfg(
+                flags,
+                name = "PhysCommonTrigMatchNoTau",
+                OutputContainerPrefix = "TrigMatch_",
+                ChainNames = triggerListsHelper.Run2TriggerNamesNoTau))
+            acc.merge(TriggerMatchingCommonRun2Cfg(
+                flags,
+                name = "PhysCommonTrigMatchTau",
+                OutputContainerPrefix = "TrigMatch_",
+                ChainNames = triggerListsHelper.Run2TriggerNamesTau,
+                DRThreshold = 0.2))
+            # This sets up a conversion of the Run-2 trigger navigation to the Run-3 style, 
+            # followed by Run-3 style navigation slimming for trigger-matching from DAOD.
+            # This function is a noop if doEDMVersionConversion=False
+            acc.merge(TriggerMatchingCommonRun2ToRun3Cfg(
+                flags,
+                TriggerList = triggerListsHelper.Run2TriggerNamesNoTau +
+                triggerListsHelper.Run2TriggerNamesTau))
+        if flags.Trigger.EDMVersion == 3:
+            # This sets up the Run-3 style navigation slimming for trigger-matching from DAOD
+            acc.merge(TriggerMatchingCommonRun3Cfg(
+                flags, TriggerList = triggerListsHelper.Run3TriggerNames))
+
+    return acc
+
diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/__init__.py b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..98e91540df2208a7f113aeba48881f18f691b7e5
--- /dev/null
+++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkNCB/python/__init__.py
@@ -0,0 +1 @@
+# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration