# Deploying the NGINX Node with AWS AMI

This article provides instructions for deploying the Wallarm [NGINX node](https://docs.wallarm.com/installation/nginx-native-node-internals.md) on AWS [in-line](https://docs.wallarm.com/installation/inline/overview.md) using the [official Amazon Machine Image (AMI)](https://aws.amazon.com/marketplace/pp/B073VRFXSD).

The image is based on Debian and the NGINX version provided by Debian. Currently, the latest image uses Debian 12, which includes NGINX stable 1.22.1.

Deploying the Wallarm Node from the AMI on AWS typically takes around 10 minutes.

![!](https://docs.wallarm.com/images/waf-installation/aws/aws-ami-flow.png)

!!! info "Security note"
    This solution is designed to follow AWS security best practices. We recommend avoiding the use of the AWS root account for deployment. Instead, use IAM users or roles with only the necessary permissions.

    The deployment process assumes the principle of least privilege, granting only the minimal access required to provision and operate Wallarm components.

For guidance on estimating AWS infrastructure costs for this deployment, see the [Cost Guidance for Deploying Wallarm in AWS](https://docs.wallarm.com/installation/cloud-platforms/aws/costs.md) page.

## Use cases

Among all supported [Wallarm deployment options](https://docs.wallarm.com/installation/supported-deployment-options.md), AMI is recommended for Wallarm deployment in these **use cases**:

* Your existing infrastructure resides on AWS.
* You aim to deploy a security solution as a separate cloud instance, rather than installing it directly on frontend systems like NGINX.

## Requirements

* An AWS account
* Understanding of AWS EC2, Security Groups
* Any AWS region of your choice, there are no specific restrictions on the region for the Wallarm node deployment

    Wallarm supports both single availability zone (AZ) and multi availability zone deployments. In multi-AZ setups, Wallarm Nodes can be launched in separate availability zones and placed behind a Load Balancer for high availability.
* Access to the account with the **Administrator** role in Wallarm Console for the [US Cloud](https://us1.my.wallarm.com/) or [EU Cloud](https://my.wallarm.com/), or [ME Cloud](https://me1.my.wallarm.com/)
* Executing all commands on a Wallarm instance as a superuser (e.g. `root`)
* No system user named `wallarm` exists 

## Installation

### 1. Launch a Wallarm Node instance

Launch an EC2 instance using the [Wallarm NGINX Node AMI](https://aws.amazon.com/marketplace/pp/prodview-5rl4dgi4wvbfe).

Recommended configuration: 

* Latest available [AMI version](https://docs.wallarm.com/updating-migrating/node-artifact-versions.md#amazon-machine-image-ami)
* Any preferred AWS region
* EC2 instance type: `t3.medium` (for testing) or `m4.xlarge` (for production), [see cost guidance for details](https://docs.wallarm.com/installation/cloud-platforms/aws/costs.md)
* [SSH key pair](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html) for accessing the instance
* Appropriate [VPC and subnet](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) based on your infrastructure
* [Security Group](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-security-group.html) inbound access to ports 22, 80, and 443

    !!! info "Using a security group preconfigured by Wallarm"
        When you deploy the instance and create a security group, AWS prompts you to use the one preconfigured by Wallarm. This group already has all the necessary ports open for inbound access.

        ![!Preconfigured security group](https://docs.wallarm.com/images/aws-ami/security-group.png)

* [Security Group](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-security-group.html) outbound access to:

    * `https://meganode.wallarm.com` to download the Wallarm installer
    * Wallarm API host for your Cloud: `https://us1.api.wallarm.com`, `https://api.wallarm.com`, or `https://me1.api.wallarm.com`. If access can be configured only via the proxy server, then use the [instructions](https://docs.wallarm.com/admin-en/configuration-guides/access-to-wallarm-api-via-proxy.md)
    * IP addresses below for downloading updates to attack detection rules and [API specifications](https://docs.wallarm.com/api-specification-enforcement/overview.md), as well as retrieving precise IPs for your [allowlisted, denylisted, or graylisted](https://docs.wallarm.com/user-guides/ip-lists/overview.md) countries, regions, or data centers

        **US Cloud:**

        ```
        node-data0.us1.wallarm.com - 34.96.64.17
        node-data1.us1.wallarm.com - 34.110.183.149
        us1.api.wallarm.com - 35.235.66.155
        34.102.90.100
        34.94.156.115
        35.235.115.105
        ```

        **EU Cloud:**

        ```
        node-data1.eu1.wallarm.com - 34.160.38.183
        node-data0.eu1.wallarm.com - 34.144.227.90
        api.wallarm.com - 34.90.110.226
        ```

        **ME Cloud:**

        ```
        node-data0.me1.wallarm.com - 34.166.82.208
        node-data1.me1.wallarm.com - 34.166.82.208
        me1.api.wallarm.com - 34.166.82.208
        ```
### 2. Prepare the Wallarm API token

The Wallarm node needs to connect to the Wallarm Cloud using a Wallarm token of the [appropriate type](https://docs.wallarm.com/user-guides/nodes/nodes.md#api-and-node-tokens-for-node-creation). An API token allows you to create a node group in the Wallarm Console UI, helping you organize your node instances more effectively.

![Grouped nodes](https://docs.wallarm.com/images/user-guides/nodes/grouped-nodes.png)

Generate a token as follows:

**API token:**


1. Open Wallarm Console → **Settings** → **API tokens** in the [US Cloud](https://us1.my.wallarm.com/settings/api-tokens) or [EU Cloud](https://my.wallarm.com/settings/api-tokens), or [ME Cloud](https://me1.my.wallarm.com/settings/api-tokens).
1. Find or create API token with the `Node deployment/Deployment` usage type.
1. Copy this token.

**Node token:**


1. Open Wallarm Console → **Nodes** in the [US Cloud](https://us1.my.wallarm.com/nodes) or [EU Cloud](https://my.wallarm.com/nodes), or [ME Cloud](https://me1.my.wallarm.com/nodes).
1. Do one of the following: 
    * Create the node of the **Wallarm node** type and copy the generated token.
    * Use existing node group - copy token using node's menu → **Copy token**.

### 3. Store the token in AWS Secrets Manager (recommended)

For secure token handling, store the token in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html). 

The secret must be in the same AWS region as your Wallarm Node EC2 instance.

1. Store the token in AWS Secrets Manager:

    **AWS Console:**

    1. Open the [AWS Secrets Manager console](https://console.aws.amazon.com/secretsmanager/).
    1. Click **Store a new secret**.
    1. Select **Other type of secret**.
    1. In **Key/value pairs**, switch to **Plaintext** and paste your Wallarm API token.
    1. Click **Next**, set the secret name to `wallarm/api-token`, then complete the wizard.

    **AWS CLI:**

    If you have the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed and configured, run the [`aws secretsmanager`](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/) command:

    ```bash
    aws secretsmanager create-secret \
      --region <AWS_REGION> \
      --name wallarm/api-token \
      --description "Wallarm node API token" \
      --secret-string "<YOUR_WALLARM_API_TOKEN>"
    ```

    ![Secret with Wallarm token in AWS Secrets Manager](https://docs.wallarm.com/images/aws-ami/secret-with-wallarm-token.png)

1. Grant the EC2 instance access to the secret. Create an IAM policy with least-privilege access to the secret, then attach it to the EC2 instance via an [IAM role](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html).

    **AWS Console:**

    1. Open the [IAM console → Policies](https://console.aws.amazon.com/iam/home#/policies) and click **Create policy**.
    1. Switch to the **JSON** tab and paste the policy.

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

        Replace `<REGION>` and `<ACCOUNT_ID>` with your values.

        If the secret is encrypted with a [customer managed KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk) (rather than the default AWS managed key), also add `kms:Decrypt` permission for that key.

    1. Name the policy (e.g., `WallarmSecretsReadOnly`) and create it.
    1. Open the [IAM console → Roles](https://console.aws.amazon.com/iam/home#/roles) and click **Create role**.
    1. Select **AWS service** → **EC2** as the trusted entity, then click **Next**.
    1. Attach the `WallarmSecretsReadOnly` policy and complete the wizard.
    1. Open the [EC2 console](https://console.aws.amazon.com/ec2/), select your Wallarm Node instance, then go to **Actions → Security → Modify IAM role** and attach the role you created.

    **AWS CLI:**

    1. Create a trust policy file that allows EC2 to assume the role:

        ```bash
        cat > trust-policy.json << 'EOF'
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": { "Service": "ec2.amazonaws.com" },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        EOF
        ```

    1. Create the IAM role and attach the policy:

        ```bash
        aws iam create-role \
          --role-name WallarmNodeRole \
          --assume-role-policy-document file://trust-policy.json

        aws iam put-role-policy \
          --role-name WallarmNodeRole \
          --policy-name WallarmSecretsReadOnly \
          --policy-document '{
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Action": ["secretsmanager:GetSecretValue"],
                "Resource": "arn:aws:secretsmanager:<REGION>:<ACCOUNT_ID>:secret:wallarm/api-token*"
              }
            ]
          }'
        ```

        Replace `<REGION>` and `<ACCOUNT_ID>` with your values.

    1. Create an instance profile and attach the role to your EC2 instance:

        ```bash
        aws iam create-instance-profile \
          --instance-profile-name WallarmNodeProfile

        aws iam add-role-to-instance-profile \
          --instance-profile-name WallarmNodeProfile \
          --role-name WallarmNodeRole

        aws ec2 associate-iam-instance-profile \
          --instance-id <INSTANCE_ID> \
          --iam-instance-profile Name=WallarmNodeProfile
        ```

### 4. Connect to the Wallarm Node instance via SSH

[Use the selected SSH key](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html) to connect to your running EC2 instance:

```bash
ssh -i <your-key.pem> admin@<your-ec2-public-ip>
```

You need to use the `admin` username to connect to the instance.

### 5. Connect the instance to the Wallarm Cloud

The instance's node connects to the Wallarm Cloud via the [cloud-init.py](https://docs.wallarm.com/installation/cloud-platforms/cloud-init.md) script. This script registers the node with the Wallarm Cloud using a provided token, globally sets it to the monitoring [mode](https://docs.wallarm.com/admin-en/configure-wallarm-mode.md), and sets up the node to forward legitimate traffic based on the `--proxy-pass` flag.

If you stored the token in AWS Secrets Manager ([step 3](#3-store-the-token-in-aws-secrets-manager-recommended)), retrieve it and run the script:

**US Cloud:**

```bash
WALLARM_TOKEN=$(aws secretsmanager get-secret-value \
  --secret-id wallarm/api-token \
  --query SecretString --output text)

sudo env WALLARM_LABELS='group=<GROUP>' \
  /opt/wallarm/usr/share/wallarm-common/cloud-init.py \
  -t "$WALLARM_TOKEN" -m monitoring \
  --proxy-pass <PROXY_ADDRESS> -H us1.api.wallarm.com
```

**EU Cloud:**

```bash
WALLARM_TOKEN=$(aws secretsmanager get-secret-value \
  --secret-id wallarm/api-token \
  --query SecretString --output text)

sudo env WALLARM_LABELS='group=<GROUP>' \
  /opt/wallarm/usr/share/wallarm-common/cloud-init.py \
  -t "$WALLARM_TOKEN" -m monitoring \
  --proxy-pass <PROXY_ADDRESS>
```

**ME Cloud:**

```bash
WALLARM_TOKEN=$(aws secretsmanager get-secret-value \
  --secret-id wallarm/api-token \
  --query SecretString --output text)

sudo env WALLARM_LABELS='group=<GROUP>' \
  /opt/wallarm/usr/share/wallarm-common/cloud-init.py \
  -t "$WALLARM_TOKEN" -m monitoring \
  --proxy-pass <PROXY_ADDRESS> -H me1.api.wallarm.com
```

* `WALLARM_LABELS='group=<GROUP>'` sets a node group name (existing, or, if does not exist, it will be created). It is only applied if using an API token.
* `<PROXY_ADDRESS>` is the address the Wallarm node proxies legitimate traffic to. It can be the IP of an application instance, a load balancer, or a DNS name (depending on your architecture), with the specified `http` or `https` protocol, e.g., `http://example.com` or `https://192.0.2.1`. [See more information on the proxy address format](https://nginx.org/en/docs/http/ngx_http_proxy_module.html?&_ga=2.23729850.1231698478.1756133814-1504295816.1756133814#proxy_pass).

Alternatively, you can pass the token directly on the command line. This approach is simpler for testing but is **not recommended for production**:

**US Cloud:**

``` bash
sudo env WALLARM_LABELS='group=<GROUP>' /opt/wallarm/usr/share/wallarm-common/cloud-init.py -t <TOKEN> -m monitoring --proxy-pass <PROXY_ADDRESS> -H us1.api.wallarm.com
```

**EU Cloud:**

``` bash
sudo env WALLARM_LABELS='group=<GROUP>' /opt/wallarm/usr/share/wallarm-common/cloud-init.py -t <TOKEN> -m monitoring --proxy-pass <PROXY_ADDRESS>
```

**ME Cloud:**

``` bash
sudo env WALLARM_LABELS='group=<GROUP>' /opt/wallarm/usr/share/wallarm-common/cloud-init.py -t <TOKEN> -m monitoring --proxy-pass <PROXY_ADDRESS> -H me1.api.wallarm.com
```

### 6. Configure sending traffic to the Wallarm instance

Configure your AWS infrastructure to route all traffic through the Wallarm Node. See [Routing Traffic to the Wallarm Node on AWS](https://docs.wallarm.com/installation/cloud-platforms/aws/traffic-routing.md) for guidance on ALB, NLB, CloudFront, and API Gateway configurations.

### 7. Test the Wallarm operation

1. The request with test [Path Traversal](https://docs.wallarm.com/attacks-vulns-list.md#path-traversal) attack to an address of either the load balancer or the machine with the Wallarm node:

    ```
    curl http://<ADDRESS>/etc/passwd
    ```
2. Open Wallarm Console → **Attacks** section in the [US Cloud](https://us1.my.wallarm.com/attacks) or [EU Cloud](https://my.wallarm.com/attacks), or [ME Cloud](https://me1.my.wallarm.com/attacks) and make sure the attack is displayed in the list.
    ![Attacks in the interface](https://docs.wallarm.com/images/admin-guides/test-attacks-quickstart.png)

    Since Wallarm operates in the monitoring mode, the Wallarm node does not block the attack but registers it.

1. Optionally, [test](https://docs.wallarm.com/admin-en/uat-checklist-en.md) other aspects of the node functioning.
## Verifying the node operation using logs and metrics

To verify the node is detecting traffic, you can check the metrics and logs as follows:

* Check Prometheus metrics exposed by the node:

    ```
    curl http://127.0.0.1:9001/metrics
    ```

* Review NGINX logs to inspect incoming requests and errors:

    * Access logs: `/var/log/nginx/access.log`
    * Error logs: `/var/log/nginx/error.log`

* Review [Wallarm-specific logs](https://docs.wallarm.com/admin-en/configure-logging.md), which include details such as data sent to the Wallarm Cloud, detected attacks, and more. These logs are located in the `/opt/wallarm/var/log/wallarm` directory.

## Fine-tune the deployed solution

The deployment is now complete. The filtering node may require some additional configuration after deployment.

Wallarm settings are defined using the [NGINX directives](https://docs.wallarm.com/admin-en/configure-parameters-en.md) or the Wallarm Console UI. Directives should be set in the following files on the Wallarm instance:

* `/etc/nginx/sites-enabled/default` defines the configuration of NGINX
* `/etc/nginx/conf.d/wallarm.conf` defines the global configuration of Wallarm filtering node
* `/etc/nginx/conf.d/wallarm-status.conf` defines the filtering node monitoring service configuration
* `/opt/wallarm/wstore/wstore.yaml` with the postanalytics service (wstore) settings

You can modify the listed files or create your own configuration files to define the operation of NGINX and Wallarm. It is recommended to create a separate configuration file with the `server` block for each group of the domains that should be processed in the same way (e.g. `example.com.conf`). To see detailed information about working with NGINX configuration files, proceed to the [official NGINX documentation](https://nginx.org/en/docs/beginners_guide.html).

!!! info "Creating a configuration file"
    When creating a custom configuration file, make sure that NGINX listens to the incoming connections on the free port.

Below there are a few of the typical settings that you can apply if needed:

* [Wallarm node auto-scaling](https://docs.wallarm.com/admin-en/installation-guides/amazon-cloud/autoscaling-overview.md)
* [Displaying the client's real IP](https://docs.wallarm.com/admin-en/using-proxy-or-balancer-en.md)
* [Allocating resources for Wallarm nodes](https://docs.wallarm.com/admin-en/configuration-guides/allocate-resources-for-node.md)
* [Limiting the single request processing time](https://docs.wallarm.com/user-guides/rules/configure-overlimit-res-detection.md)
* [Limiting the server reply waiting time](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout)
* [Limiting the maximum request size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size)
* [Wallarm node logging](https://docs.wallarm.com/admin-en/configure-logging.md)

To apply the settings, restart NGINX on the Wallarm instance:

``` bash
sudo systemctl restart nginx
```

Each configuration file change requires NGINX to be restarted to apply it.
