diff --git a/bin/system-info.c b/bin/system-info.c
index 14284cc5469bd57f4e2b403c8bbd80f96db35143..264599791a0590b857135fe5bfde8b823ef4e602 100644
--- a/bin/system-info.c
+++ b/bin/system-info.c
@@ -543,6 +543,101 @@ main (int argc,
   json_builder_end_array (builder);
   json_builder_end_object (builder);
 
+  json_builder_set_member_name (builder, "os-release");
+  json_builder_begin_object (builder);
+    {
+      GStrv strv;
+      gsize i;
+      gchar *tmp;
+
+      tmp = srt_system_info_dup_os_id (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "id");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      strv = srt_system_info_dup_os_id_like (info, FALSE);
+
+      if (strv != NULL)
+        {
+          json_builder_set_member_name (builder, "id_like");
+          json_builder_begin_array (builder);
+            {
+              for (i = 0; strv[i] != NULL; i++)
+                json_builder_add_string_value (builder, strv[i]);
+            }
+          json_builder_end_array (builder);
+          g_strfreev (strv);
+        }
+
+      tmp = srt_system_info_dup_os_name (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "name");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      tmp = srt_system_info_dup_os_pretty_name (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "pretty_name");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      tmp = srt_system_info_dup_os_version_id (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "version_id");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      tmp = srt_system_info_dup_os_version_codename (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "version_codename");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      tmp = srt_system_info_dup_os_build_id (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "build_id");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      tmp = srt_system_info_dup_os_variant_id (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "variant_id");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+
+      tmp = srt_system_info_dup_os_variant (info);
+
+      if (tmp != NULL)
+        {
+          json_builder_set_member_name (builder, "variant");
+          json_builder_add_string_value (builder, tmp);
+          g_free (tmp);
+        }
+    }
+  json_builder_end_object (builder);
+
   json_builder_set_member_name (builder, "architectures");
   json_builder_begin_object (builder);
 
diff --git a/bin/system-info.md b/bin/system-info.md
index be107bbb16f05630c3c743e48685094535302d94..114929ff7ae5ded8bb0b93d64ad9c73146b2cf49 100644
--- a/bin/system-info.md
+++ b/bin/system-info.md
@@ -138,6 +138,112 @@ keys:
             likely to break the use of libraries from the host system,
             in particular the Mesa graphics drivers.
 
+**os-release**
+:   An object describing the operating system or container in which
+    **steam-runtime-system-info** was run. The keys and values are
+    strings, and any field that is not known is omitted.
+
+    **id**
+    :   A short lower-case string identifying the operating system,
+        for example **debian** or **arch**. In a Steam Runtime
+        chroot or container this will be **steamrt**.
+
+        This is the **ID** from **os-release**(5).
+        If **os-release**(5) is not available, future versions of this
+        library might derive a similar ID from **lsb_release**(1).
+
+    **id_like**
+    :   An array of short lower-case strings identifying operating systems
+        that this one was derived from. For example, Steam Runtime 1 'scout'
+        is derived from Ubuntu, which is itself derived from Debian, so
+        in a scout chroot or container this will be **["ubuntu", "debian"]**.
+
+        This is the **ID_LIKE** field from **os-release**(5), split
+        at whitespace. It does not include the **id**.
+
+        If **os-release**(5) is not available, future versions of this
+        library might derive a similar array from **lsb_release**(1)
+        or from hard-coded knowledge of particular operating systems.
+
+    **name**
+    :   A human-readable name for the operating system without its
+        version, for example **Debian GNU/Linux** or **Arch Linux**.
+
+        This is the **NAME** from **os-release**(5).
+        If **os-release**(5) is not available, future versions of this
+        library might derive a similar name from **lsb_release**(1).
+
+    **pretty_name**
+    :   A human-readable name for the operating system, including its
+        version if applicable, for example
+        **Debian GNU/Linux 10 (buster)** or **Arch Linux**. For rolling
+        releases like Debian testing/unstable and Arch Linux, this
+        might be the same as **name**.
+
+        This is the **PRETTY_NAME** from **os-release**(5).
+        If **os-release**(5) is not available, future versions of this
+        library might derive a similar name from **lsb_release**(1).
+
+    **version_id**
+    :   A short machine-readable string identifying the operating system,
+        for example **10** for Debian 10 'buster'. In a
+        Steam Runtime 1 'scout' chroot or container this will be **1**.
+        In rolling releases like Debian testing/unstable and Arch Linux,
+        this is likely to be omitted. It is not guaranteed to be numeric.
+
+        This is the **VERSION_ID** from **os-release**(5).
+        If **os-release**(5) is not available, future versions of this
+        library might derive a similar ID from **lsb_release**(1).
+
+    **version_codename**
+    :   A short string identifying the operating system release codename,
+        for example **buster** for Debian 10 'buster'. In a
+        Steam Runtime 1 'scout' chroot or container this will be **scout**
+        if present.
+
+        In rolling releases like Debian testing/unstable and Arch Linux,
+        and in operating systems like Fedora that have codenames but do
+        not use them in a machine-readable context, this is likely to be
+        omitted.
+
+        This is the **VERSION_CODENAME** from **os-release**(5).
+        If **os-release**(5) is not available, future versions of this
+        library might derive a similar ID from **lsb_release**(1).
+
+    **build_id**
+    :   A short machine-readable string identifying the image from which
+        the operating system was installed (depending on the operating
+        system, it might have been upgraded since then). In operating
+        systems with only non-image-based installation methods this will
+        usually be omitted.
+
+        In a Steam Runtime 1 'scout' chroot or container, if present this
+        identifies the Steam Runtime build on which the chroot or container
+        is based, such as **0.20190926.0** for an official build or
+        **tools-test-0.20190926.0** for an unofficial build (but, again, it
+        might have been upgraded since then).
+
+        This is the **BUILD_ID** from **os-release**(5).
+
+    **variant_id**
+    :   A short machine-readable string identifying the variant or edition
+        of the operating system, such as **workstation**.
+
+        In a Steam Runtime 1 'scout' chroot or container built from a
+        Flatpak-style runtime, this will currently be something like
+        **com.valvesoftware.steamruntime.platform-amd64_i386-scout**.
+
+        This is the **VARIANT_ID** from **os-release**(5).
+
+    **variant**
+    :   A human-readable string identifying the variant or edition
+        of the operating system, such as **Workstation Edition**.
+
+        In a Steam Runtime 1 'scout' chroot or container built from a
+        Flatpak-style runtime, this will usually be **Platform** or **SDK**.
+
+        This is the **VARIANT** from **os-release**(5).
+
 **architectures**
 :   An object with architecture-specific information. The keys are
     Debian-style *multiarch tuples* describing ABIs, as returned by
diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c
index 3aeaa10054ec98dc53f05f363a78c63a854dd685..615744918f0c57151b8741a9f262ead338cfff8f 100644
--- a/steam-runtime-tools/graphics.c
+++ b/steam-runtime-tools/graphics.c
@@ -1706,7 +1706,7 @@ _srt_load_egl_icds (gchar **envp,
    * https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md
    * for details of the search order. */
 
-  sysroot = g_environ_getenv (envp, "SRT_TEST_ICD_SYSROOT");
+  sysroot = g_environ_getenv (envp, "SRT_TEST_SYSROOT");
   value = g_environ_getenv (envp, "__EGL_VENDOR_LIBRARY_FILENAMES");
 
   if (value != NULL)
@@ -2282,7 +2282,7 @@ _srt_load_vulkan_icds (gchar **envp,
    * documentation is not completely up to date (as of September 2019)
    * so you should also look at the reference implementation. */
 
-  sysroot = g_environ_getenv (envp, "SRT_TEST_ICD_SYSROOT");
+  sysroot = g_environ_getenv (envp, "SRT_TEST_SYSROOT");
   value = g_environ_getenv (envp, "VK_ICD_FILENAMES");
 
   if (value != NULL)
diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build
index 2bdea03919a5f5dbe6075597e06498e5d9cbf5be..1e6abaefc1496e0ebe72016a159a9aa33b5c1000 100644
--- a/steam-runtime-tools/meson.build
+++ b/steam-runtime-tools/meson.build
@@ -30,6 +30,8 @@ libsteamrt_sources = [
     'library.c',
     'locale-internal.h',
     'locale.c',
+    'os-internal.h',
+    'os.c',
     'runtime-internal.h',
     'runtime.c',
     'steam-internal.h',
diff --git a/steam-runtime-tools/os-internal.h b/steam-runtime-tools/os-internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed65cae0a056b07472c5e321c9d7e6ee1eb32a17
--- /dev/null
+++ b/steam-runtime-tools/os-internal.h
@@ -0,0 +1,49 @@
+/*<private_header>*/
+/*
+ * Copyright © 2019 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+
+typedef struct
+{
+  gchar *build_id;
+  gchar *id;
+  gchar *id_like;
+  gchar *name;
+  gchar *pretty_name;
+  gchar *variant;
+  gchar *variant_id;
+  gchar *version_codename;
+  gchar *version_id;
+  gboolean populated;
+} SrtOsRelease;
+
+G_GNUC_INTERNAL void _srt_os_release_init (SrtOsRelease *self);
+G_GNUC_INTERNAL void _srt_os_release_populate (SrtOsRelease *self,
+                                               gchar **envp);
+G_GNUC_INTERNAL void _srt_os_release_clear (SrtOsRelease *self);
diff --git a/steam-runtime-tools/os.c b/steam-runtime-tools/os.c
new file mode 100644
index 0000000000000000000000000000000000000000..d5334e675147a7f8e0030157b53f7d087b515b31
--- /dev/null
+++ b/steam-runtime-tools/os.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2019 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "steam-runtime-tools/os-internal.h"
+
+#include <string.h>
+
+#include "steam-runtime-tools/glib-compat.h"
+
+#include <glib.h>
+
+#include "steam-runtime-tools/utils.h"
+
+G_GNUC_INTERNAL void
+_srt_os_release_init (SrtOsRelease *self)
+{
+  self->build_id = NULL;
+  self->id = NULL;
+  self->id_like = NULL;
+  self->name = NULL;
+  self->pretty_name = NULL;
+  self->variant = NULL;
+  self->variant_id = NULL;
+  self->version_codename = NULL;
+  self->version_id = NULL;
+  self->populated = FALSE;
+}
+
+static const char * const os_release_paths[] =
+{
+  "/etc/os-release",
+  "/usr/lib/os-release"
+};
+
+static void
+do_line (SrtOsRelease *self,
+         const char *path,
+         gchar *line)
+{
+  char *equals;
+  gchar *unquoted = NULL;
+  gchar **dest = NULL;
+  GError *local_error = NULL;
+
+  /* Modify line in-place to strip leading and trailing whitespace */
+  g_strstrip (line);
+
+  if (line[0] == '\0' || line[0] == '#')
+    return;
+
+  g_debug ("%s: %s", path, line);
+
+  equals = strchr (line, '=');
+
+  if (equals == NULL)
+    {
+      g_debug ("Unable to parse line \"%s\" in %s: no \"=\" found",
+               line, path);
+      return;
+    }
+
+  unquoted = g_shell_unquote (equals + 1, &local_error);
+
+  if (unquoted == NULL)
+    {
+      g_debug ("Unable to parse line \"%s\" in %s: %s",
+               line, path, local_error->message);
+      g_clear_error (&local_error);
+      return;
+    }
+
+  *equals = '\0';
+
+  if (strcmp (line, "BUILD_ID") == 0)
+    dest = &self->build_id;
+  else if (strcmp (line, "ID") == 0)
+    dest = &self->id;
+  else if (strcmp (line, "ID_LIKE") == 0)
+    dest = &self->id_like;
+  else if (strcmp (line, "NAME") == 0)
+    dest = &self->name;
+  else if (strcmp (line, "PRETTY_NAME") == 0)
+    dest = &self->pretty_name;
+  else if (strcmp (line, "VARIANT") == 0)
+    dest = &self->variant;
+  else if (strcmp (line, "VARIANT_ID") == 0)
+    dest = &self->variant_id;
+  else if (strcmp (line, "VERSION_CODENAME") == 0)
+    dest = &self->version_codename;
+  else if (strcmp (line, "VERSION_ID") == 0)
+    dest = &self->version_id;
+
+  if (dest != NULL)
+    {
+      if (*dest != NULL)
+        {
+          /* Using the last one matches the behaviour of a shell script
+           * that uses ". /usr/lib/os-release" */
+          g_debug ("%s appears more than once in %s, will use last instance",
+                   line, path);
+          g_free (*dest);
+        }
+
+      *dest = unquoted;
+    }
+  else
+    {
+      g_free (unquoted);
+    }
+}
+
+G_GNUC_INTERNAL void
+_srt_os_release_populate (SrtOsRelease *self,
+                          gchar **envp)
+{
+  const char *sysroot = NULL;
+  gsize i;
+
+  g_return_if_fail (_srt_check_not_setuid ());
+  g_return_if_fail (!self->populated);
+  g_return_if_fail (self->build_id == NULL);
+  g_return_if_fail (self->id == NULL);
+  g_return_if_fail (self->name == NULL);
+  g_return_if_fail (self->pretty_name == NULL);
+  g_return_if_fail (self->variant == NULL);
+  g_return_if_fail (self->variant_id == NULL);
+  g_return_if_fail (self->version_codename == NULL);
+  g_return_if_fail (self->version_id == NULL);
+
+  if (envp != NULL)
+    sysroot = g_environ_getenv (envp, "SRT_TEST_SYSROOT");
+  else
+    sysroot = g_getenv ("SRT_TEST_SYSROOT");
+
+  for (i = 0; i < G_N_ELEMENTS (os_release_paths); i++)
+    {
+      gchar *built_path = NULL;
+      gchar *contents = NULL;
+      const char *path = NULL;
+      char *beginning_of_line;
+      GError *local_error = NULL;
+      gsize len;
+      gsize j;
+
+      if (sysroot != NULL)
+        {
+          built_path = g_build_filename (sysroot, os_release_paths[i], NULL);
+          path = built_path;
+        }
+      else
+        {
+          path = os_release_paths[i];
+        }
+
+      if (!g_file_get_contents (path, &contents, &len, &local_error))
+        {
+          g_debug ("Unable to open %s: %s", path, local_error->message);
+          g_clear_error (&local_error);
+          g_free (built_path);
+          continue;
+        }
+
+      beginning_of_line = contents;
+
+      for (j = 0; j < len; j++)
+        {
+          if (contents[j] == '\n')
+            {
+              contents[j] = '\0';
+              do_line (self, path, beginning_of_line);
+              /* g_file_get_contents adds an extra \0 at contents[len],
+               * so this is safe to do without overrunning the buffer */
+              beginning_of_line = contents + j + 1;
+            }
+        }
+
+      /* Collect a possible partial line */
+      do_line (self, path, beginning_of_line);
+
+      g_free (contents);
+      g_free (built_path);
+      break;
+    }
+
+  /* Special case for the Steam Runtime: Flatpak-style scout images have
+   * historically not had a VERSION_CODENAME in os-release(5), but
+   * we know that version 1 is scout, so let's add it. */
+  if (self->version_codename == NULL
+      && g_strcmp0 (self->id, "steamrt") == 0
+      && g_strcmp0 (self->version_id, "1") == 0)
+    self->version_codename = g_strdup ("scout");
+
+  /* Special case for the Steam Runtime: we got this wrong in the past. */
+  if (g_strcmp0 (self->id_like, "ubuntu") == 0)
+    {
+      g_free (self->id_like);
+      self->id_like = g_strdup ("ubuntu debian");
+    }
+
+  self->populated = TRUE;
+}
+
+G_GNUC_INTERNAL void
+_srt_os_release_clear (SrtOsRelease *self)
+{
+  g_clear_pointer (&self->build_id, g_free);
+  g_clear_pointer (&self->id, g_free);
+  g_clear_pointer (&self->id_like, g_free);
+  g_clear_pointer (&self->name, g_free);
+  g_clear_pointer (&self->pretty_name, g_free);
+  g_clear_pointer (&self->variant, g_free);
+  g_clear_pointer (&self->variant_id, g_free);
+  g_clear_pointer (&self->version_codename, g_free);
+  g_clear_pointer (&self->version_id, g_free);
+  self->populated = FALSE;
+}
diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c
index dd5f7060f0231c22299fdf6c281810e9fe8d3cc2..7aef99565fccd8647e4ecbe0c332e24abf00a08f 100644
--- a/steam-runtime-tools/system-info.c
+++ b/steam-runtime-tools/system-info.c
@@ -32,6 +32,7 @@
 #include "steam-runtime-tools/graphics-internal.h"
 #include "steam-runtime-tools/library-internal.h"
 #include "steam-runtime-tools/locale-internal.h"
+#include "steam-runtime-tools/os-internal.h"
 #include "steam-runtime-tools/runtime-internal.h"
 #include "steam-runtime-tools/steam-internal.h"
 #include "steam-runtime-tools/utils-internal.h"
@@ -123,6 +124,7 @@ struct _SrtSystemInfo
     gboolean have_egl;
     gboolean have_vulkan;
   } icds;
+  SrtOsRelease os_release;
   SrtTestFlags test_flags;
   Tristate can_write_uinput;
   /* (element-type Abi) */
@@ -248,6 +250,8 @@ srt_system_info_init (SrtSystemInfo *self)
 
   /* Assume that in practice we will usually add two ABIs: amd64 and i386 */
   self->abis = g_ptr_array_new_full (2, abi_free);
+
+  _srt_os_release_init (&self->os_release);
 }
 
 static void
@@ -313,6 +317,16 @@ forget_runtime (SrtSystemInfo *self)
   self->runtime.issues = SRT_RUNTIME_ISSUES_NONE;
 }
 
+/*
+ * Forget any cached information about the OS.
+ */
+static void
+forget_os (SrtSystemInfo *self)
+{
+  _srt_os_release_clear (&self->os_release);
+  forget_runtime (self);
+}
+
 /*
  * Forget any cached information about the Steam installation.
  */
@@ -347,6 +361,7 @@ srt_system_info_finalize (GObject *object)
 
   forget_icds (self);
   forget_locales (self);
+  forget_os (self);
   forget_runtime (self);
   forget_steam (self);
 
@@ -1028,6 +1043,7 @@ srt_system_info_set_environ (SrtSystemInfo *self,
   forget_libraries (self);
   forget_graphics_results (self);
   forget_locales (self);
+  forget_os (self);
   g_strfreev (self->env);
   self->env = g_strdupv ((gchar **) env);
 
@@ -1150,6 +1166,274 @@ srt_system_info_dup_steam_data_path (SrtSystemInfo *self)
   return g_strdup (self->steam.data_path);
 }
 
+static void
+ensure_os_cached (SrtSystemInfo *self)
+{
+  if (!self->os_release.populated)
+    _srt_os_release_populate (&self->os_release, self->env);
+}
+
+/**
+ * srt_system_info_dup_os_build_id:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a machine-readable identifier for the system image used as the
+ * origin for a distribution, for example `0.20190925.0`. If called
+ * from inside a Steam Runtime container, return the Steam Runtime build
+ * ID, which currently looks like `0.20190925.0`.
+ *
+ * In operating systems that do not use image-based installation, such
+ * as Debian, this will be %NULL.
+ *
+ * This is the `BUILD_ID` from os-release(5).
+ *
+ * Returns: (transfer full) (type utf8): The build ID, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_build_id (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.build_id);
+}
+
+/**
+ * srt_system_info_dup_os_id:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a lower-case machine-readable operating system identifier,
+ * for example `debian` or `arch`. If called from inside a Steam Runtime
+ * container, return `steamrt`.
+ *
+ * This is the `ID` in os-release(5). If os-release(5) is not available,
+ * future versions of this library might derive a similar ID from
+ * lsb_release(1).
+ *
+ * Returns: (transfer full) (type utf8): The OS ID, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_id (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.id);
+}
+
+static const char WHITESPACE[] = " \t\n\r";
+
+/**
+ * srt_system_info_dup_os_id_like:
+ * @self: The #SrtSystemInfo object
+ * @include_self: If %TRUE, include srt_system_info_dup_os_id() in the
+ *  returned array (if known)
+ *
+ * Return an array of lower-case machine-readable operating system
+ * identifiers similar to srt_system_info_dup_os_id() describing OSs
+ * that this one resembles or is derived from.
+ *
+ * For example, the Steam Runtime 1 'scout' is derived from Ubuntu,
+ * which is itself derived from Debian, so srt_system_info_dup_os_id_like()
+ * would return `{ "debian", "ubuntu", NULL }` if @include_self is false,
+ * `{ "steamrt", "debian", "ubuntu", NULL }` otherwise.
+ *
+ * This is the `ID_LIKE` field from os-release(5), possibly combined
+ * with the `ID` field.
+ *
+ * Returns: (array zero-terminated=1) (transfer full) (element-type utf8) (nullable): An
+ *  array of OS IDs, or %NULL if nothing is known.
+ *  Free with g_strfreev().
+ */
+gchar **
+srt_system_info_dup_os_id_like (SrtSystemInfo *self,
+                                gboolean include_self)
+{
+  GPtrArray *builder;
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+
+  builder = g_ptr_array_new_with_free_func (g_free);
+
+  if (self->os_release.id != NULL && include_self)
+    g_ptr_array_add (builder, g_strdup (self->os_release.id));
+
+  if (self->os_release.id_like != NULL)
+    {
+      GStrv split;
+      gsize i;
+
+      split = g_strsplit_set (self->os_release.id_like, WHITESPACE, -1);
+
+      for (i = 0; split != NULL && split[i] != NULL; i++)
+        g_ptr_array_add (builder, g_steal_pointer (&split[i]));
+
+      /* We already transferred ownership of the contents */
+      g_free (split);
+    }
+
+  if (builder->len > 0)
+    {
+      g_ptr_array_add (builder, NULL);
+      return (gchar **) g_ptr_array_free (builder, FALSE);
+    }
+  else
+    {
+      g_ptr_array_free (builder, TRUE);
+      return NULL;
+    }
+}
+
+/**
+ * srt_system_info_dup_os_name:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a human-readable identifier for the operating system without
+ * its version, for example `Debian GNU/Linux` or `Arch Linux`.
+ *
+ * This is the `NAME` in os-release(5). If os-release(5) is not
+ * available, future versions of this library might derive a similar
+ * name from lsb_release(1).
+ *
+ * Returns: (transfer full) (type utf8): The name, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_name (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.name);
+}
+
+/**
+ * srt_system_info_dup_os_pretty_name:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a human-readable identifier for the operating system,
+ * including its version if any, for example `Debian GNU/Linux 10 (buster)`
+ * or `Arch Linux`.
+ *
+ * If the OS uses rolling releases, this will probably be the same as
+ * or similar to srt_system_info_dup_os_name().
+ *
+ * This is the `PRETTY_NAME` in os-release(5). If os-release(5) is not
+ * available, future versions of this library might derive a similar
+ * name from lsb_release(1).
+ *
+ * Returns: (transfer full) (type utf8): The name, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_pretty_name (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.pretty_name);
+}
+
+/**
+ * srt_system_info_dup_os_variant:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a human-readable identifier for the operating system variant,
+ * for example `Workstation Edition`, `Server Edition` or
+ * `Raspberry Pi Edition`. In operating systems that do not have
+ * formal variants this will usually be %NULL.
+ *
+ * This is the `VARIANT` in os-release(5).
+ *
+ * Returns: (transfer full) (type utf8): The name, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_variant (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.variant);
+}
+
+/**
+ * srt_system_info_dup_os_variant_id:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a lower-case machine-readable identifier for the operating system
+ * variant in a form suitable for use in filenames, for example
+ * `workstation`, `server` or `rpi`. In operating systems that do not
+ * have formal variants this will usually be %NULL.
+ *
+ * This is the `VARIANT_ID` in os-release(5).
+ *
+ * Returns: (transfer full) (type utf8): The variant ID, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_variant_id (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.variant_id);
+}
+
+/**
+ * srt_system_info_dup_os_version_codename:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a lower-case machine-readable identifier for the operating
+ * system version codename, for example `buster` for Debian 10 "buster".
+ * In operating systems that do not use codenames in machine-readable
+ * contexts, this will usually be %NULL.
+ *
+ * This is the `VERSION_CODENAME` in os-release(5). If os-release(5) is not
+ * available, future versions of this library might derive a similar
+ * codename from lsb_release(1).
+ *
+ * Returns: (transfer full) (type utf8): The codename, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_version_codename (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.version_codename);
+}
+
+/**
+ * srt_system_info_dup_os_version_id:
+ * @self: The #SrtSystemInfo object
+ *
+ * Return a machine-readable identifier for the operating system version,
+ * for example `10` for Debian 10 "buster". In operating systems that
+ * only have rolling releases, such as Arch Linux, or in OS branches
+ * that behave like rolling releases, such as Debian unstable, this
+ * will usually be %NULL.
+ *
+ * This is the `VERSION_ID` in os-release(5). If os-release(5) is not
+ * available, future versions of this library might derive a similar
+ * identifier from lsb_release(1).
+ *
+ * Returns: (transfer full) (type utf8): The ID, or %NULL if not known.
+ *  Free with g_free().
+ */
+gchar *
+srt_system_info_dup_os_version_id (SrtSystemInfo *self)
+{
+  g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL);
+
+  ensure_os_cached (self);
+  return g_strdup (self->os_release.version_id);
+}
+
 /**
  * srt_system_info_set_expected_runtime_version:
  * @self: The #SrtSystemInfo object
@@ -1193,23 +1477,54 @@ srt_system_info_dup_expected_runtime_version (SrtSystemInfo *self)
 static void
 ensure_runtime_cached (SrtSystemInfo *self)
 {
+  ensure_os_cached (self);
   ensure_steam_cached (self);
 
   if (self->runtime.issues == SRT_RUNTIME_ISSUES_NONE &&
       self->runtime.path == NULL)
-    self->runtime.issues = _srt_runtime_check (self->steam.bin32,
-                                               self->runtime.expected_version,
-                                               self->env,
-                                               &self->runtime.version,
-                                               &self->runtime.path);
+    {
+      if (g_strcmp0 (self->os_release.id, "steamrt") == 0)
+        {
+          self->runtime.path = g_strdup ("/");
+          self->runtime.version = g_strdup (self->os_release.build_id);
+
+          if (self->runtime.expected_version != NULL
+              && g_strcmp0 (self->runtime.expected_version, self->runtime.version) != 0)
+            {
+              self->runtime.issues |= SRT_RUNTIME_ISSUES_UNEXPECTED_VERSION;
+            }
+
+          if (self->runtime.version == NULL)
+            {
+              self->runtime.issues |= SRT_RUNTIME_ISSUES_NOT_RUNTIME;
+            }
+          else
+            {
+              const char *p;
+
+              for (p = self->runtime.version; *p != '\0'; p++)
+                {
+                  if (!g_ascii_isdigit (*p) && *p != '.')
+                    self->runtime.issues |= SRT_RUNTIME_ISSUES_UNOFFICIAL;
+                }
+            }
+        }
+      else
+        {
+          self->runtime.issues = _srt_runtime_check (self->steam.bin32,
+                                                     self->runtime.expected_version,
+                                                     self->env,
+                                                     &self->runtime.version,
+                                                     &self->runtime.path);
+        }
+    }
 }
 
 /**
  * srt_system_info_get_runtime_issues:
  * @self: The #SrtSystemInfo object
  *
- * Detect and return any problems encountered with the
- * `LD_LIBRARY_PATH`-based Steam Runtime.
+ * Detect and return any problems encountered with the Steam Runtime.
  *
  * Returns: Any problems detected with the Steam Runtime,
  *  or %SRT_RUNTIME_ISSUES_NONE if no problems were detected
@@ -1228,9 +1543,13 @@ srt_system_info_get_runtime_issues (SrtSystemInfo *self)
  * srt_system_info_dup_runtime_path:
  * @self: The #SrtSystemInfo object
  *
- * Return the absolute path to the `LD_LIBRARY_PATH`-based Steam Runtime
- * in use (the directory containing `run.sh`, `version.txt` and
- * similar files).
+ * Return the absolute path to the Steam Runtime in use.
+ *
+ * For the `LD_LIBRARY_PATH`-based Steam Runtime, this is the directory
+ * containing `run.sh`, `version.txt` and similar files.
+ *
+ * If running in a Steam Runtime container or chroot, this function
+ * returns `/` to indicate that the entire container is the Steam Runtime.
  *
  * This will typically be below
  * srt_system_info_dup_steam_installation_path(), unless overridden.
@@ -1256,9 +1575,10 @@ srt_system_info_dup_runtime_path (SrtSystemInfo *self)
  * srt_system_info_dup_runtime_version:
  * @self: The #SrtSystemInfo object
  *
- * Return the version number of the `LD_LIBRARY_PATH`-based Steam Runtime
+ * Return the version number of the Steam Runtime
  * in use, for example `0.20190711.3`, or %NULL if it could not be
- * determined.
+ * determined. This could either be the `LD_LIBRARY_PATH`-based Steam
+ * Runtime, or a Steam Runtime container or chroot.
  *
  * If the Steam Runtime has been disabled or could not be found, or its
  * version number could not be read, then at least one flag will be set
diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h
index b6f9e7d735422d325d8aac5a089cd654f9033b6c..4aabb3b7332dc2aeeac270d1c52f385ec2852cdf 100644
--- a/steam-runtime-tools/system-info.h
+++ b/steam-runtime-tools/system-info.h
@@ -118,6 +118,17 @@ SrtLocale *srt_system_info_check_locale (SrtSystemInfo *self,
                                          const char *requested_name,
                                          GError **error);
 
+gchar *srt_system_info_dup_os_build_id (SrtSystemInfo *self);
+gchar *srt_system_info_dup_os_id (SrtSystemInfo *self);
+gchar **srt_system_info_dup_os_id_like (SrtSystemInfo *self,
+                                        gboolean include_self);
+gchar *srt_system_info_dup_os_name (SrtSystemInfo *self);
+gchar *srt_system_info_dup_os_pretty_name (SrtSystemInfo *self);
+gchar *srt_system_info_dup_os_variant (SrtSystemInfo *self);
+gchar *srt_system_info_dup_os_variant_id (SrtSystemInfo *self);
+gchar *srt_system_info_dup_os_version_codename (SrtSystemInfo *self);
+gchar *srt_system_info_dup_os_version_id (SrtSystemInfo *self);
+
 #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtSystemInfo, g_object_unref)
 #endif
diff --git a/tests/fake-home.c b/tests/fake-home.c
index 80ef0811bf2ff19e206d94eac3f152cc66c01abb..e5887212989de5757bd4a149e0fde579ad9f17fc 100644
--- a/tests/fake-home.c
+++ b/tests/fake-home.c
@@ -236,6 +236,9 @@ fake_home_create_structure (FakeHome *f)
   f->env = g_get_environ ();
   f->env = g_environ_setenv (f->env, "HOME", f->home, TRUE);
   f->env = g_environ_setenv (f->env, "XDG_DATA_HOME", local_share, TRUE);
+  /* Make sure we don't find /etc/os-release or /usr/lib/os-release
+   * if we happen to be in a Steam Runtime container */
+  f->env = g_environ_setenv (f->env, "SRT_TEST_SYSROOT", f->home, TRUE);
 
   if (f->add_environments)
     {
diff --git a/tests/graphics.c b/tests/graphics.c
index 7199c5369049cb00ef4b8bd86a2a1a7c59c60c2d..f94020b9cf00e3e7943047dddc99164b1737fc4c 100644
--- a/tests/graphics.c
+++ b/tests/graphics.c
@@ -84,7 +84,7 @@ setup (Fixture *f,
     {
       tmp = g_build_filename (f->srcdir, "fake-icds", NULL);
       f->fake_icds_envp = g_environ_setenv (f->fake_icds_envp,
-                                            "SRT_TEST_ICD_SYSROOT", tmp, TRUE);
+                                            "SRT_TEST_SYSROOT", tmp, TRUE);
       g_free (tmp);
     }
 
diff --git a/tests/meson.build b/tests/meson.build
index f52bd91f45d3c6609b34a24951e5f820c1b0a67f..110f8687cf620085049bd65d7c0b1498fb27b5b3 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -60,6 +60,7 @@ install_subdir('expectations_with_missings', install_dir : tests_dir)
 # Vulkan *.json files. (The order of EGL *.json files is well-defined.)
 install_subdir('fake-icds', install_dir : tests_dir)
 install_subdir('fake-steam-runtime', install_dir : tests_dir)
+install_subdir('sysroots', install_dir : tests_dir)
 
 executable(
   'mock-true',
diff --git a/tests/sysroots/debian-unstable/etc/os-release b/tests/sysroots/debian-unstable/etc/os-release
new file mode 100644
index 0000000000000000000000000000000000000000..55f123897e199d8115372e4ff3bb6fb3b5643221
--- /dev/null
+++ b/tests/sysroots/debian-unstable/etc/os-release
@@ -0,0 +1,6 @@
+PRETTY_NAME="Debian GNU/Linux bullseye/sid"
+NAME="Debian GNU/Linux"
+ID=debian
+HOME_URL="https://www.debian.org/"
+SUPPORT_URL="https://www.debian.org/support"
+BUG_REPORT_URL="https://bugs.debian.org/"
diff --git a/tests/sysroots/debian10/usr/lib/os-release b/tests/sysroots/debian10/usr/lib/os-release
new file mode 100644
index 0000000000000000000000000000000000000000..9b5419df8bfb3ee0266ea3f6b46b6d349c06ce97
--- /dev/null
+++ b/tests/sysroots/debian10/usr/lib/os-release
@@ -0,0 +1,9 @@
+PRETTY_NAME="Debian GNU/Linux 10 (buster)"
+NAME="Debian GNU/Linux"
+VERSION_ID="10"
+VERSION="10 (buster)"
+VERSION_CODENAME=buster
+ID=debian
+HOME_URL="https://www.debian.org/"
+SUPPORT_URL="https://www.debian.org/support"
+BUG_REPORT_URL="https://bugs.debian.org/"
diff --git a/tests/sysroots/invalid-os-release/usr/lib/os-release b/tests/sysroots/invalid-os-release/usr/lib/os-release
new file mode 100644
index 0000000000000000000000000000000000000000..c951a991f894bd325018b2ece0b997fffdb715df
--- /dev/null
+++ b/tests/sysroots/invalid-os-release/usr/lib/os-release
@@ -0,0 +1,6 @@
+ID=steamrt
+PRETTY_NAME="The first name"
+VERSION_CODENAME
+VERSION_ID="foo
+PRETTY_NAME="The second name"
+NAME="This file does not end with a newline"
\ No newline at end of file
diff --git a/tests/sysroots/no-os-release/.gitignore b/tests/sysroots/no-os-release/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tests/sysroots/steamrt-unofficial/etc/os-release b/tests/sysroots/steamrt-unofficial/etc/os-release
new file mode 120000
index 0000000000000000000000000000000000000000..c4c75b419cfd1a831f48769e8b4ac8680f728654
--- /dev/null
+++ b/tests/sysroots/steamrt-unofficial/etc/os-release
@@ -0,0 +1 @@
+../usr/lib/os-release
\ No newline at end of file
diff --git a/tests/sysroots/steamrt-unofficial/usr/lib/os-release b/tests/sysroots/steamrt-unofficial/usr/lib/os-release
new file mode 100644
index 0000000000000000000000000000000000000000..75e8b300d70fcd5b4a6b8a8906b0cd3fff79c783
--- /dev/null
+++ b/tests/sysroots/steamrt-unofficial/usr/lib/os-release
@@ -0,0 +1,9 @@
+NAME="Steam Runtime"
+VERSION="1 (scout)"
+ID=steamrt
+ID_LIKE=ubuntu
+PRETTY_NAME="Steam Runtime 1 (scout)"
+VERSION_ID="1"
+BUILD_ID="unofficial-0.20190924.0"
+VARIANT=Platform
+VARIANT_ID="com.valvesoftware.steamruntime.platform-amd64_i386-scout"
diff --git a/tests/sysroots/steamrt/etc/os-release b/tests/sysroots/steamrt/etc/os-release
new file mode 120000
index 0000000000000000000000000000000000000000..c4c75b419cfd1a831f48769e8b4ac8680f728654
--- /dev/null
+++ b/tests/sysroots/steamrt/etc/os-release
@@ -0,0 +1 @@
+../usr/lib/os-release
\ No newline at end of file
diff --git a/tests/sysroots/steamrt/usr/lib/os-release b/tests/sysroots/steamrt/usr/lib/os-release
new file mode 100644
index 0000000000000000000000000000000000000000..064dec3e50ce858cccfac132e4b198ed87ef1bd4
--- /dev/null
+++ b/tests/sysroots/steamrt/usr/lib/os-release
@@ -0,0 +1,9 @@
+NAME="Steam Runtime"
+VERSION="1 (scout)"
+ID=steamrt
+ID_LIKE=ubuntu
+PRETTY_NAME="Steam Runtime 1 (scout)"
+VERSION_ID="1"
+BUILD_ID="0.20190924.0"
+VARIANT=Platform
+VARIANT_ID="com.valvesoftware.steamruntime.platform-amd64_i386-scout"
diff --git a/tests/system-info.c b/tests/system-info.c
index 34d842c91a8feb528e6a760662e9b2156223ce96..e74622c5e9a5db29f1c3899190ee420fb3785092 100644
--- a/tests/system-info.c
+++ b/tests/system-info.c
@@ -1225,6 +1225,445 @@ testing_beta_client (Fixture *f,
   g_free (data_path);
 }
 
+static void
+os_debian10 (Fixture *f,
+             gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar **envp;
+  gchar **strv;
+  gchar *sysroot;
+  gchar *s;
+
+  sysroot = g_build_filename (f->srcdir, "sysroots", "debian10", NULL);
+  envp = g_get_environ ();
+  envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE);
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, envp);
+
+  s = srt_system_info_dup_os_build_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_id (info);
+  g_assert_cmpstr (s, ==, "debian");
+  g_free (s);
+
+  strv = srt_system_info_dup_os_id_like (info, FALSE);
+  g_assert_null (strv);
+  g_strfreev (strv);
+
+  strv = srt_system_info_dup_os_id_like (info, TRUE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "debian");
+  g_assert_cmpstr (strv[1], ==, NULL);
+  g_strfreev (strv);
+
+  s = srt_system_info_dup_os_name (info);
+  g_assert_cmpstr (s, ==, "Debian GNU/Linux");
+  g_free (s);
+
+  s = srt_system_info_dup_os_pretty_name (info);
+  g_assert_cmpstr (s, ==, "Debian GNU/Linux 10 (buster)");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_codename (info);
+  g_assert_cmpstr (s, ==, "buster");
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_id (info);
+  g_assert_cmpstr (s, ==, "10");
+  g_free (s);
+
+  g_object_unref (info);
+  g_free (sysroot);
+  g_strfreev (envp);
+}
+
+static void
+os_debian_unstable (Fixture *f,
+                    gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar **envp;
+  gchar **strv;
+  gchar *sysroot;
+  gchar *s;
+
+  sysroot = g_build_filename (f->srcdir, "sysroots", "debian-unstable", NULL);
+  envp = g_get_environ ();
+  envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE);
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, envp);
+
+  s = srt_system_info_dup_os_build_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_id (info);
+  g_assert_cmpstr (s, ==, "debian");
+  g_free (s);
+
+  strv = srt_system_info_dup_os_id_like (info, FALSE);
+  g_assert_null (strv);
+  g_strfreev (strv);
+
+  strv = srt_system_info_dup_os_id_like (info, TRUE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "debian");
+  g_assert_cmpstr (strv[1], ==, NULL);
+  g_strfreev (strv);
+
+  s = srt_system_info_dup_os_name (info);
+  g_assert_cmpstr (s, ==, "Debian GNU/Linux");
+  g_free (s);
+
+  s = srt_system_info_dup_os_pretty_name (info);
+  g_assert_cmpstr (s, ==, "Debian GNU/Linux bullseye/sid");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_codename (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  g_object_unref (info);
+  g_free (sysroot);
+  g_strfreev (envp);
+}
+
+static void
+os_steamrt (Fixture *f,
+            gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar **envp;
+  gchar **strv;
+  gchar *sysroot;
+  gchar *s;
+  SrtRuntimeIssues runtime_issues;
+
+  sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt", NULL);
+  envp = g_get_environ ();
+  envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE);
+  envp = g_environ_unsetenv (envp, "STEAM_RUNTIME");
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, envp);
+
+  s = srt_system_info_dup_os_build_id (info);
+  g_assert_cmpstr (s, ==, "0.20190924.0");
+  g_free (s);
+
+  s = srt_system_info_dup_os_id (info);
+  g_assert_cmpstr (s, ==, "steamrt");
+  g_free (s);
+
+  strv = srt_system_info_dup_os_id_like (info, FALSE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "ubuntu");
+  g_assert_cmpstr (strv[1], ==, "debian");
+  g_assert_cmpstr (strv[2], ==, NULL);
+  g_strfreev (strv);
+
+  strv = srt_system_info_dup_os_id_like (info, TRUE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "steamrt");
+  g_assert_cmpstr (strv[1], ==, "ubuntu");
+  g_assert_cmpstr (strv[2], ==, "debian");
+  g_assert_cmpstr (strv[3], ==, NULL);
+  g_strfreev (strv);
+
+  s = srt_system_info_dup_os_name (info);
+  g_assert_cmpstr (s, ==, "Steam Runtime");
+  g_free (s);
+
+  s = srt_system_info_dup_os_pretty_name (info);
+  g_assert_cmpstr (s, ==, "Steam Runtime 1 (scout)");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant (info);
+  g_assert_cmpstr (s, ==, "Platform");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant_id (info);
+  g_assert_cmpstr (s, ==, "com.valvesoftware.steamruntime.platform-amd64_i386-scout");
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_codename (info);
+  /* It isn't in os-release(5), but we infer it from the ID and VERSION_ID */
+  g_assert_cmpstr (s, ==, "scout");
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_id (info);
+  g_assert_cmpstr (s, ==, "1");
+  g_free (s);
+
+  runtime_issues = srt_system_info_get_runtime_issues (info);
+  g_assert_cmpint (runtime_issues, ==, SRT_RUNTIME_ISSUES_NONE);
+
+  s = srt_system_info_dup_runtime_path (info);
+  g_assert_cmpstr (s, ==, "/");
+  g_free (s);
+
+  s = srt_system_info_dup_runtime_version (info);
+  g_assert_cmpstr (s, ==, "0.20190924.0");
+  g_free (s);
+
+  g_object_unref (info);
+  g_free (sysroot);
+  g_strfreev (envp);
+}
+
+static void
+os_steamrt_unofficial (Fixture *f,
+                       gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar **envp;
+  gchar **strv;
+  gchar *sysroot;
+  gchar *s;
+  SrtRuntimeIssues runtime_issues;
+
+  sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt-unofficial", NULL);
+  envp = g_get_environ ();
+  envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE);
+  envp = g_environ_unsetenv (envp, "STEAM_RUNTIME");
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, envp);
+  srt_system_info_set_expected_runtime_version (info, "0.20190711.3");
+
+  s = srt_system_info_dup_os_build_id (info);
+  g_assert_cmpstr (s, ==, "unofficial-0.20190924.0");
+  g_free (s);
+
+  s = srt_system_info_dup_os_id (info);
+  g_assert_cmpstr (s, ==, "steamrt");
+  g_free (s);
+
+  strv = srt_system_info_dup_os_id_like (info, FALSE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "ubuntu");
+  g_assert_cmpstr (strv[1], ==, "debian");
+  g_assert_cmpstr (strv[2], ==, NULL);
+  g_strfreev (strv);
+
+  strv = srt_system_info_dup_os_id_like (info, TRUE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "steamrt");
+  g_assert_cmpstr (strv[1], ==, "ubuntu");
+  g_assert_cmpstr (strv[2], ==, "debian");
+  g_assert_cmpstr (strv[3], ==, NULL);
+  g_strfreev (strv);
+
+  s = srt_system_info_dup_os_name (info);
+  g_assert_cmpstr (s, ==, "Steam Runtime");
+  g_free (s);
+
+  s = srt_system_info_dup_os_pretty_name (info);
+  g_assert_cmpstr (s, ==, "Steam Runtime 1 (scout)");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant (info);
+  g_assert_cmpstr (s, ==, "Platform");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant_id (info);
+  g_assert_cmpstr (s, ==, "com.valvesoftware.steamruntime.platform-amd64_i386-scout");
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_codename (info);
+  /* It isn't in os-release(5), but we infer it from the ID and VERSION_ID */
+  g_assert_cmpstr (s, ==, "scout");
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_id (info);
+  g_assert_cmpstr (s, ==, "1");
+  g_free (s);
+
+  runtime_issues = srt_system_info_get_runtime_issues (info);
+  g_assert_cmpint (runtime_issues, ==,
+                   (SRT_RUNTIME_ISSUES_UNOFFICIAL
+                    | SRT_RUNTIME_ISSUES_UNEXPECTED_VERSION));
+
+  s = srt_system_info_dup_runtime_path (info);
+  g_assert_cmpstr (s, ==, "/");
+  g_free (s);
+
+  s = srt_system_info_dup_runtime_version (info);
+  g_assert_cmpstr (s, ==, "unofficial-0.20190924.0");
+  g_free (s);
+
+  g_object_unref (info);
+  g_free (sysroot);
+  g_strfreev (envp);
+}
+
+static void
+os_invalid_os_release (Fixture *f,
+                       gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar **envp;
+  gchar **strv;
+  gchar *sysroot;
+  gchar *s;
+  SrtRuntimeIssues runtime_issues;
+
+  sysroot = g_build_filename (f->srcdir, "sysroots", "invalid-os-release", NULL);
+  envp = g_get_environ ();
+  envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE);
+  envp = g_environ_unsetenv (envp, "STEAM_RUNTIME");
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, envp);
+  srt_system_info_set_expected_runtime_version (info, "0.20190711.3");
+
+  s = srt_system_info_dup_os_build_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_id (info);
+  g_assert_cmpstr (s, ==, "steamrt");
+  g_free (s);
+
+  strv = srt_system_info_dup_os_id_like (info, FALSE);
+  g_assert_null (strv);
+  g_strfreev (strv);
+
+  strv = srt_system_info_dup_os_id_like (info, TRUE);
+  g_assert_nonnull (strv);
+  g_assert_cmpstr (strv[0], ==, "steamrt");
+  g_assert_cmpstr (strv[1], ==, NULL);
+  g_strfreev (strv);
+
+  s = srt_system_info_dup_os_name (info);
+  g_assert_cmpstr (s, ==, "This file does not end with a newline");
+  g_free (s);
+
+  s = srt_system_info_dup_os_pretty_name (info);
+  g_assert_cmpstr (s, ==, "The second name");
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_codename (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  runtime_issues = srt_system_info_get_runtime_issues (info);
+  g_assert_cmpint (runtime_issues, ==,
+                   (SRT_RUNTIME_ISSUES_UNEXPECTED_VERSION
+                    | SRT_RUNTIME_ISSUES_NOT_RUNTIME));
+
+  s = srt_system_info_dup_runtime_path (info);
+  g_assert_cmpstr (s, ==, "/");
+  g_free (s);
+
+  s = srt_system_info_dup_runtime_version (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  g_object_unref (info);
+  g_free (sysroot);
+  g_strfreev (envp);
+}
+
+static void
+os_no_os_release (Fixture *f,
+                  gconstpointer context)
+{
+  SrtSystemInfo *info;
+  gchar **envp;
+  gchar **strv;
+  gchar *sysroot;
+  gchar *s;
+
+  sysroot = g_build_filename (f->srcdir, "sysroots", "no-os-release", NULL);
+  envp = g_get_environ ();
+  envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE);
+
+  info = srt_system_info_new (NULL);
+  srt_system_info_set_environ (info, envp);
+
+  s = srt_system_info_dup_os_build_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  strv = srt_system_info_dup_os_id_like (info, FALSE);
+  g_assert_null (strv);
+  g_strfreev (strv);
+
+  strv = srt_system_info_dup_os_id_like (info, TRUE);
+  g_assert_null (strv);
+  g_strfreev (strv);
+
+  s = srt_system_info_dup_os_name (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_pretty_name (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_variant_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_codename (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  s = srt_system_info_dup_os_version_id (info);
+  g_assert_cmpstr (s, ==, NULL);
+  g_free (s);
+
+  g_object_unref (info);
+  g_free (sysroot);
+  g_strfreev (envp);
+}
+
 int
 main (int argc,
       char **argv)
@@ -1266,5 +1705,18 @@ main (int argc,
   g_test_add ("/system-info/testing_beta_client", Fixture, NULL,
               setup, testing_beta_client, teardown);
 
+  g_test_add ("/system-info/os/debian10", Fixture, NULL,
+              setup, os_debian10, teardown);
+  g_test_add ("/system-info/os/debian-unstable", Fixture, NULL,
+              setup, os_debian_unstable, teardown);
+  g_test_add ("/system-info/os/steamrt", Fixture, NULL,
+              setup, os_steamrt, teardown);
+  g_test_add ("/system-info/os/steamrt-unofficial", Fixture, NULL,
+              setup, os_steamrt_unofficial, teardown);
+  g_test_add ("/system-info/os/invalid-os-release", Fixture, NULL,
+              setup, os_invalid_os_release, teardown);
+  g_test_add ("/system-info/os/no-os-release", Fixture, NULL,
+              setup, os_no_os_release, teardown);
+
   return g_test_run ();
 }