diff --git a/tfclient/src/config.rs b/tfclient/src/config.rs
index c3b6adb..ff14660 100644
--- a/tfclient/src/config.rs
+++ b/tfclient/src/config.rs
@@ -1,6 +1,7 @@
-
+use std::collections::HashMap;
 use std::error::Error;
 use std::fs;
+use std::net::{Ipv4Addr, SocketAddrV4};
 
 
 use log::{debug, info};
@@ -94,4 +95,51 @@ pub fn save_cdata(instance: &str, data: TFClientData) -> Result<(), Box<dyn Erro
     fs::write(config_file, config)?;
     info!("Saved cdata successfully");
     Ok(())
-}
\ No newline at end of file
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct NebulaConfig {
+    pub pki: NebulaConfigPki,
+    #[serde(default = "empty_hashmap")]
+    pub static_host_map: HashMap<Ipv4Addr, Vec<SocketAddrV4>>,
+    pub lighthouse: Option<NebulaConfigLighthouse>
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct NebulaConfigPki {
+    pub ca: String,
+    pub cert: String,
+    pub key: String,
+    #[serde(default = "empty_vec")]
+    pub blocklist: Vec<String>,
+    #[serde(default = "bool_false")]
+    pub disconnect_invalid: bool
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct NebulaConfigLighthouse {
+    #[serde(default = "bool_false")]
+    pub am_lighthouse: bool,
+    #[serde(default = "bool_false")]
+    pub serve_dns: bool,
+    pub dns: Option<NebulaConfigLighthouseDns>,
+    #[serde(default = "u32_10")]
+    pub interval: u32,
+    #[serde(default = "empty_vec")]
+    pub hosts: Vec<Ipv4Addr>,
+    #[serde(default = "empty_hashmap")]
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct NebulaConfigLighthouseDns {
+    pub host: Ipv4Addr,
+    #[serde(default = "u16_53")]
+    pub port: u16
+}
+
+// Default values for serde
+fn empty_vec<T>() -> Vec<T> { vec![] }
+fn empty_hashmap<A, B>() -> HashMap<A, B> { HashMap::new() }
+fn bool_false() -> bool { false }
+fn u16_53() -> u16 { 53 }
+fn u32_10() -> u32 { 10 }
\ No newline at end of file
diff --git a/tfclient/src/daemon.rs b/tfclient/src/daemon.rs
index 00c56a2..7d912e0 100644
--- a/tfclient/src/daemon.rs
+++ b/tfclient/src/daemon.rs
@@ -89,8 +89,9 @@ pub fn daemon_main(name: String, server: String) {
     info!("Starting Nebula thread...");
     let config_nebula = config.clone();
     let transmitter_nebula = transmitter.clone();
+    let name_nebula = name.clone();
     let nebula_thread = thread::spawn(move || {
-        nebulaworker_main(config_nebula, transmitter_nebula, rx_nebula);
+        nebulaworker_main(config_nebula, name, transmitter_nebula, rx_nebula);
     });
 
     info!("Starting timer thread...");
diff --git a/tfclient/src/nebulaworker.rs b/tfclient/src/nebulaworker.rs
index d54df49..7cb685a 100644
--- a/tfclient/src/nebulaworker.rs
+++ b/tfclient/src/nebulaworker.rs
@@ -2,7 +2,7 @@
 
 use std::sync::mpsc::{Receiver, TryRecvError};
 use log::{error, info};
-use crate::config::TFClientConfig;
+use crate::config::{load_cdata, save_cdata, TFClientConfig};
 use crate::daemon::ThreadMessageSender;
 
 pub enum NebulaWorkerMessage {
@@ -10,7 +10,17 @@ pub enum NebulaWorkerMessage {
     ConfigUpdated
 }
 
-pub fn nebulaworker_main(_config: TFClientConfig, _transmitter: ThreadMessageSender, rx: Receiver<NebulaWorkerMessage>) {
+pub fn nebulaworker_main(_config: TFClientConfig, instance: String, _transmitter: ThreadMessageSender, rx: Receiver<NebulaWorkerMessage>) {
+    let cdata = match load_cdata(&instance) {
+        Ok(data) => data,
+        Err(e) => {
+            error!("unable to load cdata: {}", e);
+            error!("nebula thread exiting with error");
+            return;
+        }
+    };
+
+    // dont need to save it, because we do not, in any circumstance, write to it
     loop {
         match rx.try_recv() {
             Ok(msg) => {