diff --git a/layerindex/urls.py b/layerindex/urls.py
index cee3d2a..1fcd11d 100644
--- a/layerindex/urls.py
+++ b/layerindex/urls.py
@@ -16,7 +16,7 @@ from layerindex.views import LayerListView, LayerReviewListView, LayerReviewDeta
     ClassicRecipeSearchView, ClassicRecipeDetailView, ClassicRecipeStatsView, LayerUpdateDetailView, UpdateListView, \
     UpdateDetailView, StatsView, publish_view, LayerCheckListView, BBClassCheckListView, TaskStatusView, \
     ComparisonRecipeSelectView, ComparisonRecipeSelectDetailView, task_log_view, task_stop_view, email_test_view, \
-    BranchCompareView, RecipeDependenciesView
+    BranchCompareView, RecipeDependenciesView, update_layer_view
 from layerindex.models import LayerItem, Recipe, RecipeChangeset
 from rest_framework import routers
 from . import restviews
diff --git a/layerindex/urls_branch.py b/layerindex/urls_branch.py
index 6736f32..40cd915 100644
--- a/layerindex/urls_branch.py
+++ b/layerindex/urls_branch.py
@@ -8,7 +8,7 @@
 
 from django.views.defaults import page_not_found
 from django.urls import include, re_path, reverse_lazy
-from layerindex.views import LayerListView, RecipeSearchView, MachineSearchView, DistroSearchView, ClassSearchView, LayerDetailView, edit_layer_view, delete_layer_view, edit_layernote_view, delete_layernote_view, RedirectParamsView, DuplicatesView, LayerUpdateDetailView, layer_export_recipes_csv_view, comparison_update_view
+from layerindex.views import LayerListView, RecipeSearchView, MachineSearchView, DistroSearchView, ClassSearchView, LayerDetailView, edit_layer_view, delete_layer_view, edit_layernote_view, delete_layernote_view, RedirectParamsView, DuplicatesView, LayerUpdateDetailView, layer_export_recipes_csv_view, comparison_update_view, update_layer_view
 
 urlpatterns = [
     re_path(r'^$',
@@ -41,6 +41,7 @@ urlpatterns = [
             template_name='layerindex/classes.html'),
             name='class_search'),
     re_path(r'^edit/(?P<slug>[-\w]+)/$', edit_layer_view, {'template_name': 'layerindex/editlayer.html'}, name="edit_layer"),
+    re_path(r'^update/(?P<slug>[-\w]+)/$', update_layer_view, {'template_name': 'layerindex/updatelayer.html'}, name="update_layer"),
     re_path(r'^duplicates/$',
         DuplicatesView.as_view(
             template_name='layerindex/duplicates.html'),
diff --git a/layerindex/views.py b/layerindex/views.py
index 1a29dde..25c045e 100644
--- a/layerindex/views.py
+++ b/layerindex/views.py
@@ -121,6 +121,41 @@ def delete_layer_view(request, template_name, slug):
             'cancel_url': layeritem.get_absolute_url()
         })
 
+def update_layer_view(request, template_name, branch='master', slug=None):
+    if not (request.user.is_authenticated and request.user.is_staff):
+        raise PermissionDenied
+    return_url = None
+    branchobj = Branch.objects.filter(name=branch)[:1].get()
+    if slug:
+        # Existing Layer Update
+        layeritem = get_object_or_404(LayerItem, name=slug)
+        layerbranch = get_object_or_404(LayerBranch, layer=layeritem, branch=branchobj)
+        returnto = request.GET.get('returnto', 'layer_item')
+        if returnto:
+            if returnto == 'layer_review':
+                return_url = reverse_lazy(returnto, args=(layeritem.name,))
+            else:
+                return_url = reverse_lazy(returnto, args=(branch, layeritem.name))
+    else:
+        # Pre-Publish Layer Update attempt
+        layeritem = LayerItem()
+        layerbranch = LayerBranch(layer=layeritem, branch=branchobj)
+
+    from celery import uuid
+
+    cmd = 'layerindex/update.py --layer %s --branch %s;' % (layeritem.name, branch)
+
+    task_id = uuid()
+    # Create this here first, because inside the task we don't have all of the required info
+    update = Update(task_id=task_id)
+    update.started = datetime.now()
+    update.triggered_by = request.user
+    update.save()
+
+    res = tasks.run_update_command.apply_async((branch, cmd), task_id=task_id)
+
+    return HttpResponseRedirect(reverse_lazy('task_status', kwargs={'task_id': task_id}))
+
 def edit_layer_view(request, template_name, branch='master', slug=None):
     return_url = None
     branchobj = Branch.objects.filter(name=branch)[:1].get()
diff --git a/templates/layerindex/detail.html b/templates/layerindex/detail.html
index 12ce156..0fa8caf 100644
--- a/templates/layerindex/detail.html
+++ b/templates/layerindex/detail.html
@@ -38,6 +38,9 @@
                         {% endif %}
                         {% if user.is_authenticated %}
                             <span class="pull-right">
+                                {% if user.is_staff %}
+                                    <a href="{% url 'update_layer' url_branch layeritem.name %}" class="btn btn-info">Update layer</a>
+                                {% endif %}
                                 {% if perms.layerindex.publish_layer or useredit %}
                                     <a href="{% url 'edit_layer' url_branch layeritem.name %}" class="btn btn-default">Edit layer</a>
                                     {% if layeritem.layernote_set.count == 0 %}
diff --git a/templates/layerindex/reviewdetail.html b/templates/layerindex/reviewdetail.html
index 8baab7c..39501be 100644
--- a/templates/layerindex/reviewdetail.html
+++ b/templates/layerindex/reviewdetail.html
@@ -47,6 +47,9 @@
                                     <a href="{% url 'delete_layer' layeritem.name %}" class="btn btn-warning">Delete layer</a>
                                     <a href="{% url 'publish' layeritem.name %}" class="btn btn-primary">Publish layer</a>
                                 {% endif %}
+                                {% if user.is_staff %}
+                                    <a href="{% url 'update_layer' 'master' layeritem.name %}" class="btn btn-info">Update layer</a>
+                                {% endif %}
                             </span>
                         {% endif %}
                     </h1>
diff --git a/templates/layerindex/updatelayer.html b/templates/layerindex/updatelayer.html
new file mode 100644
index 0000000..799fb51
--- /dev/null
+++ b/templates/layerindex/updatelayer.html
@@ -0,0 +1,119 @@
+{% extends "base.html" %}
+{% load i18n %}
+{% load extrafilters %}
+
+{% comment %}
+
+  layerindex-web - update page
+
+  Copyright (C) 2016, 2018 Intel Corporation
+  Licensed under the MIT license, see COPYING.MIT for details
+
+{% endcomment %}
+
+<!--
+{% block title_append %} - {{ update.started }} {% endblock %}
+-->
+
+{% block content %}
+{% autoescape on %}
+
+        <ul class="breadcrumb">
+            <li><a href="{% url 'update_list' %}">Updates</a></li>
+            <li class="active">{{ update.started }}</li>
+        </ul>
+
+
+<h2>{{ update.started }} {% if update.reload %}(reload){% endif %}
+<span id="status-label" class="label {% if update.finished %}{% if update.retcode %}label-danger{% else %}label-success{% endif %}{% endif %} pull-right">{% if update.finished %}{% if update.retcode < 0 %}TERMINATED ({{ update.retcode }}){% elif update.retcode %}FAILED{% endif %}{% endif %}</span>
+</h2>
+
+{% if update.log %}
+    <pre>{{ update.log }}</pre>
+{% endif %}
+
+{% for layerupdate in layerupdates %}
+    <table class="table table-bordered">
+        <thead>
+            {% with layerbranch_exists=layerupdate.layerbranch_exists %}
+            <tr><td{% if layerupdate.errors > 0 or layerupdate.retcode != 0 %} class="error"{% elif layerupdate.warnings %} class="warning"{% endif %}>
+            {% if layerbranch_exists %}<a href="{% url 'layer_item' layerupdate.branch.name layerupdate.layer.name %}">{% endif %}<strong>{{ layerupdate.layer.name }} {{ layerupdate.branch.name }}</strong>{% if layerbranch_exists %}</a>{% endif %}
+            {% if layerupdate.vcs_before_rev != layerupdate.vcs_after_rev %}
+            <span class="pull-right">
+                {% if layerbranch_exists %}
+                {% with before_url=layerupdate.vcs_before_commit_url after_url=layerupdate.vcs_after_commit_url %}
+                {% if before_url %}<a href="{{ before_url }}">{% endif %}{{ layerupdate.vcs_before_rev|truncatesimple:10 }}{% if before_url %}</a>{% endif %} &rarr; {% if after_url %}<a href="{{ after_url }}">{% endif %}{{ layerupdate.vcs_after_rev|truncatesimple:10 }}{% if after_url %}</a>{% endif %}
+                {% endwith %}
+                {% else %}
+                {{ layerupdate.vcs_before_rev|truncatesimple:10 }} → {{ layerupdate.vcs_after_rev|truncatesimple:10 }}
+                {% endif %}
+            </span>
+            {% endif %}
+            </td></tr>
+            {% endwith %}
+        </thead>
+        <tbody>
+            {% if layerupdate.log %}
+            <tr><td class="td-pre">
+            <pre class="pre-scrollable pre-plain">{{ layerupdate.log }}</pre>
+            </td></tr>
+            {% endif %}
+        </tbody>
+    </table>
+{% endfor %}
+
+{% if not update.log and not layerupdates %}
+    <p>No messages or layer updates</p>
+{% endif %}
+
+{% if update.comparisonrecipeupdate_set.exists %}
+<h3>Updated comparison recipes</h3>
+<ul>
+{% for recipeupdate in update.comparisonrecipeupdate_set.all %}
+    <li><a href="{% url 'comparison_recipe' recipeupdate.recipe.id %}">{{ recipeupdate.recipe.pn }}</a> {% if recipeupdate.meta_updated and recipeupdate.link_updated %}(meta, link){% elif recipeupdate.link_updated %}(link){% elif recipeupdate.meta_updated %}(meta){% endif %}</li>
+{% endfor %}
+</ul>
+{% endif %}
+
+{% endautoescape %}
+
+{% endblock %}
+{% if updates.count > 0 %}
+<div class="tab-pane" id="updates">
+    <nav class="navbar navbar-default">
+        <div class="container-fluid">
+            <div class="navbar-header">
+                <a class="navbar-brand">{{ layeritem.name }} updates</a>
+            </div>
+        </div>
+    </nav>
+
+    <table class="table table-bordered">
+        <thead>
+            <tr>
+                <th>Date/time</th>
+                <th>Errors</th>
+                <th>Warnings</th>
+            </tr>
+        </thead>
+        <tbody>
+            {% for update in updates %}
+                <tr>
+                    <td>
+                        {% if update.log %}
+                            <a href="{% url 'layerupdate' update.id %}">{{ update.started }}{% if update.update.reload %} (reload){% endif%}</a>
+                        {% else %}
+                            <span class="text-muted">{{ update.started }}{% if update.update.reload %} (reload){% endif%}</span>
+                        {% endif %}
+                    </td>
+                    <td>{% if update.errors %}<span class="badge badge-important">{{ update.errors }}</span>{% endif %}</td>
+                    <td>{% if update.warnings %}<span class="badge badge-warning">{{ update.warnings }}</span>{% endif %}</td>
+                </tr>
+            {% endfor %}
+        </tbody>
+    </table>
+</div>
+{% endif %}
+
+{% block scripts %}
+{% endblock %}
