diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 9db5fac..f02e235 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -44,6 +44,9 @@
   <PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'linux-arm64'">
     <DefineConstants>$(DefineConstants);ARM64</DefineConstants>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'linux-s390x'">
+    <DefineConstants>$(DefineConstants);S390X</DefineConstants>
+  </PropertyGroup>
 
   <!-- Set TRACE/DEBUG vars -->
   <PropertyGroup>
diff --git a/src/Misc/externals.sh b/src/Misc/externals.sh
index 383221e..1555f67 100755
--- a/src/Misc/externals.sh
+++ b/src/Misc/externals.sh
@@ -189,3 +189,8 @@ if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
     acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
     acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-armv7l.tar.gz" node20 fix_nested_dir
 fi
+
+if [[ "$PACKAGERUNTIME" == "linux-s390x" ]]; then
+    acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-s390x.tar.gz" node16 fix_nested_dir
+    acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-s390x.tar.gz" node20 fix_nested_dir
+fi
diff --git a/src/Misc/layoutroot/config.sh b/src/Misc/layoutroot/config.sh
index 14cc6ba..9b5b8e6 100755
--- a/src/Misc/layoutroot/config.sh
+++ b/src/Misc/layoutroot/config.sh
@@ -20,25 +20,29 @@ then
 
     message="Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies."
 
-    ldd ./bin/libcoreclr.so | grep 'not found'
-    if [ $? -eq 0 ]; then
-        echo "Dependencies is missing for Dotnet Core 6.0"
-        echo $message
-        exit 1
-    fi
+    ARCH=`uname -m`
+    if [ "${ARCH}" != "s390x" -a "${ARCH}" != "ppc64le" ]
+    then
+        ldd ./bin/libcoreclr.so | grep 'not found'
+        if [ $? -eq 0 ]; then
+            echo "Dependencies is missing for Dotnet Core 6.0"
+            echo $message
+            exit 1
+        fi
 
-    ldd ./bin/libSystem.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
-    if [ $? -eq 0 ]; then
-        echo "Dependencies is missing for Dotnet Core 6.0"
-        echo $message
-        exit 1
-    fi
+        ldd ./bin/libSystem.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
+        if [ $? -eq 0 ]; then
+            echo "Dependencies is missing for Dotnet Core 6.0"
+            echo $message
+            exit 1
+        fi
 
-    ldd ./bin/libSystem.IO.Compression.Native.so | grep 'not found'
-    if [ $? -eq 0 ]; then
-        echo "Dependencies is missing for Dotnet Core 6.0"
-        echo $message
-        exit 1
+        ldd ./bin/libSystem.IO.Compression.Native.so | grep 'not found'
+        if [ $? -eq 0 ]; then
+            echo "Dependencies is missing for Dotnet Core 6.0"
+            echo $message
+            exit 1
+        fi
     fi
 
     if ! [ -x "$(command -v ldconfig)" ]; then
diff --git a/src/Runner.Common/Constants.cs b/src/Runner.Common/Constants.cs
index 177e3c9..9545981 100644
--- a/src/Runner.Common/Constants.cs
+++ b/src/Runner.Common/Constants.cs
@@ -58,7 +58,8 @@ namespace GitHub.Runner.Common
             X86,
             X64,
             Arm,
-            Arm64
+            Arm64,
+	    S390x
         }
 
         public static class Runner
@@ -81,6 +82,8 @@ namespace GitHub.Runner.Common
             public static readonly Architecture PlatformArchitecture = Architecture.Arm;
 #elif ARM64
             public static readonly Architecture PlatformArchitecture = Architecture.Arm64;
+#elif S390X
+            public static readonly Architecture PlatformArchitecture = Architecture.S390x;
 #else
             public static readonly Architecture PlatformArchitecture = Architecture.X64;
 #endif
diff --git a/src/Runner.Common/Util/VarUtil.cs b/src/Runner.Common/Util/VarUtil.cs
index 97273a1..2a34430 100644
--- a/src/Runner.Common/Util/VarUtil.cs
+++ b/src/Runner.Common/Util/VarUtil.cs
@@ -53,6 +53,8 @@ namespace GitHub.Runner.Common.Util
                         return "ARM";
                     case Constants.Architecture.Arm64:
                         return "ARM64";
+                    case Constants.Architecture.S390x:
+                        return "S390X";
                     default:
                         throw new NotSupportedException(); // Should never reach here.
                 }
diff --git a/src/Test/L0/ConstantGenerationL0.cs b/src/Test/L0/ConstantGenerationL0.cs
index 2042485..a9d8b46 100644
--- a/src/Test/L0/ConstantGenerationL0.cs
+++ b/src/Test/L0/ConstantGenerationL0.cs
@@ -20,6 +20,7 @@ namespace GitHub.Runner.Common.Tests
                 "linux-x64",
                 "linux-arm",
                 "linux-arm64",
+                "linux-s390x",
                 "osx-x64",
                 "osx-arm64"
             };
diff --git a/src/Test/L0/Listener/SelfUpdaterL0.cs b/src/Test/L0/Listener/SelfUpdaterL0.cs
index 26ba65e..6791df3 100644
--- a/src/Test/L0/Listener/SelfUpdaterL0.cs
+++ b/src/Test/L0/Listener/SelfUpdaterL0.cs
@@ -1,4 +1,4 @@
-﻿#if !(OS_WINDOWS && ARM64)
+﻿#if !(OS_WINDOWS && ARM64) && !S390X
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -16,6 +16,7 @@ using Xunit;
 
 namespace GitHub.Runner.Common.Tests.Listener
 {
+#if !S390X // Self-update is not currently supported on S390X
     public sealed class SelfUpdaterL0
     {
         private Mock<IRunnerServer> _runnerServer;
@@ -291,5 +292,6 @@ namespace GitHub.Runner.Common.Tests.Listener
             }
         }
     }
+#endif
 }
 #endif
diff --git a/src/Test/L0/Listener/SelfUpdaterV2L0.cs b/src/Test/L0/Listener/SelfUpdaterV2L0.cs
index 5115a6b..dd8d198 100644
--- a/src/Test/L0/Listener/SelfUpdaterV2L0.cs
+++ b/src/Test/L0/Listener/SelfUpdaterV2L0.cs
@@ -1,4 +1,4 @@
-﻿#if !(OS_WINDOWS && ARM64)
+﻿#if !(OS_WINDOWS && ARM64) && !S390X
 using System;
 using System.Collections.Generic;
 using System.IO;
diff --git a/src/Test/L0/Worker/StepHostL0.cs b/src/Test/L0/Worker/StepHostL0.cs
index f6b5889..26f8e21 100644
--- a/src/Test/L0/Worker/StepHostL0.cs
+++ b/src/Test/L0/Worker/StepHostL0.cs
@@ -31,7 +31,7 @@ namespace GitHub.Runner.Common.Tests.Worker
             return hc;
         }
 
-#if OS_LINUX
+#if OS_LINUX && !S390X
         [Fact]
         [Trait("Level", "L0")]
         [Trait("Category", "Worker")]
diff --git a/src/dev.sh b/src/dev.sh
index fa637d1..8c66f37 100755
--- a/src/dev.sh
+++ b/src/dev.sh
@@ -54,6 +54,7 @@ elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
         case $CPU_NAME in
             armv7l) RUNTIME_ID="linux-arm";;
             aarch64) RUNTIME_ID="linux-arm64";;
+            s390x) RUNTIME_ID="linux-s390x";;
         esac
     fi
 elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then
@@ -80,7 +81,7 @@ if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
         exit 1
     fi
 elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
-    if [[ ("$RUNTIME_ID" != 'linux-x64') && ("$RUNTIME_ID" != 'linux-x86') && ("$RUNTIME_ID" != 'linux-arm64') && ("$RUNTIME_ID" != 'linux-arm') ]]; then
+	if [[ ("$RUNTIME_ID" != 'linux-x64') && ("$RUNTIME_ID" != 'linux-x86') && ("$RUNTIME_ID" != 'linux-arm64') && ("$RUNTIME_ID" != 'linux-arm')  && ("$RUNTIME_ID" != 'linux-s390x') ]]; then
        echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2
        exit 1
     fi
@@ -199,7 +200,8 @@ function package ()
     popd > /dev/null
 }
 
-if [[ (! -d "${DOTNETSDK_INSTALLDIR}") || (! -e "${DOTNETSDK_INSTALLDIR}/.${DOTNETSDK_VERSION}") || (! -e "${DOTNETSDK_INSTALLDIR}/dotnet") ]]; then
+if [[ "${RUNTIME_ID}" != "linux-s390x" && ((! -d "${DOTNETSDK_INSTALLDIR}") || (! -e "${DOTNETSDK_INSTALLDIR}/.${DOTNETSDK_VERSION}") || (! -e "${DOTNETSDK_INSTALLDIR}/dotnet")) ]]; then
+
 
     # Download dotnet SDK to ../_dotnetsdk directory
     heading "Ensure Dotnet SDK"
@@ -224,8 +226,10 @@ if [[ (! -d "${DOTNETSDK_INSTALLDIR}") || (! -e "${DOTNETSDK_INSTALLDIR}/.${DOTN
     echo "${DOTNETSDK_VERSION}" > "${DOTNETSDK_INSTALLDIR}/.${DOTNETSDK_VERSION}"
 fi
 
-echo "Prepend ${DOTNETSDK_INSTALLDIR} to %PATH%"
-export PATH=${DOTNETSDK_INSTALLDIR}:$PATH
+if [[ -d "${DOTNETSDK_INSTALLDIR}" ]]; then
+    echo "Prepend ${DOTNETSDK_INSTALLDIR} to %PATH%"
+    export PATH=${DOTNETSDK_INSTALLDIR}:$PATH
+fi
 
 heading "Dotnet SDK Version"
 dotnet --version
diff --git a/src/dir.proj b/src/dir.proj
index 056a312..8370922 100644
--- a/src/dir.proj
+++ b/src/dir.proj
@@ -41,8 +41,18 @@
     </ItemGroup>
 
     <Target Name="Build" DependsOnTargets="GenerateConstant">
-        <MSBuild Targets="Restore" Projects="@(ProjectFiles)" StopOnFirstFailure="true" />
-        <MSBuild Targets="Publish" Projects="@(ProjectFiles)" BuildInParallel="false" StopOnFirstFailure="true" Properties="Configuration=$(BUILDCONFIG);PackageRuntime=$(PackageRuntime);Version=$(RunnerVersion);RuntimeIdentifier=$(PackageRuntime);PublishDir=$(MSBuildProjectDirectory)/../_layout/bin" />
+        <PropertyGroup>
+            <!-- Normally we want to publish a self-contained app for $(PackageRuntime) -->
+            <PublishRuntimeIdentifier>RuntimeIdentifier=$(PackageRuntime)</PublishRuntimeIdentifier>
+            <!-- However, on s390x there are no apphost or runtime packages on nuget.org, so self-contained publishing is not supported.
+                 Perform a non-self-contained publish using the current runtime identifier (normally something like rhel.8-s390x) instead.
+                 In addition, when not using an explicit runtime identifier, the SDK will copy runtime assets from dependent packages;
+                 as this would confuse the expected layout, disable that behavior as well.  -->
+            <PublishRuntimeIdentifier Condition="'$(PackageRuntime)' == 'linux-s390x'">SelfContained=false;CopyLocalRuntimeTargetAssets=false</PublishRuntimeIdentifier>
+        </PropertyGroup>
+
+        <MSBuild Targets="Restore" Projects="@(ProjectFiles)" StopOnFirstFailure="true" Properties="$(PublishRuntimeIdentifier)" />
+        <MSBuild Targets="Publish" Projects="@(ProjectFiles)" BuildInParallel="false" StopOnFirstFailure="true" Properties="Configuration=$(BUILDCONFIG);PackageRuntime=$(PackageRuntime);Version=$(RunnerVersion);$(PublishRuntimeIdentifier);PublishDir=$(MSBuildProjectDirectory)/../_layout/bin" />
         <Exec Command="%22$(DesktopMSBuild)%22 Runner.Service/Windows/RunnerService.csproj /p:Configuration=$(BUILDCONFIG) /p:PackageRuntime=$(PackageRuntime) /p:OutputPath=%22$(MSBuildProjectDirectory)/../_layout/bin%22" ConsoleToMSBuild="true" Condition="'$(PackageRuntime)' == 'win-x64' Or '$(PackageRuntime)' == 'win-x86' Or '$(PackageRuntime)' == 'win-arm64'" />
     </Target>

