diff --git a/Cargo.lock b/Cargo.lock
index 5e6dc73e..df7e88f6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -142,6 +142,7 @@ dependencies = [
 name = "conduit"
 version = "0.1.0"
 dependencies = [
+ "base64 0.12.0",
  "directories",
  "http",
  "js_int",
@@ -1265,6 +1266,7 @@ dependencies = [
  "ruma-api",
  "ruma-events",
  "ruma-identifiers",
+ "ruma-serde",
  "serde",
  "serde_json",
 ]
@@ -1292,7 +1294,6 @@ dependencies = [
 [[package]]
 name = "ruma-signatures"
 version = "0.6.0-dev.1"
-source = "git+https://github.com/ruma/ruma-signatures.git#c3f8399c268695464730afd6077c7ce50155b8d5"
 dependencies = [
  "base64 0.12.0",
  "ring",
diff --git a/Cargo.toml b/Cargo.toml
index 2a3a0b63..afe23f79 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,7 +17,7 @@ ruma-client-api = { git = "https://github.com/ruma/ruma-client-api.git" }
 ruma-identifiers = "0.15.1"
 ruma-api = "0.16.0-rc.1"
 ruma-events = "0.19.0"
-ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git" }
+ruma-signatures = { path = "../ruma-signatures" }
 ruma-federation-api = { path = "../ruma-federation-api" }
 pretty_env_logger = "0.4.0"
 log = "0.4.8"
@@ -30,3 +30,4 @@ tokio = { version = "0.2.18", features = ["macros"] }
 rand = "0.7.3"
 rust-argon2 = "0.8.2"
 reqwest = "0.10.4"
+base64 = "0.12.0"
diff --git a/src/client_server.rs b/src/client_server.rs
index c97ba80c..a2cc5754 100644
--- a/src/client_server.rs
+++ b/src/client_server.rs
@@ -756,7 +756,7 @@ pub async fn get_public_rooms_filtered_route(
     chunk.extend_from_slice(
         &server_server::send_request(
             &data,
-            "https://matrix.org".to_owned(),
+            "https://matrix.koesters.xyz".to_owned(),
             ruma_federation_api::v1::get_public_rooms::Request {
                 limit: None,
                 since: None,
diff --git a/src/main.rs b/src/main.rs
index f26ed913..0794fcfe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -60,6 +60,10 @@ fn setup_rocket(data: Data) -> rocket::Rocket {
                 client_server::turn_server_route,
                 client_server::publicised_groups_route,
                 client_server::options_route,
+                server_server::well_known_server,
+                server_server::get_server_version,
+                server_server::get_server_keys,
+                server_server::get_server_keys_deprecated,
             ],
         )
         .manage(data)
@@ -72,7 +76,7 @@ fn main() {
     }
     pretty_env_logger::init();
 
-    let data = Data::load_or_create("matrixtesting.koesters.xyz");
+    let data = Data::load_or_create("matrixtesting.koesters.xyz:14004");
     //data.debug();
 
     setup_rocket(data).launch().unwrap();
diff --git a/src/server_server.rs b/src/server_server.rs
index 8f355c0e..cbdcb6ad 100644
--- a/src/server_server.rs
+++ b/src/server_server.rs
@@ -1,10 +1,20 @@
-use log::error;
+use crate::{utils, Data, MatrixResult, Ruma};
 use http::header::{HeaderValue, AUTHORIZATION};
+use log::error;
+use rocket::{get, options, post, put, response::content::Json, State};
 use ruma_api::{
     error::{FromHttpRequestError, FromHttpResponseError},
     Endpoint, Outgoing,
 };
-use std::convert::{TryFrom, TryInto};
+use ruma_client_api::error::{Error, ErrorKind};
+use ruma_federation_api::{v1::get_server_version, v2::get_server_keys};
+use serde_json::json;
+use std::{
+    collections::{BTreeMap, HashMap},
+    convert::{TryFrom, TryInto},
+    path::PathBuf,
+    time::{Duration, SystemTime},
+};
 
 pub async fn send_request<T: Endpoint>(
     data: &crate::Data,
@@ -39,7 +49,7 @@ where
     request_map.insert("origin".to_owned(), data.hostname().into());
     request_map.insert("destination".to_owned(), destination.to_string().into());
 
-    ruma_signatures::sign_json(data.hostname(), data.keypair(), dbg!(&mut request_json)).unwrap();
+    ruma_signatures::sign_json(data.hostname(), data.keypair(), &mut request_json).unwrap();
     let signatures = request_json["signatures"]
         .as_object()
         .unwrap()
@@ -52,7 +62,16 @@ where
         .map(|(k, v)| (k, v.as_str().unwrap()));
 
     for s in signatures {
-        http_request.headers_mut().insert(AUTHORIZATION, HeaderValue::from_str(dbg!(&format!("X-Matrix origin={},key=\"{}\",sig=\"{}\"", data.hostname(), s.0, s.1))).unwrap());
+        http_request.headers_mut().insert(
+            AUTHORIZATION,
+            HeaderValue::from_str(&format!(
+                "X-Matrix origin={},key=\"{}\",sig=\"{}\"",
+                data.hostname(),
+                s.0,
+                s.1
+            ))
+            .unwrap(),
+        );
     }
 
     let reqwest_response = data
@@ -79,7 +98,13 @@ where
                 .unwrap()
                 .into_iter()
                 .collect();
-            Some(<T::Response as Outgoing>::Incoming::try_from(dbg!(http_response.body(body).unwrap())).ok().unwrap())
+            Some(
+                <T::Response as Outgoing>::Incoming::try_from(
+                    dbg!(http_response.body(body)).unwrap(),
+                )
+                .ok()
+                .unwrap(),
+            )
         }
         Err(e) => {
             println!("ERROR: {}", e);
@@ -87,3 +112,54 @@ where
         }
     }
 }
+
+#[get("/.well-known/matrix/server")]
+pub fn well_known_server(data: State<Data>) -> Json<String> {
+    rocket::response::content::Json(
+        json!({ "m.server": "matrixtesting.koesters.xyz:14004"}).to_string(),
+    )
+}
+
+#[get("/_matrix/federation/v1/version")]
+pub fn get_server_version(data: State<Data>) -> MatrixResult<get_server_version::Response, Error> {
+    MatrixResult(Ok(get_server_version::Response {
+        server: get_server_version::Server {
+            name: Some("Conduit".to_owned()),
+            version: Some(env!("CARGO_PKG_VERSION").to_owned()),
+        },
+    }))
+}
+
+#[get("/_matrix/key/v2/server", data = "<body>")]
+pub fn get_server_keys(data: State<Data>, body: Ruma<get_server_keys::Request>) -> Json<String> {
+    let mut verify_keys = BTreeMap::new();
+    verify_keys.insert(
+        format!("ed25519:{}", data.keypair().version()),
+        get_server_keys::VerifyKey {
+            key: base64::encode_config(data.keypair().public_key(), base64::STANDARD_NO_PAD),
+        },
+    );
+    let mut response = serde_json::from_slice(
+        http::Response::try_from(get_server_keys::Response {
+            server_name: data.hostname().to_owned(),
+            verify_keys,
+            old_verify_keys: BTreeMap::new(),
+            signatures: BTreeMap::new(),
+            valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 60 * 24),
+        })
+        .unwrap()
+        .body(),
+    )
+    .unwrap();
+    ruma_signatures::sign_json(data.hostname(), data.keypair(), &mut response).unwrap();
+    Json(dbg!(response.to_string()))
+}
+
+#[get("/_matrix/key/v2/server/<_key_id>", data = "<body>")]
+pub fn get_server_keys_deprecated(
+    data: State<Data>,
+    body: Ruma<get_server_keys::Request>,
+    _key_id: String,
+) -> Json<String> {
+    get_server_keys(data, body)
+}