Class: Falcon::Service::Virtual

Inherits:
Async::Service::Generic
  • Object
show all
Defined in:
lib/falcon/service/virtual.rb

Overview

A controller which mananages several virtual hosts. Spawns instances of Proxy and Redirect to handle incoming requests.

A virtual host is an application bound to a specific authority (essentially a hostname). The virtual controller manages multiple hosts and allows a single server to host multiple applications easily.

Instance Method Summary collapse

Instance Method Details

#assume_privileges(path) ⇒ Object

Drop privileges according to the user and group of the specified path.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/falcon/service/virtual.rb', line 18

def assume_privileges(path)
	# Process.exec / Process.spawn don't replace the environment but instead update it, so we need to clear out any existing BUNDLE_ variables using `nil` values, which will cause them to be removed from the child environment:
	env = ENV.to_h do |key, value|
		if key.start_with?("BUNDLE_")
			[key, nil]
		else
			[key, value]
		end
	end
	
	env["PWD"] = File.dirname(path)
	
	stat = File.stat(path)
	
	Process::GID.change_privilege(stat.gid)
	Process::UID.change_privilege(stat.uid)
	
	home = Etc.getpwuid(stat.uid).dir
	env["HOME"] = home
	
	return env
end

#setup(container) ⇒ Object

Setup the container with Redirect and Proxy child processes. These processes are gracefully restarted if they are already running.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/falcon/service/virtual.rb', line 56

def setup(container)
	if proxy = container[:proxy]
		proxy.kill(:HUP)
	end
	
	if redirect = container[:redirect]
		redirect.kill(:HUP)
	end
	
	container.reload do
		evaluator = @environment.evaluator
		falcon_path = evaluator.falcon_path
		
		Console.info(self, "Loading configurations:", paths: evaluator.resolved_configuration_paths)
		
		evaluator.resolved_configuration_paths.each do |path|
			path = File.expand_path(path)
			root = File.dirname(path)
			
			spawn(path, container, chdir: root)
		end
		
		container.spawn(name: "Falcon Redirector", restart: true, key: :redirect) do |instance|
			instance.exec(falcon_path, "redirect",
				"--bind", evaluator.bind_insecure,
				"--timeout", evaluator.timeout.to_s,
				"--redirect", evaluator.bind_secure,
				*evaluator.configuration_paths, ready: false
			)
		end
		
		container.spawn(name: "Falcon Proxy", restart: true, key: :proxy) do |instance|
			instance.exec(falcon_path, "proxy",
				"--bind", evaluator.bind_secure,
				"--timeout", evaluator.timeout.to_s,
				*evaluator.configuration_paths, ready: false
			)
		end
	end
end

#spawn(path, container, **options) ⇒ Object

Spawn an application instance from the specified path.



45
46
47
48
49
50
51
# File 'lib/falcon/service/virtual.rb', line 45

def spawn(path, container, **options)
	container.spawn(name: "Falcon Application", restart: true, key: path) do |instance|
		env = assume_privileges(path)
		
		instance.exec(env, "bundle", "exec", path, ready: false, **options)
	end
end