diff --git a/.gitignore b/.gitignore
index 78b6b31..3a3bab3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-SOURCES/bubblewrap-0.1.1.tar.gz
-SOURCES/rpm-ostree-2016.13.tar.xz
+SOURCES/bubblewrap-0.1.7.tar.xz
+SOURCES/rpm-ostree-2017.1.tar.xz
diff --git a/.rpm-ostree.metadata b/.rpm-ostree.metadata
index cfa53ca..03b2608 100644
--- a/.rpm-ostree.metadata
+++ b/.rpm-ostree.metadata
@@ -1,2 +1,2 @@
-903322415b3e8824c6d6513a25a8b3ca03083186 SOURCES/bubblewrap-0.1.1.tar.gz
-d2a5234a6b1bc97edb8d16652fffb4f78be6b652 SOURCES/rpm-ostree-2016.13.tar.xz
+a0058efeff906bc72cb5880d37b2553d8c5430d1 SOURCES/bubblewrap-0.1.7.tar.xz
+116c5e7da5bd8476fb0abb6243e42ba8da45bbb0 SOURCES/rpm-ostree-2017.1.tar.xz
diff --git a/SOURCES/0001-Revert-selector-prefer-obsoletes-Related-RhBug-10965.patch b/SOURCES/0001-Revert-selector-prefer-obsoletes-Related-RhBug-10965.patch
index 795bb72..0d95162 100644
--- a/SOURCES/0001-Revert-selector-prefer-obsoletes-Related-RhBug-10965.patch
+++ b/SOURCES/0001-Revert-selector-prefer-obsoletes-Related-RhBug-10965.patch
@@ -1,16 +1,4 @@
-From 1a32ea40288d88be40030665090bb2ae418cd0aa Mon Sep 17 00:00:00 2001
-From: Colin Walters <walters@verbum.org>
-Date: Tue, 25 Oct 2016 09:53:14 -0400
-Subject: [PATCH] Revert "selector: prefer obsoletes (Related:RhBug:1096506)"
-
-This reverts commit 94ac2e5b980f9095faa372568a8e381e8a4523bc.
----
- data/tests/hawkey/greedy.repo |  2 --
- libdnf/hy-goal.c              | 34 ++--------------------------------
- tests/hawkey/test_goal.c      | 23 -----------------------
- 3 files changed, 2 insertions(+), 57 deletions(-)
-
-diff --git a/data/tests/hawkey/greedy.repo b/data/tests/hawkey/greedy.repo
+diff --git a/libdnf/data/tests/hawkey/greedy.repo b/libdnf/data/tests/hawkey/greedy.repo
 index d450885..64bb85a 100644
 --- a/libdnf/data/tests/hawkey/greedy.repo
 +++ b/libdnf/data/tests/hawkey/greedy.repo
@@ -22,11 +10,11 @@ index d450885..64bb85a 100644
  =Pkg: C 1 0 noarch
  =Prv: somereq
 -=Pkg: somereq 1 0 noarch
-diff --git a/libdnf/hy-goal.c b/libdnf/hy-goal.c
-index b404921..c50e8f5 100644
+diff --git a/libdnf/libdnf/hy-goal.c b/libdnf/libdnf/hy-goal.c
+index dc05c1c..3ff1ce6 100644
 --- a/libdnf/libdnf/hy-goal.c
 +++ b/libdnf/libdnf/hy-goal.c
-@@ -523,36 +523,6 @@ filter_name2job(DnfSack *sack, const struct _Filter *f, Queue *job)
+@@ -550,34 +550,6 @@ filter_name2job(DnfSack *sack, const struct _Filter *f, Queue *job)
      return 0;
  }
  
@@ -39,8 +27,6 @@ index b404921..c50e8f5 100644
 -static void
 -add_preferred_provide(DnfSack *sack, Queue *job, Id id)
 -{
--    g_autoptr(GPtrArray) plist = g_ptr_array_new_with_free_func(
--        (GDestroyNotify) g_object_unref);
 -    Pool *pool = dnf_sack_get_pool(sack);
 -    const char *name = pool_dep2str(pool, id);
 -    HyQuery q = hy_query_create(sack);
@@ -49,7 +35,7 @@ index b404921..c50e8f5 100644
 -    hy_query_filter(q, HY_PKG_PROVIDES, HY_EQ, name);
 -    hy_query_filter_package_in(q, HY_PKG_OBSOLETES, HY_NEQ, pset);
 -    DnfPackage *pkg;
--    plist = hy_query_run(q);
+-    g_autoptr(GPtrArray) plist = hy_query_run(q);
 -    for (guint i = 0; i < plist->len; i++) {
 -        pkg = g_ptr_array_index(plist, i);
 -        queue_push2(job, SOLVER_DISFAVOR|SOLVER_SOLVABLE,
@@ -63,7 +49,7 @@ index b404921..c50e8f5 100644
  static int
  filter_provides2job(DnfSack *sack, const struct _Filter *f, Queue *job)
  {
-@@ -568,7 +538,7 @@ filter_provides2job(DnfSack *sack, const struct _Filter *f, Queue *job)
+@@ -593,7 +565,7 @@ filter_provides2job(DnfSack *sack, const struct _Filter *f, Queue *job)
      switch (f->cmp_type) {
      case HY_EQ:
          id = dnf_reldep_get_id (f->matches[0].reldep);
@@ -72,7 +58,7 @@ index b404921..c50e8f5 100644
          break;
      case HY_GLOB:
          dataiterator_init(&di, pool, 0, 0, SOLVABLE_PROVIDES, name, SEARCH_GLOB);
-@@ -579,7 +549,7 @@ filter_provides2job(DnfSack *sack, const struct _Filter *f, Queue *job)
+@@ -604,7 +576,7 @@ filter_provides2job(DnfSack *sack, const struct _Filter *f, Queue *job)
          assert(di.idp);
          id = *di.idp;
          if (!job_has(job, SOLVABLE_PROVIDES, id))
@@ -81,11 +67,11 @@ index b404921..c50e8f5 100644
          dataiterator_free(&di);
          break;
      default:
-diff --git a/tests/hawkey/test_goal.c b/tests/hawkey/test_goal.c
-index 6217c38..ce2c8bd 100644
+diff --git a/libdnf/tests/hawkey/test_goal.c b/libdnf/tests/hawkey/test_goal.c
+index 7c30097..2a98983 100644
 --- a/libdnf/tests/hawkey/test_goal.c
 +++ b/libdnf/tests/hawkey/test_goal.c
-@@ -230,28 +230,6 @@ START_TEST(test_goal_install_selector)
+@@ -230,27 +230,6 @@ START_TEST(test_goal_install_selector)
  }
  END_TEST
  
@@ -103,9 +89,8 @@ index 6217c38..ce2c8bd 100644
 -    assert_iueo(goal, 1, 0, 0, 0);
 -
 -    GPtrArray *plist = hy_goal_list_installs(goal, NULL);
--    char *nvra = dnf_package_get_nevra(g_ptr_array_index(plist, 0));
+-    const char *nvra = dnf_package_get_nevra(g_ptr_array_index(plist, 0));
 -    ck_assert_str_eq(nvra, "B-1-0.noarch");
--    g_free(nvra);
 -    g_ptr_array_unref(plist);
 -    hy_goal_free(goal);
 -}
@@ -114,7 +99,7 @@ index 6217c38..ce2c8bd 100644
  START_TEST(test_goal_install_selector_err)
  {
      int rc;
-@@ -1459,7 +1437,6 @@ goal_suite(void)
+@@ -1456,7 +1435,6 @@ goal_suite(void)
      tc = tcase_create("Greedy");
      tcase_add_unchecked_fixture(tc, fixture_greedy_only, teardown);
      tcase_add_test(tc, test_goal_run_all);
@@ -122,6 +107,3 @@ index 6217c38..ce2c8bd 100644
      tcase_add_test(tc, test_goal_install_weak_deps);
      suite_add_tcase(s, tc);
  
--- 
-2.7.4
-
diff --git a/SOURCES/0001-core-Do-GPG-verification-before-importing.patch b/SOURCES/0001-core-Do-GPG-verification-before-importing.patch
new file mode 100644
index 0000000..a89cee8
--- /dev/null
+++ b/SOURCES/0001-core-Do-GPG-verification-before-importing.patch
@@ -0,0 +1,153 @@
+From 74c4068b9da7f2dff16a8ee2605d3350a6a782f6 Mon Sep 17 00:00:00 2001
+From: Colin Walters <walters@verbum.org>
+Date: Thu, 2 Feb 2017 15:41:29 -0500
+Subject: [PATCH] core: Do GPG verification before importing
+
+While reading a recent conversation about GPG checking at treecompose
+time, I had a sudden thought - were we actually doing verification
+client side?  Turned out, we aren't.  That happens as part of
+`dnf_transaction_commit()` which we don't use.
+
+That function verifies every package at one go, but for us I think it's better
+to do it before "importing". We shouldn't have untrusted bits that we've
+unpacked (they might have suid binaries, for one thing).
+
+This is an embarassing problem, but it's worth emphasizing that everyone should
+be retrieving repodata at a minimum over TLS, which sets a baseline. On RHEL, we
+already do pinned TLS, and there are discussions about extending that elsewhere.
+---
+ libdnf                             |  2 +-
+ src/libpriv/rpmostree-core.c       | 12 +++++++++++-
+ tests/common/libvm.sh              | 16 ++++++++++++++++
+ tests/vmcheck/test-layering-gpg.sh | 37 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 65 insertions(+), 2 deletions(-)
+ create mode 100755 tests/vmcheck/test-layering-gpg.sh
+
+diff --git a/src/libpriv/rpmostree-core.c b/src/libpriv/rpmostree-core.c
+index 2daaa48..0b4a3ab 100644
+--- a/src/libpriv/rpmostree-core.c
++++ b/src/libpriv/rpmostree-core.c
+@@ -1152,18 +1152,25 @@ import_one_package (RpmOstreeContext *self,
+   g_autofree char *ostree_commit = NULL;
+   glnx_unref_object RpmOstreeUnpacker *unpacker = NULL;
+   g_autofree char *pkg_path;
++  DnfRepo *pkg_repo;
+   int flags = 0;
+ 
++  pkg_repo = dnf_package_get_repo (pkg);
++
+   if (pkg_is_local (pkg))
+     pkg_path = g_strdup (dnf_package_get_filename (pkg));
+   else
+     {
+       const char *pkg_location = dnf_package_get_location (pkg);
+       pkg_path =
+-        g_build_filename (dnf_repo_get_location (dnf_package_get_repo (pkg)),
++        g_build_filename (dnf_repo_get_location (pkg_repo),
+                           "packages", glnx_basename (pkg_location), NULL);
+     }
+ 
++  /* Verify signatures if enabled */
++  if (!dnf_transaction_gpgcheck_package (dnf_context_get_transaction (hifctx), pkg, error))
++    goto out;
++
+   flags = RPMOSTREE_UNPACKER_FLAGS_OSTREE_CONVENTION;
+   if (self->unprivileged)
+     flags |= RPMOSTREE_UNPACKER_FLAGS_UNPRIVILEGED;
+@@ -1220,6 +1227,9 @@ rpmostree_context_import (RpmOstreeContext *self,
+ 
+   g_return_val_if_fail (get_pkgcache_repo (self) != NULL, FALSE);
+ 
++  if (!dnf_transaction_import_keys (dnf_context_get_transaction (hifctx), error))
++    goto out;
++
+   {
+     glnx_unref_object DnfState *hifstate = dnf_state_new ();
+     dnf_state_set_number_steps (hifstate, install->packages_to_import->len);
+diff --git a/tests/common/libvm.sh b/tests/common/libvm.sh
+index 3b7cb35..bbbcba2 100644
+--- a/tests/common/libvm.sh
++++ b/tests/common/libvm.sh
+@@ -51,6 +51,11 @@ vm_cmd() {
+   $SSH "$@"
+ }
+ 
++# Delete anything which we might change between runs
++vm_clean_caches() {
++    vm_cmd rm /ostree/repo/extensions/rpmostree/pkgcache/refs/heads/* -rf
++}
++
+ # run rpm-ostree in vm
+ # - $@    args
+ vm_rpmostree() {
+@@ -68,6 +73,7 @@ vm_send() {
+ 
+ # copy the test repo to the vm
+ vm_send_test_repo() {
++  gpgcheck=${1:-0}
+   vm_cmd rm -rf /tmp/vmcheck
+   vm_send /tmp/vmcheck ${commondir}/compose/yum/repo
+ 
+@@ -77,6 +83,16 @@ name=test-repo
+ baseurl=file:///tmp/vmcheck/repo
+ EOF
+ 
++  if [ $gpgcheck -eq 1 ]; then
++      cat >> vmcheck.repo <<EOF
++gpgcheck=1
++gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-25-primary
++EOF
++  else
++      echo "Enabling vmcheck.repo without GPG"
++      echo 'gpgcheck=0' >> vmcheck.repo
++  fi
++
+   vm_send /etc/yum.repos.d vmcheck.repo
+ }
+ 
+diff --git a/tests/vmcheck/test-layering-gpg.sh b/tests/vmcheck/test-layering-gpg.sh
+new file mode 100755
+index 0000000..6b66a79
+--- /dev/null
++++ b/tests/vmcheck/test-layering-gpg.sh
+@@ -0,0 +1,37 @@
++#!/bin/bash
++#
++# Copyright (C) 2017 Red Hat, Inc.
++#
++# This library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2 of the License, or (at your option) any later version.
++#
++# This library 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
++# Lesser General Public License for more details.
++#
++# You should have received a copy of the GNU Lesser General Public
++# License along with this library; if not, write to the
++# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++# Boston, MA 02111-1307, USA.
++
++set -e
++
++. ${commondir}/libtest.sh
++. ${commondir}/libvm.sh
++
++set -x
++
++vm_send_test_repo 1
++vm_clean_caches
++
++# make sure the package is not already layered
++vm_assert_layered_pkg foo absent
++
++if vm_rpmostree pkg-add foo-1.0 2>err.txt; then
++    assert_not_reached "Installed unsigned package"
++fi
++assert_file_has_content err.txt 'package not signed: foo'
++echo "ok failed to install unsigned package"
+-- 
+2.9.3
+
diff --git a/SOURCES/0001-daemon-Avoid-erroring-out-on-startup-status-with-ori.patch b/SOURCES/0001-daemon-Avoid-erroring-out-on-startup-status-with-ori.patch
new file mode 100644
index 0000000..7eb621d
--- /dev/null
+++ b/SOURCES/0001-daemon-Avoid-erroring-out-on-startup-status-with-ori.patch
@@ -0,0 +1,109 @@
+From c48a889da09af0c2cc9d540fa5f3868d6f239e3e Mon Sep 17 00:00:00 2001
+From: Colin Walters <walters@verbum.org>
+Date: Mon, 13 Feb 2017 21:01:31 -0500
+Subject: [PATCH] daemon: Avoid erroring out on startup/status with origin
+ unconfigured-state
+
+As part of an earlier cleanup of origin parsing, we started checking
+the origin `unconfigured-state` even just starting the daemon, which
+is kind of bad.
+
+It's tempting to flip the default for the parser so that we *only* check
+unconfigured state if we go to upgrade, but let's not do that in this patch.
+
+Closes: #626
+Approved by: jlebon
+---
+ src/daemon/rpmostree-sysroot-upgrader.c  |  3 ++-
+ src/daemon/rpmostreed-deployment-utils.c |  6 ++++--
+ src/daemon/rpmostreed-os.c               |  3 ++-
+ tests/check/test-basic.sh                | 14 +++++++++++++-
+ 4 files changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/src/daemon/rpmostree-sysroot-upgrader.c b/src/daemon/rpmostree-sysroot-upgrader.c
+index edadde0..cdb90d4 100644
+--- a/src/daemon/rpmostree-sysroot-upgrader.c
++++ b/src/daemon/rpmostree-sysroot-upgrader.c
+@@ -1321,7 +1321,8 @@ clean_pkgcache_orphans (RpmOstreeSysrootUpgrader *self,
+       OstreeDeployment *deployment = deployments->pdata[i];
+       g_autoptr(RpmOstreeOrigin) origin = NULL;
+ 
+-      origin = rpmostree_origin_parse_deployment (deployment, error);
++      origin = rpmostree_origin_parse_deployment_ex (deployment, RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED,
++                                                     error);
+       if (!origin)
+         return FALSE;
+ 
+diff --git a/src/daemon/rpmostreed-deployment-utils.c b/src/daemon/rpmostreed-deployment-utils.c
+index 9b2fb9a..43c814f 100644
+--- a/src/daemon/rpmostreed-deployment-utils.c
++++ b/src/daemon/rpmostreed-deployment-utils.c
+@@ -185,7 +185,8 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
+   
+   id = rpmostreed_deployment_generate_id (deployment);
+ 
+-  origin = rpmostree_origin_parse_deployment (deployment, error);
++  origin = rpmostree_origin_parse_deployment_ex (deployment, RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED,
++                                                 error);
+   if (!origin)
+     return NULL;
+ 
+@@ -254,7 +255,8 @@ rpmostreed_commit_generate_cached_details_variant (OstreeDeployment *deployment,
+     {
+       g_autoptr(RpmOstreeOrigin) origin = NULL;
+   
+-      origin = rpmostree_origin_parse_deployment (deployment, error);
++      origin = rpmostree_origin_parse_deployment_ex (deployment, RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED,
++                                                     error);
+       if (!origin)
+         return NULL;
+       origin_refspec = g_strdup (rpmostree_origin_get_refspec (origin));
+diff --git a/src/daemon/rpmostreed-os.c b/src/daemon/rpmostreed-os.c
+index ded637d..3fde7da 100644
+--- a/src/daemon/rpmostreed-os.c
++++ b/src/daemon/rpmostreed-os.c
+@@ -1166,7 +1166,8 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error)
+       g_autoptr(RpmOstreeOrigin) origin = NULL;
+ 
+       /* Don't fail here for unknown origin types */
+-      origin = rpmostree_origin_parse_deployment (merge_deployment, NULL);
++      origin = rpmostree_origin_parse_deployment_ex (merge_deployment, RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED,
++                                                     NULL);
+       if (origin)
+         {
+           cached_update = rpmostreed_commit_generate_cached_details_variant (merge_deployment,
+diff --git a/tests/check/test-basic.sh b/tests/check/test-basic.sh
+index 8b7baa6..670a668 100755
+--- a/tests/check/test-basic.sh
++++ b/tests/check/test-basic.sh
+@@ -24,7 +24,7 @@ export RPMOSTREE_SUPPRESS_REQUIRES_ROOT_CHECK=yes
+ 
+ ensure_dbus
+ 
+-echo "1..14"
++echo "1..15"
+ 
+ setup_os_repository "archive-z2" "syslinux"
+ 
+@@ -145,6 +145,18 @@ $OSTREE remote add secureos file://$(pwd)/testos-repo
+ rpm-ostree rebase --os=testos secureos:$branch gpg-signed
+ echo "ok deploy from remote with unsigned and signed commits"
+ 
++originpath=$(ostree admin --sysroot=sysroot --print-current-dir).origin
++echo "unconfigured-state=Access to TestOS requires ONE BILLION DOLLARS" >> ${originpath}
++pid=$(pgrep -u $(id -u) -f 'rpm-ostree.*daemon')
++test -n "${pid}" || assert_not_reached "failed to find rpm-ostree pid"
++kill -9 ${pid}
++rpm-ostree status
++if rpm-ostree upgrade --os=testos 2>err.txt; then
++    assert_not_reached "Upgraded from unconfigured-state"
++fi
++assert_file_has_content err.txt 'ONE BILLION DOLLARS'
++echo "ok unconfigured status"
++
+ # Ensure it returns an error when passing a wrong option.
+ rpm-ostree --help | awk '/^$/ {in_commands=0} {if(in_commands==1){print $0}} /^Builtin Commands:/ {in_commands=1}' > commands
+ while read command; do
+-- 
+2.9.3
+
diff --git a/SOURCES/0001-unpacker-support-root-owned-var-run-files.patch b/SOURCES/0001-unpacker-support-root-owned-var-run-files.patch
new file mode 100644
index 0000000..8c7c248
--- /dev/null
+++ b/SOURCES/0001-unpacker-support-root-owned-var-run-files.patch
@@ -0,0 +1,86 @@
+From 8cf071127e670671065d041f2cb678cdc303b9c1 Mon Sep 17 00:00:00 2001
+From: Jonathan Lebon <jlebon@redhat.com>
+Date: Mon, 13 Feb 2017 11:32:19 -0500
+Subject: [PATCH 1/2] unpacker: support root-owned /var & /run files
+
+I'm not sure why we weren't doing this before, but we need to also
+support files in /var and /run that are owned by root.
+
+Related: RHBZ#1421781
+
+Closes: #622
+Approved by: cgwalters
+---
+ src/libpriv/rpmostree-unpacker.c             | 9 +++++----
+ tests/common/compose/yum/nonrootcap.spec     | 4 ++++
+ tests/vmcheck/test-layering-non-root-caps.sh | 6 +++++-
+ 3 files changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/src/libpriv/rpmostree-unpacker.c b/src/libpriv/rpmostree-unpacker.c
+index 34e133a..98586d9 100644
+--- a/src/libpriv/rpmostree-unpacker.c
++++ b/src/libpriv/rpmostree-unpacker.c
+@@ -594,11 +594,12 @@ compose_filter_cb (OstreeRepo         *repo,
+ 
+   get_rpmfi_override (self, path, &user, &group, NULL);
+ 
+-  /* First, look for non-root paths in /run and /var */
+-  if ((user != NULL || group != NULL) &&
+-      (g_str_has_prefix (path, "/run/") || g_str_has_prefix (path, "/var/")))
++  /* convert /run and /var entries to tmpfiles.d */
++  if (g_str_has_prefix (path, "/run/") ||
++      g_str_has_prefix (path, "/var/"))
+     {
+-      append_tmpfiles_d (self, path, file_info, user, group);
++      append_tmpfiles_d (self, path, file_info,
++                         user ?: "root", group ?: "root");
+       return OSTREE_REPO_COMMIT_FILTER_SKIP;
+     }
+   else if (!error_was_set)
+diff --git a/tests/common/compose/yum/nonrootcap.spec b/tests/common/compose/yum/nonrootcap.spec
+index 8f9dead..be5959d 100644
+--- a/tests/common/compose/yum/nonrootcap.spec
++++ b/tests/common/compose/yum/nonrootcap.spec
+@@ -38,6 +38,8 @@ mkdir -p %{buildroot}/usr/bin
+ install *.sh %{buildroot}/usr/bin
+ mkdir -p %{buildroot}/var/lib/nonrootcap
+ mkdir -p %{buildroot}/run/nonrootcap
++mkdir -p %{buildroot}/var/lib/nonrootcap-rootowned
++mkdir -p %{buildroot}/run/nonrootcap-rootowned
+ 
+ %clean
+ rm -rf %{buildroot}
+@@ -53,6 +55,8 @@ rm -rf %{buildroot}
+ %attr(4775, nrcuser, nrcgroup) %caps(cap_net_bind_service=ep) /usr/bin/nrc-usergroupcaps-setuid.sh
+ %attr(-, nrcuser, nrcgroup) /var/lib/nonrootcap
+ %attr(-, nrcuser, nrcgroup) /run/nonrootcap
++/var/lib/nonrootcap-rootowned
++/run/nonrootcap-rootowned
+ 
+ %changelog
+ * Wed Jan 05 2017 Jonathan Lebon <jlebon@redhat.com> 1.0-1
+diff --git a/tests/vmcheck/test-layering-non-root-caps.sh b/tests/vmcheck/test-layering-non-root-caps.sh
+index aa9991c..6cba6e2 100755
+--- a/tests/vmcheck/test-layering-non-root-caps.sh
++++ b/tests/vmcheck/test-layering-non-root-caps.sh
+@@ -51,7 +51,9 @@ if ! vm_has_files /usr/bin/nrc-none.sh \
+                   /usr/bin/nrc-usergroup.sh \
+                   /usr/bin/nrc-usergroupcaps.sh \
+                   /var/lib/nonrootcap \
+-                  /run/nonrootcap; then
++                  /run/nonrootcap \
++                  /var/lib/nonrootcap-rootowned \
++                  /run/nonrootcap-rootowned; then
+   assert_not_reached "not all files were layered"
+ fi
+ echo "ok all files layered"
+@@ -96,4 +98,6 @@ check_file /usr/bin/nrc-usergroupcaps-setuid.sh nrcuser nrcgroup "cap_net_bind_s
+ vm_cmd test -u /usr/bin/nrc-usergroupcaps-setuid.sh
+ check_file /var/lib/nonrootcap nrcuser nrcgroup
+ check_file /run/nonrootcap nrcuser nrcgroup
++check_file /var/lib/nonrootcap-rootowned root root
++check_file /run/nonrootcap-rootowned root root
+ echo "ok correct user/group and fcaps"
+-- 
+2.10.2
+
diff --git a/SOURCES/libdnf-gpg.patch b/SOURCES/libdnf-gpg.patch
new file mode 100644
index 0000000..4b9bac4
--- /dev/null
+++ b/SOURCES/libdnf-gpg.patch
@@ -0,0 +1,318 @@
+From b2ded5a4da58940159f5d337e9e29c5de5cc0f7a Mon Sep 17 00:00:00 2001
+From: Colin Walters <walters@verbum.org>
+Date: Thu, 2 Feb 2017 10:00:06 -0500
+Subject: [PATCH 1/2] repo: Enable GPG by default
+
+This increases compatibility with dnf/yum. It was very surprising to me that we
+didn't do this. Most repos do seem to use `gpgcheck=1`, but I'm fairly certain
+I've seen repo configs in the wild that actually depend on it, though after
+looking at a few (ceph, postgres), I can't find one yet.
+
+Still, I think it's worth making this change. I suspect very few people will
+edit `/etc/yum/yum.conf` to globally disable GPG checking, versus disabling it
+per repository.
+---
+ libdnf/dnf-repo.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/libdnf/dnf-repo.c b/libdnf/dnf-repo.c
+index 08e0d8b..017c82d 100644
+--- a/libdnf/libdnf/dnf-repo.c
++++ b/libdnf/libdnf/dnf-repo.c
+@@ -858,7 +858,16 @@ dnf_repo_set_keyfile_data(DnfRepo *repo, GError **error)
+     /* gpgkey is optional for gpgcheck=1, but required for repo_gpgcheck=1 */
+     g_free(priv->gpgkey);
+     priv->gpgkey = g_key_file_get_string(priv->keyfile, priv->id, "gpgkey", NULL);
+-    priv->gpgcheck_pkgs = dnf_repo_get_boolean(priv->keyfile, priv->id, "gpgcheck", NULL);
++    /* Currently, we don't have a global configuration file.  The way this worked in yum
++     * is that the yum package enabled gpgcheck=1 by default in /etc/yum.conf.  Basically,
++     * I don't think many people changed that.  It's just saner to disable it in the individual
++     * repo files as required.  To claim compatibility with yum repository files, I think
++     * we need to basically hard code the yum.conf defaults here.
++     */
++    if (!g_key_file_has_key (priv->keyfile, priv->id, "gpgcheck", NULL))
++        priv->gpgcheck_pkgs = TRUE;
++    else
++        priv->gpgcheck_pkgs = dnf_repo_get_boolean(priv->keyfile, priv->id, "gpgcheck", NULL);
+     priv->gpgcheck_md = dnf_repo_get_boolean(priv->keyfile, priv->id, "repo_gpgcheck", NULL);
+     if (priv->gpgcheck_md && priv->gpgkey == NULL) {
+         g_set_error_literal(error,
+-- 
+2.9.3
+
+
+From 0d68ebac7d39a9278ebb5259c4912efa55c080da Mon Sep 17 00:00:00 2001
+From: Colin Walters <walters@verbum.org>
+Date: Tue, 31 Jan 2017 17:14:37 -0500
+Subject: [PATCH 2/2] transaction: Export parts of the GPG functionality
+
+rpm-ostree doesn't use `dnf_transaction_commit()`, because it uses libostree to
+store the RPMs, and bubblewrap to run `%post`s. However, we do need the GPG
+functionality.
+---
+ libdnf/libdnf/dnf-transaction.c | 193 ++++++++++++++++++++++++++++-------------------
+ libdnf/libdnf/dnf-transaction.h |  11 +++
+ 2 files changed, 127 insertions(+), 77 deletions(-)
+
+diff --git a/libdnf/libdnf/dnf-transaction.c b/libdnf/libdnf/dnf-transaction.c
+index 62fcc51..dd73245 100644
+--- a/libdnf/libdnf/dnf-transaction.c
++++ b/libdnf/libdnf/dnf-transaction.c
+@@ -328,17 +328,88 @@ dnf_transaction_ensure_repo_list(DnfTransaction *transaction,
+     return TRUE;
+ }
+ 
++gboolean
++dnf_transaction_gpgcheck_package (DnfTransaction *transaction,
++                                  DnfPackage     *pkg,
++                                  GError        **error)
++{
++    DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
++    GError *error_local = NULL;
++    DnfRepo *repo;
++    const gchar *fn;
++
++    /* ensure the filename is set */
++    if (!dnf_transaction_ensure_repo(transaction, pkg, error)) {
++        g_prefix_error(error, "Failed to check untrusted: ");
++        return FALSE;
++    }
++
++    /* find the location of the local file */
++    fn = dnf_package_get_filename(pkg);
++    if (fn == NULL) {
++        g_set_error(error,
++                    DNF_ERROR,
++                    DNF_ERROR_FILE_NOT_FOUND,
++                    "Downloaded file for %s not found",
++                    dnf_package_get_name(pkg));
++        return FALSE;
++    }
++
++    /* check file */
++    if (!dnf_keyring_check_untrusted_file(priv->keyring, fn, &error_local)) {
++
++        /* probably an i/o error */
++        if (!g_error_matches(error_local,
++                             DNF_ERROR,
++                             DNF_ERROR_GPG_SIGNATURE_INVALID)) {
++            g_propagate_error(error, error_local);
++            return FALSE;
++        }
++
++        /* if the repo is signed this is ALWAYS an error */
++        repo = dnf_package_get_repo(pkg);
++        if (repo != NULL && dnf_repo_get_gpgcheck(repo)) {
++            g_set_error(error,
++                        DNF_ERROR,
++                        DNF_ERROR_FILE_INVALID,
++                        "package %s cannot be verified "
++                        "and repo %s is GPG enabled: %s",
++                        dnf_package_get_nevra(pkg),
++                        dnf_repo_get_id(repo),
++                        error_local->message);
++            g_error_free(error_local);
++            return FALSE;
++        }
++
++        /* we can only install signed packages in this mode */
++        if ((priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) > 0) {
++            g_propagate_error(error, error_local);
++            return FALSE;
++        }
++
++        /* we can install unsigned packages */
++        g_warning("ignoring as allow-untrusted: %s",
++                error_local->message);
++        g_clear_error(&error_local);
++    }
++
++    return TRUE;
++}
++
+ /**
+  * dnf_transaction_check_untrusted:
++ * @transaction: Transaction
++ * @goal: Target goal
++ * @error: Error
++ *
++ * Verify GPG signatures for all pending packages to be changed as part
++ * of @goal.
+  */
+-static gboolean
++gboolean
+ dnf_transaction_check_untrusted(DnfTransaction *transaction,
+                                 HyGoal goal,
+                                 GError **error)
+ {
+-    DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
+-    DnfPackage *pkg;
+-    const gchar *fn;
+     guint i;
+     g_autoptr(GPtrArray) install = NULL;
+ 
+@@ -354,64 +425,10 @@ dnf_transaction_check_untrusted(DnfTransaction *transaction,
+ 
+     /* find any packages in untrusted repos */
+     for (i = 0; i < install->len; i++) {
+-        GError *error_local = NULL;
+-        DnfRepo *repo;
+-        pkg = g_ptr_array_index(install, i);
++        DnfPackage *pkg = g_ptr_array_index(install, i);
+ 
+-        /* ensure the filename is set */
+-        if (!dnf_transaction_ensure_repo(transaction, pkg, error)) {
+-            g_prefix_error(error, "Failed to check untrusted: ");
++        if (!dnf_transaction_gpgcheck_package (transaction, pkg, error))
+             return FALSE;
+-        }
+-
+-        /* find the location of the local file */
+-        fn = dnf_package_get_filename(pkg);
+-        if (fn == NULL) {
+-            g_set_error(error,
+-                        DNF_ERROR,
+-                        DNF_ERROR_FILE_NOT_FOUND,
+-                        "Downloaded file for %s not found",
+-                        dnf_package_get_name(pkg));
+-            return FALSE;
+-        }
+-
+-        /* check file */
+-        if (!dnf_keyring_check_untrusted_file(priv->keyring, fn, &error_local)) {
+-
+-            /* probably an i/o error */
+-            if (!g_error_matches(error_local,
+-                                 DNF_ERROR,
+-                                 DNF_ERROR_GPG_SIGNATURE_INVALID)) {
+-                g_propagate_error(error, error_local);
+-                return FALSE;
+-            }
+-
+-            /* if the repo is signed this is ALWAYS an error */
+-            repo = dnf_package_get_repo(pkg);
+-            if (repo != NULL && dnf_repo_get_gpgcheck(repo)) {
+-                g_set_error(error,
+-                            DNF_ERROR,
+-                            DNF_ERROR_FILE_INVALID,
+-                            "package %s cannot be verified "
+-                            "and repo %s is GPG enabled: %s",
+-                            dnf_package_get_nevra(pkg),
+-                            dnf_repo_get_id(repo),
+-                            error_local->message);
+-                g_error_free(error_local);
+-                return FALSE;
+-            }
+-
+-            /* we can only install signed packages in this mode */
+-            if ((priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) > 0) {
+-                g_propagate_error(error, error_local);
+-                return FALSE;
+-            }
+-
+-            /* we can install unsigned packages */
+-            g_debug("ignoring as allow-untrusted: %s",
+-                 error_local->message);
+-            g_clear_error(&error_local);
+-        }
+     }
+     return TRUE;
+ }
+@@ -1167,6 +1184,44 @@ dnf_transaction_reset(DnfTransaction *transaction)
+ }
+ 
+ /**
++ * dnf_transaction_import_keys:
++ * @transaction: a #DnfTransaction instance.
++ * @error: A #GError or %NULL
++ *
++ * Imports all keys from /etc/pki/rpm-gpg as well as any
++ * downloaded per-repo keys.  Note this is called automatically
++ * by dnf_transaction_commit().
++ **/
++gboolean
++dnf_transaction_import_keys(DnfTransaction *transaction,
++                            GError **error)
++{
++    guint i;
++
++    DnfTransactionPrivate *priv = GET_PRIVATE(transaction);
++    /* import all system wide GPG keys */
++    if (!dnf_keyring_add_public_keys(priv->keyring, error))
++        return FALSE;
++
++    /* import downloaded repo GPG keys */
++    for (i = 0; i < priv->repos->len; i++) {
++        DnfRepo *repo = g_ptr_array_index(priv->repos, i);
++        const gchar *pubkey;
++
++        /* does this file actually exist */
++        pubkey = dnf_repo_get_public_key(repo);
++        if (g_file_test(pubkey, G_FILE_TEST_EXISTS)) {
++            /* import */
++            if (!dnf_keyring_add_public_key(priv->keyring, pubkey, error))
++                return FALSE;
++        }
++    }
++
++    return TRUE;
++}
++
++
++/**
+  * dnf_transaction_commit:
+  * @transaction: a #DnfTransaction instance.
+  * @goal: A #HyGoal
+@@ -1237,26 +1292,10 @@ dnf_transaction_commit(DnfTransaction *transaction,
+     if (!ret)
+         goto out;
+ 
+-    /* import all system wide GPG keys */
+-    ret = dnf_keyring_add_public_keys(priv->keyring, error);
++    ret = dnf_transaction_import_keys(transaction, error);
+     if (!ret)
+         goto out;
+ 
+-    /* import downloaded repo GPG keys */
+-    for (i = 0; i < priv->repos->len; i++) {
+-        DnfRepo *repo = g_ptr_array_index(priv->repos, i);
+-        const gchar *pubkey;
+-
+-        /* does this file actually exist */
+-        pubkey = dnf_repo_get_public_key(repo);
+-        if (g_file_test(pubkey, G_FILE_TEST_EXISTS)) {
+-            /* import */
+-            ret = dnf_keyring_add_public_key(priv->keyring, pubkey, error);
+-            if (!ret)
+-                goto out;
+-        }
+-    }
+-
+     /* find any packages without valid GPG signatures */
+     ret = dnf_transaction_check_untrusted(transaction, goal, error);
+     if (!ret)
+diff --git a/libdnf/libdnf/dnf-transaction.h b/libdnf/libdnf/dnf-transaction.h
+index 6131374..84d1365 100644
+--- a/libdnf/libdnf/dnf-transaction.h
++++ b/libdnf/libdnf/dnf-transaction.h
+@@ -95,6 +95,17 @@ gboolean         dnf_transaction_depsolve               (DnfTransaction *transac
+ gboolean         dnf_transaction_download               (DnfTransaction *transaction,
+                                                          DnfState       *state,
+                                                          GError         **error);
++
++gboolean         dnf_transaction_import_keys            (DnfTransaction *transaction,
++                                                         GError **error);
++
++gboolean         dnf_transaction_gpgcheck_package        (DnfTransaction *transaction,
++                                                          DnfPackage     *pkg,
++                                                          GError        **error);
++gboolean         dnf_transaction_check_untrusted        (DnfTransaction *transaction,
++                                                         HyGoal          goal,
++                                                         GError        **error);
++
+ gboolean         dnf_transaction_commit                 (DnfTransaction *transaction,
+                                                          HyGoal          goal,
+                                                          DnfState       *state,
+-- 
+2.9.3
+
diff --git a/SPECS/rpm-ostree.spec b/SPECS/rpm-ostree.spec
index d486c6c..b4c8b37 100644
--- a/SPECS/rpm-ostree.spec
+++ b/SPECS/rpm-ostree.spec
@@ -1,8 +1,8 @@
-%global bubblewrap_version 0.1.1
+%global bubblewrap_version 0.1.7
 Summary: Client side upgrade program and server side compose tool
 Name: rpm-ostree
-Version: 2016.13
-Release: 1.atomic%{?dist}
+Version: 2017.1
+Release: 5.atomic%{?dist}
 #VCS: https://github.com/cgwalters/rpm-ostree
 # This tarball is generated via "make -f Makefile.dist-packaging dist-snapshot"
 # because github doesn't support placing submodules in tarballs and RPM
@@ -10,9 +10,13 @@ Release: 1.atomic%{?dist}
 Source0: rpm-ostree-%{version}.tar.xz
 License: LGPLv2+
 URL: https://github.com/projectatomic/rpm-ostree
-Source1: bubblewrap-%{bubblewrap_version}.tar.gz
+Source1: https://github.com/projectatomic/bubblewrap/releases/download/v%{bubblewrap_version}/bubblewrap-%{bubblewrap_version}.tar.xz
 
 Patch1: 0001-Revert-selector-prefer-obsoletes-Related-RhBug-10965.patch
+Patch2: 0001-unpacker-support-root-owned-var-run-files.patch
+Patch3: 0001-daemon-Avoid-erroring-out-on-startup-status-with-ori.patch
+Patch4: libdnf-gpg.patch
+Patch5: 0001-core-Do-GPG-verification-before-importing.patch
 
 Requires: ostree-fuse
 
@@ -70,7 +74,7 @@ tar xf %{SOURCE1}
 
 %build
 (cd bubblewrap-%{bubblewrap_version} &&
- env NOCONFIGURE=1 ./autogen.sh &&
+ if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; fi &&
  %configure --disable-silent-rules
  make %{?_smp_mflags}
 )
@@ -132,6 +136,22 @@ python autofiles.py > files.devel \
 %files devel -f files.devel
 
 %changelog
+* Tue Feb 14 2017 Colin Walters <walters@verbum.org> - 2017.1-5.atomic
+- Add patch to do GPG checking before importing/installing RPMs
+- Resolves: #1422157
+
+* Tue Feb 14 2017 Colin Walters <walters@verbum.org> - 2017.1-4.atomic
+- Backport patch for unconfigured-state handling
+- Resolves: #1421867
+
+* Mon Feb 13 2017 Jonathan Lebon <jlebon@redhat.com> - 2017.1-3.atomic
+- Resolves: #1421781
+
+* Tue Jan 24 2017 Colin Walters <walters@verbum.org> - 2017.1-2.atomic
+- New upstream version
+  Resolves: #1416089
+- Bump bubblewrap to latest release too
+
 * Mon Dec 12 2016 walters@redhat.com - 2016.13-1.atomic
 - New upstream version
 - Resolves: #1403933