couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jan Lehnardt <>
Subject Re: Setting up CouchDB 2.0
Date Sun, 26 Oct 2014 20:25:54 GMT

> On 26 Oct 2014, at 20:31 , Alexander Shorin <> wrote:
> Hi Jan,
> Suddenly, gists doesn't supports per-line comments. Replied inline
> with questions.

Good questions, thanks! Answers inline :)

> On Sun, Oct 26, 2014 at 10:04 PM, Jan Lehnardt <> wrote:
>> N. End User Action
>> - What happens behind the scenes.
>> 1. Launch CouchDB with `$ couchdb`, or init.d, or any other way, exactly
>> like it is done in 1.x.x.
>> - CouchDB launches and listens on
>> From here on, there are two paths, one is via Fauxton (a) the other is
>> using a HTTP endpoint (b). Fauxton just uses the HTTP endpoint in (b).
>> (b) can be used to set up a cluster programmatically.
>> 2.a. Go to Fauxton. There is a “Cluster Setup” tab in the sidebar. Go
>> to the tab and get presented with a form that asks you to enter an admin
>> username, admin password and optionally a bind_address and port to bind
>> to publicly. Submit the form with the [Enable Cluster] button.
>> - POST to /_setup with
>>   {
>>     "action": "enable_cluster",
>>     "admin": {
>>       "user": "username",
>>       "pass": "password"
>>     },
>>     ["bind_address": "xxxx",]
>>     ["port": yyyy]
>>   }
>> This sets up the admin user on the current node and binds to
>> or the specified ip:port. Logs admin user into Fauxton automatically.
>> 2.b. POST to /_setup as shown above.
>> Repeat on all nodes.
>> - keep the same username/password everywhere.
> Question:
> - Is /_setup admin-only resource?

Definitely, sorry for missing that bit.

> - If node already has admin-party fixed should it accepts new admin credentials?

Good question, I’d say if an admin already exists, no new admin credentials are needed/

> - Any reasons to replace 1-3 PUT requests to /_config with single POST
> one in this case?

I’m not sure what the 1-3 PUT requests are?

> 3. Pick any one node, for simplicity use the first one, to be the
>> “setup coordination node”.
>> - this is a “master” node that manages the setup and requires all
>>   other nodes to be able to see it and vice versa. Setup won’t work
>>   with unavailable nodes (duh). The notion of “master” will be gone
>>   once the setup is finished. At that point, the system has no
>>   master node. Ignore I ever said “master”.
>> a. Go to Fauxton / Cluster Setup, once we have enabled the cluster, the
>> UI shows an “Add Node” interface with the fields admin, and node:
>> - POST to /_setup with
>>   {
>>     "action": "add_node",
>>     "admin": { // should be auto-filled from Fauxton
>>       "user": "username",
>>       "pass": "password"
>>     },
>>     "node": {
>>       "host": "hostname",
>>       ["port": 5984]
>>     }
>>   }
>> b. as in a, but without the Fauxton bits, just POST to /_setup
>> - this request will do this:
>>  - on the “setup coordination node”:
>>   - check if we have an Erlang Cookie Secret. If not, generate
>>     a UUID and set the erlang cookie to to that UUID.
>>     // TBD: persist the cookie, so it survives restarts
>>   - make a POST request to the node specified in the body above
>>     using the admin credentials in the body above:
>>     POST to http://username:password@node_b:5984/_setup with:
>>     {
>>       "action": "receive_cookie",
>>       "cookie": "<secretcookie>",
>>     }
>>     // TBD: persist the cookie on node B, so it survives restarts
>>   - when the request to node B returns, we know the Erlang-level
>>     inter-cluster communication is enabled and we can start adding
>>     the node on the CouchDB level. To do that, the “setup
>>     coordination node” does this to it’s own HTTP endpoint:
>>     PUT /nodes/node_b:5984 or the same thing with internal APIs.
>> - Repeat for all nodes.
>> - Fauxton keeps a list of all set up nodes for users to see.
> Question:
> - Since Fauxton already known all the nodes admin credentials and all
> the nodes are bounded to iface (from previous step), will
> Fauxton automate nodes join into the cluster? This is about to skip
> "Repeat on all nodes" step

How does Fauxton know about the other nodes at this point?
(I guess since the Erlang cluster is already set up, it could expose that
info to Fauxton in a zeroconf kind of fashion and auto-populate the Fauxton
UI with nodes that then can be joined with just a click of a button.)

> - If some of my nodes have different admin credentials, is this the
> blocker error case or should Fauxton ask me for these credentials?

That’s why `add_node` takes a username and password as options, you
can set that up if you want. / This could also be made an error case.
It should certainly not be recommended.

> - Any reasons for replacing regular request to /_nodes with custom
> /_setup?

I don’t know what /_nodes is. Do you mean /nodes? — The reason this isn’t
using /nodes at this point is that /nodes already has a special meaning
and I didn’t want to complicate the existing logic. In addition, /nodes
might have to be adjusted to carry the username and password of the target
CouchDB to do the setup (if we otherwise keep the proposed model, happy
to see alternatives, though!).

If we can reduce all of what I outlined to `PUT /nodes/node_b|c|d`, that
would be nice. Fauxton could then offer the setup UI based on whether /nodes
has any entries. But I don’t know enough about the semantics and other
uses of /nodes, so I haven’t thought about this option too much.

> Point about cookie counts.

Not sure I follow.

> 4.a. When all nodes are added, click the [Finish Cluster Setup] button
>> in Fauxton.
>> - this does POST /_setup
>>   {
>>     "action": "finish_setup"
>>   }
>> b. Same as in a.
>> - this manages the final setup bits, like creating the _users,
>>   _replicator and _db_updates endpoints and whatever else is needed.
>>   // TBD: collect what else is needed.
> This is the only useful thing that /_setup does from my current point
> of view - everything else was just masking standard requests to
> existed API.

Which existing API in particular?

If you mean that this all can be done over /_config and /nodes, yes totally,
but Fauxton on node_a can’t access /_config on node_b. That’s one of the
reasons of why I suggest using /_setup, so it can do all this from a single
node via Fauxton. The other reason is that it is a dedicated API end-point
that hides a lot of complexity instead of having end-users hit a bunch of
seemingly random endpoints (although this *could* be hidden in Fauxton maybe,
except for the cross domain issue).

>> ## The Setup Endpoint
>> This is not a REST-y endpoint, it is a simple state machine operated
>> by HTTP POST with JSON bodies that have an `action` field.
>> ### State 1: No Cluster Enabled
>> This is right after starting a node for the first time, and any time
>> before the cluster is enabled as outlined above.
>> GET /_setup
>> {"state": "cluster_disabled"}
>> POST /_setup {"action":"enable_cluster"...} -> Transition to State 2
>> POST /_setup {"action":"enable_cluster"...} with empty admin user/pass or invalid
host/post or host/port not available -> Error
>> POST /_setup {"action":"anything_but_enable_cluster"...} -> Error
> If "enable_cluster" only creates/setups admin and bind address, could
> this step be skipped? Because the same actions are possible to do via
> regular config setup.

Yes! It just needs to ensure these things are done. If Fauxton detects
they *are* done, it can skip the enable step and show the add_node interface
right away.

>> ### State 2: Cluster enabled, admin user set, waiting for nodes to be added.
>> GET /_setup
>> {"state":"cluster_enabled","nodes":[]}
>> POST /_setup {"action":"enable_cluster"...} -> Error
>> POST /_setup {"action":"add_node"...} -> Stay in State 2, but return "nodes":["node
B"}] on GET
>> POST /_setup {"action":"add_node"...} -> if target node not available, Error
>> POST /_setup {"action":"finish_cluster"} with no nodes set up -> Error
>> POST /_setup {"action":"finish_cluster"} -> Transition to State 3
> Questions:
> - How much nodes required to be added? 1? 2? 3?...

Doesn’t matter.

> - How to remove accidentally added node from cluster?

Delete from /nodes database. Could be added as a UI element in Fauxton.

>> ### State 3: Cluster set up, all nodes operational
>> GET /_setup
>> {"state":"cluster_finished","nodes":["node a", "node b", ...]}
>> POST /_setup {"action":"enable_cluster"...} -> Error
>> POST /_setup {"action":"finish_cluster"...} -> Stay in State 3, do nothing
>> POST /_setup {"action":"add_node"...} -> Error
>> POST /_setup?i_know_what_i_am_doing=true {"action":"add_node"...} -> Add node,
stay in State 3.
>> // TBD: we need to persist the setup state somewhere.
> Questions:
> - Why adding a new node after finish_cluster is some specific case to
> mark it with "i_know_what_i_am_doing" parameter?

Because I think it is not advisable to do this regularly, but someone might
want to do this regardless (see next).

> - How to enlarge / reduce cluster after his setup or even disband it?

Enlarge: see above.
Reduce: delete from /nodes
Disband: shut down all CouchDB processes :)

I don’t know the BigCouch/Cloudant best practices for this. I’ll chalk
this down as a “needs input from Cloudant people” :)

> Or this isn't what /_setup should cares about?

In general, this isn’t really covered by the setup proposal here. I’d like
to keep this out of scope for now, but we should have good answers to that
going forward.

> - What happens with /_setup resource after finish_cluster? Any case
> for it to be useful?

Only for Fauxton to show the correct setup state.

> - How could /_setup helps with admin password change among the all
> cluster nodes?

At least on the first run setup, Fauxton can just keep the new password in
memory and pre-fill the add_node screens with the same username and password.
/_setup then transports it over.

For later setups, I don’t know, as we would have the admin to enter the password
in plaintext so we can send it. Alternatively, we could use the /_config API to
read and send the PBKDF2 hash *waves hands*.

> - If I add a new node after "finish_cluster" setup, will it have all
> system databases (global_changes, cassim, _users...whatever else)
> created?

That is unspecified at this point. I’d need more input from the Cloudant people
on this one. I’m happy to go either way, or make it an option for later joined


>> * * *
>> So far.
>> I think this is simpler than the first try. It retains the simplicity
>> of getting started of 1.x.x. It is fully scriptable via HTTP. It has
>> the same setup-security properties as 1.x.x. It requires an admin account
>> for cluster setup, but only on the last possible occasion in the
>> process. It still fully hides the Erlang cluster / secure cookie setup
>> from the end-user.
>> Does this sound sensible to you? Am I missing anything aside from the
>> TBD bits, for which, if you have ideas, I’d love your input! :)
>> Are there any deal-breaker flaws in this? What can be made simpler or
>> more clear?
>> Note that all the HTTP endpoints and field names are just placeholders,
>> no need to bikeshed on these just yet :)
>> I’m looking forward to your feedback!
> --
> ,,,^..^,,,

View raw message