diff --git a/Cargo.lock b/Cargo.lock
index 91260ad..e756bda 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -76,6 +76,15 @@ dependencies = [
  "syn 2.0.39",
 ]
 
+[[package]]
+name = "atomic"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
+dependencies = [
+ "bytemuck",
+]
+
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -202,6 +211,12 @@ version = "3.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
 
+[[package]]
+name = "bytemuck"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+
 [[package]]
 name = "bytes"
 version = "1.5.0"
@@ -364,6 +379,7 @@ dependencies = [
  "bitvec",
  "bytes",
  "env_logger",
+ "figment",
  "futures-util",
  "hickory-resolver",
  "include_dir",
@@ -376,7 +392,6 @@ dependencies = [
  "regex",
  "serde",
  "serde_json",
- "serde_yaml",
  "tokio",
  "tokio-stream",
  "tokio-util",
@@ -384,6 +399,20 @@ dependencies = [
  "zettabgp",
 ]
 
+[[package]]
+name = "figment"
+version = "0.10.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "649f3e5d826594057e9a519626304d8da859ea8a0b18ce99500c586b8d45faee"
+dependencies = [
+ "atomic",
+ "pear",
+ "serde",
+ "serde_yaml",
+ "uncased",
+ "version_check",
+]
+
 [[package]]
 name = "fnv"
 version = "1.0.7"
@@ -687,6 +716,12 @@ dependencies = [
  "hashbrown 0.14.2",
 ]
 
+[[package]]
+name = "inlinable_string"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
+
 [[package]]
 name = "ipconfig"
 version = "0.3.2"
@@ -1042,6 +1077,29 @@ dependencies = [
  "windows-targets",
 ]
 
+[[package]]
+name = "pear"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c"
+dependencies = [
+ "inlinable_string",
+ "pear_codegen",
+ "yansi",
+]
+
+[[package]]
+name = "pear_codegen"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54"
+dependencies = [
+ "proc-macro2",
+ "proc-macro2-diagnostics",
+ "quote",
+ "syn 2.0.39",
+]
+
 [[package]]
 name = "percent-encoding"
 version = "2.3.0"
@@ -1110,6 +1168,19 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "proc-macro2-diagnostics"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.39",
+ "version_check",
+ "yansi",
+]
+
 [[package]]
 name = "prometheus"
 version = "0.13.3"
@@ -1620,6 +1691,15 @@ version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
 
+[[package]]
+name = "uncased"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68"
+dependencies = [
+ "version_check",
+]
+
 [[package]]
 name = "unicase"
 version = "2.7.0"
@@ -1892,6 +1972,12 @@ dependencies = [
  "tap",
 ]
 
+[[package]]
+name = "yansi"
+version = "1.0.0-rc.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377"
+
 [[package]]
 name = "zettabgp"
 version = "0.3.4"
diff --git a/Cargo.toml b/Cargo.toml
index ed3bc13..571e5d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,7 +24,6 @@ rayon = "1.6.1"
 regex = "1.7.1"
 serde = { version = "1.0.152", features = ["derive"] }
 serde_json = "1.0.91"
-serde_yaml = "0.9.16"
 tokio = { version = "1.23.0", features = ["rt", "macros", "time", "rt-multi-thread", "io-util", "fs", "signal"] }
 tokio-stream = "0.1.11"
 tokio-util = { version = "0.7.4", features = ["codec"] }
@@ -35,10 +34,7 @@ zettabgp = "0.3.4"
 hickory-resolver = "0.24.0"
 include_dir = { version = "0.7.3", optional = true }
 mime_guess = { version = "2.0.4", optional = true }
-
-[[bin]]
-name = "fernglas-configcheck"
-path = "src/config_check.rs"
+figment = { version = "0.10.12", features = ["yaml", "env"] }
 
 [features]
 embed-static = ["include_dir", "mime_guess"]
diff --git a/flake.nix b/flake.nix
index e11e9dd..b177a76 100644
--- a/flake.nix
+++ b/flake.nix
@@ -157,7 +157,7 @@
           name = "config.yaml";
           text = builtins.toJSON cfg.settings;
           checkPhase = ''
-            ${fernglasPkgs.fernglas}/bin/fernglas-configcheck $out
+            FERNGLAS_CONFIG_CHECK=1 ${fernglasPkgs.fernglas}/bin/fernglas $out
           '';
         };
       in {
diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js
index 63688c8..f6143f0 100644
--- a/frontend/webpack.config.js
+++ b/frontend/webpack.config.js
@@ -16,7 +16,7 @@ module.exports = {
     static: dist,
     proxy: {
       "/api/": {
-        target: 'http://localhost:3000'
+        target: 'https://lg.staging.service.wobcom.de'
       }
     },
   },
diff --git a/src/config_check.rs b/src/config_check.rs
deleted file mode 100644
index 4200947..0000000
--- a/src/config_check.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use fernglas::*;
-
-#[tokio::main]
-async fn main() -> anyhow::Result<()> {
-    env_logger::init();
-
-    let config_path = config_path_from_args();
-    let cfg: Config = serde_yaml::from_slice(&tokio::fs::read(&config_path).await?)?;
-
-    println!("{:#?}", cfg);
-
-    Ok(())
-}
diff --git a/src/lib.rs b/src/lib.rs
index 94348d4..10dbde1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,21 +9,18 @@ pub mod table_impl;
 
 use serde::Deserialize;
 
-pub fn config_path_from_args() -> String {
-    let mut args = std::env::args();
-    let program = args.next().unwrap();
-    let config_path = match args.next() {
-        Some(v) => v,
-        _ => usage(&program),
-    };
+pub fn config_path_from_args() -> Option<String> {
+    let mut args = std::env::args().skip(1);
+    let config_path = args.next();
     if args.next().is_some() {
-        usage(&program);
+        usage();
     }
 
     config_path
 }
 
-fn usage(program: &str) -> ! {
+pub fn usage() -> ! {
+    let program = std::env::args().next().unwrap();
     eprintln!("usage: {} <CONFIG>", program);
     std::process::exit(1)
 }
@@ -39,4 +36,7 @@ pub enum CollectorConfig {
 pub struct Config {
     pub collectors: Vec<CollectorConfig>,
     pub api: api::ApiServerConfig,
+    /// Only check config and exit
+    #[serde(default)]
+    pub check_config: bool,
 }
diff --git a/src/main.rs b/src/main.rs
index 2d23558..d5e91a2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,6 +2,8 @@ use fernglas::*;
 use futures_util::future::{join_all, select_all};
 use log::*;
 use tokio::signal::unix::{signal, SignalKind};
+use figment::Figment;
+use figment::providers::{Yaml, Env, Format};
 
 #[cfg(feature = "mimalloc")]
 #[global_allocator]
@@ -11,8 +13,21 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
 async fn main() -> anyhow::Result<()> {
     env_logger::init();
 
-    let config_path = config_path_from_args();
-    let cfg: Config = serde_yaml::from_slice(&tokio::fs::read(&config_path).await?)?;
+    let mut figment = Figment::new();
+    if let Some(config_path) = config_path_from_args() {
+        figment = figment.merge(Yaml::file(config_path));
+    }
+    figment = figment.merge(Env::prefixed("FERNGLAS_"));
+
+    let cfg: Config = figment.extract()?;
+
+    if cfg.collectors.is_empty() {
+        fernglas::usage();
+    }
+
+    if cfg.check_config {
+        std::process::exit(0);
+    }
 
     let store: store_impl::InMemoryStore = Default::default();