mirror of
				https://github.com/dani-garcia/vaultwarden.git
				synced 2025-10-28 00:40:01 +02:00 
			
		
		
		
	Add Kubernetes environment detection (#4290)
Also check if we are running within a Kubernetes environment. These do not always run using Docker or Podman of course. Also renamed all the functions and variables to use `container` instead of `docker`.
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							77cd5b5954
						
					
				
				
					commit
					569add453d
				
			| @@ -23,8 +23,8 @@ use crate::{ | |||||||
|     error::{Error, MapResult}, |     error::{Error, MapResult}, | ||||||
|     mail, |     mail, | ||||||
|     util::{ |     util::{ | ||||||
|         docker_base_image, format_naive_datetime_local, get_display_size, get_reqwest_client, is_running_in_docker, |         container_base_image, format_naive_datetime_local, get_display_size, get_reqwest_client, | ||||||
|         NumberOrString, |         is_running_in_container, NumberOrString, | ||||||
|     }, |     }, | ||||||
|     CONFIG, VERSION, |     CONFIG, VERSION, | ||||||
| }; | }; | ||||||
| @@ -608,7 +608,7 @@ use cached::proc_macro::cached; | |||||||
| /// Cache this function to prevent API call rate limit. Github only allows 60 requests per hour, and we use 3 here already. | /// Cache this function to prevent API call rate limit. Github only allows 60 requests per hour, and we use 3 here already. | ||||||
| /// It will cache this function for 300 seconds (5 minutes) which should prevent the exhaustion of the rate limit. | /// It will cache this function for 300 seconds (5 minutes) which should prevent the exhaustion of the rate limit. | ||||||
| #[cached(time = 300, sync_writes = true)] | #[cached(time = 300, sync_writes = true)] | ||||||
| async fn get_release_info(has_http_access: bool, running_within_docker: bool) -> (String, String, String) { | async fn get_release_info(has_http_access: bool, running_within_container: bool) -> (String, String, String) { | ||||||
|     // If the HTTP Check failed, do not even attempt to check for new versions since we were not able to connect with github.com anyway. |     // If the HTTP Check failed, do not even attempt to check for new versions since we were not able to connect with github.com anyway. | ||||||
|     if has_http_access { |     if has_http_access { | ||||||
|         ( |         ( | ||||||
| @@ -625,9 +625,9 @@ async fn get_release_info(has_http_access: bool, running_within_docker: bool) -> | |||||||
|                 } |                 } | ||||||
|                 _ => "-".to_string(), |                 _ => "-".to_string(), | ||||||
|             }, |             }, | ||||||
|             // Do not fetch the web-vault version when running within Docker. |             // Do not fetch the web-vault version when running within a container. | ||||||
|             // The web-vault version is embedded within the container it self, and should not be updated manually |             // The web-vault version is embedded within the container it self, and should not be updated manually | ||||||
|             if running_within_docker { |             if running_within_container { | ||||||
|                 "-".to_string() |                 "-".to_string() | ||||||
|             } else { |             } else { | ||||||
|                 match get_json_api::<GitRelease>( |                 match get_json_api::<GitRelease>( | ||||||
| @@ -681,7 +681,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn) | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|     // Execute some environment checks |     // Execute some environment checks | ||||||
|     let running_within_docker = is_running_in_docker(); |     let running_within_container = is_running_in_container(); | ||||||
|     let has_http_access = has_http_access().await; |     let has_http_access = has_http_access().await; | ||||||
|     let uses_proxy = env::var_os("HTTP_PROXY").is_some() |     let uses_proxy = env::var_os("HTTP_PROXY").is_some() | ||||||
|         || env::var_os("http_proxy").is_some() |         || env::var_os("http_proxy").is_some() | ||||||
| @@ -695,7 +695,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn) | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     let (latest_release, latest_commit, latest_web_build) = |     let (latest_release, latest_commit, latest_web_build) = | ||||||
|         get_release_info(has_http_access, running_within_docker).await; |         get_release_info(has_http_access, running_within_container).await; | ||||||
|  |  | ||||||
|     let ip_header_name = match &ip_header.0 { |     let ip_header_name = match &ip_header.0 { | ||||||
|         Some(h) => h, |         Some(h) => h, | ||||||
| @@ -710,8 +710,8 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn) | |||||||
|         "web_vault_enabled": &CONFIG.web_vault_enabled(), |         "web_vault_enabled": &CONFIG.web_vault_enabled(), | ||||||
|         "web_vault_version": web_vault_version.version.trim_start_matches('v'), |         "web_vault_version": web_vault_version.version.trim_start_matches('v'), | ||||||
|         "latest_web_build": latest_web_build, |         "latest_web_build": latest_web_build, | ||||||
|         "running_within_docker": running_within_docker, |         "running_within_container": running_within_container, | ||||||
|         "docker_base_image": if running_within_docker { docker_base_image() } else { "Not applicable" }, |         "container_base_image": if running_within_container { container_base_image() } else { "Not applicable" }, | ||||||
|         "has_http_access": has_http_access, |         "has_http_access": has_http_access, | ||||||
|         "ip_header_exists": &ip_header.0.is_some(), |         "ip_header_exists": &ip_header.0.is_some(), | ||||||
|         "ip_header_match": ip_header_name == CONFIG.ip_header(), |         "ip_header_match": ip_header_name == CONFIG.ip_header(), | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -88,7 +88,7 @@ pub use config::CONFIG; | |||||||
| pub use error::{Error, MapResult}; | pub use error::{Error, MapResult}; | ||||||
| use rocket::data::{Limits, ToByteUnit}; | use rocket::data::{Limits, ToByteUnit}; | ||||||
| use std::sync::Arc; | use std::sync::Arc; | ||||||
| pub use util::is_running_in_docker; | pub use util::is_running_in_container; | ||||||
|  |  | ||||||
| #[rocket::main] | #[rocket::main] | ||||||
| async fn main() -> Result<(), Error> { | async fn main() -> Result<(), Error> { | ||||||
| @@ -415,7 +415,7 @@ async fn check_data_folder() { | |||||||
|     let path = Path::new(data_folder); |     let path = Path::new(data_folder); | ||||||
|     if !path.exists() { |     if !path.exists() { | ||||||
|         error!("Data folder '{}' doesn't exist.", data_folder); |         error!("Data folder '{}' doesn't exist.", data_folder); | ||||||
|         if is_running_in_docker() { |         if is_running_in_container() { | ||||||
|             error!("Verify that your data volume is mounted at the correct location."); |             error!("Verify that your data volume is mounted at the correct location."); | ||||||
|         } else { |         } else { | ||||||
|             error!("Create the data folder and try again."); |             error!("Create the data folder and try again."); | ||||||
| @@ -427,9 +427,9 @@ async fn check_data_folder() { | |||||||
|         exit(1); |         exit(1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if is_running_in_docker() |     if is_running_in_container() | ||||||
|         && std::env::var("I_REALLY_WANT_VOLATILE_STORAGE").is_err() |         && std::env::var("I_REALLY_WANT_VOLATILE_STORAGE").is_err() | ||||||
|         && !docker_data_folder_is_persistent(data_folder).await |         && !container_data_folder_is_persistent(data_folder).await | ||||||
|     { |     { | ||||||
|         error!( |         error!( | ||||||
|             "No persistent volume!\n\ |             "No persistent volume!\n\ | ||||||
| @@ -448,7 +448,7 @@ async fn check_data_folder() { | |||||||
| /// A none persistent volume in either Docker or Podman is represented by a 64 alphanumerical string. | /// A none persistent volume in either Docker or Podman is represented by a 64 alphanumerical string. | ||||||
| /// If we detect this string, we will alert about not having a persistent self defined volume. | /// If we detect this string, we will alert about not having a persistent self defined volume. | ||||||
| /// This probably means that someone forgot to add `-v /path/to/vaultwarden_data/:/data` | /// This probably means that someone forgot to add `-v /path/to/vaultwarden_data/:/data` | ||||||
| async fn docker_data_folder_is_persistent(data_folder: &str) -> bool { | async fn container_data_folder_is_persistent(data_folder: &str) -> bool { | ||||||
|     if let Ok(mountinfo) = File::open("/proc/self/mountinfo").await { |     if let Ok(mountinfo) = File::open("/proc/self/mountinfo").await { | ||||||
|         // Since there can only be one mountpoint to the DATA_FOLDER |         // Since there can only be one mountpoint to the DATA_FOLDER | ||||||
|         // We do a basic check for this mountpoint surrounded by a space. |         // We do a basic check for this mountpoint surrounded by a space. | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								src/static/scripts/admin_diagnostics.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								src/static/scripts/admin_diagnostics.js
									
									
									
									
										vendored
									
									
								
							| @@ -77,7 +77,7 @@ async function generateSupportString(event, dj) { | |||||||
|     supportString += `* Vaultwarden version: v${dj.current_release}\n`; |     supportString += `* Vaultwarden version: v${dj.current_release}\n`; | ||||||
|     supportString += `* Web-vault version: v${dj.web_vault_version}\n`; |     supportString += `* Web-vault version: v${dj.web_vault_version}\n`; | ||||||
|     supportString += `* OS/Arch: ${dj.host_os}/${dj.host_arch}\n`; |     supportString += `* OS/Arch: ${dj.host_os}/${dj.host_arch}\n`; | ||||||
|     supportString += `* Running within Docker: ${dj.running_within_docker} (Base: ${dj.docker_base_image})\n`; |     supportString += `* Running within a container: ${dj.running_within_container} (Base: ${dj.container_base_image})\n`; | ||||||
|     supportString += "* Environment settings overridden: "; |     supportString += "* Environment settings overridden: "; | ||||||
|     if (dj.overrides != "") { |     if (dj.overrides != "") { | ||||||
|         supportString += "true\n"; |         supportString += "true\n"; | ||||||
| @@ -179,7 +179,7 @@ function initVersionCheck(dj) { | |||||||
|     } |     } | ||||||
|     checkVersions("server", serverInstalled, serverLatest, serverLatestCommit); |     checkVersions("server", serverInstalled, serverLatest, serverLatestCommit); | ||||||
|  |  | ||||||
|     if (!dj.running_within_docker) { |     if (!dj.running_within_container) { | ||||||
|         const webInstalled = dj.web_vault_version; |         const webInstalled = dj.web_vault_version; | ||||||
|         const webLatest = dj.latest_web_build; |         const webLatest = dj.latest_web_build; | ||||||
|         checkVersions("web", webInstalled, webLatest); |         checkVersions("web", webInstalled, webLatest); | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ | |||||||
|                     <dd class="col-sm-7"> |                     <dd class="col-sm-7"> | ||||||
|                         <span id="web-installed">{{page_data.web_vault_version}}</span> |                         <span id="web-installed">{{page_data.web_vault_version}}</span> | ||||||
|                     </dd> |                     </dd> | ||||||
|                     {{#unless page_data.running_within_docker}} |                     {{#unless page_data.running_within_container}} | ||||||
|                     <dt class="col-sm-5">Web Latest |                     <dt class="col-sm-5">Web Latest | ||||||
|                         <span class="badge bg-secondary d-none" id="web-failed" title="Unable to determine latest version.">Unknown</span> |                         <span class="badge bg-secondary d-none" id="web-failed" title="Unable to determine latest version.">Unknown</span> | ||||||
|                     </dt> |                     </dt> | ||||||
| @@ -59,12 +59,12 @@ | |||||||
|                     <dd class="col-sm-7"> |                     <dd class="col-sm-7"> | ||||||
|                         <span class="d-block"><b>{{ page_data.host_os }} / {{ page_data.host_arch }}</b></span> |                         <span class="d-block"><b>{{ page_data.host_os }} / {{ page_data.host_arch }}</b></span> | ||||||
|                     </dd> |                     </dd> | ||||||
|                     <dt class="col-sm-5">Running within Docker</dt> |                     <dt class="col-sm-5">Running within a container</dt> | ||||||
|                     <dd class="col-sm-7"> |                     <dd class="col-sm-7"> | ||||||
|                     {{#if page_data.running_within_docker}} |                     {{#if page_data.running_within_container}} | ||||||
|                         <span class="d-block"><b>Yes (Base: {{ page_data.docker_base_image }})</b></span> |                         <span class="d-block"><b>Yes (Base: {{ page_data.container_base_image }})</b></span> | ||||||
|                     {{/if}} |                     {{/if}} | ||||||
|                     {{#unless page_data.running_within_docker}} |                     {{#unless page_data.running_within_container}} | ||||||
|                         <span class="d-block"><b>No</b></span> |                         <span class="d-block"><b>No</b></span> | ||||||
|                     {{/unless}} |                     {{/unless}} | ||||||
|                     </dd> |                     </dd> | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/util.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/util.rs
									
									
									
									
									
								
							| @@ -531,14 +531,17 @@ pub fn parse_date(date: &str) -> NaiveDateTime { | |||||||
| // Deployment environment methods | // Deployment environment methods | ||||||
| // | // | ||||||
|  |  | ||||||
| /// Returns true if the program is running in Docker or Podman. | /// Returns true if the program is running in Docker, Podman or Kubernetes. | ||||||
| pub fn is_running_in_docker() -> bool { | pub fn is_running_in_container() -> bool { | ||||||
|     Path::new("/.dockerenv").exists() || Path::new("/run/.containerenv").exists() |     Path::new("/.dockerenv").exists() | ||||||
|  |         || Path::new("/run/.containerenv").exists() | ||||||
|  |         || Path::new("/run/secrets/kubernetes.io").exists() | ||||||
|  |         || Path::new("/var/run/secrets/kubernetes.io").exists() | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Simple check to determine on which docker base image vaultwarden is running. | /// Simple check to determine on which container base image vaultwarden is running. | ||||||
| /// We build images based upon Debian or Alpine, so these we check here. | /// We build images based upon Debian or Alpine, so these we check here. | ||||||
| pub fn docker_base_image() -> &'static str { | pub fn container_base_image() -> &'static str { | ||||||
|     if Path::new("/etc/debian_version").exists() { |     if Path::new("/etc/debian_version").exists() { | ||||||
|         "Debian" |         "Debian" | ||||||
|     } else if Path::new("/etc/alpine-release").exists() { |     } else if Path::new("/etc/alpine-release").exists() { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user