Hi Team,
Is it possible to run multiple instances of companion app that are related? We have companion deployed with our server which is highly available. When instance count > 1 provider oauth flow fails with
companion: 2019-09-23T08:49:42.840Z [error] grant.oauth.error grant.js responded with error: error=Grant%3A%20missing%20session%20or%20misconfigured%20provider
Earlier I was getting a different error that was resolved after I added transport: 'session' to my custom providers.
From looking at the code extensively, I believe the redis integration only provides for storing update progress and not the session storage itself. Is it possible today to have companion running in high availability with shared session storage?
You _can_ have multiple instances behind a load balancer or something, but the sessions have to be sticky, so that users always hit the same instance. To facilitate that Companion sends an I-Am: xyz.my-app.com header with the hostname of that instance, and Uppy uses that hostname for subsequent requests. For ex with Transloadit, the client-side sets the companion url to https://api2.transloadit.com/companion, the API-side load balancer sends it to eg https://api2-joy.transloadit.com/companion, which replies with an I-Am: api2-joy.transloadit.com header. Later requests will be sent directly to api2-joy.
Hope that makes sense, I don't have any experience with setups with many servers beyond what I heard from the rest of the Transloadit team :laughing:
Thanks for quick response, @goto-bus-stop
That will be a lot of orchestration for my deployment. The server's are deployed in containers fronted by an AWS application load balancer fronted by an nginx. Enabling sticky session for companion app alone will not be feasible.
If you or someone from the team can point me to the concerned set of classes, I will try to store sessions into redis and make them distributed.
If not, will probably have to deploy companion app separately with its own ALB (with sticky sessions enabled).
@ifedapoolarewaju could you help here please?
@serverdevil sorry for the delayed response here. To run companion in multiple instances, you need to set the following options when instantiating companion (see the server section in options):
companion.app({
...
server: {
oauthDomain: <master domain (e.g sub1.mydomain.com) to handle your oauth>,
validHosts: <a list of valid domains running your Companion instances. The list may also contain regex patterns. e.g ['sub2.mydomain.com', '(\\w+).mydomain.com']>
}
})
please let me know if this works for you, or if you have any other questions
@ifedapoolarewaju no harm done!!
We moved the app to uploads.example.com as per the suggestion. Works well for us that way.
When we plan on scaling our upload service.. will try out your suggestion.
Question: so master domain handles all authentication while other servers chip in for heavy lifting? Are sticky sessions still required in this case?
@serverdevil when a companion instance receives the first request, it will redirect to the master domain for the oauth dance to be handled. After the Oauth dance is done, further requests are passed back to the instance that received the first request.
so long as you are setting the sendSelfEndpoint option per companion instance to it's actual URL i.e https://instance1.server.com, and it is directly accessible via this URL, then companion will try to achieve this sticky session behaviour by itself.
Thanks for the explanation. And kudos again, for an amazing product.
Most helpful comment
@serverdevil when a companion instance receives the first request, it will redirect to the master domain for the oauth dance to be handled. After the Oauth dance is done, further requests are passed back to the instance that received the first request.
so long as you are setting the
sendSelfEndpointoption per companion instance to it's actual URL i.ehttps://instance1.server.com, and it is directly accessible via this URL, then companion will try to achieve this sticky session behaviour by itself.