# Deploy with Puppet

This guide provides a complete Puppet module for installing and enrolling LinuxGuard. Credentials are stored in Hiera using the eyaml encryption backend, which encrypts individual values in Hiera YAML files while keeping keys readable. The module is idempotent — safe to apply on already-enrolled nodes because the enroll exec resource includes an `unless` guard on `/var/lib/linuxguard/config`.

## Prerequisites

* Puppet 7 or 8 with Puppet Server
* hiera-eyaml available on Puppet Server (bundled with Puppet Server 5.2.0+; install with `puppetserver gem install hiera-eyaml` if needed)
* A LinuxGuard API key and tenant ID (from the LinuxGuard console)

## Module Structure

Create the following structure in your Puppet environment's `modules/` directory:

```
modules/
└── linuxguard/
    ├── metadata.json        # Module name, author, version, dependencies
    └── manifests/
        └── init.pp          # Main class: install, service, enroll
```

Hiera data lives in the environment, not in the module:

```
environments/production/
├── hiera.yaml               # Hierarchy with eyaml backend
└── data/
    └── common.eyaml         # Encrypted LinuxGuard credentials
```

## Step 1: Generate eyaml Encryption Keys

eyaml uses PKCS7 key pairs to encrypt Hiera values. Generate the keys on your Puppet Server:

```bash
eyaml createkeys
```

The keys are generated in `./keys/` by default. Move them to the standard location:

```bash
sudo mkdir -p /etc/puppetlabs/puppet/eyaml
sudo mv keys/private_key.pkcs7.pem /etc/puppetlabs/puppet/eyaml/
sudo mv keys/public_key.pkcs7.pem /etc/puppetlabs/puppet/eyaml/
```

Then fix key ownership so Puppet Server can read them:

```bash
sudo chown -R puppet:puppet /etc/puppetlabs/puppet/eyaml
sudo chmod -R 0500 /etc/puppetlabs/puppet/eyaml
```

> **Note:** Puppet Server runs as the `puppet` user. If the key files are owned by root, Puppet catalog compilation will fail with a permission error when attempting to decrypt Hiera values.

## Step 2: Encrypt LinuxGuard Credentials

Run `eyaml encrypt` for each credential value:

```bash
eyaml encrypt -s '<YOUR_API_KEY>'
eyaml encrypt -s '<YOUR_TENANT_ID>'
```

Each command outputs an `ENC[PKCS7,...]` block. Copy the outputs into `environments/production/data/common.eyaml`:

```yaml
---
linuxguard::api_key: ENC[PKCS7,MIIBiAYJKoZIhvfQ...]
linuxguard::tenant_id: ENC[PKCS7,MIIBmAYJKoZIhvfQ...]
```

Replace the placeholder `ENC[PKCS7,...]` strings with the actual output from the `eyaml encrypt` commands above.

## Step 3: Configure the Hiera eyaml Backend

Create or update `environments/production/hiera.yaml` with the eyaml backend configuration:

```yaml
---
version: 5
defaults:
  datadir: data
  data_hash: yaml_data
hierarchy:
  - name: "Encrypted secrets"
    lookup_key: eyaml_lookup_key
    paths:
      - "common.eyaml"
    options:
      pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem
      pkcs7_public_key:  /etc/puppetlabs/puppet/eyaml/public_key.pkcs7.pem
```

Place this file at `environments/production/hiera.yaml`, or the equivalent path for your environment name.

## Step 4: Create the Module Files

### metadata.json

```json
{
  "name": "yourorg-linuxguard",
  "version": "1.0.0",
  "author": "yourorg",
  "license": "Apache-2.0",
  "summary": "Install and enroll LinuxGuard agent",
  "source": "https://github.com/yourorg/puppet-linuxguard",
  "dependencies": []
}
```

Replace `yourorg` with your organisation's name.

### manifests/init.pp

```puppet
class linuxguard (
  String $api_key   = lookup('linuxguard::api_key'),
  String $tenant_id = lookup('linuxguard::tenant_id'),
) {
  exec { 'install_linuxguard':
    command => 'curl -fsSL https://packages.linuxguard.io/install-linuxguard.sh | bash -s -- --yes',
    path    => ['/usr/bin', '/bin'],
    unless  => 'test -f /usr/bin/linuxguard-agent',
  }

  service { 'linuxguard-agent':
    ensure  => running,
    enable  => true,
    require => Exec['install_linuxguard'],
  }

  exec { 'enroll_linuxguard':
    command => "/usr/bin/linuxguard-agent enroll --api-key=${api_key} --tenant-id=${tenant_id}",
    unless  => 'test -f /var/lib/linuxguard/config',
    path    => ['/usr/bin', '/bin'],
    require => Service['linuxguard-agent'],
  }
}
```

> **Note:** The `unless => 'test -f /var/lib/linuxguard/config'` guard skips enrollment if the agent is already enrolled. The `require` attributes enforce ordering: install -> service -> enroll. See [Automated Deployment Overview](/how-to-guides/how-to/automated-deployment.md) for details on the agent's built-in idempotency behavior.

## Step 5: Apply the Module

Classify the node with the module using the Puppet site manifest or an ENC:

```puppet
# site.pp or node classification
node 'my-server.example.com' {
  include linuxguard
}
```

Or classify via the Puppet Enterprise console or your node classifier of choice.

Then trigger a Puppet agent run on the target node:

```bash
puppet agent --test
```

Enrolled nodes appear in the **Infrastructure** view of the LinuxGuard console within a few minutes of successful enrollment.

***

**Related**: [Automated Deployment Overview](/how-to-guides/how-to/automated-deployment.md) | [Installation](/how-to-guides/how-to/installation.md) | [Configuration](/how-to-guides/how-to/configuration.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.linuxguard.io/how-to-guides/how-to/automated-deployment/deploy-with-puppet.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
