18874: Add 'services/workbench2/' from commit 'f6f88d9ca9cdeeeebfadcfe999789bfb9f69e5c6'
[arvados.git] / doc / admin / config-urls.html.textile.liquid
1 ---
2 layout: default
3 navsection: installguide
4 title: InternalURLs and ExternalURL
5 ...
6
7 {% comment %}
8 Copyright (C) The Arvados Authors. All rights reserved.
9
10 SPDX-License-Identifier: CC-BY-SA-3.0
11 {% endcomment %}
12
13 The Arvados configuration is stored at @/etc/arvados/config.yml@. See the "Configuration reference":config.html for more detail.
14
15 The @Services@ section lists a number of Arvados services, each with an @InternalURLs@ and/or @ExternalURL@ configuration key. This document explains the precise meaning of these configuration keys, and how they are used by the Arvados services.
16
17 The @ExternalURL@ is the address where the service should be reachable by clients, both from inside and from outside the Arvados cluster. Some services do not expose an Arvados API, only Prometheus metrics. In that case, @ExternalURL@ is not used.
18
19 The keys under @InternalURLs@ are the URLs through which Arvados system components can connect to one another, including the reverse proxy (e.g. Nginx) that fronts Arvados services. The exception is the @Keepstore@ service, where clients on the local network connect directly to @Keepstore.InternalURLs@ (while clients from outside networks connect to @Keepproxy.ExternalURL@). If a service is not fronted by a reverse proxy, e.g. when its endpoint only exposes Prometheus metrics, the intention is that metrics are collected directly from the endpoints defined in @InternalURLs@.
20
21 Each entry in the @InternalURLs@ section may also indicate a @ListenURL@ to determine the protocol, address/interface, and port where the service process will listen, in case the desired listening address differs from the @InternalURLs@ key itself -- for example, when passing internal traffic through a reverse proxy.
22
23 If the Arvados service lives behind a reverse proxy (e.g. Nginx), configuring the reverse proxy and the @InternalURLs@ and @ExternalURL@ values must be done in concert.
24
25 h2. Overview
26
27 <div class="offset1">
28 table(table table-bordered table-condensed).
29 |_.Service     |_.ExternalURL required? |_.InternalURLs required?|_.InternalURLs must be reachable from other cluster nodes?|_.Note|
30 |railsapi       |no                     |yes|no ^1^|InternalURLs only used by Controller|
31 |controller     |yes                    |yes|yes ^2,4^|InternalURLs used by reverse proxy and container shell connections|
32 |arvados-dispatch-cloud|no              |yes|no ^3^|InternalURLs only used to expose Prometheus metrics|
33 |arvados-dispatch-lsf|no                |yes|no ^3^|InternalURLs only used to expose Prometheus metrics|
34 |git-http       |yes                    |yes|no ^2^|InternalURLs only used by reverse proxy (e.g. Nginx)|
35 |git-ssh        |yes                    |no |no    ||
36 |keepproxy      |yes                    |yes|no ^2^|InternalURLs only used by reverse proxy (e.g. Nginx)|
37 |keepstore      |no                     |yes|yes   |All clients connect to InternalURLs|
38 |keep-balance   |no                     |yes|no ^3^|InternalURLs only used to expose Prometheus metrics|
39 |keep-web       |yes                    |yes|yes ^5^|InternalURLs used by reverse proxy and container log API|
40 |websocket      |yes                    |yes|no ^2^|InternalURLs only used by reverse proxy (e.g. Nginx)|
41 |workbench1     |yes                    |no|no     ||
42 |workbench2     |yes                    |no|no     ||
43 </div>
44
45 ^1^ If @Controller@ runs on a different host than @RailsAPI@, the @InternalURLs@ will need to be reachable from the host that runs @Controller@.
46 ^2^ If the reverse proxy (e.g. Nginx) does not run on the same host as the Arvados service it fronts, the @InternalURLs@ will need to be reachable from the host that runs the reverse proxy.
47 ^3^ If the Prometheus metrics are not collected from the same machine that runs the service, the @InternalURLs@ will need to be reachable from the host that collects the metrics.
48 ^4^ If dispatching containers to HPC (Slurm/LSF) and there are multiple @Controller@ services, they must be able to connect to one another using their InternalURLs, otherwise the "tunnel connections":{{site.baseurl}}/architecture/hpc.html enabling "container shell access":{{site.baseurl}}/install/container-shell-access.html will not work.
49 ^5^ All URLs in @Services.WebDAV.InternalURLs@ must be reachable by all Controller services. Alternatively, each entry in @Services.Controller.InternalURLs@ must have a corresponding entry in @Services.WebDAV.InternalURLs@ with the same hostname.
50
51 When @InternalURLs@ do not need to be reachable from other nodes, it is most secure to use loopback addresses as @InternalURLs@, e.g. @http://127.0.0.1:9005@.
52
53 It is recommended to use a split-horizon DNS setup where the hostnames specified in @ExternalURL@ resolve to an internal IP address from inside the Arvados cluster, and a publicly routed external IP address when resolved from outside the cluster. This simplifies firewalling and provides optimally efficient traffic routing. In a cloud environment where traffic that flows via public IP addresses is charged, using split horizon DNS can also avoid unnecessary expense.
54
55 h2. Examples
56
57 The remainder of this document walks through a number of examples to provide more detail.
58
59 h3. Keep-balance
60
61 Consider this section for the @Keep-balance@ service:
62
63 {% codeblock as yaml %}
64       Keepbalance:
65         InternalURLs:
66           "http://ip-10-0-1-233.internal:9005/": {}
67 {% endcodeblock %}
68
69 @Keep-balance@ has an API endpoint, but it is only used to expose "Prometheus":https://prometheus.io metrics.
70
71 There is no @ExternalURL@ key because @Keep-balance@ does not have an Arvados API, no Arvados services need to connect to @Keep-balance@.
72
73 The value for @InternalURLs@ tells the @Keep-balance@ service to start up and listen on port 9005, if it is started on a host where @ip-10-0-1-233.internal@ resolves to a local IP address. If @Keep-balance@ is started on a machine where the @ip-10-0-1-233.internal@ hostname does not resolve to a local IP address, it would refuse to start up, because it would not be able to find a local IP address to listen on.
74
75 It is also possible to use IP addresses in @InternalURLs@, for example:
76
77 {% codeblock as yaml %}
78       Keepbalance:
79         InternalURLs:
80           "http://127.0.0.1:9005/": {}
81 {% endcodeblock %}
82
83 In this example, @Keep-balance@ would start up and listen on port 9005 at the @127.0.0.1@ IP address. Prometheus would only be able to access the @Keep-balance@ metrics if it could reach that IP and port, e.g. if it runs on the same machine.
84
85 Finally, it is also possible to listen on all interfaces, for example:
86
87 {% codeblock as yaml %}
88       Keepbalance:
89         InternalURLs:
90           "http://0.0.0.0:9005/": {}
91 {% endcodeblock %}
92
93 In this case, @Keep-balance@ will listen on port 9005 on all IP addresses local to the machine.
94
95 h3. Keepstore
96
97 Consider this section for the @Keepstore@ service:
98
99 {% codeblock as yaml %}
100       Keepstore:
101         InternalURLs:
102           "http://keep0.ClusterID.example.com:25107": {}
103           "http://keep1.ClusterID.example.com:25107": {}
104 {% endcodeblock %}
105
106 There is no @ExternalURL@ key because @Keepstore@ is only accessed from inside the Arvados cluster. For access from outside, all traffic goes via @Keepproxy@.
107
108 When @Keepstore@ is installed on the host where @keep0.ClusterID.example.com@ resolves to a local IP address, it will listen on port 25107 on that IP address. Likewise on the @keep1.ClusterID.example.com@ host. On all other systems, @Keepstore@ will refuse to start.
109
110 h3. Keepproxy
111
112 Consider this section for the @Keepproxy@ service:
113
114 {% codeblock as yaml %}
115       Keepproxy:
116         ExternalURL: https://keep.ClusterID.example.com
117         InternalURLs:
118           "http://localhost:25107": {}
119 {% endcodeblock %}
120
121 The @ExternalURL@ advertised is @https://keep.ClusterID.example.com@. The @Keepproxy@ service will start up on @localhost@ port 25107, however. This is possible because we also configure Nginx to terminate SSL and sit in front of the @Keepproxy@ service:
122
123 <notextile><pre><code>upstream keepproxy {
124   server                127.0.0.1:<span class="userinput">25107</span>;
125 }
126
127 server {
128   listen                  443 ssl;
129   server_name             <span class="userinput">keep.ClusterID.example.com</span>;
130
131   proxy_connect_timeout   90s;
132   proxy_read_timeout      300s;
133   proxy_set_header        X-Real-IP $remote_addr;
134   proxy_http_version      1.1;
135   proxy_request_buffering off;
136   proxy_max_temp_file_size 0;
137
138   ssl_certificate     <span class="userinput">/YOUR/PATH/TO/cert.pem</span>;
139   ssl_certificate_key <span class="userinput">/YOUR/PATH/TO/cert.key</span>;
140
141   # Clients need to be able to upload blocks of data up to 64MiB in size.
142   client_max_body_size    64m;
143
144   location / {
145     proxy_pass            http://keepproxy;
146   }
147 }
148 </code></pre></notextile>
149
150 If a client connects to the @Keepproxy@ service, it will talk to Nginx which will reverse proxy the traffic to the @Keepproxy@ service.
151
152 h3. Workbench
153
154 Consider this section for the @Workbench@ service:
155
156 {% codeblock as yaml %}
157   Workbench1:
158     ExternalURL: "https://workbench.ClusterID.example.com"
159 {% endcodeblock %}
160
161 The @ExternalURL@ advertised is @https://workbench.ClusterID.example.com@. There is no value for @InternalURLs@ because Workbench1 is a Rails application served by Passenger. The only client connecting to the Passenger process is the reverse proxy (e.g. Nginx), and the listening host/post is configured in its configuration:
162
163 <notextile><pre><code>
164 server {
165   listen       443 ssl;
166   server_name  workbench.ClusterID.example.com;
167
168   ssl_certificate     /YOUR/PATH/TO/cert.pem;
169   ssl_certificate_key /YOUR/PATH/TO/cert.key;
170
171   root /var/www/arvados-workbench/current/public;
172   index  index.html;
173
174   passenger_enabled on;
175   # If you're using RVM, uncomment the line below.
176   #passenger_ruby /usr/local/rvm/wrappers/default/ruby;
177
178   # `client_max_body_size` should match the corresponding setting in
179   # the API.MaxRequestSize and Controller's server's Nginx configuration.
180   client_max_body_size 128m;
181 }
182 </code></pre></notextile>
183
184 h3. API server
185
186 Consider this section for the @RailsAPI@ service:
187
188 {% codeblock as yaml %}
189       RailsAPI:
190         InternalURLs:
191           "http://localhost:8004": {}
192 {% endcodeblock %}
193
194 There is no @ExternalURL@ defined because the @RailsAPI@ is not directly accessible and does not need to advertise a URL: all traffic to it flows via @Controller@, which is the only client that talks to it.
195
196 The @RailsAPI@ service is also a Rails application, and its listening host/port is defined in the Nginx configuration:
197
198 <notextile><pre><code>
199 server {
200   # This configures the Arvados API server.  It is written using Ruby
201   # on Rails and uses the Passenger application server.
202
203   listen localhost:8004;
204   server_name localhost-api;
205
206   root /var/www/arvados-api/current/public;
207   index  index.html index.htm index.php;
208
209   passenger_enabled on;
210
211   # If you are using RVM, uncomment the line below.
212   # If you're using system ruby, leave it commented out.
213   #passenger_ruby /usr/local/rvm/wrappers/default/ruby;
214
215   # This value effectively limits the size of API objects users can
216   # create, especially collections.  If you change this, you should
217   # also ensure the following settings match it:
218   # * `client_max_body_size` in the previous server section
219   # * `API.MaxRequestSize` in config.yml
220   client_max_body_size 128m;
221 }
222 </code></pre></notextile>
223
224 So then, why is there a need to specify @InternalURLs@ for the @RailsAPI@ service? It is there because this is how the @Controller@ service locates the @RailsAPI@ service it should talk to. Since this connection is internal to the Arvados cluster, @Controller@ uses @InternalURLs@ to find the @RailsAPI@ endpoint.
225
226 h3. Controller
227
228 Consider this section for the @Controller@ service:
229
230 {% codeblock as yaml %}
231   Controller:
232     InternalURLs:
233       "https://ctrl-0.internal":
234         ListenURL: "http://localhost:8003"
235     ExternalURL: "https://ClusterID.example.com"
236 {% endcodeblock %}
237
238 The @ExternalURL@ advertised to clients is @https://ClusterID.example.com@. The @arvados-controller@ process will listen on @localhost@ port 8003. Other Arvados service processes in the cluster can connect to this specific controller instance, using the URL @https://ctrl-0.internal@. Nginx is configured to sit in front of the @Controller@ service and terminate TLS:
239
240 <notextile><pre><code>
241 # This is the port where nginx expects to contact arvados-controller.
242 upstream controller {
243   server     localhost:8003  fail_timeout=10s;
244 }
245
246 server {
247   # This configures the public https port that clients will actually connect to,
248   # the request is reverse proxied to the upstream 'controller'
249
250   listen       443 ssl;
251   server_name  ClusterID.example.com ctrl-0.internal;
252
253   ssl_certificate     /YOUR/PATH/TO/cert.pem;
254   ssl_certificate_key /YOUR/PATH/TO/cert.key;
255
256   # Refer to the comment about this setting in the passenger (arvados
257   # api server) section of your Nginx configuration.
258   client_max_body_size 128m;
259
260   location / {
261     proxy_pass               http://controller;
262     proxy_redirect           off;
263     proxy_connect_timeout    90s;
264     proxy_read_timeout       300s;
265     proxy_max_temp_file_size 0;
266     proxy_request_buffering  off;
267     proxy_buffering          off;
268     proxy_http_version       1.1;
269
270     proxy_set_header      Host              $http_host;
271     proxy_set_header      Upgrade           $http_upgrade;
272     proxy_set_header      Connection        "upgrade";
273     proxy_set_header      X-External-Client $external_client;
274     proxy_set_header      X-Forwarded-For   $proxy_add_x_forwarded_for;
275     proxy_set_header      X-Forwarded-Proto https;
276     proxy_set_header      X-Real-IP         $remote_addr;
277   }
278 }
279 </code></pre></notextile>
280
281 If the host part of @ListenURL@ is ambiguous, in the sense that more than one system host is able to listen on that address (e.g., @localhost@), configure each host's startup scripts to set the environment variable @ARVADOS_SERVICE_INTERNAL_URL@ to the @InternalURLs@ key that will reach that host. In the example above, this would be @ARVADOS_SERVICE_INTERNAL_URL=https://ctrl-0.internal@.
282
283 If the cluster has just a single node running all of the Arvados server processes, configuration can be simplified:
284
285 {% codeblock as yaml %}
286   Controller:
287     InternalURLs:
288       "http://localhost:8003": {}
289     ExternalURL: "https://ClusterID.example.com"
290 {% endcodeblock %}