diff --git a/grin/Cargo.toml b/grin/Cargo.toml
index d4f6bb5b4..b4b3a46cd 100644
--- a/grin/Cargo.toml
+++ b/grin/Cargo.toml
@@ -19,6 +19,8 @@ futures-cpupool = "^0.1.3"
 hyper = { git = "https://github.com/hyperium/hyper" }
 log = "^0.3"
 time = "^0.1"
+serde = "~0.9.10"
+serde_derive = "~0.9.10"
 tokio-core="^0.1.1"
 tokio-timer="^0.1.0"
 rand = "^0.3"
diff --git a/grin/src/lib.rs b/grin/src/lib.rs
index 184000468..51a6243cb 100644
--- a/grin/src/lib.rs
+++ b/grin/src/lib.rs
@@ -28,6 +28,9 @@ extern crate futures;
 extern crate futures_cpupool as cpupool;
 extern crate hyper;
 extern crate rand;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
 extern crate time;
 extern crate tokio_core;
 extern crate tokio_timer;
@@ -48,4 +51,5 @@ mod seed;
 mod sync;
 mod types;
 
-pub use server::{Server, ServerConfig, Seeding};
+pub use server::Server;
+pub use types::{ServerConfig, Seeding};
diff --git a/grin/src/server.rs b/grin/src/server.rs
index 70f09f7c8..76fbb1284 100644
--- a/grin/src/server.rs
+++ b/grin/src/server.rs
@@ -19,9 +19,11 @@
 use std::net::SocketAddr;
 use std::sync::{Arc, Mutex};
 use std::thread;
+use std::time;
 
-use futures::{future, Future};
+use futures::{future, Future, Stream};
 use tokio_core::reactor;
+use tokio_timer::Timer;
 
 use adapters::{NetToChainAdapter, ChainToNetAdapter};
 use api;
@@ -33,71 +35,7 @@ use p2p;
 use seed;
 use store;
 use sync;
-
-/// Errors than can be reported by a server implementation, mostly wraps
-/// underlying components errors.
-#[derive(Debug)]
-pub enum Error {
-	/// Error when trying to add a block to the chain
-	ChainErr(chain::pipe::Error),
-	/// Peer connection error
-	PeerErr(core::ser::Error),
-	/// Data store error
-	StoreErr(store::Error),
-}
-
-impl From<store::Error> for Error {
-	fn from(e: store::Error) -> Error {
-		Error::StoreErr(e)
-	}
-}
-
-/// Type of seeding the server will use to find other peers on the network.
-#[derive(Debug, Clone)]
-pub enum Seeding {
-	/// No seeding, mostly for tests that programmatically connect
-	None,
-	/// A list of seed addresses provided to the server
-	List(Vec<String>),
-	/// Automatically download a gist with a list of server addresses
-	Gist,
-}
-
-/// Full server configuration, aggregating configurations required for the
-/// different components.
-#[derive(Debug, Clone)]
-pub struct ServerConfig {
-	/// Directory under which the rocksdb stores will be created
-	pub db_root: String,
-
-	/// Network address for the Rest API HTTP server.
-	pub api_http_addr: String,
-
-	/// Allows overriding the default cuckoo cycle size
-	pub cuckoo_size: u8,
-
-	/// Capabilities expose by this node, also conditions which other peers this
-	/// node will have an affinity toward when connection.
-	pub capabilities: p2p::Capabilities,
-
-	pub seeding_type: Seeding,
-
-	/// Configuration for the peer-to-peer server
-	pub p2p_config: p2p::P2PConfig,
-}
-
-impl Default for ServerConfig {
-	fn default() -> ServerConfig {
-		ServerConfig {
-			db_root: ".grin".to_string(),
-			api_http_addr: "127.0.0.1:13415".to_string(),
-			cuckoo_size: 0,
-			capabilities: p2p::FULL_NODE,
-			seeding_type: Seeding::None,
-			p2p_config: p2p::P2PConfig::default(),
-		}
-	}
-}
+use types::*;
 
 /// Grin server holding internal structures.
 pub struct Server {
@@ -118,9 +56,22 @@ impl Server {
 	/// Instantiates and starts a new server.
 	pub fn start(config: ServerConfig) -> Result<Server, Error> {
 		let mut evtlp = reactor::Core::new().unwrap();
-		let serv = Server::future(config, &evtlp.handle());
-		evtlp.run(future::ok::<(), ()>(())).unwrap();
-		serv
+		let enable_mining = config.enable_mining;
+		let serv = Server::future(config, &evtlp.handle())?;
+		if enable_mining {
+			serv.start_miner();
+		}
+
+		let forever = Timer::default()
+			.interval(time::Duration::from_secs(60))
+			.for_each(move |_| {
+				debug!("event loop running");
+				Ok(())
+			})
+			.map_err(|_| ());
+
+		evtlp.run(forever).unwrap();
+		Ok(serv)
 	}
 
 	/// Instantiates a new server associated with the provided future reactor.
@@ -145,8 +96,8 @@ impl Server {
 			Seeding::List(seeds) => {
 				seed.connect_and_monitor(evt_handle.clone(), seed::predefined_seeds(seeds));
 			}
-			Seeding::Gist => {
-				seed.connect_and_monitor(evt_handle.clone(), seed::gist_seeds(evt_handle.clone()));
+			Seeding::WebStatic => {
+				seed.connect_and_monitor(evt_handle.clone(), seed::web_seeds(evt_handle.clone()));
 			}
 		}
 
@@ -202,25 +153,26 @@ impl Server {
 fn store_head(config: &ServerConfig)
               -> Result<(Arc<chain::store::ChainKVStore>, chain::Tip), Error> {
 	let chain_store = try!(chain::store::ChainKVStore::new(config.db_root.clone())
-		.map_err(&Error::StoreErr));
+		.map_err(&Error::Store));
 
 	// check if we have a head in store, otherwise the genesis block is it
 	let head = match chain_store.head() {
 		Ok(tip) => tip,
 		Err(store::Error::NotFoundErr) => {
-			debug!("No genesis block found, creating and saving one.");
+			info!("No genesis block found, creating and saving one.");
 			let mut gen = core::genesis::genesis();
 			if config.cuckoo_size > 0 {
 				gen.header.cuckoo_len = config.cuckoo_size;
 				let diff = gen.header.difficulty.clone();
 				core::pow::pow(&mut gen.header, diff).unwrap();
 			}
-			try!(chain_store.save_block(&gen).map_err(&Error::StoreErr));
+			try!(chain_store.save_block(&gen).map_err(&Error::Store));
 			let tip = chain::types::Tip::new(gen.hash());
-			try!(chain_store.save_head(&tip).map_err(&Error::StoreErr));
+			try!(chain_store.save_head(&tip).map_err(&Error::Store));
+			info!("Saved genesis block with hash {}", gen.hash());
 			tip
 		}
-		Err(e) => return Err(Error::StoreErr(e)),
+		Err(e) => return Err(Error::Store(e)),
 	};
 	Ok((Arc::new(chain_store), head))
 }
diff --git a/grin/src/types.rs b/grin/src/types.rs
index 3a93d97c3..f5309a539 100644
--- a/grin/src/types.rs
+++ b/grin/src/types.rs
@@ -18,9 +18,14 @@ use chain;
 use p2p;
 use store;
 
+/// Error type wrapping underlying module errors.
+#[derive(Debug)]
 pub enum Error {
+	/// Error originating from the db storage.
 	Store(store::Error),
+	/// Error originating from the blockchain implementation.
 	Chain(chain::Error),
+	/// Error originating from the peer-to-peer network.
 	P2P(p2p::Error),
 }
 
@@ -41,3 +46,55 @@ impl From<store::Error> for Error {
 		Error::Store(e)
 	}
 }
+
+/// Type of seeding the server will use to find other peers on the network.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub enum Seeding {
+	/// No seeding, mostly for tests that programmatically connect
+	None,
+	/// A list of seed addresses provided to the server
+	List(Vec<String>),
+	/// Automatically download a text file with a list of server addresses
+	WebStatic,
+}
+
+/// Full server configuration, aggregating configurations required for the
+/// different components.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct ServerConfig {
+	/// Directory under which the rocksdb stores will be created
+	pub db_root: String,
+
+	/// Network address for the Rest API HTTP server.
+	pub api_http_addr: String,
+
+	/// Allows overriding the default cuckoo cycle size
+	pub cuckoo_size: u8,
+
+	/// Capabilities expose by this node, also conditions which other peers this
+	/// node will have an affinity toward when connection.
+	pub capabilities: p2p::Capabilities,
+
+	/// Method used to get the list of seed nodes for initial bootstrap.
+	pub seeding_type: Seeding,
+
+	/// Configuration for the peer-to-peer server
+	pub p2p_config: p2p::P2PConfig,
+
+	/// Whethere to start the miner with the server
+	pub enable_mining: bool,
+}
+
+impl Default for ServerConfig {
+	fn default() -> ServerConfig {
+		ServerConfig {
+			db_root: ".grin".to_string(),
+			api_http_addr: "127.0.0.1:13415".to_string(),
+			cuckoo_size: 0,
+			capabilities: p2p::FULL_NODE,
+			seeding_type: Seeding::None,
+			p2p_config: p2p::P2PConfig::default(),
+			enable_mining: false,
+		}
+	}
+}
diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml
index 97902e9cc..1614ba775 100644
--- a/p2p/Cargo.toml
+++ b/p2p/Cargo.toml
@@ -11,6 +11,8 @@ futures = "^0.1.9"
 log = "^0.3"
 net2 = "0.2.0"
 rand = "^0.3"
+serde = "~0.9.10"
+serde_derive = "~0.9.10"
 tokio-core="^0.1.1"
 tokio-timer="^0.1.0"
 time = "^0.1"
diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs
index ddcde0d77..f68d4e968 100644
--- a/p2p/src/lib.rs
+++ b/p2p/src/lib.rs
@@ -35,6 +35,9 @@ extern crate futures;
 extern crate tokio_core;
 extern crate tokio_timer;
 extern crate rand;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
 extern crate time;
 extern crate num;
 
diff --git a/p2p/src/types.rs b/p2p/src/types.rs
index 971bc9a4b..ef2b80e48 100644
--- a/p2p/src/types.rs
+++ b/p2p/src/types.rs
@@ -63,7 +63,7 @@ impl From<TimerError> for Error {
 }
 
 /// Configuration for the peer-to-peer server.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
 pub struct P2PConfig {
 	pub host: IpAddr,
 	pub port: u16,
@@ -82,6 +82,7 @@ impl Default for P2PConfig {
 
 bitflags! {
   /// Options for what type of interaction a peer supports
+  #[derive(Serialize, Deserialize)]
   pub flags Capabilities: u32 {
     /// We don't know (yet) what the peer can do.
     const UNKNOWN = 0b00000000,