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}, | ||||
|     mail, | ||||
|     util::{ | ||||
|         docker_base_image, format_naive_datetime_local, get_display_size, get_reqwest_client, is_running_in_docker, | ||||
|         NumberOrString, | ||||
|         container_base_image, format_naive_datetime_local, get_display_size, get_reqwest_client, | ||||
|         is_running_in_container, NumberOrString, | ||||
|     }, | ||||
|     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. | ||||
| /// 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)] | ||||
| 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 has_http_access { | ||||
|         ( | ||||
| @@ -625,9 +625,9 @@ async fn get_release_info(has_http_access: bool, running_within_docker: bool) -> | ||||
|                 } | ||||
|                 _ => "-".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 | ||||
|             if running_within_docker { | ||||
|             if running_within_container { | ||||
|                 "-".to_string() | ||||
|             } else { | ||||
|                 match get_json_api::<GitRelease>( | ||||
| @@ -681,7 +681,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn) | ||||
|         }; | ||||
|  | ||||
|     // 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 uses_proxy = 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) = | ||||
|         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 { | ||||
|         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_version": web_vault_version.version.trim_start_matches('v'), | ||||
|         "latest_web_build": latest_web_build, | ||||
|         "running_within_docker": running_within_docker, | ||||
|         "docker_base_image": if running_within_docker { docker_base_image() } else { "Not applicable" }, | ||||
|         "running_within_container": running_within_container, | ||||
|         "container_base_image": if running_within_container { container_base_image() } else { "Not applicable" }, | ||||
|         "has_http_access": has_http_access, | ||||
|         "ip_header_exists": &ip_header.0.is_some(), | ||||
|         "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}; | ||||
| use rocket::data::{Limits, ToByteUnit}; | ||||
| use std::sync::Arc; | ||||
| pub use util::is_running_in_docker; | ||||
| pub use util::is_running_in_container; | ||||
|  | ||||
| #[rocket::main] | ||||
| async fn main() -> Result<(), Error> { | ||||
| @@ -415,7 +415,7 @@ async fn check_data_folder() { | ||||
|     let path = Path::new(data_folder); | ||||
|     if !path.exists() { | ||||
|         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."); | ||||
|         } else { | ||||
|             error!("Create the data folder and try again."); | ||||
| @@ -427,9 +427,9 @@ async fn check_data_folder() { | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     if is_running_in_docker() | ||||
|     if is_running_in_container() | ||||
|         && 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!( | ||||
|             "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. | ||||
| /// 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` | ||||
| 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 { | ||||
|         // Since there can only be one mountpoint to the DATA_FOLDER | ||||
|         // 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 += `* Web-vault version: v${dj.web_vault_version}\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: "; | ||||
|     if (dj.overrides != "") { | ||||
|         supportString += "true\n"; | ||||
| @@ -179,7 +179,7 @@ function initVersionCheck(dj) { | ||||
|     } | ||||
|     checkVersions("server", serverInstalled, serverLatest, serverLatestCommit); | ||||
|  | ||||
|     if (!dj.running_within_docker) { | ||||
|     if (!dj.running_within_container) { | ||||
|         const webInstalled = dj.web_vault_version; | ||||
|         const webLatest = dj.latest_web_build; | ||||
|         checkVersions("web", webInstalled, webLatest); | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
|                     <dd class="col-sm-7"> | ||||
|                         <span id="web-installed">{{page_data.web_vault_version}}</span> | ||||
|                     </dd> | ||||
|                     {{#unless page_data.running_within_docker}} | ||||
|                     {{#unless page_data.running_within_container}} | ||||
|                     <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> | ||||
|                     </dt> | ||||
| @@ -59,12 +59,12 @@ | ||||
|                     <dd class="col-sm-7"> | ||||
|                         <span class="d-block"><b>{{ page_data.host_os }} / {{ page_data.host_arch }}</b></span> | ||||
|                     </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"> | ||||
|                     {{#if page_data.running_within_docker}} | ||||
|                         <span class="d-block"><b>Yes (Base: {{ page_data.docker_base_image }})</b></span> | ||||
|                     {{#if page_data.running_within_container}} | ||||
|                         <span class="d-block"><b>Yes (Base: {{ page_data.container_base_image }})</b></span> | ||||
|                     {{/if}} | ||||
|                     {{#unless page_data.running_within_docker}} | ||||
|                     {{#unless page_data.running_within_container}} | ||||
|                         <span class="d-block"><b>No</b></span> | ||||
|                     {{/unless}} | ||||
|                     </dd> | ||||
|   | ||||
							
								
								
									
										13
									
								
								src/util.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/util.rs
									
									
									
									
									
								
							| @@ -531,14 +531,17 @@ pub fn parse_date(date: &str) -> NaiveDateTime { | ||||
| // Deployment environment methods | ||||
| // | ||||
|  | ||||
| /// Returns true if the program is running in Docker or Podman. | ||||
| pub fn is_running_in_docker() -> bool { | ||||
|     Path::new("/.dockerenv").exists() || Path::new("/run/.containerenv").exists() | ||||
| /// Returns true if the program is running in Docker, Podman or Kubernetes. | ||||
| pub fn is_running_in_container() -> bool { | ||||
|     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. | ||||
| pub fn docker_base_image() -> &'static str { | ||||
| pub fn container_base_image() -> &'static str { | ||||
|     if Path::new("/etc/debian_version").exists() { | ||||
|         "Debian" | ||||
|     } else if Path::new("/etc/alpine-release").exists() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user