diff --git a/crates/cli/src/server.rs b/crates/cli/src/server.rs index 2841c8471..3965982f6 100644 --- a/crates/cli/src/server.rs +++ b/crates/cli/src/server.rs @@ -5,9 +5,10 @@ // Please see LICENSE in the repository root for full details. use std::{ + fs, future::ready, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, ToSocketAddrs}, - os::unix::net::UnixListener, + os::unix::{fs::PermissionsExt, net::UnixListener}, }; use anyhow::Context; @@ -377,8 +378,20 @@ pub fn build_listeners( listener.try_into()? } - HttpBindConfig::Unix { socket } => { + HttpBindConfig::Unix { socket, mode } => { let listener = UnixListener::bind(socket).context("could not bind socket")?; + + if let Some(mode) = mode { + let mut permissions = fs::metadata(socket) + .context("could not read socket metadata")? + .permissions(); + let mode = u32::from_str_radix(mode, 8) + .with_context(|| format!("could not parse mode: {mode}"))?; + permissions.set_mode(mode); + fs::set_permissions(socket, permissions) + .context("could not set socket permissions")?; + } + listener.try_into()? } diff --git a/crates/config/src/sections/http.rs b/crates/config/src/sections/http.rs index 8bf4a7588..618604d9c 100644 --- a/crates/config/src/sections/http.rs +++ b/crates/config/src/sections/http.rs @@ -36,6 +36,10 @@ fn http_address_example_4() -> &'static str { "0.0.0.0:8080" } +fn unix_mode_example() -> Option { + Some("660".to_string()) +} + #[cfg(not(any(feature = "docker", feature = "dist")))] fn http_listener_assets_path_default() -> Utf8PathBuf { "./frontend/dist/".into() @@ -124,6 +128,11 @@ pub enum BindConfig { /// Path to the socket #[schemars(with = "String")] socket: Utf8PathBuf, + + /// Socket file mode. A string representing UNIX permission bits, in octal + /// integer format. + #[schemars(example = "unix_mode_example")] + mode: Option, }, /// Accept connections on file descriptors passed by the parent process. diff --git a/docs/config.schema.json b/docs/config.schema.json index 818f592e7..60a16bdf1 100644 --- a/docs/config.schema.json +++ b/docs/config.schema.json @@ -893,6 +893,13 @@ "socket": { "description": "Path to the socket", "type": "string" + }, + "mode": { + "description": "Socket file mode. A string representing UNIX permission bits, in octal integer format.", + "examples": [ + "660" + ], + "type": "string" } } }, diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index e6c504e0c..9a8bc704c 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -58,6 +58,7 @@ http: # Third option: listen on the given UNIX socket - socket: /tmp/mas.sock + mode: "660" # permissions to set on the socket, optional # Fourth option: grab an already open file descriptor given by the parent process # This is useful when using systemd socket activation