diff --git a/src/NzbDrone.Api/Calendar/CalendarModule.cs b/src/NzbDrone.Api/Calendar/CalendarModule.cs
index 484d3a52b..79fabf7ed 100644
--- a/src/NzbDrone.Api/Calendar/CalendarModule.cs
+++ b/src/NzbDrone.Api/Calendar/CalendarModule.cs
@@ -3,19 +3,12 @@ using System.Collections.Generic;
 using System.Linq;
 using NzbDrone.Api.Episodes;
 using NzbDrone.Api.Extensions;
-using NzbDrone.Api.Mapping;
-using NzbDrone.Core.Datastore.Events;
-using NzbDrone.Core.Download;
-using NzbDrone.Core.MediaFiles.Events;
 using NzbDrone.Core.Messaging.Commands;
-using NzbDrone.Core.Messaging.Events;
 using NzbDrone.Core.Tv;
 
 namespace NzbDrone.Api.Calendar
 {
-    public class CalendarModule : NzbDroneRestModuleWithSignalR<EpisodeResource, Episode>,
-                                  IHandle<EpisodeGrabbedEvent>,                         
-                                  IHandle<EpisodeDownloadedEvent>
+    public class CalendarModule : EpisodeModuleWithSignalR
     {
         private readonly IEpisodeService _episodeService;
         private readonly SeriesRepository _seriesRepository;
@@ -23,18 +16,12 @@ namespace NzbDrone.Api.Calendar
         public CalendarModule(ICommandExecutor commandExecutor,
                               IEpisodeService episodeService,
                               SeriesRepository seriesRepository)
-            : base(commandExecutor, "calendar")
+            : base(episodeService, commandExecutor, "calendar")
         {
             _episodeService = episodeService;
             _seriesRepository = seriesRepository;
 
             GetResourceAll = GetCalendar;
-            GetResourceById = GetEpisode;
-        }
-
-        private EpisodeResource GetEpisode(int id)
-        {
-            return _episodeService.GetEpisode(id).InjectTo<EpisodeResource>();
         }
 
         private List<EpisodeResource> GetCalendar()
@@ -53,24 +40,5 @@ namespace NzbDrone.Api.Calendar
 
             return resources.OrderBy(e => e.AirDateUtc).ToList();
         }
-
-        public void Handle(EpisodeGrabbedEvent message)
-        {
-            foreach (var episode in message.Episode.Episodes)
-            {
-                var resource = episode.InjectTo<EpisodeResource>();
-                resource.Grabbed = true;
-
-                BroadcastResourceChange(ModelAction.Updated, resource);
-            }
-        }
-
-        public void Handle(EpisodeDownloadedEvent message)
-        {
-            foreach (var episode in message.Episode.Episodes)
-            {
-                BroadcastResourceChange(ModelAction.Updated, episode.Id);
-            }
-        }
     }
 }
diff --git a/src/NzbDrone.Api/Episodes/EpisodeModule.cs b/src/NzbDrone.Api/Episodes/EpisodeModule.cs
index 4e24cb78f..e698ab242 100644
--- a/src/NzbDrone.Api/Episodes/EpisodeModule.cs
+++ b/src/NzbDrone.Api/Episodes/EpisodeModule.cs
@@ -1,24 +1,16 @@
 using System.Collections.Generic;
-using NzbDrone.Api.Mapping;
 using NzbDrone.Api.REST;
-using NzbDrone.Core.Datastore.Events;
-using NzbDrone.Core.Download;
-using NzbDrone.Core.MediaFiles.Events;
 using NzbDrone.Core.Messaging.Commands;
-using NzbDrone.Core.Messaging.Events;
 using NzbDrone.Core.Tv;
 
 namespace NzbDrone.Api.Episodes
 {
-    public class EpisodeModule : NzbDroneRestModuleWithSignalR<EpisodeResource, Episode>,
-                                 IHandle<EpisodeGrabbedEvent>,                         
-                                 IHandle<EpisodeDownloadedEvent>
-                                 
+    public class EpisodeModule : EpisodeModuleWithSignalR     
     {
         private readonly IEpisodeService _episodeService;
 
         public EpisodeModule(ICommandExecutor commandExecutor, IEpisodeService episodeService)
-            : base(commandExecutor)
+            : base(episodeService, commandExecutor)
         {
             _episodeService = episodeService;
 
@@ -43,29 +35,5 @@ namespace NzbDrone.Api.Episodes
         {
             _episodeService.SetEpisodeMonitored(episodeResource.Id, episodeResource.Monitored);
         }
-
-        private EpisodeResource GetEpisode(int id)
-        {
-            return _episodeService.GetEpisode(id).InjectTo<EpisodeResource>();
-        }
-
-        public void Handle(EpisodeGrabbedEvent message)
-        {
-            foreach (var episode in message.Episode.Episodes)
-            {
-                var resource = episode.InjectTo<EpisodeResource>();
-                resource.Grabbed = true;
-
-                BroadcastResourceChange(ModelAction.Updated, resource);
-            }
-        }
-
-        public void Handle(EpisodeDownloadedEvent message)
-        {
-            foreach (var episode in message.Episode.Episodes)
-            {
-                BroadcastResourceChange(ModelAction.Updated, episode.Id);
-            }
-        }
     }
 }
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Episodes/EpisodeModuleWithSignalR.cs b/src/NzbDrone.Api/Episodes/EpisodeModuleWithSignalR.cs
new file mode 100644
index 000000000..7612a9601
--- /dev/null
+++ b/src/NzbDrone.Api/Episodes/EpisodeModuleWithSignalR.cs
@@ -0,0 +1,55 @@
+using NzbDrone.Api.Mapping;
+using NzbDrone.Core.Datastore.Events;
+using NzbDrone.Core.Download;
+using NzbDrone.Core.MediaFiles.Events;
+using NzbDrone.Core.Messaging.Commands;
+using NzbDrone.Core.Messaging.Events;
+using NzbDrone.Core.Tv;
+
+namespace NzbDrone.Api.Episodes
+{
+    public abstract class EpisodeModuleWithSignalR : NzbDroneRestModuleWithSignalR<EpisodeResource, Episode>,
+        IHandle<EpisodeGrabbedEvent>,                         
+        IHandle<EpisodeDownloadedEvent>
+    {
+        private readonly IEpisodeService _episodeService;
+
+        protected EpisodeModuleWithSignalR(IEpisodeService episodeService, ICommandExecutor commandExecutor)
+            : base(commandExecutor)
+        {
+            _episodeService = episodeService;
+
+            GetResourceById = GetEpisode;
+        }
+
+        protected EpisodeModuleWithSignalR(IEpisodeService episodeService, ICommandExecutor commandExecutor, string resource)
+            : base(commandExecutor, resource)
+        {
+            _episodeService = episodeService;
+        }
+
+        protected EpisodeResource GetEpisode(int id)
+        {
+            return _episodeService.GetEpisode(id).InjectTo<EpisodeResource>();
+        }
+
+        public void Handle(EpisodeGrabbedEvent message)
+        {
+            foreach (var episode in message.Episode.Episodes)
+            {
+                var resource = episode.InjectTo<EpisodeResource>();
+                resource.Grabbed = true;
+
+                BroadcastResourceChange(ModelAction.Updated, resource);
+            }
+        }
+
+        public void Handle(EpisodeDownloadedEvent message)
+        {
+            foreach (var episode in message.Episode.Episodes)
+            {
+                BroadcastResourceChange(ModelAction.Updated, episode.Id);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Extensions/Pipelines/CacheHeaderPipeline.cs b/src/NzbDrone.Api/Extensions/Pipelines/CacheHeaderPipeline.cs
index 1ac4ae86c..28cecd695 100644
--- a/src/NzbDrone.Api/Extensions/Pipelines/CacheHeaderPipeline.cs
+++ b/src/NzbDrone.Api/Extensions/Pipelines/CacheHeaderPipeline.cs
@@ -13,7 +13,10 @@ namespace NzbDrone.Api.Extensions.Pipelines
 
         private void Handle(NancyContext context)
         {
-            context.Response.Headers.Add("X-ApplicationVersion", BuildInfo.Version.ToString());
+            if (!context.Response.Headers.ContainsKey("X-ApplicationVersion"))
+            {
+                context.Response.Headers.Add("X-ApplicationVersion", BuildInfo.Version.ToString());
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Frontend/Mappers/LogFileMapper.cs b/src/NzbDrone.Api/Frontend/Mappers/LogFileMapper.cs
index bc7124a97..588775839 100644
--- a/src/NzbDrone.Api/Frontend/Mappers/LogFileMapper.cs
+++ b/src/NzbDrone.Api/Frontend/Mappers/LogFileMapper.cs
@@ -6,11 +6,11 @@ using NzbDrone.Common.EnvironmentInfo;
 
 namespace NzbDrone.Api.Frontend.Mappers
 {
-    public class LogFileMapper : StaticResourceMapperBase
+    public class UpdateLogFileMapper : StaticResourceMapperBase
     {
         private readonly IAppFolderInfo _appFolderInfo;
 
-        public LogFileMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger)
+        public UpdateLogFileMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger)
             : base(diskProvider, logger)
         {
             _appFolderInfo = appFolderInfo;
@@ -21,12 +21,12 @@ namespace NzbDrone.Api.Frontend.Mappers
             var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar);
             path = Path.GetFileName(path);
 
-            return Path.Combine(_appFolderInfo.GetLogFolder(), path);
+            return Path.Combine(_appFolderInfo.GetUpdateLogFolder(), path);
         }
 
         public override bool CanHandle(string resourceUrl)
         {
-            return resourceUrl.StartsWith("/logfile/") && resourceUrl.EndsWith(".txt");
+            return resourceUrl.StartsWith("/updatelogfile/") && resourceUrl.EndsWith(".txt");
         }
     }
 }
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Frontend/Mappers/UpdateLogFileMapper.cs b/src/NzbDrone.Api/Frontend/Mappers/UpdateLogFileMapper.cs
new file mode 100644
index 000000000..bc7124a97
--- /dev/null
+++ b/src/NzbDrone.Api/Frontend/Mappers/UpdateLogFileMapper.cs
@@ -0,0 +1,32 @@
+using System.IO;
+using NLog;
+using NzbDrone.Common;
+using NzbDrone.Common.Disk;
+using NzbDrone.Common.EnvironmentInfo;
+
+namespace NzbDrone.Api.Frontend.Mappers
+{
+    public class LogFileMapper : StaticResourceMapperBase
+    {
+        private readonly IAppFolderInfo _appFolderInfo;
+
+        public LogFileMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, Logger logger)
+            : base(diskProvider, logger)
+        {
+            _appFolderInfo = appFolderInfo;
+        }
+
+        protected override string Map(string resourceUrl)
+        {
+            var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar);
+            path = Path.GetFileName(path);
+
+            return Path.Combine(_appFolderInfo.GetLogFolder(), path);
+        }
+
+        public override bool CanHandle(string resourceUrl)
+        {
+            return resourceUrl.StartsWith("/logfile/") && resourceUrl.EndsWith(".txt");
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Logs/LogFileModule.cs b/src/NzbDrone.Api/Logs/LogFileModule.cs
index b44e77b6d..aaa8797d3 100644
--- a/src/NzbDrone.Api/Logs/LogFileModule.cs
+++ b/src/NzbDrone.Api/Logs/LogFileModule.cs
@@ -1,63 +1,43 @@
 using System.Collections.Generic;
 using System.IO;
-using System.Linq;
 using NzbDrone.Common;
 using NzbDrone.Common.Disk;
 using NzbDrone.Common.EnvironmentInfo;
-using Nancy;
-using Nancy.Responses;
+using NzbDrone.Core.Configuration;
 
 namespace NzbDrone.Api.Logs
 {
-    public class LogFileModule : NzbDroneRestModule<LogFileResource>
+    public class LogFileModule : LogFileModuleBase
     {
-        private const string LOGFILE_ROUTE = @"/(?<filename>nzbdrone(?:\.\d+)?\.txt)";
-
         private readonly IAppFolderInfo _appFolderInfo;
         private readonly IDiskProvider _diskProvider;
 
         public LogFileModule(IAppFolderInfo appFolderInfo,
-                             IDiskProvider diskProvider)
-            : base("log/file")
+                             IDiskProvider diskProvider,
+                             IConfigFileProvider configFileProvider)
+            : base(diskProvider, configFileProvider, "")
         {
             _appFolderInfo = appFolderInfo;
             _diskProvider = diskProvider;
-            GetResourceAll = GetLogFiles;
-
-            Get[LOGFILE_ROUTE] = options => GetLogFile(options.filename);
         }
 
-        private List<LogFileResource> GetLogFiles()
+        protected override IEnumerable<string> GetLogFiles()
         {
-            var result = new List<LogFileResource>();
-            
-            var files = _diskProvider.GetFiles(_appFolderInfo.GetLogFolder(), SearchOption.TopDirectoryOnly);
+            return _diskProvider.GetFiles(_appFolderInfo.GetLogFolder(), SearchOption.TopDirectoryOnly);
+        }
 
-            for (int i = 0; i < files.Length; i++)
+        protected override string GetLogFilePath(string filename)
+        {
+            return Path.Combine(_appFolderInfo.GetLogFolder(), filename);
+        }
+
+        protected override string DownloadUrlRoot
+        {
+            get
             {
-                var file = files[i];
-                
-                result.Add(new LogFileResource
-                {
-                    Id = i + 1,
-                    Filename = Path.GetFileName(file),
-                    LastWriteTime = _diskProvider.FileGetLastWriteUtc(file)
-                });
+                return "logfile";
             }
-
-            return result.OrderByDescending(l => l.LastWriteTime).ToList();
         }
 
-        private Response GetLogFile(string filename)
-        {
-            var filePath = Path.Combine(_appFolderInfo.GetLogFolder(), filename);
-
-            if (!_diskProvider.FileExists(filePath))
-                return new NotFoundResponse();
-
-            var data = _diskProvider.ReadAllText(filePath);
-            
-            return new TextResponse(data);
-        }
     }
 }
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Logs/LogFileModuleBase.cs b/src/NzbDrone.Api/Logs/LogFileModuleBase.cs
new file mode 100644
index 000000000..3f1a531d6
--- /dev/null
+++ b/src/NzbDrone.Api/Logs/LogFileModuleBase.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using NzbDrone.Common.Disk;
+using Nancy;
+using Nancy.Responses;
+using NzbDrone.Core.Configuration;
+
+namespace NzbDrone.Api.Logs
+{
+    public abstract class LogFileModuleBase : NzbDroneRestModule<LogFileResource>
+    {
+        protected const string LOGFILE_ROUTE = @"/(?<filename>[-.a-zA-Z0-9]+?\.txt)";
+
+        private readonly IDiskProvider _diskProvider;
+        private readonly IConfigFileProvider _configFileProvider;
+
+        public LogFileModuleBase(IDiskProvider diskProvider,
+                                 IConfigFileProvider configFileProvider,
+                                 String route)
+            : base("log/file" + route)
+        {
+            _diskProvider = diskProvider;
+            _configFileProvider = configFileProvider;
+            GetResourceAll = GetLogFilesResponse;
+
+            Get[LOGFILE_ROUTE] = options => GetLogFileResponse(options.filename);
+        }
+
+        private List<LogFileResource> GetLogFilesResponse()
+        {
+            var result = new List<LogFileResource>();
+
+            var files = GetLogFiles().ToList();
+
+            for (int i = 0; i < files.Count; i++)
+            {
+                var file = files[i];
+                var filename = Path.GetFileName(file);
+                
+                result.Add(new LogFileResource
+                {
+                    Id = i + 1,
+                    Filename = filename,
+                    LastWriteTime = _diskProvider.FileGetLastWriteUtc(file),
+                    ContentsUrl = String.Format("{0}/api/{1}/{2}", _configFileProvider.UrlBase, Resource, filename),
+                    DownloadUrl = String.Format("{0}/{1}/{2}", _configFileProvider.UrlBase, DownloadUrlRoot, filename)
+                });
+            }
+
+            return result.OrderByDescending(l => l.LastWriteTime).ToList();
+        }
+
+        private Response GetLogFileResponse(String filename)
+        {
+            var filePath = GetLogFilePath(filename);
+
+            if (!_diskProvider.FileExists(filePath))
+                return new NotFoundResponse();
+
+            var data = _diskProvider.ReadAllText(filePath);
+            
+            return new TextResponse(data);
+        }
+
+        protected abstract IEnumerable<String> GetLogFiles();
+        protected abstract String GetLogFilePath(String filename);
+
+        protected abstract String DownloadUrlRoot { get; }
+    }
+}
\ No newline at end of file
diff --git a/src/NzbDrone.Api/Logs/LogFileResource.cs b/src/NzbDrone.Api/Logs/LogFileResource.cs
index 9d2847e89..8109eeb07 100644
--- a/src/NzbDrone.Api/Logs/LogFileResource.cs
+++ b/src/NzbDrone.Api/Logs/LogFileResource.cs
@@ -7,5 +7,7 @@ namespace NzbDrone.Api.Logs
     {
         public String Filename { get; set; }
         public DateTime LastWriteTime { get; set; }
+        public String ContentsUrl { get; set; }
+        public String DownloadUrl { get; set; }
     }
 }
diff --git a/src/NzbDrone.Api/Logs/UpdateLogFileModule.cs b/src/NzbDrone.Api/Logs/UpdateLogFileModule.cs
new file mode 100644
index 000000000..3c91173ce
--- /dev/null
+++ b/src/NzbDrone.Api/Logs/UpdateLogFileModule.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using NzbDrone.Common;
+using NzbDrone.Common.Disk;
+using NzbDrone.Common.EnvironmentInfo;
+using NzbDrone.Core.Configuration;
+
+namespace NzbDrone.Api.Logs
+{
+    public class UpdateLogFileModule : LogFileModuleBase
+    {
+        private readonly IAppFolderInfo _appFolderInfo;
+        private readonly IDiskProvider _diskProvider;
+
+        public UpdateLogFileModule(IAppFolderInfo appFolderInfo,
+                                   IDiskProvider diskProvider,
+                                   IConfigFileProvider configFileProvider)
+            : base(diskProvider, configFileProvider, "/update")
+        {
+            _appFolderInfo = appFolderInfo;
+            _diskProvider = diskProvider;
+        }
+
+        protected override IEnumerable<String> GetLogFiles()
+        {
+            return _diskProvider.GetFiles(_appFolderInfo.GetUpdateLogFolder(), SearchOption.TopDirectoryOnly)
+                                     .Where(f => Regex.IsMatch(Path.GetFileName(f), LOGFILE_ROUTE.TrimStart('/'), RegexOptions.IgnoreCase))
+                                     .ToList();
+        }
+
+        protected override String GetLogFilePath(String filename)
+        {
+            return Path.Combine(_appFolderInfo.GetUpdateLogFolder(), filename);
+        }
+
+        protected override String DownloadUrlRoot
+        {
+            get
+            {
+                return "updatelogfile";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/NzbDrone.Api/NzbDrone.Api.csproj b/src/NzbDrone.Api/NzbDrone.Api.csproj
index 0c23ee731..21a84886e 100644
--- a/src/NzbDrone.Api/NzbDrone.Api.csproj
+++ b/src/NzbDrone.Api/NzbDrone.Api.csproj
@@ -117,6 +117,7 @@
     <Compile Include="EpisodeFiles\EpisodeFileResource.cs" />
     <Compile Include="Directories\DirectoryLookupService.cs" />
     <Compile Include="Directories\DirectoryModule.cs" />
+    <Compile Include="Episodes\EpisodeModuleWithSignalR.cs" />
     <Compile Include="Episodes\EpisodeModule.cs" />
     <Compile Include="Episodes\EpisodeResource.cs" />
     <Compile Include="Episodes\RenameEpisodeModule.cs" />
@@ -129,6 +130,7 @@
     <Compile Include="Extensions\NancyJsonSerializer.cs" />
     <Compile Include="Extensions\RequestExtensions.cs" />
     <Compile Include="Frontend\IsCacheableSpecification.cs" />
+    <Compile Include="Frontend\Mappers\UpdateLogFileMapper.cs" />
     <Compile Include="Frontend\Mappers\FaviconMapper.cs" />
     <Compile Include="Frontend\Mappers\IndexHtmlMapper.cs" />
     <Compile Include="Frontend\Mappers\LogFileMapper.cs" />
@@ -141,6 +143,8 @@
     <Compile Include="Health\HealthModule.cs" />
     <Compile Include="History\HistoryResource.cs" />
     <Compile Include="History\HistoryModule.cs" />
+    <Compile Include="Logs\LogFileModuleBase.cs" />
+    <Compile Include="Logs\UpdateLogFileModule.cs" />
     <Compile Include="MediaCovers\MediaCoverModule.cs" />
     <Compile Include="Metadata\MetadataResource.cs" />
     <Compile Include="Metadata\MetadataModule.cs" />
diff --git a/src/NzbDrone.Api/Wanted/CutoffModule.cs b/src/NzbDrone.Api/Wanted/CutoffModule.cs
index ee0b9f219..da2e44ef7 100644
--- a/src/NzbDrone.Api/Wanted/CutoffModule.cs
+++ b/src/NzbDrone.Api/Wanted/CutoffModule.cs
@@ -2,17 +2,18 @@
 using NzbDrone.Api.Episodes;
 using NzbDrone.Api.Extensions;
 using NzbDrone.Core.Datastore;
+using NzbDrone.Core.Messaging.Commands;
 using NzbDrone.Core.Tv;
 
 namespace NzbDrone.Api.Wanted
 {
-    public class CutoffModule : NzbDroneRestModule<EpisodeResource>
+    public class CutoffModule : EpisodeModuleWithSignalR
     {
         private readonly IEpisodeCutoffService _episodeCutoffService;
-        private readonly SeriesRepository _seriesRepository;
+        private readonly ISeriesRepository _seriesRepository;
 
-        public CutoffModule(IEpisodeCutoffService episodeCutoffService, SeriesRepository seriesRepository)
-            :base("wanted/cutoff")
+        public CutoffModule(IEpisodeService episodeService, IEpisodeCutoffService episodeCutoffService, ISeriesRepository seriesRepository, ICommandExecutor commandExecutor)
+            :base(episodeService, commandExecutor, "wanted/cutoff")
         {
             _episodeCutoffService = episodeCutoffService;
             _seriesRepository = seriesRepository;
diff --git a/src/NzbDrone.Api/Wanted/MissingModule.cs b/src/NzbDrone.Api/Wanted/MissingModule.cs
index dd4d97f69..14fef9104 100644
--- a/src/NzbDrone.Api/Wanted/MissingModule.cs
+++ b/src/NzbDrone.Api/Wanted/MissingModule.cs
@@ -2,17 +2,18 @@
 using NzbDrone.Api.Episodes;
 using NzbDrone.Api.Extensions;
 using NzbDrone.Core.Datastore;
+using NzbDrone.Core.Messaging.Commands;
 using NzbDrone.Core.Tv;
 
 namespace NzbDrone.Api.Wanted
 {
-    public class MissingModule : NzbDroneRestModule<EpisodeResource>
+    public class MissingModule : EpisodeModuleWithSignalR
     {
         private readonly IEpisodeService _episodeService;
-        private readonly SeriesRepository _seriesRepository;
+        private readonly ISeriesRepository _seriesRepository;
 
-        public MissingModule(IEpisodeService episodeService, SeriesRepository seriesRepository)
-            :base("wanted/missing")
+        public MissingModule(IEpisodeService episodeService, ISeriesRepository seriesRepository, ICommandExecutor commandExecutor)
+            :base(episodeService, commandExecutor, "wanted/missing")
         {
             _episodeService = episodeService;
             _seriesRepository = seriesRepository;
diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs
index e99382894..6dd047f4c 100644
--- a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs
+++ b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs
@@ -42,9 +42,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
         {
             var url = remoteEpisode.Release.DownloadUrl;
             var title = remoteEpisode.Release.Title + ".nzb";
-
-            string category = Settings.TvCategory;
-            int priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
+            var category = Settings.TvCategory;
+            var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
 
             _logger.Info("Adding report [{0}] to the queue.", title);
 
@@ -271,10 +270,9 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
             _proxy.GetVersion(settings);
 
             var config = _proxy.GetConfig(settings);
-
             var categories = GetCategories(config);
 
-            if (!categories.Any(v => v.Name == settings.TvCategory))
+            if (!settings.TvCategory.IsNullOrWhiteSpace() && !categories.Any(v => v.Name == settings.TvCategory))
             {
                 throw new ApplicationException("Category does not exist");
             }
diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs
index e14c15336..5c5a05e31 100644
--- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs
+++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs
@@ -222,7 +222,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
         {
             var categories = _proxy.GetCategories(settings);
 
-            if (!categories.Any(v => v == settings.TvCategory))
+            if (!settings.TvCategory.IsNullOrWhiteSpace() && !categories.Any(v => v == settings.TvCategory))
             {
                 throw new ApplicationException("Category does not exist");
             }
diff --git a/src/NzbDrone.Core/Instrumentation/Commands/DeleteUpdateLogFilesCommand.cs b/src/NzbDrone.Core/Instrumentation/Commands/DeleteUpdateLogFilesCommand.cs
new file mode 100644
index 000000000..a55e91502
--- /dev/null
+++ b/src/NzbDrone.Core/Instrumentation/Commands/DeleteUpdateLogFilesCommand.cs
@@ -0,0 +1,15 @@
+using NzbDrone.Core.Messaging.Commands;
+
+namespace NzbDrone.Core.Instrumentation.Commands
+{
+    public class DeleteUpdateLogFilesCommand : Command
+    {
+        public override bool SendUpdatesToClient
+        {
+            get
+            {
+                return true;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/NzbDrone.Core/Instrumentation/DeleteLogFilesService.cs b/src/NzbDrone.Core/Instrumentation/DeleteLogFilesService.cs
index 25ae79cad..e2e31ca7b 100644
--- a/src/NzbDrone.Core/Instrumentation/DeleteLogFilesService.cs
+++ b/src/NzbDrone.Core/Instrumentation/DeleteLogFilesService.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
 using NLog;
 using NzbDrone.Common;
 using NzbDrone.Common.Disk;
@@ -12,7 +13,7 @@ namespace NzbDrone.Core.Instrumentation
     {
     }
 
-    public class DeleteLogFilesService : IDeleteLogFilesService, IExecute<DeleteLogFilesCommand>
+    public class DeleteLogFilesService : IDeleteLogFilesService, IExecute<DeleteLogFilesCommand>, IExecute<DeleteUpdateLogFilesCommand>
     {
         private readonly IDiskProvider _diskProvider;
         private readonly IAppFolderInfo _appFolderInfo;
@@ -27,12 +28,14 @@ namespace NzbDrone.Core.Instrumentation
 
         public void Execute(DeleteLogFilesCommand message)
         {
-            var logFiles = _diskProvider.GetFiles(_appFolderInfo.GetLogFolder(), SearchOption.TopDirectoryOnly);
+            _logger.Debug("Deleting all files in: {0}", _appFolderInfo.GetLogFolder());
+            _diskProvider.EmptyFolder(_appFolderInfo.GetLogFolder());
+        }
 
-            foreach (var logFile in logFiles)
-            {
-                _diskProvider.DeleteFile(logFile);
-            }
+        public void Execute(DeleteUpdateLogFilesCommand message)
+        {
+            _logger.Debug("Deleting all files in: {0}", _appFolderInfo.GetUpdateLogFolder());
+            _diskProvider.EmptyFolder(_appFolderInfo.GetUpdateLogFolder());
         }
     }
 }
diff --git a/src/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs b/src/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs
index 060f3c3ba..6a81ee4c8 100644
--- a/src/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs
+++ b/src/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs
@@ -73,8 +73,9 @@ namespace NzbDrone.Core.MediaFiles
 
         private IEnumerable<RenameEpisodeFilePreview> GetPreviews(Series series, List<Episode> episodes, List<EpisodeFile> files)
         {
-            foreach (var file in files)
+            foreach (var f in files)
             {
+                var file = f;
                 var episodesInFile = episodes.Where(e => e.EpisodeFileId == file.Id).ToList();
 
                 if (!episodesInFile.Any())
@@ -95,18 +96,13 @@ namespace NzbDrone.Core.MediaFiles
                                      SeasonNumber = seasonNumber,
                                      EpisodeNumbers = episodesInFile.Select(e => e.EpisodeNumber).ToList(),
                                      EpisodeFileId = file.Id,
-                                     ExistingPath = GetRelativePath(series.Path, file.Path),
-                                     NewPath = GetRelativePath(series.Path, newPath)
+                                     ExistingPath = series.Path.GetRelativePath(file.Path),
+                                     NewPath = series.Path.GetRelativePath(newPath)
                                  };
                 }
             }
         }
 
-        private string GetRelativePath(string seriesPath, string path)
-        {
-            return path.Substring(seriesPath.Length + 1);
-        }
-
         private void RenameFiles(List<EpisodeFile> episodeFiles, Series series)
         {
             var renamed = new List<EpisodeFile>();
diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj
index 8b70b8ca6..97f8093a6 100644
--- a/src/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/src/NzbDrone.Core/NzbDrone.Core.csproj
@@ -334,6 +334,7 @@
     <Compile Include="Indexers\RssSyncCommand.cs" />
     <Compile Include="Indexers\XElementExtensions.cs" />
     <Compile Include="Instrumentation\Commands\ClearLogCommand.cs" />
+    <Compile Include="Instrumentation\Commands\DeleteUpdateLogFilesCommand.cs" />
     <Compile Include="Instrumentation\Commands\DeleteLogFilesCommand.cs" />
     <Compile Include="Instrumentation\Commands\TrimLogCommand.cs" />
     <Compile Include="Instrumentation\DeleteLogFilesService.cs" />
diff --git a/src/UI/AddSeries/AddSeriesLayout.js b/src/UI/AddSeries/AddSeriesLayout.js
index e6e265abe..b51245d3a 100644
--- a/src/UI/AddSeries/AddSeriesLayout.js
+++ b/src/UI/AddSeries/AddSeriesLayout.js
@@ -55,7 +55,7 @@ define(
 
             _importSeries: function () {
                 this.rootFolderLayout = new RootFolderLayout();
-                this.rootFolderLayout.on('folderSelected', this._folderSelected, this);
+                this.listenTo(this.rootFolderLayout, 'folderSelected', this._folderSelected);
                 AppLayout.modalRegion.show(this.rootFolderLayout);
             },
 
diff --git a/src/UI/AddSeries/SearchResultViewTemplate.html b/src/UI/AddSeries/SearchResultViewTemplate.html
index d87a7e126..9fa74a539 100644
--- a/src/UI/AddSeries/SearchResultViewTemplate.html
+++ b/src/UI/AddSeries/SearchResultViewTemplate.html
@@ -10,9 +10,14 @@
             <div class="row">
                 <h2 class="series-title">
                     {{titleWithYear}}
-                    {{#unless_eq status compare="continuing"}}
-                        <span class="label label-important">Ended</span>
-                    {{/unless_eq}}
+
+                    <span class="labels">
+                        <span class="label label-primary">{{network}}</span>
+                        {{#unless_eq status compare="continuing"}}
+                            <span class="label label-danger">Ended</span>
+                        {{/unless_eq}}
+                    </span>
+
                 </h2>
             </div>
             <div class="row new-series-overview x-overview">
diff --git a/src/UI/AddSeries/addSeries.less b/src/UI/AddSeries/addSeries.less
index 01a3b19fd..d0fdf3579 100644
--- a/src/UI/AddSeries/addSeries.less
+++ b/src/UI/AddSeries/addSeries.less
@@ -40,9 +40,13 @@
     padding-bottom : 20px;
 
     .series-title {
-      .label {
-        margin-left: 15px;
-        vertical-align: middle;
+      .labels {
+        margin-left : 10px;
+
+        .label {
+          font-size      : 12px;
+          vertical-align : middle;
+        }
       }
 
       .year {
diff --git a/src/UI/Calendar/CalendarFeedView.js b/src/UI/Calendar/CalendarFeedView.js
index e69895af9..cf18cb711 100644
--- a/src/UI/Calendar/CalendarFeedView.js
+++ b/src/UI/Calendar/CalendarFeedView.js
@@ -14,7 +14,7 @@ define(
             },
 
             templateHelpers: {
-                icalHttpUrl   : window.location.protocol + '//' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics',
+                icalHttpUrl   : window.location.protocol + '//' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics?apikey=' + window.NzbDrone.ApiKey,
                 icalWebCalUrl : 'webcal://' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics'
             },
 
diff --git a/src/UI/Calendar/CalendarFeedViewTemplate.html b/src/UI/Calendar/CalendarFeedViewTemplate.html
index d920089b3..56ba9eb61 100644
--- a/src/UI/Calendar/CalendarFeedViewTemplate.html
+++ b/src/UI/Calendar/CalendarFeedViewTemplate.html
@@ -6,21 +6,26 @@
         </div>
         <div class="modal-body edit-series-modal">
             <div class="row">
-                <div>
+                <div class="col-md-12">
                     <div class="form-horizontal">
-                        <div class="form-group">
-                            <label class="control-label">iCal feed</label>
 
-                            <div class="controls ical-url">
-                                <div class="input-group">
-                                    <input type="text" class="x-ical-url" value="{{icalHttpUrl}}" readonly="readonly" />
-                                    <button class="btn btn-icon-only x-ical-copy" title="Copy to clipboard"><i class="icon-copy"></i></button>
-                                    <a class="btn btn-icon-only no-router" title="Subscribe" href="{{icalWebCalUrl}}" target="_blank"><i class="icon-calendar-empty"></i></a>
-                                </div>
-                                <span class="help-inline">
-                                    <i class="icon-nd-form-info" title="Copy this url into your clients subscription form or use the subscribe button if your browser support webcal"/>
-                                </span>
+                        <div class="form-group">
+                            <label class="col-sm-3 control-label">iCal feed</label>
+
+                            <div class="col-sm-1 col-sm-push-8 help-inline">
+                                <i class="icon-nd-form-info" title="Copy this url into your clients subscription form or use the subscribe button if your browser support webcal"/>
                             </div>
+
+                            <div class="col-sm-8 col-sm-pull-1">
+                                <div class="input-group ical-url">
+                                    <input type="text" class="form-control x-ical-url" value="{{icalHttpUrl}}" readonly="readonly" />
+                                    <div class="input-group-btn">
+                                        <button class="btn btn-icon-only x-ical-copy" title="Copy to clipboard"><i class="icon-copy"></i></button>
+                                        <button class="btn btn-icon-only no-router"><a title="Subscribe" href="{{icalWebCalUrl}}" target="_blank"><i class="icon-calendar-empty"></i></a></button>
+                                    </div>
+                                </div>
+                            </div>
+
                         </div>
                     </div>
                 </div>
diff --git a/src/UI/Calendar/calendar.less b/src/UI/Calendar/calendar.less
index 3aedf3eef..5b6b1faf7 100644
--- a/src/UI/Calendar/calendar.less
+++ b/src/UI/Calendar/calendar.less
@@ -178,7 +178,6 @@
 .ical-url {
 
   input {
-    width  : 440px;
-    cursor : text;
+    cursor : text !important;
   }
 }
diff --git a/src/UI/History/Blacklist/BlacklistLayout.js b/src/UI/History/Blacklist/BlacklistLayout.js
index 8a6a74487..d8b214ca2 100644
--- a/src/UI/History/Blacklist/BlacklistLayout.js
+++ b/src/UI/History/Blacklist/BlacklistLayout.js
@@ -67,8 +67,9 @@ define(
 
             initialize: function () {
                 this.collection = new BlacklistCollection({ tableName: 'blacklist' });
+
                 this.listenTo(this.collection, 'sync', this._showTable);
-                vent.on(vent.Events.CommandComplete, this._commandComplete, this);
+                this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
             },
 
             onShow: function () {
diff --git a/src/UI/Series/Details/SeriesDetailsLayout.js b/src/UI/Series/Details/SeriesDetailsLayout.js
index 95d20c627..cceef6655 100644
--- a/src/UI/Series/Details/SeriesDetailsLayout.js
+++ b/src/UI/Series/Details/SeriesDetailsLayout.js
@@ -59,8 +59,7 @@ define(
             initialize: function () {
                 this.listenTo(this.model, 'change:monitored', this._setMonitoredState);
                 this.listenTo(vent, vent.Events.SeriesDeleted, this._onSeriesDeleted);
-
-                vent.on(vent.Events.CommandComplete, this._commandComplete, this);
+                this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
             },
 
             onShow: function () {
diff --git a/src/UI/Settings/General/GeneralView.js b/src/UI/Settings/General/GeneralView.js
index b28ed659c..1b5aaaed7 100644
--- a/src/UI/Settings/General/GeneralView.js
+++ b/src/UI/Settings/General/GeneralView.js
@@ -31,7 +31,7 @@ define(
             },
 
             initialize: function () {
-                vent.on(vent.Events.CommandComplete, this._commandComplete, this);
+                this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
             },
 
             onRender: function(){
diff --git a/src/UI/System/Logs/Files/ContentsModel.js b/src/UI/System/Logs/Files/ContentsModel.js
index d109013dc..baf529561 100644
--- a/src/UI/System/Logs/Files/ContentsModel.js
+++ b/src/UI/System/Logs/Files/ContentsModel.js
@@ -1,12 +1,11 @@
 'use strict';
 define(
     [
-        'backbone',
-        'System/StatusModel'
-    ], function (Backbone, StatusModel) {
+        'backbone'
+    ], function (Backbone) {
         return Backbone.Model.extend({
             url: function () {
-                return StatusModel.get('urlBase') + '/api/log/file/' + this.get('filename');
+                return this.get('contentsUrl');
             },
 
             parse: function (contents) {
diff --git a/src/UI/System/Logs/Files/DownloadLogCell.js b/src/UI/System/Logs/Files/DownloadLogCell.js
index 6ce544374..63dfb66f2 100644
--- a/src/UI/System/Logs/Files/DownloadLogCell.js
+++ b/src/UI/System/Logs/Files/DownloadLogCell.js
@@ -1,16 +1,15 @@
 'use strict';
 define(
     [
-        'Cells/NzbDroneCell',
-        'System/StatusModel'
-    ], function (NzbDroneCell, StatusModel) {
+        '../../../Cells/NzbDroneCell'
+    ], function (NzbDroneCell) {
         return NzbDroneCell.extend({
 
             className: 'download-log-cell',
 
             render: function () {
                 this.$el.empty();
-                this.$el.html('<a href="{0}/logfile/{1}" class="no-router" target="_blank">Download</a>'.format(StatusModel.get('urlBase'), this.cellValue));
+                this.$el.html('<a href="{0}" class="no-router" target="_blank">Download</a>'.format(this.cellValue));
 
                 return this;
             }
diff --git a/src/UI/System/Logs/Files/FilenameCell.js b/src/UI/System/Logs/Files/FilenameCell.js
index 3fefb67a5..feec6ed8b 100644
--- a/src/UI/System/Logs/Files/FilenameCell.js
+++ b/src/UI/System/Logs/Files/FilenameCell.js
@@ -1,7 +1,7 @@
 'use strict';
 define(
     [
-        'Cells/NzbDroneCell'
+        '../../../Cells/NzbDroneCell'
     ], function (NzbDroneCell) {
         return NzbDroneCell.extend({
 
diff --git a/src/UI/System/Logs/Files/LogFileLayout.js b/src/UI/System/Logs/Files/LogFileLayout.js
index 8cffc029e..75280515a 100644
--- a/src/UI/System/Logs/Files/LogFileLayout.js
+++ b/src/UI/System/Logs/Files/LogFileLayout.js
@@ -7,7 +7,6 @@ define(
         'System/Logs/Files/FilenameCell',
         'Cells/RelativeDateCell',
         'System/Logs/Files/DownloadLogCell',
-        'System/Logs/Files/LogFileCollection',
         'System/Logs/Files/Row',
         'System/Logs/Files/ContentsView',
         'System/Logs/Files/ContentsModel',
@@ -20,7 +19,6 @@ define(
         FilenameCell,
         RelativeDateCell,
         DownloadLogCell,
-        LogFileCollection,
         LogFileRow,
         ContentsView,
         ContentsModel,
@@ -48,18 +46,19 @@ define(
                         cell : RelativeDateCell
                     },
                     {
-                        name    : 'filename',
+                        name    : 'downloadUrl',
                         label   : '',
                         cell    : DownloadLogCell,
                         sortable: false
                     }
                 ],
 
-            initialize: function () {
-                this.collection = new LogFileCollection();
+            initialize: function (options) {
+                this.collection = options.collection;
+                this.deleteFilesCommand = options.deleteFilesCommand;
 
-                vent.on(vent.Commands.ShowLogFile, this._fetchLogFileContents, this);
-                vent.on(vent.Events.CommandComplete, this._commandComplete, this);
+                this.listenTo(vent, vent.Commands.ShowLogFile, this._fetchLogFileContents);
+                this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
                 this.listenTo(this.collection, 'sync', this._collectionSynced);
 
                 this.collection.fetch();
@@ -83,11 +82,10 @@ define(
                                 ownerContext  : this,
                                 callback      : this._refreshTable
                             },
-
                             {
                                 title          : 'Delete Log Files',
                                 icon           : 'icon-trash',
-                                command        : 'deleteLogFiles',
+                                command        : this.deleteFilesCommand,
                                 successMessage : 'Log files have been deleted',
                                 errorMessage   : 'Failed to delete log files'
                             }
@@ -125,11 +123,7 @@ define(
                 this.contents.show(new LoadingView());
 
                 var model = options.model;
-                var filename = model.get('filename');
-
-                var contentsModel = new ContentsModel({
-                    filename: filename
-                });
+                var contentsModel = new ContentsModel(model.toJSON());
 
                 this.listenToOnce(contentsModel, 'sync', this._showDetails);
 
@@ -151,7 +145,7 @@ define(
             },
 
             _commandComplete: function (options) {
-                if (options.command.get('name') === 'deletelogfiles') {
+                if (options.command.get('name') === this.deleteFilesCommand.toLowerCase()) {
                     this._refreshTable();
                 }
             }
diff --git a/src/UI/System/Logs/Files/Row.js b/src/UI/System/Logs/Files/Row.js
index 926869008..b506e214d 100644
--- a/src/UI/System/Logs/Files/Row.js
+++ b/src/UI/System/Logs/Files/Row.js
@@ -1,7 +1,7 @@
 'use strict';
 define(
     [
-        'vent',
+        '../../../vent',
         'backgrid'
     ], function (vent, Backgrid) {
 
diff --git a/src/UI/System/Logs/LogsLayout.js b/src/UI/System/Logs/LogsLayout.js
index 15511b431..a8c1cf0ac 100644
--- a/src/UI/System/Logs/LogsLayout.js
+++ b/src/UI/System/Logs/LogsLayout.js
@@ -3,24 +3,29 @@ define(
     [
         'marionette',
         'System/Logs/Table/LogsTableLayout',
-        'System/Logs/Files/LogFileLayout'
-    ], function (Marionette, LogsTableLayout, LogsFileLayout) {
+        'System/Logs/Files/LogFileLayout',
+        'System/Logs/Files/LogFileCollection',
+        'System/Logs/Updates/LogFileCollection'
+    ], function (Marionette, LogsTableLayout, LogsFileLayout, LogFileCollection, UpdateLogFileCollection) {
         return Marionette.Layout.extend({
             template: 'System/Logs/LogsLayoutTemplate',
 
             ui: {
-                tableTab: '.x-table-tab',
-                filesTab: '.x-files-tab'
+                tableTab       : '.x-table-tab',
+                filesTab       : '.x-files-tab',
+                updateFilesTab : '.x-update-files-tab'
             },
 
             regions: {
-                table: '#table',
-                files: '#files'
+                table       : '#table',
+                files       : '#files',
+                updateFiles : '#update-files'
             },
 
             events: {
-                'click .x-table-tab': '_showTable',
-                'click .x-files-tab': '_showFiles'
+                'click .x-table-tab'        : '_showTable',
+                'click .x-files-tab'        : '_showFiles',
+                'click .x-update-files-tab' : '_showUpdateFiles'
             },
 
             onShow: function () {
@@ -42,7 +47,22 @@ define(
                 }
 
                 this.ui.filesTab.tab('show');
-                this.files.show(new LogsFileLayout());
+                this.files.show(new LogsFileLayout({
+                    collection: new LogFileCollection(),
+                    deleteFilesCommand: 'deleteLogFiles'
+                }));
+            },
+
+            _showUpdateFiles: function (e) {
+                if (e) {
+                    e.preventDefault();
+                }
+
+                this.ui.updateFilesTab.tab('show');
+                this.updateFiles.show(new LogsFileLayout({
+                    collection: new UpdateLogFileCollection(),
+                    deleteFilesCommand: 'deleteUpdateLogFiles'
+                }));
             }
         });
     });
diff --git a/src/UI/System/Logs/LogsLayoutTemplate.html b/src/UI/System/Logs/LogsLayoutTemplate.html
index aa250b933..a9832519a 100644
--- a/src/UI/System/Logs/LogsLayoutTemplate.html
+++ b/src/UI/System/Logs/LogsLayoutTemplate.html
@@ -1,15 +1,17 @@
 <div class="row">
-    <div class="col-md-1 col-sm-2">
+    <div class="col-md-2 col-sm-2">
         <ul class="nav nav-pills nav-stacked">
             <li><a href="#table" class="x-table-tab no-router">Table</a></li>
             <li><a href="#files" class="x-files-tab no-router">Files</a></li>
+            <li><a href="#update-files" class="x-update-files-tab no-router">Updates</a></li>
         </ul>
     </div>
 
-    <div class="col-md-11 col-sm-10">
+    <div class="col-md-10 col-sm-10">
         <div class="tab-content">
             <div class="tab-pane" id="table"></div>
             <div class="tab-pane" id="files"></div>
+            <div class="tab-pane" id="update-files"></div>
         </div>
     </div>
 </div>
\ No newline at end of file
diff --git a/src/UI/System/Logs/Table/LogsTableLayout.js b/src/UI/System/Logs/Table/LogsTableLayout.js
index 841a5a92b..2e06e1b7d 100644
--- a/src/UI/System/Logs/Table/LogsTableLayout.js
+++ b/src/UI/System/Logs/Table/LogsTableLayout.js
@@ -61,7 +61,7 @@ define(
                 this.collection = new LogCollection();
 
                 this.listenTo(this.collection, 'sync', this._showTable);
-                vent.on(vent.Events.CommandComplete, this._commandComplete, this);
+                this.listenTo(vent, vent.Events.CommandComplete, this._commandComplete);
             },
 
             onRender: function () {
diff --git a/src/UI/System/Logs/Updates/LogFileCollection.js b/src/UI/System/Logs/Updates/LogFileCollection.js
new file mode 100644
index 000000000..9a6d928f9
--- /dev/null
+++ b/src/UI/System/Logs/Updates/LogFileCollection.js
@@ -0,0 +1,17 @@
+'use strict';
+
+define(
+    [
+        'backbone',
+        'System/Logs/Updates/LogFileModel'
+    ], function (Backbone, LogFileModel) {
+        return Backbone.Collection.extend({
+            url  : window.NzbDrone.ApiRoot + '/log/file/update',
+            model: LogFileModel,
+
+            state: {
+                sortKey: 'lastWriteTime',
+                order  : 1
+            }
+        });
+    });
diff --git a/src/UI/System/Logs/Updates/LogFileModel.js b/src/UI/System/Logs/Updates/LogFileModel.js
new file mode 100644
index 000000000..17c0fd6da
--- /dev/null
+++ b/src/UI/System/Logs/Updates/LogFileModel.js
@@ -0,0 +1,8 @@
+'use strict';
+define(
+    [
+        'backbone'
+    ], function (Backbone) {
+        return Backbone.Model.extend({
+        });
+    });
diff --git a/src/UI/System/SystemLayoutTemplate.html b/src/UI/System/SystemLayoutTemplate.html
index c84df1ca7..e3b245715 100644
--- a/src/UI/System/SystemLayoutTemplate.html
+++ b/src/UI/System/SystemLayoutTemplate.html
@@ -4,10 +4,10 @@
     <li><a href="#updates" class="x-updates-tab no-router">Updates</a></li>
     <li class="lifecycle-controls pull-right">
         <div class="btn-group">
-            <button class="btn btn-default btn-icon-only x-shutdown" title="Shutdown">
+            <button class="btn btn-default btn-icon-only x-shutdown" title="Shutdown" data-container="body">
                 <i class="icon-nd-shutdown"></i>
             </button>
-            <button class="btn btn-default btn-icon-only x-restart" title="Restart">
+            <button class="btn btn-default btn-icon-only x-restart" title="Restart" data-container="body">
                 <i class="icon-nd-restart"></i>
             </button>
         </div>
diff --git a/src/UI/Wanted/Cutoff/CutoffUnmetLayout.js b/src/UI/Wanted/Cutoff/CutoffUnmetLayout.js
index d01397bd4..df889f4f5 100644
--- a/src/UI/Wanted/Cutoff/CutoffUnmetLayout.js
+++ b/src/UI/Wanted/Cutoff/CutoffUnmetLayout.js
@@ -14,7 +14,8 @@ define([
     'Shared/LoadingView',
     'Shared/Messenger',
     'Commands/CommandController',
-    'backgrid.selectall'
+    'backgrid.selectall',
+    'Mixins/backbone.signalr.mixin'
 ], function (_,
              Marionette,
              Backgrid,
@@ -81,7 +82,7 @@ define([
         ],
 
         initialize : function () {
-            this.collection = new CutoffUnmetCollection();
+            this.collection = new CutoffUnmetCollection().bindSignalR({ updateOnly: true });
 
             this.listenTo(this.collection, 'sync', this._showTable);
         },
diff --git a/src/UI/Wanted/Missing/MissingLayout.js b/src/UI/Wanted/Missing/MissingLayout.js
index 45bfb9d4e..7e1cf6ae2 100644
--- a/src/UI/Wanted/Missing/MissingLayout.js
+++ b/src/UI/Wanted/Missing/MissingLayout.js
@@ -14,7 +14,8 @@ define([
     'Shared/LoadingView',
     'Shared/Messenger',
     'Commands/CommandController',
-    'backgrid.selectall'
+    'backgrid.selectall',
+    'Mixins/backbone.signalr.mixin'
 ], function (_,
              Marionette,
              Backgrid,
@@ -81,7 +82,7 @@ define([
         ],
 
         initialize : function () {
-            this.collection = new MissingCollection();
+            this.collection = new MissingCollection().bindSignalR({ updateOnly: true });
 
             this.listenTo(this.collection, 'sync', this._showTable);
         },