diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..94a969dc1f2264778bbdf7ecd0917c3cc4c7f9be
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+/target
+.env
+Dockerfile
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5ffc2ce997518f8aaa8d2457548d246261efda32..af965808505f24eca6498781a71d48d5c6268168 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,6 +11,8 @@ stages:
 .test-template:
   tags:
     - kube
+  except:
+    - master
   image: rust:1.67.1-buster
   stage: test
   interruptible: true
@@ -35,3 +37,16 @@ fmt:
   script:
     - rustup component add rustfmt
     - pre-commit run fmt -av
+
+build_img:
+  tags:
+    - kube
+  only:
+    - master
+  image:
+    name: r.j3ss.co/img
+    entrypoint: [""]
+  script:
+    - img login --password "${DOCKER_PASSWORD}" --username "${DOCKER_USER}" "${DOCKER_REGISTRY}"
+    - img build --no-console -t docker.le-memese.com/bots/s3bot:latest .
+    - img push docker.le-memese.com/bots/s3bot:latest
diff --git a/Cargo.lock b/Cargo.lock
index 804087c3f1f65b918d6d0ce00bae60908fa14300..48e9db9dfe516c23feb6dfd77fa6d6a5c598e352 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1964,6 +1964,7 @@ dependencies = [
  "libc",
  "memchr",
  "mio",
+ "num_cpus",
  "parking_lot",
  "pin-project-lite",
  "signal-hook-registry",
diff --git a/Cargo.toml b/Cargo.toml
index d86072d128bddbfb889be2eba361269b820f5ed6..bc66a3b666993989f4e18730e03b3bdafae004c2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,4 +25,9 @@ rand = "0.8.5"
 rayon = "1.6.1"
 serde = { version = "1.0.152", features = ["derive"] }
 serde_json = "1.0.93"
-tokio = { version = "1.25.0", features = ["bytes", "rt", "macros"] }
+tokio = { version = "1.25.0", features = [
+    "bytes",
+    "rt",
+    "macros",
+    "rt-multi-thread",
+] }
diff --git a/Dockerfile b/Dockerfile
index 08ebc90f0d45884285702206eec16ad0e024961b..54495390c433c5ac6f2239133c8490b2bdf62a54 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,15 @@
-FROM rust:1.67.1-alpine3.17 as builder
+FROM rust:1.67.1-buster as builder
 
 WORKDIR /app
-COPY Cargo.toml Cargo.lock ./
+COPY Cargo.toml Cargo.lock askama.toml ./
 COPY src ./src
+COPY static ./static
 RUN cargo build --release --all-features
 
 FROM debian:bullseye-20230109-slim as base
 
+WORKDIR /
+
 RUN apt-get update \
     && apt-get install -y openssl ca-certificates \
     && rm -rf /var/lib/apt/lists/*
@@ -21,4 +24,5 @@ FROM base as rootless
 
 RUN useradd --create-home  -u 1000 --user-group s3bot
 WORKDIR /home/s3bot
+RUN mv /static ./static
 USER s3bot
diff --git a/src/main.rs b/src/main.rs
index aa91b0e893b702671650770dcfc02bf553bf66de..1d4ed0d8f8bead92de0d5f527789f8576ebede54 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,9 @@
-use futures::{stream::FuturesUnordered, StreamExt};
+use futures::{stream::FuturesUnordered, Future};
 use std::sync::Arc;
 use tokio::sync::RwLock;
 
 use clap::Parser;
+use futures::StreamExt;
 use logging::setup_logger;
 
 mod args;
@@ -11,7 +12,12 @@ mod logging;
 mod server;
 pub mod utils;
 
-#[tokio::main(flavor = "current_thread")]
+async fn error_wrap<T>(fut: impl Future<Output = std::io::Result<T>>) -> anyhow::Result<T> {
+    let res = fut.await?;
+    Ok(res)
+}
+
+#[tokio::main]
 async fn main() -> anyhow::Result<()> {
     dotenvy::dotenv().ok();
     let args = args::Arguments::parse();
@@ -22,29 +28,24 @@ async fn main() -> anyhow::Result<()> {
     let bot_token = token_lock.clone();
     let server_token = token_lock.clone();
 
-    let local_set = tokio::task::LocalSet::new();
-    local_set
-        .run_until(async {
-            let tasks = vec![
-                tokio::task::spawn_local(bot::start(args.bot.clone(), bot_token)),
-                tokio::task::spawn_local(server::start(args.server.clone(), server_token)),
-            ];
-            // Here we wait for one async task to complete.
-            let completed = tasks
-                .into_iter()
-                .collect::<FuturesUnordered<_>>()
-                .take(1)
-                .collect::<Vec<_>>()
-                .await;
-            // Now we get all completed futures (one future),
-            // and return it's result.
-            if let Some(fut) = completed.into_iter().next() {
-                fut?
-            } else {
-                Ok(())
-            }
-        })
-        .await?;
-
-    Ok(())
+    let web_server = server::create(args.server.clone(), server_token)?;
+    let bot_future = bot::start(args.bot.clone(), bot_token);
+
+    let tasks = [
+        tokio::task::spawn(bot_future),
+        tokio::task::spawn(error_wrap(web_server)),
+    ];
+
+    let completed = tasks
+        .into_iter()
+        .collect::<FuturesUnordered<_>>()
+        .take(1)
+        .collect::<Vec<_>>()
+        .await;
+
+    if let Some(fut) = completed.into_iter().next() {
+        fut?
+    } else {
+        Ok(())
+    }
 }
diff --git a/src/server/main.rs b/src/server/main.rs
index 016606fd539c8f85afe5b33f9c3483d5e4cec7b7..8559ea06af58f2075725f79d7092f43db2af1033 100644
--- a/src/server/main.rs
+++ b/src/server/main.rs
@@ -1,15 +1,15 @@
 use std::sync::Arc;
 use tokio::sync::RwLock;
 
-use actix_web::{web::Data, App, HttpServer};
+use actix_web::{dev::Server, web::Data, App, HttpServer};
 
 use crate::args::ServerConfig;
 
 use super::routes::{healthcheck, index, login};
 
-pub async fn start(args: ServerConfig, token: Arc<RwLock<Option<String>>>) -> anyhow::Result<()> {
+pub fn create(args: ServerConfig, token: Arc<RwLock<Option<String>>>) -> anyhow::Result<Server> {
     let addr = (args.host.clone(), args.port);
-    HttpServer::new(move || {
+    let server = HttpServer::new(move || {
         App::new()
             .wrap(actix_web::middleware::Logger::new(
                 "\"%r\" \"-\" \"%s\" \"%a\" \"%D\"",
@@ -23,7 +23,6 @@ pub async fn start(args: ServerConfig, token: Arc<RwLock<Option<String>>>) -> an
     })
     .bind(addr)?
     .workers(1)
-    .run()
-    .await?;
-    Ok(())
+    .run();
+    Ok(server)
 }
diff --git a/src/server/mod.rs b/src/server/mod.rs
index f35abb767028ff61dd8a83e413d8862bb770e7bf..4092409882b66f62f37ec96842126ed23a1f91c9 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -3,4 +3,4 @@ mod routes;
 mod schema;
 mod templates;
 
-pub use main::start;
+pub use main::create;