# Virtual machine or bare metal




This page describes how to install F5 WAF for NGINX in a virtual machine or bare metal environment.

## Before you begin

To complete this guide, you will need the following prerequisites:

- A [supported operating system](/waf/fundamentals/technical-specifications.md#supported-operating-systems).
- Ensure you have an active F5 WAF for NGINX subscription (purchased or trial) and have downloaded the associated [SSL certificate, private key, and JWT license](#download-your-subscription-credentials) file from the MyF5 Customer Portal.

Depending on your deployment type, you may have additional requirements:

You should read the [IP intelligence](/waf/policies/ip-intelligence.md) topics for additional set-up configuration if you want to use them immediately.

**Note:** 

Security mechanisms like SELinux or AppArmor may potentially block necessary file access for the NGINX process and any component containers.

For more information, view the [Configure SELinux](/waf/configure/selinux.md) topic.

## Default security policy and logging profile

F5 WAF for NGINX uses built-in default security policy and logging profile after installation. To use custom policies or logging profiles, update your NGINX configuration file accordingly.

## Download your subscription credentials 

To use NGINX Plus, you will need to download the JWT license file associated with your F5 WAF for NGINX WAF subscription from the [MyF5](https://my.f5.com/manage/s/) Customer Portal:

1. Log in to [MyF5](https://my.f5.com/manage/s/).
1. Go to **My Products & Plans > Subscriptions** to see your active subscriptions.
1. Find your NGINX subscription, and select the **Subscription ID** for details.
1. Download the **SSL Certificate**, **Private Key** and **JSON Web Token** files from the subscription page.

**Note:**  Starting from [NGINX Plus Release 33](nginx/releases.md#r33), a JWT file is required for each NGINX Plus instance. For more information, see [About Subscription Licenses](/solutions/about-subscription-licenses.md). 

## Platform-specific instructions

Navigate to your chosen operating system, which are alphabetically ordered.

### Alpine Linux

Add the F5 WAF for NGINX signing key:

```shell
sudo wget -O /etc/apk/keys/app-protect-security-updates.rsa.pub https://cs.nginx.com/static/keys/app-protect-security-updates.rsa.pub
```

Add the F5 WAF for NGINX repository:

```shell
printf "https://pkgs.nginx.com/app-protect/alpine/v`egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release`/main\n" | sudo tee -a /etc/apk/repositories
printf "https://pkgs.nginx.com/app-protect-security-updates/alpine/v`egrep -o '^[0-9]+\.[0-9]+' /etc/alpine-release`/main\n" | sudo tee -a /etc/apk/repositories
```

Update the repositories, then install the F5 WAF for NGINX package and its dependencies:

```shell
sudo apk update
sudo apk add openssl ca-certificates app-protect
```

#### Installing a specific version of F5 WAF for NGINX

If you need to install a specific version of F5 WAF for NGINX, you can use `apk info` to list available versions, then append it to the package name:

```shell
sudo apk info app-protect
sudo apk add openssl ca-certificates app-protect=<desired-version>
```

### Amazon Linux

Add the F5 WAF for NGINX repository:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/app-protect-amazonlinux2023.repo
```

Add F5 WAF for NGINX dependencies:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.amazonlinux2023.repo
```

Install the F5 WAF for NGINX package and its dependencies:

```shell
sudo dnf install app-protect
```

#### Installing a specific version of F5 WAF for NGINX

If you need to install a specific version of F5 WAF for NGINX, you can use `--showduplicates list` to list available versions, then append it to the package name:

```shell
sudo dnf --showduplicates list app-protect
sudo dnf install app-protect-=<desired-version>
```

### Debian

Add the F5 WAF for NGINX signing key:

```shell
wget -qO - https://cs.nginx.com/static/keys/app-protect-security-updates.key | gpg --dearmor | \
sudo tee /usr/share/keyrings/app-protect-security-updates.gpg > /dev/null
```

Add the F5 WAF for NGINX repositories:

```shell
printf "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
https://pkgs.nginx.com/app-protect/debian `lsb_release -cs` nginx-plus\n" | \
sudo tee /etc/apt/sources.list.d/nginx-app-protect.list

printf "deb [signed-by=/usr/share/keyrings/app-protect-security-updates.gpg] \
https://pkgs.nginx.com/app-protect-security-updates/debian `lsb_release -cs` nginx-plus\n" | \
sudo tee /etc/apt/sources.list.d/app-protect-security-updates.list
```

Update the repositories, then install the F5 WAF for NGINX package and its dependencies:

```shell
sudo apt-get update
sudo apt-get install app-protect
```

#### Installing a specific version of F5 WAF for NGINX

If you need to install a specific version of F5 WAF for NGINX, you can use `apt-cache` to list available versions, then append it to the package name:

```shell
sudo apt-get update
sudo apt-cache policy app-protect
sudo apt-get install app-protect=<desired-version>
```

When installing a specific version of F5 WAF for NGINX, you will also need to manually install its package dependencies. 

You can use the following script to get the dependent packages:

```shell
findDeps () { local pkgs=$(apt show $1 2>/dev/null | grep Depends: | grep -oE "(nginx-plus-module|app-protect)-[a-z]+ *\(= *[0-9\+\.-]+~`lsb_release -cs`\)" | tr -d ' ()'); for p in ${pkgs[@]}; do echo $p; findDeps $p; done; }
findDeps app-protect=<desired-version>
```

### Oracle Linux / RHEL / Rocky Linux 8

**Note:** 

The steps are identical for these platforms due to their similar architecture.

Add the F5 WAF for NGINX repository:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/app-protect-8.repo
```

Add F5 WAF for NGINX dependencies:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo
```

Enable F5 WAF for NGINX dependencies:

```shell
sudo dnf config-manager --set-enabled crb
```

Enable the _ol8_codeready_builder_ repository:

```shell
sudo dnf config-manager --set-enabled ol8_codeready_builder
```

Install the F5 WAF for NGINX package and its dependencies:

```shell
sudo dnf install app-protect
```

#### Installing a specific version of F5 WAF for NGINX

If you need to install a specific version of F5 WAF for NGINX, you can use `--showduplicates list` to list available versions, then append it to the package name:

```shell
sudo dnf --showduplicates list app-protect
sudo dnf install app-protect-=<desired-version>
```

### RHEL / Rocky Linux 9

Add the F5 WAF for NGINX repository:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/app-protect-9.repo
```

Add F5 WAF for NGINX dependencies:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo
```

Enable F5 WAF for NGINX dependencies:

```shell
sudo dnf config-manager --set-enabled crb
```

Install the F5 WAF for NGINX package and its dependencies:

```shell
sudo dnf install app-protect
```

### RHEL 10

Add the F5 WAF for NGINX repository:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/app-protect-10.repo
```

Add F5 WAF for NGINX dependencies:

```shell
sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo
```

Install the F5 WAF for NGINX package and its dependencies:

```shell
sudo dnf install app-protect
```

#### Installing a specific version of F5 WAF for NGINX

If you need to install a specific version of F5 WAF for NGINX, you can use `--showduplicates list` to list available versions, then append it to the package name:

```shell
sudo dnf --showduplicates list app-protect
sudo dnf install app-protect-=<desired-version>
```

### Ubuntu

Add the F5 WAF for NGINX signing key:

```shell
wget -qO - https://cs.nginx.com/static/keys/app-protect-security-updates.key | \
gpg --dearmor | sudo tee /usr/share/keyrings/app-protect-security-updates.gpg > /dev/null
```

Add the F5 WAF for NGINX repositories:

```shell
printf "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
https://pkgs.nginx.com/app-protect/ubuntu `lsb_release -cs` nginx-plus\n" | \
sudo tee /etc/apt/sources.list.d/nginx-app-protect.list

printf "deb [signed-by=/usr/share/keyrings/app-protect-security-updates.gpg] \
https://pkgs.nginx.com/app-protect-security-updates/ubuntu `lsb_release -cs` nginx-plus\n" | \
sudo tee /etc/apt/sources.list.d/app-protect-security-updates.list
```

Update the repositories, then install the F5 WAF for NGINX package and its dependencies:

```shell
sudo apt-get update
sudo apt-get install app-protect
```

#### Installing a specific version of F5 WAF for NGINX

If you need to install a specific version of F5 WAF for NGINX, you can use `apt-cache` to list available versions, then append it to the package name:

```shell
sudo apt-get update
sudo apt-cache policy app-protect
sudo apt-get install app-protect=<desired-version>
```

When installing a specific version of F5 WAF for NGINX, you will also need to manually install its package dependencies.

You can use the following script to get the dependent packages:

```shell
findDeps () { local pkgs=$(apt show $1 2>/dev/null | grep Depends: | grep -oE "(nginx-plus-module|app-protect)-[a-z]+ *\(= *[0-9\+\.-]+~`lsb_release -cs`\)" | tr -d ' ()'); for p in ${pkgs[@]}; do echo $p; findDeps $p; done; }
findDeps app-protect=<desired-version>
```

## Install NGINX Plus license

If you have not already copied your NGINX Plus JWT license file to the `/etc/nginx/` directory (for example, if NGINX Plus was installed automatically as a dependency), do so now:

```shell
sudo cp <downloaded-file-name>.jwt /etc/nginx/license.jwt
```

## Update configuration files

Once you have installed F5 WAF for NGINX, you must load it as a module in the main context of your NGINX configuration.

```nginx
load_module modules/ngx_http_app_protect_module.so;
```

And finally, F5 WAF for NGINX can enabled on a _http_, _server_ or _location_ context:

```nginx
app_protect_enable on;
```

**Note:** 

You should only enable F5 WAF for NGINX on _proxy_pass_ and _grpc_pass_ locations.

Here are two examples of how these additions could look in configuration files:

#### nginx.conf

The default path for this file is `/etc/nginx/nginx.conf`.

```nginx {hl_lines=[5]}
user  nginx;
worker_processes  auto;

# F5 WAF for NGINX
load_module modules/ngx_http_app_protect_module.so;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
```

#### default.conf

The default path for this file is `/etc/nginx/conf.d/default.conf`.

```nginx {hl_lines=[9]}
server {
    listen 80;
    server_name domain.com;

    location / {

        # F5 WAF for NGINX
        app_protect_enable on;

        client_max_body_size 0;
        default_type text/html;
        proxy_pass http://127.0.0.1:8080/;
    }
}

server {
    listen 8080;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}
```

Once you have updated your configuration files, reload NGINX with the following command:

- `nginx -s reload`

## Post-installation checks

The following steps check that F5 WAF for NGINX enforcement is operational.

They should be ran in the environment with the WAF components.

Check that the three processes for F5 WAF for NGINX are running using `ps aux`:

- _bd-socket-plugin_
- _nginx: master process_
- _nginx: worker process_

```shell
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         8  1.3  2.4 3486948 399092 ?      Sl   09:11   0:02 /usr/share/ts/bin/bd-socket-plugin tmm_count 4 proc_cpuinfo_cpu_mhz 2000000 total_xml_memory 307200000 total_umu_max_size 3129344 sys_max_account_id 1024 no_static_config
root        14  0.0  0.1  71060 26680 ?        S    09:11   0:00 nginx: master process /usr/sbin/nginx -c /tmp/policy/test_nginx.conf -g daemon off;
root        26  0.0  0.3  99236 52092 ?        S    09:12   0:00 nginx: worker process
root        28  0.0  0.0  11788  2920 pts/0    Ss   09:12   0:00 bash
root        43  0.0  0.0  47460  3412 pts/0    R+   09:14   0:00 ps aux
```

Verify there are no errors in the file `/var/log/nginx/error.log` and that the policy compiled successfully:

```none
2020/05/10 13:21:04 [notice] 402#402: APP_PROTECT { "event": "configuration_load_start", "configSetFile": "/opt/f5waf/config/config_set.json" }
2020/05/10 13:21:04 [notice] 402#402: APP_PROTECT policy 'app_protect_default_policy' from: /etc/app_protect/conf/NginxDefaultPolicy.json compiled successfully
2020/05/10 13:21:04 [notice] 402#402: APP_PROTECT { "event": "configuration_load_success", "software_version": "1.1.1", "attack_signatures_package":{"revision_datetime":"2019-07-16T12:21:31Z"},"completed_successfully":true}
2020/05/10 13:21:04 [notice] 402#402: using the "epoll" event method
2020/05/10 13:21:04 [notice] 402#402: nginx/1.17.6 (nginx-plus-r20)
2020/05/10 13:21:04 [notice] 402#402: built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
2020/05/10 13:21:04 [notice] 402#402: OS: Linux 3.10.0-957.27.2.el7.x86_64
2020/05/10 13:21:04 [notice] 402#402: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2020/05/10 13:21:04 [notice] 406#406: start worker processes
2020/05/10 13:21:04 [notice] 406#406: start worker process 407
```

Check that sending an attack signature in a request returns a response block page containing a support ID:

```shell
Request:
http://10.240.185.211/?a=<script>

Response:
The requested URL was rejected. Please consult with your administrator.

Your support ID is: 9847191526422998597

[Go Back]
```

If your policy includes JSON/XML profiles, check `/var/log/app_protect/bd-socket-plugin.log` for possible errors:

```shell
grep '|ERR' /var/log/app_protect/bd-socket-plugin.log
```

Verify that Enforcement functionality is working by checking the following request is rejected:

```shell
curl "localhost/<script>"
```

If you notice problems, there are ways to remediate them based on the context:

| Description             | Solution  |
| ----------------------- | --------  |
| *NGINX is not running or F5 WAF for NGINX does not behave as expected* | Review warning or error messages within [the log files](/waf/logging/logs-overview.md) |
| *unknown directive app_protect_xxx error message* | Ensure F5 WAF for NGINX is [loaded as a module](#update-configuration-files) in the main context of NGINX configuration. |
| *Too many open files error message* | Increase the maximum amount of open files with the [worker_rlimit_nofile](https://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile) directive. |
| *setrlimit ... failed (Permission denied) error message* | Increase the limit by by running the following command as root: `setsebool -P httpd_setrlimit 1` |

## Next steps

Once you have successfully installed F5 WAF for NGINX, there are some topics you may want to follow afterwards:

- [Configure NGINX features with F5 WAF](/waf/configure/nginx-features.md), to see common configurations
- [Configure policies](/waf/policies/configuration.md), to begin customizing your deployment
- [Converter tools](/waf/configure/converters.md), to convert existing resources from a BIG-IP environment
- [Changelog](/waf/changelog.md), to view information from the latest releases

