# Deploy with AWS EC2 User-Data

This guide provides a complete EC2 user-data script that installs and enrolls LinuxGuard at instance launch. Credentials are retrieved from AWS Secrets Manager at runtime — no API keys or tenant IDs are hardcoded in the script.

## Prerequisites

* AWS CLI installed locally for the one-time setup steps
* An EC2 instance role (instance profile) attached to your target instances
* A LinuxGuard API key and tenant ID (from the LinuxGuard console)

## Step 1: Store credentials in Secrets Manager

Run this command once from your local machine or CI/CD pipeline to create the secret:

```bash
aws secretsmanager create-secret \
  --name linuxguard/credentials \
  --secret-string '{"api_key":"<API_KEY>","tenant_id":"<TENANT_ID>"}' \
  --region <AWS_REGION>
```

Note the **ARN** in the command output — you will reference it when scoping the IAM policy in the next step.

## Step 2: Attach an IAM policy to your instance role

The EC2 instance needs permission to read the specific secret created above. Attach the following least-privilege inline or managed policy to the IAM role assigned to your EC2 instances (via the instance profile):

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:<AWS_REGION>:<ACCOUNT_ID>:secret:linuxguard/credentials-*"
    }
  ]
}
```

> **Note:** The `-*` suffix in the resource ARN matches the random suffix that AWS appends to secret ARNs. Omitting it causes `AccessDeniedException` when the instance attempts to read the secret. Replace `<AWS_REGION>` and `<ACCOUNT_ID>` with your values.

## Step 3: Configure and launch with user-data

> **Note:** EC2 user-data scripts run **once** on first instance launch by default. Re-enrollment on subsequent reboots is not a concern — the script does not run again unless you explicitly reconfigure the instance to do so.

Paste the script below into the **User data** field when launching your EC2 instance (via the console, CLI, Launch Template, or CloudFormation). Replace the two values in the `# Configuration` section:

```bash
#!/usr/bin/env bash
set -euo pipefail

# ===========================================================
# Configuration — replace these values for your environment
# ===========================================================
SECRET_NAME="linuxguard/credentials"
AWS_REGION="<AWS_REGION>"
# ===========================================================

# Install jq if not present (needed to parse Secrets Manager JSON output)
if ! command -v jq &> /dev/null; then
  apt-get install -y jq 2>/dev/null || yum install -y jq 2>/dev/null || true
fi

# Retrieve credentials from Secrets Manager (IAM instance role provides access)
SECRET=$(aws secretsmanager get-secret-value \
  --secret-id "${SECRET_NAME}" \
  --region "${AWS_REGION}" \
  --query 'SecretString' \
  --output text)
API_KEY=$(echo "${SECRET}" | jq -r '.api_key')
TENANT_ID=$(echo "${SECRET}" | jq -r '.tenant_id')

# Install LinuxGuard agent
curl -fsSL https://packages.linuxguard.io/install-linuxguard.sh | bash -s -- --yes

# Enroll agent — built-in guard prevents re-enrollment if already enrolled
linuxguard-agent enroll \
  --api-key="${API_KEY}" \
  --tenant-id="${TENANT_ID}"
```

> **Note:** For operators who want explicit visibility into whether enrollment was skipped, replace the enroll step with a conditional check:
>
> ```bash
> if ! systemctl is-active --quiet linuxguard-agent; then
>   linuxguard-agent enroll \
>     --api-key="${API_KEY}" \
>     --tenant-id="${TENANT_ID}"
> fi
> ```
>
> This approach skips enrollment if the service is already running. See [Automated Deployment Overview](/how-to-guides/how-to/automated-deployment.md) for details on the agent's built-in idempotency guard.

After launch, enrolled servers appear in the LinuxGuard console under **Infrastructure** within a few minutes.

***

**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-aws-userdata.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.
