diff --git a/Koha/App/Koha.pm b/Koha/App/Koha.pm
index 88fb2df..5e9b674 100644
--- a/Koha/App/Koha.pm
+++ b/Koha/App/Koha.pm
@@ -13,7 +13,11 @@ sub startup {
     my ($self) = @_;
 
     push @{$self->plugins->namespaces}, 'Koha::App::Plugin';
-    push @{$self->static->paths}, $self->home->rel_file('koha-tmpl');
+    push @{$self->static->paths}, '/usr/share/koha/opac/htdocs';
+    push @{$self->static->paths}, '/usr/share/koha/intranet/htdocs';
+
+    # Load config
+    $self->plugin('Config', {file => '/etc/koha/app.conf'});
 
     # Create route for all CGI scripts, need to be loaded first because of
     # CGI::Compile
@@ -46,6 +50,7 @@ sub startup {
 
     $r->any('/')->to(cb => sub { shift->redirect_to('/cgi-bin/koha/opac-main.pl') });
     $r->any('/intranet')->to(cb => sub { shift->redirect_to('/cgi-bin/koha/mainpage.pl') });
+    $r->any('/*')->to(cb => sub { shift->redirect_to('/cgi-bin/koha/errors/404.pl') });
 }
 
 sub _before_dispatch {
@@ -57,6 +62,12 @@ sub _before_dispatch {
     # Remove Koha version from URL
     $url =~ s/_\d{2}\.\d{7}\.(js|css)/.$1/;
 
+    # Set caches for static content
+    if ($url =~ /\.(js|css|gif|png)$/) {
+        $c->res->headers->cache_control('public');
+        $c->res->headers->expires(Mojo::Date->new(time+86400));
+    }
+
     # See FIXME above
     if ($url =~ m|^/api/v|) {
         $url = '/api' . $url;
diff --git a/Koha/App/Plugin/CGIBinKoha.pm b/Koha/App/Plugin/CGIBinKoha.pm
index 1c1989f..548363e 100644
--- a/Koha/App/Plugin/CGIBinKoha.pm
+++ b/Koha/App/Plugin/CGIBinKoha.pm
@@ -32,11 +32,16 @@ sub register {
         # Guess if it's an OPAC script, or an Intranet script
         # FIXME: errors scripts (400.pl, 401.pl, ...) exist in both intranet and
         # opac. The intranet ones will never be executed
-        if (-e $c->app->home->rel_file("opac/$script")) {
-            $script = "opac/$script";
-        }
 
-        unless (-e $c->app->home->rel_file($script)) {
+        my $base = $app->config->{basepath};
+
+        if (-e "$base/opac/cgi-bin/opac/$script") {
+            $script = "$base/opac/cgi-bin/opac/$script";
+        }
+        elsif (-e "$base/intranet/cgi-bin/$script") {
+            $script = "$base/intranet/cgi-bin/$script";
+        }
+        else {
             return $c->reply->not_found;
         }
 
diff --git a/etc/app.conf b/etc/app.conf
new file mode 100644
index 0000000..e9963d6
--- /dev/null
+++ b/etc/app.conf
@@ -0,0 +1,8 @@
+{
+  basepath => '/usr/share/koha',
+  hypnotoad => {
+    listen  => ['http://127.0.0.1:3000'],
+    workers => 10,
+    pid_file => '/run/koha/koha-app.pid'
+  }
+};
diff --git a/etc/systemd/koha-app.service b/etc/systemd/koha-app.service
new file mode 100644
index 0000000..9d7b3fc
--- /dev/null
+++ b/etc/systemd/koha-app.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Koha ILMS Mojolicious App
+After=network.target local-fs.target
+
+[Service]
+Type=forking
+PIDFile=/run/koha/koha-app.pid
+ExecStart=/usr/bin/hypnotoad ./bin/koha
+ExecReload=/usr/bin/hypnotoad ./bin/koha
+KillMode=process
+WorkingDirectory=/usr/share/koha
+Environment=MOJO_LOG_LEVEL=warn
+
+[Install]
+WantedBy=multi-user.target