20.5. Configuring an Apache VirtualHost running Couchdb for a domain of perspectives models
In this paragraph we explore the issue of configuring Apache for a particular domain of Perspectives models. We assume the server runs Couchdb, which is available as an http server on localhost. Apache will forward requests for resources to this local couchdb server.
Note
|
This is different from the situation where a domain is hosted on a server that does not have a Couchdb installation. The VirtualHost configuration on such a server must forward requests to another, external server. See the next paragraph for that. |
As an example we’ll use the namespace of the System model, perspectives.domains
(like model://perspectives.domains#System
). For this domain, we will configure a VirtualHost in Apache on the relevant server. The VirtualHost starts out like this:
<VirtualHost *:443> ServerName https://perspectives.domains ServerAlias *.perspectives.domains </VirtualHost>
All requests to https://perspectives.domains
will now be captured by this virtualhost (assuming, of course, that the DNS refers this domain name to our server).
Note
|
this topic is related to Booting the Perspectives Universe |
20.5.1. Forwarding requests to Couchdb
In principle, we just want to pass all requests in the perspectives.domains
namespace to Couchdb. We can use ProxyPass for that. However, we have reason to except some requests (we’ll come back to that in the next paragraph), so we use ProxyPassMatch.
ProxyPassMatch "^(?!.*index\.html)(.*)$" "http://localhost:5984/$1" Header edit Set-Cookie (.*) "$1; Secure; Domain=perspectives.domains; SameSite=None;"
Notice that we edit the cookie. Couchdb will return an AuthSession
cookie when we request it at the _session
endpoint, presenting our credentials. In order to make the browser keep it and return it with subsequent requests, we have to add some attributes:
-
as we forward internally over http, we have to add the Secure attribute manually in Apache;
-
Couchdb does not include the Domain attribute. It seems wise (but has not proven to be necessary) to include the domain;
-
we absolutely must include the SameSite attribute; otherwise the browser will ignore the cookie.
20.5.2. Preflight requests
Given the fact that the PDR runs in the mycontexts.com
domain and we request resources from the perspectives.domains
domain, we have to deal with CORS.
A problem to solve is that the browser sends a preflight request for .json resources, before it sends a PUT or POST request to store some information in the database on our server. However, Couchdb doesn’t accept the OPTIONS method (which goes into the preflight request). So we have to have Apache handle that. We do so using url rewriting:
RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(OPTIONS)$ RewriteRule ^/.*$ index.html [R=204]
Every request using the OPTIONS method is rewritten as a request to a standard resource index.html
(its content is of no importance). Referring back to the previous paragraph, this explains the condition for ProxyPassMatch:
-
we have Apache apply the url rewriting first;
-
and only then do we forward requests to the local Couchdb - in principle any request, except a request for index.html!
We force the response code 204 (No content), described by There is no content to send for this request, but the headers may be useful.. So what headers do we return?
Header always set Access-Control-Allow-Credentials "true" Header always set Access-Control-Allow-Origin https://mycontexts.com Header always set Access-Control-Allow-Headers "content-type"
Notice that these should be read as server instructions to the browser as to what headers it (the server) will allow in requests from the browser. We should also inform the browser what methods are allowed, but here we need a refinement for the PDR. This is the subject of the next paragraph.
First, however, we have to make absolutely sure that we control these headers, by unsetting them first:
Header unset Access-Control-Allow-Credentials Header unset Access-Control-Allow-Methods Header unset Access-Control-Allow-Origin Header unset Access-Control-Allow-Headers
20.5.3. Certificates
To complete the treatment, we should of course include references to the necessary certificate and key file for Apache to handle SSL.
SSLEngine on SSLCertificateFile /path/to/certs/perspectives.domains-2023-certificate.crt SSLCertificateKeyFile /path/to/keys/perspectives.domains-2023-certificate.key
20.5.4. Putting it all together
In the right order, we now have:
<VirtualHost *:443> ServerName https://perspectives.domains ServerAlias *.perspectives.domains RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(OPTIONS)$ RewriteRule ^/.*$ index.html [R=204] ProxyPassMatch "^(?!.*index\.html)(.*)$" "http://localhost:5984/$1" Header edit Set-Cookie (.*) "$1; Secure; Domain=perspectives.domains; SameSite=None;" Header unset Access-Control-Allow-Credentials Header unset Access-Control-Allow-Methods Header unset Access-Control-Allow-Origin Header unset Access-Control-Allow-Headers Header always set Access-Control-Allow-Credentials "true" Header always set Access-Control-Allow-Origin https://mycontexts.com Header always set Access-Control-Allow-Headers "content-type" Header always Set Access-Control-Allow-Methods "GET, PUT, POST, DELETE, OPTIONS" SSLEngine on SSLCertificateFile /path/to/certs/perspectives.domains-2023-certificate.crt SSLCertificateKeyFile /path/to/keys/perspectives.domains-2023-certificate.key </VirtualHost>
Finally, notice that it is useful to add some more instructions like ServerAdmin, DocumentRoot, LogLevel, ErrorLog and CustomLog.