diff --git a/.dockerignore b/.dockerignore
index 4288d3cb5..d7177be49 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -2,4 +2,5 @@ ui/node_modules
 ui/dist
 server/target
 docker/dev/volumes
+docker/federation-test/volumes
 .git
diff --git a/ansible/templates/docker-compose.yml b/ansible/templates/docker-compose.yml
index 57ee142a6..ffd5b9c2b 100644
--- a/ansible/templates/docker-compose.yml
+++ b/ansible/templates/docker-compose.yml
@@ -6,6 +6,8 @@ services:
     ports:
       - "127.0.0.1:8536:8536"
     restart: always
+    environment:
+      - RUST_LOG=debug
     volumes:
       - ./lemmy.hjson:/config/config.hjson:ro
     depends_on:
@@ -43,4 +45,4 @@ services:
     image: mwader/postfix-relay
     environment:
       - POSTFIX_myhostname={{ domain }}
-    restart: "always"
\ No newline at end of file
+    restart: "always"
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index 64ba1db43..a7d289b21 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -18,6 +18,8 @@ services:
     ports:
       - "127.0.0.1:8536:8536"
     restart: always
+    environment:
+      - RUST_LOG=debug
     volumes:
       - ../lemmy.hjson:/config/config.hjson:ro
     depends_on: 
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 70c6bfe70..9f5e89259 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -16,6 +16,8 @@ services:
     ports:
       - "127.0.0.1:8536:8536"
     restart: always
+    environment:
+      - RUST_LOG=debug
     volumes:
       - ./lemmy.hjson:/config/config.hjson:ro
     depends_on:
diff --git a/install.sh b/install.sh
index b368891cf..ad3e4ab3a 100755
--- a/install.sh
+++ b/install.sh
@@ -16,7 +16,7 @@ init_db_final=0
 while [ "$init_db_valid" == 0 ]
 do
   read -p "Initialize database (y/n)? " init_db
-  case "${init_db,,}" in 
+  case "${init_db,,}" in
     y|yes ) init_db_valid=1; init_db_final=1;;
     n|no ) init_db_valid=1; init_db_final=0;;
     * ) echo "Invalid input" 1>&2;;
@@ -37,7 +37,7 @@ yarn build
 
 # Build and run the backend
 cd ../server
-cargo run
+RUST_LOG=debug cargo run
 
 # For live coding, where both the front and back end, automagically reload on any save, do:
 # cd ui && yarn start
diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs
index 5c6149666..8373a338b 100644
--- a/server/src/api/comment.rs
+++ b/server/src/api/comment.rs
@@ -2,6 +2,7 @@ use super::*;
 use crate::send_email;
 use crate::settings::Settings;
 use diesel::PgConnection;
+use log::error;
 use std::str::FromStr;
 
 #[derive(Serialize, Deserialize)]
@@ -128,7 +129,7 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
           // Let the uniqueness handle this fail
           match UserMention::create(&conn, &user_mention_form) {
             Ok(_mention) => (),
-            Err(_e) => eprintln!("{}", &_e),
+            Err(_e) => error!("{}", &_e),
           };
 
           // Send an email to those users that have notifications on
@@ -145,7 +146,7 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
               );
               match send_email(subject, &mention_email, &mention_user.name, html) {
                 Ok(_o) => _o,
-                Err(e) => eprintln!("{}", e),
+                Err(e) => error!("{}", e),
               };
             }
           }
@@ -174,7 +175,7 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
               );
               match send_email(subject, &comment_reply_email, &parent_user.name, html) {
                 Ok(_o) => _o,
-                Err(e) => eprintln!("{}", e),
+                Err(e) => error!("{}", e),
               };
             }
           }
@@ -199,7 +200,7 @@ impl Perform<CommentResponse> for Oper<CreateComment> {
               );
               match send_email(subject, &post_reply_email, &parent_user.name, html) {
                 Ok(_o) => _o,
-                Err(e) => eprintln!("{}", e),
+                Err(e) => error!("{}", e),
               };
             }
           }
@@ -318,7 +319,7 @@ impl Perform<CommentResponse> for Oper<EditComment> {
           // Let the uniqueness handle this fail
           match UserMention::create(&conn, &user_mention_form) {
             Ok(_mention) => (),
-            Err(_e) => eprintln!("{}", &_e),
+            Err(_e) => error!("{}", &_e),
           }
         }
       }
diff --git a/server/src/api/user.rs b/server/src/api/user.rs
index f73138953..333fd9494 100644
--- a/server/src/api/user.rs
+++ b/server/src/api/user.rs
@@ -3,6 +3,7 @@ use crate::settings::Settings;
 use crate::{generate_random_string, send_email};
 use bcrypt::verify;
 use diesel::PgConnection;
+use log::error;
 use std::str::FromStr;
 
 #[derive(Serialize, Deserialize, Debug)]
@@ -1008,7 +1009,7 @@ impl Perform<PrivateMessageResponse> for Oper<CreatePrivateMessage> {
         );
         match send_email(subject, &email, &recipient_user.name, html) {
           Ok(_o) => _o,
-          Err(e) => eprintln!("{}", e),
+          Err(e) => error!("{}", e),
         };
       }
     }
diff --git a/server/src/lib.rs b/server/src/lib.rs
index f437c200b..eeaadb63a 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -39,6 +39,7 @@ use lettre::smtp::extension::ClientId;
 use lettre::smtp::ConnectionReuseParameters;
 use lettre::{ClientSecurity, SmtpClient, Transport};
 use lettre_email::Email;
+use log::error;
 use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
 use rand::distributions::Alphanumeric;
 use rand::{thread_rng, Rng};
@@ -190,7 +191,7 @@ fn fetch_iframely_and_pictshare_data(
     Some(url) => match fetch_iframely(&url) {
       Ok(res) => (res.title, res.description, res.thumbnail_url, res.html),
       Err(e) => {
-        eprintln!("iframely err: {}", e);
+        error!("iframely err: {}", e);
         (None, None, None, None)
       }
     },
@@ -202,7 +203,7 @@ fn fetch_iframely_and_pictshare_data(
     Some(iframely_thumbnail_url) => match fetch_pictshare(&iframely_thumbnail_url) {
       Ok(res) => Some(res.url),
       Err(e) => {
-        eprintln!("pictshare err: {}", e);
+        error!("pictshare err: {}", e);
         None
       }
     },
diff --git a/server/src/routes/websocket.rs b/server/src/routes/websocket.rs
index a68b2bcde..6c4326fd3 100644
--- a/server/src/routes/websocket.rs
+++ b/server/src/routes/websocket.rs
@@ -3,6 +3,7 @@ use actix::prelude::*;
 use actix_web::web;
 use actix_web::*;
 use actix_web_actors::ws;
+use log::{error, info};
 use std::time::{Duration, Instant};
 
 pub fn config(cfg: &mut web::ServiceConfig) {
@@ -99,7 +100,6 @@ impl Handler<WSMessage> for WSSession {
   type Result = ();
 
   fn handle(&mut self, msg: WSMessage, ctx: &mut Self::Context) {
-    // println!("id: {} msg: {}", self.id, msg.0);
     ctx.text(msg.0);
   }
 }
@@ -107,11 +107,10 @@ impl Handler<WSMessage> for WSSession {
 /// WebSocket message handler
 impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WSSession {
   fn handle(&mut self, result: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
-    // println!("WEBSOCKET MESSAGE: {:?} from id: {}", msg, self.id);
     let message = match result {
       Ok(m) => m,
       Err(e) => {
-        println!("{}", e);
+        error!("{}", e);
         return;
       }
     };
@@ -125,7 +124,7 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WSSession {
       }
       ws::Message::Text(text) => {
         let m = text.trim().to_owned();
-        println!("WEBSOCKET MESSAGE: {:?} from id: {}", &m, self.id);
+        info!("Message received: {:?} from id: {}", &m, self.id);
 
         self
           .cs_addr
@@ -138,14 +137,14 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WSSession {
             match res {
               Ok(res) => ctx.text(res),
               Err(e) => {
-                eprintln!("{}", &e);
+                error!("{}", &e);
               }
             }
             actix::fut::ready(())
           })
           .wait(ctx);
       }
-      ws::Message::Binary(_bin) => println!("Unexpected binary"),
+      ws::Message::Binary(_bin) => info!("Unexpected binary"),
       ws::Message::Close(_) => {
         ctx.stop();
       }
@@ -163,7 +162,7 @@ impl WSSession {
       // check client heartbeats
       if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT {
         // heartbeat timed out
-        println!("Websocket Client heartbeat failed, disconnecting!");
+        error!("Websocket Client heartbeat failed, disconnecting!");
 
         // notify chat server
         act.cs_addr.do_send(Disconnect {
diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs
index e200b1b99..831f12ee1 100644
--- a/server/src/websocket/server.rs
+++ b/server/src/websocket/server.rs
@@ -6,7 +6,7 @@ use actix::prelude::*;
 use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
 use diesel::PgConnection;
 use failure::Error;
-use log::warn;
+use log::{error, info, warn};
 use rand::{rngs::ThreadRng, Rng};
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
@@ -344,7 +344,7 @@ impl ChatServer {
           }
 
           if rate_limit.allowance < 1.0 {
-            println!(
+            warn!(
               "Rate limited IP: {}, time_passed: {}, allowance: {}",
               &info.ip, time_passed, rate_limit.allowance
             );
@@ -388,7 +388,7 @@ impl Handler<Connect> for ChatServer {
   fn handle(&mut self, msg: Connect, _ctx: &mut Context<Self>) -> Self::Result {
     // register session with random id
     let id = self.rng.gen::<usize>();
-    println!("{} joined", &msg.ip);
+    info!("{} joined", &msg.ip);
 
     self.sessions.insert(
       id,
@@ -451,11 +451,11 @@ impl Handler<StandardMessage> for ChatServer {
   fn handle(&mut self, msg: StandardMessage, _: &mut Context<Self>) -> Self::Result {
     match parse_json_message(self, msg) {
       Ok(m) => {
-        println!("Message Sent: {}", m);
+        info!("Message Sent: {}", m);
         MessageResult(m)
       }
       Err(e) => {
-        warn!("Error during message handling {}", e);
+        error!("Error during message handling {}", e);
         MessageResult(e.to_string())
       }
     }