If you also want to emulate a real-world environment, you'll need to [set up a Puppet server](#set-up-a-puppet-server).
## How the module works
```mermaid
sequenceDiagram
autonumber
participant A as Agent
participant P as Puppet Server
participant F as Fleet
A->>P: Catalog request
P->>F: POST /mdm/apple/profiles/preassign <br/> for each `fleetdm::profile` resource
P->>A: Catalog compilation finished
A->>P: Results of the run
Note over A,P: Puppet run is completed
P->>F: POST POST /mdm/apple/profiles/match <br/> to signal end of run and match profiles
Note over F: create/edit a team with the pre-assigned profiles
Note over F: assign the host to the team
```
The sequence diagram above illustrates a typical run:
1. The agent initiates communication with the Puppet server, similar to how `osquery` checks in with the Fleet server.
2. The server builds a catalog (a JSON with instructions) based on the resources defined by the IT admin in manifests (files with `.pp` extension).
- Inside manifests, one or more [`fleetdm::profile`](https://github.com/fleetdm/fleet/blob/main/ee/tools/puppet/fleetdm/manifests/profile.pp) resources can be declared.
- Each time the Puppet server finds a `fleetdm::profile`, it makes a request to the Fleet server to ["pre-assign" the profile](https://fleetdm.com/docs/contributing/api-for-contributors#preassign-profiles-to-devices).
- On each request, the Fleet server stores information about the profile and the host in Redis.
3. The Puppet server sends the catalog back. Unlike typical modules, this catalog doesn't contain instructions related to profiles; all the work is done by the Fleet server through the MDM protocol.
4. The agent applies the catalog and signals to the Puppet server when it finishes.
5. After the run, the server can send one or more [reports](https://www.puppet.com/docs/puppet/8/reporting_about.html) about the run, containing information like the duration of the run. We utilize this feature to send a [match request](https://fleetdm.com/docs/contributing/api-for-contributors#match-preassigned-profiles) to the Fleet server to signal that the run for the node is done in our [custom reporter](https://github.com/fleetdm/fleet/blob/main/ee/tools/puppet/fleetdm/lib/puppet/reports/fleetdm.rb).
Once the run is complete, the server collects all pre-assigned profiles from Redis and performs the following:
1. Creates/edits a team with the set of pre-assigned profiles.
2. Adds the host to the team.
## Set up a Puppet server
The easiest way to set-up a local instance is by using [`puppetlabs/pupperware`](https://github.com/puppetlabs/pupperware). Follow the instructions on their README to get a server running.
> Note: `pupperware` doesn't work on macOS with ARM processors.
After the server is running, edit your hosts file (in macOS `/etc/hosts`,) to resove the `puppet` hostname to the IP of your Puppet server, for example:
```
192.168.100.13 puppet
```
> Note: there are ways to configure Puppet if you don't want to edit your hosts file, but doing this will save you some trouble.
Once your server is running, you need to configure it, some usefult paths are:
-`/etc/puppetlabs/code` to manage modules and different environments
-`/opt/puppetlabs/server` for server-specific stuff
The only thing left to do is to add the `fleetdm/fleetdm` module to your server. You can either:
- Copy and paste the contents of this directory in `/etc/puppetlabs/code/environments/production/modules` (the whole `/etc/puppetlabs/code` directory is a Docker volume)
- Install the module running `puppet module install fleetdm-fleetdm --version 0.2.1` and tweak the installed code.
> **Important** if you make changes to the `utils` folder of the module, you need to run `puppetserver reload` in your Puppet server afterwards, files in that folder are not autoloaded.
## Releasing
1. Bump the module version in the [metadata.json](https://github.com/fleetdm/fleet/blob/main/ee/tools/puppet/fleetdm/metadata.json) file.