diff --git a/Cargo.lock b/Cargo.lock
index 09ab31d..0142b54 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -33,22 +33,59 @@ dependencies = [
 ]
 
 [[package]]
-name = "arc-swap"
-version = "1.6.0"
+name = "anstream"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
 
 [[package]]
-name = "atty"
-version = "0.2.14"
+name = "anstyle-parse"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
 dependencies = [
- "hermit-abi 0.1.19",
- "libc",
- "winapi",
+ "utf8parse",
 ]
 
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "arc-swap"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f"
+
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -72,15 +109,15 @@ dependencies = [
 
 [[package]]
 name = "base64"
-version = "0.21.5"
+version = "0.21.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 
 [[package]]
 name = "bcder"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf16bec990f8ea25cab661199904ef452fcf11f565c404ce6cffbdf3f8cbbc47"
+checksum = "c627747a6774aab38beb35990d88309481378558875a41da1a4b2e373c906ef0"
 dependencies = [
  "bytes",
  "smallvec",
@@ -92,11 +129,17 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
+[[package]]
+name = "bitflags"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+
 [[package]]
 name = "bumpalo"
-version = "3.14.0"
+version = "3.15.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
 
 [[package]]
 name = "bytes"
@@ -106,12 +149,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
 
 [[package]]
 name = "cc"
-version = "1.0.83"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
-dependencies = [
- "libc",
-]
+checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
 
 [[package]]
 name = "cfg-if"
@@ -121,9 +161,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.31"
+version = "0.4.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
@@ -131,39 +171,60 @@ dependencies = [
  "num-traits",
  "serde",
  "wasm-bindgen",
- "windows-targets",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
 name = "clap"
-version = "3.2.25"
+version = "4.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
+checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
 dependencies = [
- "atty",
- "bitflags",
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
+dependencies = [
+ "anstream",
+ "anstyle",
  "clap_lex",
- "indexmap 1.9.3",
- "once_cell",
  "strsim",
- "termcolor",
- "textwrap",
 ]
 
 [[package]]
-name = "clap_lex"
-version = "0.2.4"
+name = "clap_derive"
+version = "4.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
+checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
 dependencies = [
- "os_str_bytes",
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
+[[package]]
+name = "clap_lex"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
 [[package]]
 name = "core-foundation"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -171,24 +232,36 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.4"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.16"
+version = "0.8.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+
+[[package]]
+name = "daemonbase"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e2e198b7af809909368f39c1ab50ef5403756b7d7cd2ba6942555bc146bc874"
 dependencies = [
- "cfg-if",
+ "chrono",
+ "clap",
+ "log",
+ "nix",
+ "serde",
+ "syslog",
+ "toml_edit 0.20.7",
 ]
 
 [[package]]
 name = "deranged"
-version = "0.3.9"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
 dependencies = [
  "powerfmt",
 ]
@@ -217,15 +290,6 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "fern"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee"
-dependencies = [
- "log",
-]
-
 [[package]]
 name = "fnv"
 version = "1.0.7"
@@ -243,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -258,9 +322,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -268,15 +332,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -285,15 +349,15 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -302,21 +366,21 @@ dependencies = [
 
 [[package]]
 name = "futures-sink"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
 
 [[package]]
 name = "futures-task"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
 
 [[package]]
 name = "futures-util"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -332,9 +396,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.11"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
 dependencies = [
  "cfg-if",
  "libc",
@@ -349,9 +413,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
 name = "h2"
-version = "0.3.22"
+version = "0.3.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
+checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
 dependencies = [
  "bytes",
  "fnv",
@@ -359,19 +423,13 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http",
- "indexmap 2.1.0",
+ "indexmap",
  "slab",
  "tokio",
  "tokio-util",
  "tracing",
 ]
 
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
 [[package]]
 name = "hashbrown"
 version = "0.14.3"
@@ -379,19 +437,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 
 [[package]]
-name = "hermit-abi"
-version = "0.1.19"
+name = "heck"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.3"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
 [[package]]
 name = "hostname"
@@ -406,9 +461,9 @@ dependencies = [
 
 [[package]]
 name = "http"
-version = "0.2.11"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
 dependencies = [
  "bytes",
  "fnv",
@@ -417,9 +472,9 @@ dependencies = [
 
 [[package]]
 name = "http-body"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
 dependencies = [
  "bytes",
  "http",
@@ -440,9 +495,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
 
 [[package]]
 name = "hyper"
-version = "0.14.27"
+version = "0.14.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
+checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -455,7 +510,7 @@ dependencies = [
  "httpdate",
  "itoa",
  "pin-project-lite",
- "socket2 0.4.10",
+ "socket2",
  "tokio",
  "tower-service",
  "tracing",
@@ -478,9 +533,9 @@ dependencies = [
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.58"
+version = "0.1.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -511,22 +566,12 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.1.0"
+version = "2.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
 dependencies = [
  "equivalent",
- "hashbrown 0.14.3",
+ "hashbrown",
 ]
 
 [[package]]
@@ -537,41 +582,30 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
 
 [[package]]
 name = "itoa"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 
 [[package]]
 name = "js-sys"
-version = "0.3.66"
+version = "0.3.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
 dependencies = [
  "wasm-bindgen",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.150"
+version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
-
-[[package]]
-name = "log-reroute"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "741a3ba679a9a1d331319dda1c7d8f204e9f6760fd867e28576a45d17048bc02"
-dependencies = [
- "arc-swap",
- "log",
- "once_cell",
-]
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 
 [[package]]
 name = "match_cfg"
@@ -581,9 +615,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
 
 [[package]]
 name = "memchr"
-version = "2.6.4"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 
 [[package]]
 name = "mime"
@@ -593,29 +627,46 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
 dependencies = [
  "adler",
 ]
 
 [[package]]
 name = "mio"
-version = "0.8.9"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
  "wasi",
- "windows-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "nix"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
+dependencies = [
+ "bitflags 2.4.2",
+ "cfg-if",
+ "libc",
 ]
 
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
 [[package]]
 name = "num-traits"
-version = "0.2.17"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
 dependencies = [
  "autocfg",
 ]
@@ -626,39 +677,33 @@ version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
- "hermit-abi 0.3.3",
+ "hermit-abi",
  "libc",
 ]
 
 [[package]]
 name = "num_threads"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "object"
-version = "0.32.1"
+version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
-
-[[package]]
-name = "os_str_bytes"
-version = "6.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "percent-encoding"
@@ -692,18 +737,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.70"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.33"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
 dependencies = [
  "proc-macro2",
 ]
@@ -749,9 +794,9 @@ dependencies = [
 
 [[package]]
 name = "reqwest"
-version = "0.11.22"
+version = "0.11.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
+checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
 dependencies = [
  "base64",
  "bytes",
@@ -775,6 +820,7 @@ dependencies = [
  "serde",
  "serde_json",
  "serde_urlencoded",
+ "sync_wrapper",
  "system-configuration",
  "tokio",
  "tokio-rustls",
@@ -804,16 +850,17 @@ dependencies = [
 
 [[package]]
 name = "ring"
-version = "0.17.5"
+version = "0.17.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b"
+checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
 dependencies = [
  "cc",
+ "cfg-if",
  "getrandom",
  "libc",
  "spin 0.9.8",
  "untrusted 0.9.0",
- "windows-sys",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -846,11 +893,10 @@ dependencies = [
  "chrono",
  "clap",
  "crossbeam-utils",
- "fern",
+ "daemonbase",
  "futures",
  "hyper",
  "log",
- "log-reroute",
  "pin-project-lite",
  "rand",
  "rand_pcg",
@@ -861,7 +907,6 @@ dependencies = [
  "serde",
  "serde_json",
  "slab",
- "syslog",
  "tokio",
  "tokio-rustls",
  "tokio-stream",
@@ -878,12 +923,12 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
 [[package]]
 name = "rustls"
-version = "0.21.9"
+version = "0.21.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9"
+checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
 dependencies = [
  "log",
- "ring 0.17.5",
+ "ring 0.17.8",
  "rustls-webpki",
  "sct",
 ]
@@ -903,15 +948,15 @@ version = "0.101.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
 dependencies = [
- "ring 0.17.5",
+ "ring 0.17.8",
  "untrusted 0.9.0",
 ]
 
 [[package]]
 name = "ryu"
-version = "1.0.15"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
 
 [[package]]
 name = "sct"
@@ -919,24 +964,24 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
 dependencies = [
- "ring 0.17.5",
+ "ring 0.17.8",
  "untrusted 0.9.0",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.193"
+version = "1.0.197"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.193"
+version = "1.0.197"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -945,9 +990,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.108"
+version = "1.0.114"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
 dependencies = [
  "itoa",
  "ryu",
@@ -956,9 +1001,9 @@ dependencies = [
 
 [[package]]
 name = "serde_spanned"
-version = "0.6.4"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
+checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
 dependencies = [
  "serde",
 ]
@@ -986,28 +1031,18 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.11.2"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
 
 [[package]]
 name = "socket2"
-version = "0.4.10"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
+checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
 dependencies = [
  "libc",
- "winapi",
-]
-
-[[package]]
-name = "socket2"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
-dependencies = [
- "libc",
- "windows-sys",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1030,15 +1065,21 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "syn"
-version = "2.0.39"
+version = "2.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-ident",
 ]
 
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
 [[package]]
 name = "syslog"
 version = "6.1.0"
@@ -1058,7 +1099,7 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "core-foundation",
  "system-configuration-sys",
 ]
@@ -1073,30 +1114,16 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "termcolor"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
-
 [[package]]
 name = "time"
-version = "0.3.30"
+version = "0.3.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
+checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
 dependencies = [
  "deranged",
  "itoa",
  "libc",
+ "num-conv",
  "num_threads",
  "powerfmt",
  "serde",
@@ -1112,10 +1139,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 [[package]]
 name = "time-macros"
-version = "0.2.15"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
+checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
 dependencies = [
+ "num-conv",
  "time-core",
 ]
 
@@ -1136,9 +1164,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.34.0"
+version = "1.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
+checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
 dependencies = [
  "backtrace",
  "bytes",
@@ -1146,9 +1174,9 @@ dependencies = [
  "mio",
  "num_cpus",
  "pin-project-lite",
- "socket2 0.5.5",
+ "socket2",
  "tokio-macros",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1199,14 +1227,14 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.8.8"
+version = "0.8.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
+checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290"
 dependencies = [
  "serde",
  "serde_spanned",
  "toml_datetime",
- "toml_edit",
+ "toml_edit 0.22.6",
 ]
 
 [[package]]
@@ -1220,15 +1248,26 @@ dependencies = [
 
 [[package]]
 name = "toml_edit"
-version = "0.21.0"
+version = "0.20.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow 0.5.40",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
+checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6"
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap",
  "serde",
  "serde_spanned",
  "toml_datetime",
- "winnow",
+ "winnow 0.6.5",
 ]
 
 [[package]]
@@ -1258,15 +1297,15 @@ dependencies = [
 
 [[package]]
 name = "try-lock"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.13"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
 
 [[package]]
 name = "unicode-ident"
@@ -1276,9 +1315,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
 name = "unicode-normalization"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
 dependencies = [
  "tinyvec",
 ]
@@ -1307,11 +1346,17 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
 [[package]]
 name = "uuid"
-version = "1.6.1"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
+checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
 
 [[package]]
 name = "version_check"
@@ -1336,9 +1381,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -1346,9 +1391,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
 dependencies = [
  "bumpalo",
  "log",
@@ -1361,9 +1406,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.39"
+version = "0.4.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
+checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -1373,9 +1418,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1383,9 +1428,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1396,15 +1441,15 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
 
 [[package]]
 name = "web-sys"
-version = "0.3.65"
+version = "0.3.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
+checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -1412,9 +1457,9 @@ dependencies = [
 
 [[package]]
 name = "webpki-roots"
-version = "0.25.3"
+version = "0.25.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
+checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
 
 [[package]]
 name = "winapi"
@@ -1432,15 +1477,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
-[[package]]
-name = "winapi-util"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
@@ -1449,11 +1485,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-core"
-version = "0.51.1"
+version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -1462,7 +1498,16 @@ version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -1471,13 +1516,28 @@ version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.4",
+ "windows_aarch64_msvc 0.52.4",
+ "windows_i686_gnu 0.52.4",
+ "windows_i686_msvc 0.52.4",
+ "windows_x86_64_gnu 0.52.4",
+ "windows_x86_64_gnullvm 0.52.4",
+ "windows_x86_64_msvc 0.52.4",
 ]
 
 [[package]]
@@ -1486,47 +1546,98 @@ version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
+
 [[package]]
 name = "winnow"
-version = "0.5.19"
+version = "0.5.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "winnow"
+version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b"
+checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
 dependencies = [
  "memchr",
 ]
@@ -1538,5 +1649,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
 dependencies = [
  "cfg-if",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 3317a5a..b76bc9f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,13 +14,12 @@ readme = "README.md"
 arc-swap        = "1.0"
 bytes           = "1"
 chrono          = "0.4.31"
-clap            = { version = "3.0", features = [ "cargo" ] }
+clap            = { version = "~4.4", features = [ "cargo", "derive" ] }
 crossbeam-utils = "0.8.4"
-fern            = "0.6.0"
+daemonbase      = "0.1.0"
 futures         = "0.3"
 hyper           = { version = "0.14.8", features = [ "server", "stream" ] }
 log             = "0.4"
-log-reroute     = "0.1.5"
 pin-project-lite = "0.2.4"
 rand            = "0.8.3"
 reqwest         = { version = "0.11.3", default-features = false, features = ["blocking", "rustls-tls"] }
@@ -37,9 +36,6 @@ toml            = "0.8.2"
 url             = { version = "2.2", features = ["serde"] }
 webpki-roots    = "0.25.2"
 
-[target.'cfg(unix)'.dependencies]
-syslog          = "6.0"
-
 [dev-dependencies]
 rand_pcg        = "0.3"
 
diff --git a/src/config.rs b/src/config.rs
index 6c2da44..3d4547f 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -6,14 +6,15 @@
 //! file referred to in command line options.
 
 use std::{borrow, error, fmt, fs, io, ops};
-use std::cell::RefCell;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::sync::Arc;
-use clap::{Arg, ArgMatches, Command};
+use clap::{Args as _, FromArgMatches};
+use daemonbase::logging;
+use daemonbase::config::ConfigPath;
+use daemonbase::error::Failed;
 use serde::Deserialize;
 use toml::Spanned;
 use crate::http;
-use crate::log::{ExitError, Failed, LogConfig};
 use crate::manager::{Manager, TargetSet, UnitSet};
 
 
@@ -39,7 +40,7 @@ pub struct Config {
 
     /// The logging configuration.
     #[serde(flatten)]
-    pub log: LogConfig,
+    pub log: logging::Config,
 
     /// The HTTP server configuration.
     #[serde(flatten)]
@@ -47,11 +48,11 @@ pub struct Config {
 }
 
 impl Config {
-    /// Initialises everything.
+    /// Adds the basic arguments to a Clap command.
     ///
-    /// This function should be called first thing.
-    pub fn init() -> Result<(), ExitError> {
-        LogConfig::init_logging()
+    /// Returns the command with the arguments added.
+    pub fn config_args(app: clap::Command) -> clap::Command {
+        Args::augment_args(app)
     }
 
     /// Creates a configuration from a bytes slice with TOML data.
@@ -66,20 +67,6 @@ impl Config {
         res
     }
 
-    /// Configures a clap app with the arguments to load the configuration.
-    pub fn config_args(app: Command) -> Command {
-        let app = app.arg(
-            Arg::new("config")
-                .short('c')
-                .long("config")
-                .required(true)
-                .takes_value(true)
-                .value_name("PATH")
-                .help("Read base configuration from this file")
-        );
-        LogConfig::config_args(app)
-    }
-
     /// Loads the configuration based on command line options provided.
     ///
     /// The `matches` must be the result of getting argument matches from a
@@ -91,30 +78,42 @@ impl Config {
     /// paths. The manager is necessary to resolve links given in the
     /// configuration.
     pub fn from_arg_matches(
-        matches: &ArgMatches,
-        cur_dir: &Path,
+        matches: &clap::ArgMatches,
         manager: &mut Manager,
     ) -> Result<Self, Failed> {
-        let conf_path = cur_dir.join(matches.value_of("config").unwrap());
-        let conf = match ConfigFile::load(&conf_path) {
+        let args = Args::from_arg_matches(
+            matches
+        ).expect("bug in command line arguments parser");
+        let conf = match ConfigFile::load(&args.config) {
             Ok(conf) => conf,
             Err(err) => {
                 eprintln!(
                     "Failed to read config file '{}': {}",
-                    conf_path.display(),
+                    args.config.display(),
                     err
                 );
                 return Err(Failed)
             }
         };
         let mut res = manager.load(conf)?;
-        res.log.update_with_arg_matches(matches, cur_dir)?;
-        res.log.switch_logging(false)?;
+        res.log.apply_args(&args.log);
         Ok(res)
     }
 }
 
 
+//------------ Args ----------------------------------------------------------
+
+#[derive(clap::Parser)]
+pub struct Args {
+    #[arg(short, long)]
+    pub config: ConfigPath,
+
+    #[command(flatten)]
+    pub log: logging::Args,
+}
+
+
 //------------ Source --------------------------------------------------------
 
 /// Description of the source of configuration.
@@ -370,77 +369,3 @@ impl fmt::Display for ConfigError {
 
 impl error::Error for ConfigError { }
 
-
-//------------ ConfigPath ----------------------------------------------------
-
-/// A path that encountered in a config file.
-///
-/// This is a basically a `PathBuf` that, when, deserialized resolves all
-/// relative paths from a certain base path so that all relative paths
-/// encountered in a config file are automatically resolved relative to the
-/// location of the config file.
-#[derive(
-    Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd
-)]
-#[serde(from = "String")]
-pub struct ConfigPath(PathBuf);
-
-impl ConfigPath {
-    thread_local!(
-        static BASE_PATH: RefCell<Option<PathBuf>> = const {
-            RefCell::new(None)
-        }
-    );
-
-    fn set_base_path(path: PathBuf) {
-        Self::BASE_PATH.with(|base_path| {
-            base_path.replace(Some(path));
-        })
-    }
-
-    fn clear_base_path() {
-        Self::BASE_PATH.with(|base_path| {
-            base_path.replace(None);
-        })
-    }
-}
-
-impl From<PathBuf> for ConfigPath {
-    fn from(path: PathBuf) -> Self {
-        Self(path)
-    }
-}
-
-impl From<ConfigPath> for PathBuf {
-    fn from(path: ConfigPath) -> Self {
-        path.0
-    }
-}
-
-impl From<String> for ConfigPath {
-    fn from(path: String) -> Self {
-        Self::BASE_PATH.with(|base_path| {
-            ConfigPath(
-                match base_path.borrow().as_ref() {
-                    Some(base_path) => base_path.join(path.as_str()),
-                    None => path.into()
-                }
-            )
-        })
-    }
-}
-
-impl ops::Deref for ConfigPath {
-    type Target = Path;
-
-    fn deref(&self) -> &Self::Target {
-        self.0.as_ref()
-    }
-}
-
-impl AsRef<Path> for ConfigPath {
-    fn as_ref(&self) -> &Path {
-        self.0.as_ref()
-    }
-}
-
diff --git a/src/http.rs b/src/http.rs
index f76800a..40439ba 100644
--- a/src/http.rs
+++ b/src/http.rs
@@ -15,6 +15,7 @@ use std::pin::Pin;
 use std::sync::{Arc, Mutex, Weak};
 use std::task::{Context, Poll};
 use arc_swap::ArcSwap;
+use daemonbase::error::ExitError;
 use futures::pin_mut;
 use hyper::{Body, Method, Request, Response, StatusCode};
 use hyper::server::accept::Accept;
@@ -24,7 +25,6 @@ use serde::Deserialize;
 use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
 use tokio::net::{TcpListener, TcpStream};
 use tokio::runtime::Runtime;
-use crate::log::ExitError;
 use crate::metrics;
 
 
@@ -64,7 +64,7 @@ impl Server {
                 Ok(listener) => listener,
                 Err(err) => {
                     error!("Fatal: error listening on {}: {}", addr, err);
-                    return Err(ExitError);
+                    return Err(ExitError::default());
                 }
             };
             if let Err(err) = listener.set_nonblocking(true) {
@@ -72,7 +72,7 @@ impl Server {
                     "Fatal: failed to set listener {} to non-blocking: {}.",
                     addr, err
                 );
-                return Err(ExitError);
+                return Err(ExitError::default());
             }
             debug!("HTTP server listening on {}", addr);
             listeners.push(listener);
diff --git a/src/lib.rs b/src/lib.rs
index 2f42a40..b792d70 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -27,7 +27,6 @@ pub mod comms;
 pub mod config;
 pub mod formats;
 pub mod http;
-pub mod log;
 pub mod manager;
 pub mod metrics;
 pub mod payload;
diff --git a/src/log.rs b/src/log.rs
deleted file mode 100644
index 90ea65b..0000000
--- a/src/log.rs
+++ /dev/null
@@ -1,457 +0,0 @@
-//! Logging.
-//!
-//! This module provides facilities to set up logging based on a configuration
-//! via [`LogConfig`].
-//!
-//! The module also provides two error types [`Failed`] and [`ExitError`] that
-//! indicate that error information has been logged and a consumer can just
-//! return quietly.
-use std::{fmt, io, process};
-use std::path::Path;
-use std::str::FromStr;
-use clap::{Arg, ArgMatches, Command};
-use log::{error, LevelFilter, Log};
-use serde::Deserialize;
-use crate::config::ConfigPath;
-
-
-//------------ LogConfig -----------------------------------------------------
-
-/// Logging configuration.
-#[derive(Deserialize)]
-pub struct LogConfig {
-    /// Where to log to?
-    #[serde(default)]
-    pub log_target: LogTarget,
-
-    /// If logging to a file, use this file.
-    ///
-    /// This isn’t part of `log_target` for deserialization reasons.
-    #[serde(default)]
-    pub log_file: ConfigPath,
-
-    /// The syslog facility when logging to syslog.
-    ///
-    /// This isn’t part of `log_target` for deserialization reasons.
-    #[cfg(unix)]
-    #[serde(default)]
-    pub log_facility: LogFacility,
-
-    /// The minimum log level to actually log.
-    #[serde(default)]
-    pub log_level: LogFilter,
-}
-
-impl LogConfig {
-    /// Configures a clap app with the options for logging.
-    pub fn config_args(app: Command) -> Command {
-        app
-        .arg(Arg::new("verbose")
-             .short('v')
-             .long("verbose")
-             .multiple_occurrences(true)
-             .help("Log more information, twice or thrice for even more")
-        )
-        .arg(Arg::new("quiet")
-             .short('q')
-             .long("quiet")
-             .multiple_occurrences(true)
-             .conflicts_with("verbose")
-             .help("Log less information, twice for no information")
-        )
-        .arg(Arg::new("syslog")
-             .long("syslog")
-             .help("Log to syslog")
-        )
-        .arg(Arg::new("syslog-facility")
-             .long("syslog-facility")
-             .takes_value(true)
-             .default_value("daemon")
-             .help("Facility to use for syslog logging")
-        )
-        .arg(Arg::new("logfile")
-             .long("logfile")
-             .takes_value(true)
-             .value_name("PATH")
-             .help("Log to this file")
-        )
-    }
-
-    /// Update the logging configuration from command line arguments.
-    ///
-    /// This should be called after the configuration file has been loaded.
-    pub fn update_with_arg_matches(
-        &mut self,
-        matches: &ArgMatches,
-        cur_dir: &Path,
-    ) -> Result<(), Failed> {
-        // log_level
-        for _ in 0..matches.occurrences_of("verbose") {
-            self.log_level.increase()
-        }
-        for _ in 0..matches.occurrences_of("quiet") {
-            self.log_level.decrease()
-        }
-
-        self.apply_log_matches(matches, cur_dir)?;
-
-        Ok(())
-    }
-
-    /// Applies the logging-specific command line arguments to the config.
-    ///
-    /// This is the Unix version that also considers syslog as a valid
-    /// target.
-    #[cfg(unix)]
-    fn apply_log_matches(
-        &mut self,
-        matches: &ArgMatches,
-        cur_dir: &Path,
-    ) -> Result<(), Failed> {
-        if matches.is_present("syslog") {
-            self.log_target = LogTarget::Syslog;
-            if let Some(value) = 
-                Self::from_str_value_of(matches, "syslog-facility")?
-            {
-                self.log_facility = value
-            }
-        }
-        else if let Some(file) = matches.value_of("logfile") {
-            if file == "-" {
-                self.log_target = LogTarget::Stderr
-            }
-            else {
-                self.log_target = LogTarget::File;
-                self.log_file = cur_dir.join(file).into();
-            }
-        }
-        Ok(())
-    }
-
-    /// Applies the logging-specific command line arguments to the config.
-    ///
-    /// This is the non-Unix version that does not use syslog.
-    #[cfg(not(unix))]
-    #[allow(clippy::unnecessary_wraps)]
-    fn apply_log_matches(
-        &mut self,
-        matches: &ArgMatches,
-        cur_dir: &Path,
-    ) -> Result<(), Failed> {
-        if let Some(file) = matches.value_of("logfile") {
-            if file == "-" {
-                self.log_target = LogTarget::Stderr
-            }
-            else {
-                self.log_target = LogTarget::File;
-                self.log_file = cur_dir.join(file).into();
-            }
-        }
-        Ok(())
-    }
-
-
-    /// Try to convert a string encoded value.
-    ///
-    /// This helper function just changes error handling. Instead of returning
-    /// the actual conversion error, it logs it as an invalid value for entry
-    /// `key` and returns the standard error.
-    #[allow(dead_code)] // unused on Windows
-    fn from_str_value_of<T>(
-        matches: &ArgMatches,
-        key: &str
-    ) -> Result<Option<T>, Failed>
-    where T: FromStr, T::Err: fmt::Display {
-        match matches.value_of(key) {
-            Some(value) => {
-                match T::from_str(value) {
-                    Ok(value) => Ok(Some(value)),
-                    Err(err) => {
-                        error!(
-                            "Invalid value for {}: {}.", 
-                            key, err
-                        );
-                        Err(Failed)
-                    }
-                }
-            }
-            None => Ok(None)
-        }
-    }
-
-    /// Initialize logging.
-    ///
-    /// All diagnostic output of RTRTR is done via logging, never to
-    /// stderr directly. Thus, it is important to initalize logging before
-    /// doing anything else that may result in such output. This function
-    /// does exactly that. It sets a maximum log level of `warn`, leading
-    /// only printing important information, and directs all logging to
-    /// stderr.
-    pub fn init_logging() -> Result<(), ExitError> {
-        log::set_max_level(log::LevelFilter::Warn);
-        if let Err(err) = log_reroute::init() {
-            eprintln!("Failed to initialize logger: {}.\nAborting.", err);
-            return Err(ExitError)
-        };
-        let dispatch = fern::Dispatch::new()
-            .level(log::LevelFilter::Error)
-            .chain(io::stderr())
-            .into_log().1;
-        log_reroute::reroute_boxed(dispatch);
-        Ok(())
-    }
-
-    /// Switches logging to the configured target.
-    ///
-    /// Once the configuration has been successfully loaded, logging should
-    /// be switched to whatever the user asked for via this method.
-    #[allow(unused_variables)] // for cfg(not(unix))
-    pub fn switch_logging(&self, daemon: bool) -> Result<(), Failed> {
-        let logger = match self.log_target {
-            #[cfg(unix)]
-            LogTarget::Default => {
-                if daemon {
-                    self.syslog_logger()?
-                }
-                else {
-                    self.stderr_logger(false)
-                }
-            }
-            #[cfg(not(unix))]
-            LogTarget::Default => {
-                self.stderr_logger(daemon)
-            }
-            #[cfg(unix)]
-            LogTarget::Syslog => {
-                self.syslog_logger()?
-            }
-            LogTarget::Stderr => {
-                self.stderr_logger(daemon)
-            }
-            LogTarget::File => {
-                self.file_logger()?
-            }
-        };
-        log_reroute::reroute_boxed(logger);
-        log::set_max_level(self.log_level.0);
-        Ok(())
-    }
-
-    /// Creates a syslog logger and configures correctly.
-    #[cfg(unix)]
-    fn syslog_logger(
-        &self
-    ) -> Result<Box<dyn Log>, Failed> {
-        let mut formatter = syslog::Formatter3164 {
-            facility: self.log_facility.0,
-            .. Default::default()
-        };
-        if formatter.hostname.is_none() {
-            formatter.hostname = Some("routinator".into());
-        }
-        let formatter = formatter;
-        let logger = syslog::unix(formatter.clone()).or_else(|_| {
-            syslog::tcp(formatter.clone(), ("127.0.0.1", 601))
-        }).or_else(|_| {
-            syslog::udp(formatter, ("127.0.0.1", 0), ("127.0.0.1", 514))
-        });
-        match logger {
-            Ok(logger) => Ok(Box::new(syslog::BasicLogger::new(logger))),
-            Err(err) => {
-                error!("Cannot connect to syslog: {}", err);
-                Err(Failed)
-            }
-        }
-    }
-
-    /// Creates a stderr logger.
-    ///
-    /// If we are in daemon mode, we add a timestamp to the output.
-    fn stderr_logger(&self, daemon: bool) -> Box<dyn Log>{
-        self.fern_logger(daemon).chain(io::stderr()).into_log().1
-    }
-
-    /// Creates a file logger using the file provided by `path`.
-    fn file_logger(&self) -> Result<Box<dyn Log>, Failed> {
-        let file = match fern::log_file(&self.log_file) {
-            Ok(file) => file,
-            Err(err) => {
-                error!(
-                    "Failed to open log file '{}': {}",
-                    self.log_file.display(), err
-                );
-                return Err(Failed)
-            }
-        };
-        Ok(self.fern_logger(true).chain(file).into_log().1)
-    }
-
-    /// Creates and returns a fern logger.
-    fn fern_logger(&self, timestamp: bool) -> fern::Dispatch {
-        let mut res = fern::Dispatch::new();
-        if timestamp {
-            res = res.format(|out, message, _record| {
-                out.finish(format_args!(
-                    "{} {} {}",
-                    chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
-                    _record.module_path().unwrap_or(""),
-                    message
-                ))
-            });
-        }
-        res = res
-            .level(self.log_level.0)
-            .level_for("rustls", LevelFilter::Error);
-        if self.log_level.0 == LevelFilter::Debug {
-            res = res
-                .level_for("tokio_reactor", LevelFilter::Info)
-                .level_for("hyper", LevelFilter::Info)
-                .level_for("reqwest", LevelFilter::Info)
-                .level_for("h2", LevelFilter::Info);
-        }
-        res
-    }
-}
-
-
-
-//------------ LogTarget -----------------------------------------------------
-
-/// The target to log to.
-#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)]
-pub enum LogTarget {
-    /// Use the system default.
-    #[serde(rename = "default")]
-    #[default]
-    Default,
-
-    /// Syslog.
-    #[cfg(unix)]
-    #[serde(rename = "syslog")]
-    Syslog,
-
-    /// Stderr.
-    #[serde(rename = "stderr")]
-    Stderr,
-
-    /// A file.
-    #[serde(rename = "file")]
-    File
-}
-
-
-//------------ LogFacility ---------------------------------------------------
-
-#[cfg(unix)]
-#[derive(Deserialize)]
-#[serde(try_from = "String")]
-pub struct LogFacility(syslog::Facility);
-
-#[cfg(unix)]
-impl Default for LogFacility {
-    fn default() -> Self {
-        LogFacility(syslog::Facility::LOG_DAEMON)
-    }
-}
-
-#[cfg(unix)]
-impl TryFrom<String> for LogFacility {
-    type Error = String;
-
-    fn try_from(value: String) -> Result<Self, Self::Error> {
-        syslog::Facility::from_str(&value).map(LogFacility).map_err(|_| {
-            format!("unknown syslog facility {}", &value)
-        })
-    }
-}
-
-#[cfg(unix)]
-impl FromStr for LogFacility {
-    type Err = &'static str;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        syslog::Facility::from_str(s).map(LogFacility).map_err(|_| {
-            "unknown facility"
-        })
-    }
-}
-
-
-//------------ LogFilter -----------------------------------------------------
-
-#[derive(Deserialize)]
-#[serde(try_from = "String")]
-pub struct LogFilter(log::LevelFilter);
-
-impl LogFilter {
-    pub fn increase(&mut self) {
-        use log::LevelFilter::*;
-
-        self.0 = match self.0 {
-            Off => Error,
-            Error => Warn,
-            Warn => Info,
-            Info => Debug,
-            Debug => Trace,
-            Trace => Trace,
-        }
-    }
-
-    pub fn decrease(&mut self) {
-        use log::LevelFilter::*;
-
-        self.0 = match self.0 {
-            Off => Off,
-            Error => Off,
-            Warn => Error,
-            Info => Warn,
-            Debug => Info,
-            Trace => Debug,
-        }
-    }
-}
-
-impl Default for LogFilter {
-    fn default() -> Self {
-        LogFilter(log::LevelFilter::Warn)
-    }
-}
-
-impl TryFrom<String> for LogFilter {
-    type Error = log::ParseLevelError;
-
-    fn try_from(value: String) -> Result<Self, Self::Error> {
-        log::LevelFilter::from_str(&value).map(LogFilter)
-    }
-}
-
-
-
-//------------ Failed --------------------------------------------------------
-
-/// An error happened that has been logged.
-///
-/// This is a marker type that can be used in results to indicate that if an
-/// error happend, it has been logged and doesn’t need further treatment.
-#[derive(Clone, Copy, Debug)]
-pub struct Failed;
-
-
-//------------ ExitError -----------------------------------------------------
-
-/// An error happened that should cause the process to exit.
-pub struct ExitError;
-
-impl ExitError {
-    /// Exits the process.
-    pub fn exit(self) -> ! {
-        process::exit(1)
-    }
-}
-
-impl From<Failed> for ExitError {
-    fn from(_: Failed) -> ExitError {
-        ExitError
-    }
-}
-
diff --git a/src/main.rs b/src/main.rs
index 067e63a..c3c3ad7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,36 +1,26 @@
-use std::env::current_dir;
 use std::process::exit;
 use clap::{Command, crate_authors, crate_version};
+use daemonbase::error::ExitError;
+use daemonbase::logging::Logger;
 use futures::future::pending;
-use log::error;
 use tokio::runtime;
 use rtrtr::config::Config;
-use rtrtr::log::ExitError;
 use rtrtr::manager::Manager;
 
 
 fn _main() -> Result<(), ExitError> {
-    Config::init()?;
+    Logger::init_logging()?;
     let matches = Config::config_args(
         Command::new("rtrtr")
         .version(crate_version!())
         .author(crate_authors!())
         .about("collecting, processing and distributing route filtering data")
     ).get_matches();
-    let cur_dir = match current_dir() {
-        Ok(dir) => dir,
-        Err(err) => {
-            error!(
-                "Fatal: cannot get current directory ({}). Aborting.",
-                err
-            );
-            return Err(ExitError);
-        }
-    };
     let mut manager = Manager::new();
     let mut config = Config::from_arg_matches(
-        &matches, &cur_dir, &mut manager
+        &matches, &mut manager
     )?;
+    Logger::from_config(&config.log)?.switch_logging(false)?;
     let runtime = runtime::Builder::new_multi_thread()
         .enable_all()
         .build()
@@ -44,7 +34,7 @@ fn _main() -> Result<(), ExitError> {
 fn main() {
     match _main() {
         Ok(_) => exit(0),
-        Err(ExitError) => exit(1),
+        Err(err) => err.exit(),
     }
 }
 
diff --git a/src/manager.rs b/src/manager.rs
index 60d2596..609e6ae 100644
--- a/src/manager.rs
+++ b/src/manager.rs
@@ -3,6 +3,7 @@
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::sync::Arc;
+use daemonbase::error::Failed;
 use log::error;
 use serde::Deserialize;
 use reqwest::Client as HttpClient;
@@ -10,7 +11,6 @@ use tokio::runtime;
 use crate::{http, metrics};
 use crate::comms::{Gate, GateAgent, Link};
 use crate::config::{Config, ConfigFile, Marked};
-use crate::log::Failed;
 use crate::targets::Target;
 use crate::units::Unit;
 
diff --git a/src/targets/http.rs b/src/targets/http.rs
index 63d44f0..95e1eef 100644
--- a/src/targets/http.rs
+++ b/src/targets/http.rs
@@ -3,6 +3,7 @@
 use std::convert::Infallible;
 use std::sync::Arc;
 use arc_swap::ArcSwap;
+use daemonbase::error::ExitError;
 use chrono::{DateTime, Utc};
 use futures::stream;
 use hyper::{Body, Method, Request, Response, StatusCode};
@@ -14,7 +15,6 @@ use serde::Deserialize;
 use crate::payload;
 use crate::comms::Link;
 use crate::formats::output;
-use crate::log::ExitError;
 use crate::manager::Component;
 use crate::utils::http::EtagsIter;
 use crate::utils::http::{format_http_date, parse_http_date};
diff --git a/src/targets/mod.rs b/src/targets/mod.rs
index d85b46f..5e7e00d 100644
--- a/src/targets/mod.rs
+++ b/src/targets/mod.rs
@@ -21,8 +21,8 @@ mod rtr;
 
 //------------ Target --------------------------------------------------------
 
+use daemonbase::error::ExitError;
 use serde::Deserialize;
-use crate::log::ExitError;
 use crate::manager::Component;
 
 
diff --git a/src/targets/rtr.rs b/src/targets/rtr.rs
index 8fcb625..b5b05aa 100644
--- a/src/targets/rtr.rs
+++ b/src/targets/rtr.rs
@@ -8,6 +8,8 @@ use std::net::TcpListener as StdTcpListener;
 use std::pin::Pin;
 use std::task::{Context, Poll};
 use arc_swap::ArcSwap;
+use daemonbase::config::ConfigPath;
+use daemonbase::error::ExitError;
 use futures::{TryFuture, ready};
 use log::{debug, error};
 use pin_project_lite::pin_project;
@@ -23,8 +25,6 @@ use tokio_rustls::server::TlsStream;
 use tokio_stream::wrappers::TcpListenerStream;
 use crate::payload;
 use crate::comms::Link;
-use crate::config::ConfigPath;
-use crate::log::ExitError;
 use crate::manager::Component;
 
 
@@ -79,7 +79,7 @@ impl Tcp {
             Ok(listener) => listener,
             Err(err) => {
                 error!("Can’t bind to {}: {}", addr, err);
-                return Err(ExitError)
+                return Err(ExitError::default())
             }
         };
         if let Err(err) = listener.set_nonblocking(true) {
@@ -87,13 +87,13 @@ impl Tcp {
                 "Fatal: failed to set listener {} to non-blocking: {}.",
                 addr, err
             );
-            return Err(ExitError);
+            return Err(ExitError::default());
         }
         let listener = match TcpListener::from_std(listener) {
             Ok(listener) => listener,
             Err(err) => {
                 error!("Fatal error listening on {}: {}", addr, err);
-                return Err(ExitError)
+                return Err(ExitError::default())
             }
         };
         tokio::spawn(async move {
@@ -158,7 +158,7 @@ impl Tls {
                         "Failed to open TLS certificate file '{}': {}.",
                         self.certificate.display(), err
                     );
-                    ExitError
+                    ExitError::default()
                 })?
             )
         ).map_err(|err| {
@@ -166,7 +166,7 @@ impl Tls {
                 "Failed to read TLS certificate file '{}': {}.",
                 self.certificate.display(), err
             );
-            ExitError
+            ExitError::default()
         }).map(|mut certs| {
             certs.drain(..).map(Certificate).collect()
         })?;
@@ -178,7 +178,7 @@ impl Tls {
                         "Failed to open TLS key file '{}': {}.",
                         self.key.display(), err
                     );
-                    ExitError
+                    ExitError::default()
                 })?
             )
         ).map_err(|err| {
@@ -186,21 +186,21 @@ impl Tls {
                 "Failed to read TLS key file '{}': {}.",
                 self.key.display(), err
             );
-            ExitError
+            ExitError::default()
         }).and_then(|mut certs| {
             if certs.is_empty() {
                 error!(
                     "TLS key file '{}' does not contain any usable keys.",
                     self.key.display()
                 );
-                return Err(ExitError)
+                return Err(ExitError::default())
             }
             if certs.len() != 1 {
                 error!(
                     "TLS key file '{}' contains multiple keys.",
                     self.key.display()
                 );
-                return Err(ExitError)
+                return Err(ExitError::default())
             }
             Ok(PrivateKey(certs.pop().unwrap()))
         })?;
@@ -211,7 +211,7 @@ impl Tls {
             .with_single_cert(certs, key)
             .map_err(|err| {
                 error!("Failed to create TLS server config: {}", err);
-                ExitError
+                ExitError::default()
             })
     }
 
@@ -224,7 +224,7 @@ impl Tls {
             Ok(listener) => listener,
             Err(err) => {
                 error!("Can’t bind to {}: {}", addr, err);
-                return Err(ExitError)
+                return Err(ExitError::default())
             }
         };
         if let Err(err) = listener.set_nonblocking(true) {
@@ -232,13 +232,13 @@ impl Tls {
                 "Fatal: failed to set listener {} to non-blocking: {}.",
                 addr, err
             );
-            return Err(ExitError);
+            return Err(ExitError::default());
         }
         let listener = match TcpListener::from_std(listener) {
             Ok(listener) => listener,
             Err(err) => {
                 error!("Fatal error listening on {}: {}", addr, err);
-                return Err(ExitError)
+                return Err(ExitError::default())
             }
         };
         tokio::spawn(async move {
diff --git a/src/test.rs b/src/test.rs
index 5485949..3aecd69 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -1,11 +1,11 @@
 //! Helpful things for testing.
 #![cfg(test)]
 
+use daemonbase::error::ExitError;
 use tokio::sync::mpsc;
 use crate::{targets, units};
 use crate::comms::{Gate, Link, Terminated, UnitStatus};
 use crate::payload;
-use crate::log::ExitError;
 use crate::manager::Component;
 
 
diff --git a/src/units/json.rs b/src/units/json.rs
index dd7956a..6021691 100644
--- a/src/units/json.rs
+++ b/src/units/json.rs
@@ -6,6 +6,8 @@ use std::time::{Duration, SystemTime};
 use std::fs::metadata;
 use chrono::{DateTime, Utc};
 use bytes::{Buf, Bytes, BytesMut};
+use daemonbase::config::ConfigPath;
+use daemonbase::error::Failed;
 use log::{debug, warn};
 use reqwest::header;
 use reqwest::{StatusCode, Url};
@@ -16,10 +18,8 @@ use tokio::task::spawn_blocking;
 use tokio::time::{Instant, timeout_at};
 use crate::payload;
 use crate::comms::{Gate, Terminated, UnitStatus};
-use crate::config::ConfigPath;
 use crate::formats::json::Set as JsonSet;
 use crate::manager::Component;
-use crate::log::Failed;
 use crate::utils::http::{format_http_date, parse_http_date};
 
 
diff --git a/src/units/rtr.rs b/src/units/rtr.rs
index f3c1714..a5f05d3 100644
--- a/src/units/rtr.rs
+++ b/src/units/rtr.rs
@@ -14,6 +14,7 @@ use std::sync::atomic::{AtomicI64, AtomicU32, AtomicU64};
 use std::task::{Context, Poll};
 use std::time::Duration;
 use chrono::{TimeZone, Utc};
+use daemonbase::config::ConfigPath;
 use futures::pin_mut;
 use futures::future::{select, Either};
 use log::{debug, error, info, warn};
@@ -33,7 +34,6 @@ use tokio_rustls::{
 use webpki::TrustAnchor;
 use crate::metrics;
 use crate::comms::{Gate, GateMetrics, GateStatus, Terminated, UnitStatus};
-use crate::config::ConfigPath;
 use crate::manager::Component;
 use crate::metrics::{Metric, MetricType, MetricUnit};
 use crate::payload;
diff --git a/src/units/slurm.rs b/src/units/slurm.rs
index 8464e53..3021740 100644
--- a/src/units/slurm.rs
+++ b/src/units/slurm.rs
@@ -5,13 +5,13 @@ use std::path::{Path, PathBuf};
 use std::sync::{Arc, Weak};
 use std::time::{Duration, SystemTime};
 use arc_swap::ArcSwap;
+use daemonbase::config::ConfigPath;
 use log::debug;
 use rpki::slurm::{SlurmFile, ValidationOutputFilters};
 use serde::Deserialize;
 use tokio::sync::Notify;
 use crate::payload;
 use crate::comms::{Gate, Link, Terminated, UnitStatus};
-use crate::config::ConfigPath;
 use crate::manager::Component;