diff --git a/config/config.example.yml b/config/config.example.yml index bc2deda57..b04e0a30b 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -130,6 +130,20 @@ https_only: false ## #hsts: true +## +## Path and permissions of a UNIX socket to listen on for incoming connections. +## +## Note: Enabling socket will make invidious stop listening on the address +## specified by 'host_binding' and 'port'. +## +## Accepted values: Any path to a new file (that doesn't exist yet) and its +## permissions following the UNIX octal convention. +## Default: +## +#socket_binding: +# path: /tmp/invidious.sock +# permissions: 777 + # ----------------------------- # Network (outbound) diff --git a/src/invidious.cr b/src/invidious.cr index 566d4dc9d..52df77bee 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -240,8 +240,6 @@ add_context_storage_type(Preferences) add_context_storage_type(Invidious::User) Kemal.config.logger = LOGGER -Kemal.config.host_binding = Kemal.config.host_binding != "0.0.0.0" ? Kemal.config.host_binding : CONFIG.host_binding -Kemal.config.port = Kemal.config.port != 3000 ? Kemal.config.port : CONFIG.port Kemal.config.app_name = "Invidious" # Use in kemal's production mode. @@ -250,4 +248,16 @@ Kemal.config.app_name = "Invidious" Kemal.config.env = "production" if !ENV.has_key?("KEMAL_ENV") {% end %} -Kemal.run +Kemal.run do |config| + if socket_binding = CONFIG.socket_binding +File.delete?(socket_binding.path) + # Create a socket and set its desired permissions + server = UNIXServer.new(socket_binding.path) + perms = socket_binding.permissions.to_i(base: 8) + File.chmod(socket_binding.path, perms) + config.server.not_nil!.bind server + else + Kemal.config.host_binding = Kemal.config.host_binding != "0.0.0.0" ? Kemal.config.host_binding : CONFIG.host_binding + Kemal.config.port = Kemal.config.port != 3000 ? Kemal.config.port : CONFIG.port + end +end diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 4b3bdafc8..453256b52 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -8,6 +8,13 @@ struct DBConfig property dbname : String end +struct SocketBindingConfig + include YAML::Serializable + + property path : String + property permissions : String +end + struct ConfigPreferences include YAML::Serializable @@ -138,6 +145,8 @@ class Config property port : Int32 = 3000 # Host to bind (overridden by command line argument) property host_binding : String = "0.0.0.0" + # Path and permissions to make Invidious listen on a UNIX socket instead of a TCP port + property socket_binding : SocketBindingConfig? = nil # Pool size for HTTP requests to youtube.com and ytimg.com (each domain has a separate pool of `pool_size`) property pool_size : Int32 = 100 # HTTP Proxy configuration @@ -255,6 +264,24 @@ class Config end end + # Check if the socket configuration is valid + if sb = config.socket_binding + if sb.path.ends_with?("/") || File.directory?(sb.path) + puts "Config: The socket path " + sb.path + " must not be a directory!" + exit(1) + end + d = File.dirname(sb.path) + if !File.directory?(d) + puts "Config: Socket directory " + sb.path + " does not exist or is not a directory!" + exit(1) + end + p = sb.permissions.to_i?(base: 8) + if !p || p < 0 || p > 0o777 + puts "Config: Socket permissions must be an octal between 0 and 777!" + exit(1) + end + end + return config end end