(bootstrapping)= # Boostrapping a model When you first start looking at the bootstrap process it all seems to be a convoluted mess. However there is method to our madness. Bootstrapping starts with the CLI command `bootstrap`. That is found in cmd/juju/bootstrap.go The first step of bootstrap is to create an Environ instance which is named. This Environ instance has the model configuration (the *config.Config instance). Initially this will check in the default config store, which is $JUJU_HOME/models. This calls through to bootstrap.PrepareForName in environs/open.go. This makes sure that the model configuration contains an admin secret, a CA cert, and a UUID. It is at this time that the initial .jenv file is written out to $JUJU_DATA/models. Further checks are then done as part of the bootstrap command: * validating the constaints * checking to make sure the model is already bootstrapped The code then moves on to the Bootstrap function defined in environs/bootstrap/bootstrap.go. bootstrap.Bootstrap starts with sanity checks: * setting a package global in the network package for prefer IPv6 (not sanity) * there is an admin-secret * that there is at least one authorised SSH key * that there is a CA Cert and CA Key * that the model storage is writable (by writing the bootstrap-init file) * finds available agent binaries - locate agent binaries available externally (matching constraints) - determine which agent binaries can be built and uploaded to make up shortfall in above - if the best agent binaries are local, we attempt to upload them This code then calls into the Bootstrap function on the environ instance (backed by a provider), which returns arch, series, and a finalizer function. Now things diverge here a little: * azure does some initial config around affinity groups and networks, then calls common.Bootstrap. * ec2, maas, and openstack all fall through to common.Bootstrap * dummy, local and manual all do their own thing Firstly, common.Bootstrap: * creates machine config for the bootstrap machine * starts an instance for the bootstrap machine * writes the instance id (as yaml) into the the "provider-state" file in environ storage - this step will go away soon, or at least become provider specific The finalizer function is run by bootstrap.Bootstrap after the following is performed: * select agent binaries from the previously calculated set based on the architecture and series of the instance that the provider started * make sure that the agent binaries are available * create the machine config struct for the bootstrap machine * set the agent binaries in that structure to the agent binaries bootstrap knows about. The common finalizer function does the following: * updates the machine config with the instance id of the new machine * calls environs.FinishMachineConfig * populates the machine config with information from the config object * checks for CA Cert * checks for admin-secret * creates a password hash using the password.CompatSalt * uses this password hash for both the APIInfo and MongoInfo passwords. * creates the controller cert and key * strips the admin-secret and server ca-private-key from the config * this step is probably not needed any more * calls common.FinishBootstrap * calls ssh with a custom script that first checks the nonce on the cloud instance * calls ConfigureMachine * creates cloud init script from the machine config, this includes the call to jujud bootstrap-state. * the bootstrap config is passed to jujud as base64 encoded yaml * runs said script over ssh jujud bootstrap-state * creates a *config.Config object from the base64 encoded yaml from the command line * sets the package global in the network package for prefer IPv6 * generates and writes out the system SSH identity file * generates a (long) shared secret for mongo * mongo is then started * the database is then initialized (state.Initialize) * copies the agent binaries into model storage - also clones the agent binaries for each series of the same OS (for the time being at least, while each series' agent binaries are equivalent)