---
title: "Standalone Deployment"
slug: "standalone-deployment"
updated: 2026-01-11T16:34:27Z
published: 2026-01-11T16:34:27Z
---

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plainid.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Standalone Deployment

## Standalone Installation Instructions

This guide explains how to install and run the PlainID Policy Authorization Agent (PAA) components in a standalone environment. It includes prerequisites, installation steps, example systemd services, a Quick Start option for development or trials, and common Runtime configuration options.

### Prerequisites

Ensure that the following prerequisites are met before installing.

- Verify the plainid-paa-X.XXX.X.tar file is already on the server in a location the setup user and PlainID services can access.
- Run the setup and installation steps as a user with **sudo privileges**.

For Quick Start or development environments, you can skip creating the PlainID user or create a normal user (not a system user). You still need Redis (if running locally) and you must use the aliases file described in Quick Start Example.

### Startup System Validation

During startup, the PlainID Policy Authorization Agent (PAA) validates system prerequisites to ensure the host environment is supported:

- Operating System (Required)
- PAA supports **Red Hat Enterprise Linux 8.10 or later**.

The operating system is validated using values from `/etc/os-release`:

- `VERSION="8.10 (Ootpa)"` or higher
- `ID="rhel"` or `ID_LIKE="fedora"`

If the operating system requirements are not met, PAA does not start and exits with an error. The following resources are validated against the recommended system requirements:

| Resource | Minimum |
| --- | --- |
| CPU | 8 cores |
| RAM | 16 GB |
| Disk | 20 GB |

If CPU, memory, or disk space are below the recommended values, PAA starts but displays warning messages during startup.

---

#### Validation Behavior

- **Unsupported operating system**
  - Startup fails
  - An error message describes the required and detected OS
- **Insufficient CPU, memory, or disk**
  - Startup continues
  - Warning messages are displayed

---

#### Example Output

```
INFO: Validating system prerequisites...
ERROR: Unsupported operating system detected
ERROR: Required: RHEL 8.10 or higher (ID=rhel or ID_LIKE=fedora)
ERROR: Detected: ID=ubuntu, VERSION=22.04.5 LTS (Jammy Jellyfish)

WARNING: Insufficient RAM detected
WARNING: Required: 16384 MB, Available: 15788 MB

WARNING: Insufficient CPU cores detected
WARNING: Required: 8 cores, Available: 4 cores

WARNING: Insufficient disk space detected
WARNING: Required: 20 GB, Available: 3 GB

ERROR: System validation failed. PAA cannot start.
ERROR: To skip validation, set PLAINID_SKIP_STARTUP_VALIDATION=true
```

---

#### Skipping Validation

Startup validation can be disabled by setting the following environment variable:

```
export PLAINID_SKIP_STARTUP_VALIDATION=true
```

> Skipping validation is not recommended and may result in unsupported or unstable deployments.

### Installation Guide

**To begin the Standalone installation**:

1. Create the `plainid` user and set permissions:

```
sudo useradd --system --no-create-home --shell /usr/sbin/nologin plainid
```

1. Untar the **plainid-paa-X.XXX.X.tar** for the PAA installation:

```
sudo tar -xvf /path/to/plainid-paa-X.XXX.X.tar -C /opt/
```

*Note: You are not required to place PlainID PAA under /opt. If you use a different location, update export `PLAINID_HOME=/opt/plainid in the /opt/plainid/init/alias` (or aliases) file accordingly.*

1. Set ownership of `/opt/plainid` to plainid user:

```
sudo chown -Rf plainid:plainid /opt/plainid
```

1. Install Redis  

Installing Redis is required when running on RHEL 8 and you want to run a local Redis server for PAA. If you use an enterprise-provided Redis service, refer to the Set Up Redis for PlainID PAA document or use the relevant configuration excerpts below.

*Note: The `plainid-paa-X.XXX.X.tar` package includes Redis binaries, but they may not run on some Linux distributions. The following example installs Redis on RHEL and is referenced later in the setup example.*

**RHEL**

```
sudo yum install redis
sudo systemctl enable redis
sudo systemctl start redis
```

1. Set a password for redis `sudo vi /etc/redis/redis.conf`
2. Update the settings as needed. If you use the Quick Start steps below, also update export `REDIS_PASS=redispass` in `/opt/plainid/init/alias` or `/opt/plainid/init/aliases`.

**Quickstart Deployment**:

```
maxmemory-policy volatile-lru
maxmemory 2000mb
save 60 1
loglevel warning
port 6379
notify-keyspace-events KA
requirepass redispass
masterauth redispass
```

`sudo systemctl restart redis`

### Setup Example

There are many best practices for running JAR files as services on Unix. The following example shows how to create a `systemd` service for each of the three services: PAA (Agent), PIP, and Runtime (PDP).

Depending on your architecture, these services might not run on the same host. In that case, you must set additional **Environment Variables** beyond what is shown here.

To review the available configuration options, see the relevant configuration files:

| Service | File |
| --- | --- |
| `PAA` | plainid-agent/conf/application.yaml |
| `PDP` | runtime/conf/config.json |
| `PIP` | pip-operator/conf/application.yaml |

To begin the setup:

1. Create an environment file.

- You may require an Environment file for each service, depending on the amount of overrides needed in your Environment (or one master override) based on your organization's best practices. You can also include Environment details in each start wrapper. See the example below for more information:

**Common Environment Variables Example** `sudo vi /opt/plainid/init/env`

```
#!/bin/bash
export PLAINID_HOME=/opt/plainid # The plainid-paa folder path (or untar to /opt/plainid)
export JAVA_HOME=/opt/plainid/jdk-17.0.5.8.1-linux-x64
export CLIENT_SECRET_KEY=9qfhbsUPC4vSDFTd03KgI8SDFDSasdfBmTyM1 # Agent Secret key (can be found under the Hybrid Agent Keys tab)
export TENANT_ID=TNT555R43QQQF9J4 # Tenant Id (can be found under the Hybrid Agent Keys tab in the Tenant Settings)
export PAA_ID=PAA4JM6BXD0OGZK # Policy Authorization Agent Id (can be found under the Policy Authorization Agents page in the Environment Settings.)
export REDIS_HOST=localhost # Or your enterprise-provided redis url
export REDIS_PASS=redispass # Or your chosen password from above OR password given to you by your Enterprise Redis team
export REDIS_PORT=6379 # Or your enterprise-provided redis port
```

1. Create a start script for each service  

*Note: Set your Java tuning parameters according to your environment and sizing requirements.*

- **Agent Start Script**

`vi /opt/plainid/init/start_plainid_agent.sh`

```
#!/bin/bash
source /opt/plainid/init/env

SERVICE_HOME=$PLAINID_HOME/plainid-agent
SERVICE_JAR=$PLAINID_HOME/plainid-agent/lib/plainid-agent.jar

export AGENT_SERVER_PORT=8080

JAVA_OPTS="-server -XX:+AlwaysPreTouch"
JAVA_OPTS="$JAVA_OPTS -Xms1536m -Xmx1536m"
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS="$JAVA_OPTS -XX:+UseStringDeduplication"
JAVA_OPTS="$JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20"
JAVA_OPTS="$JAVA_OPTS -XX:+ParallelRefProcEnabled"
JAVA_OPTS="$JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent"
JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceExpansion=64M"
JAVA_OPTS="$JAVA_OPTS -Dspring.config.location=$SERVICE_HOME/conf/application.yaml -Dlogging.config=$SERVICE_HOME/conf/logback-spring-text.xml"

$JAVA_HOME/bin/java $JAVA_OPTS -jar $SERVICE_JAR
```

- **Runtime Start Script**

`sudo vi /opt/plainid/init/start_plainid_runtime.sh`

```
#!/bin/bash
source /opt/plainid/init/env

#!/bin/bash
JAR_NAME=runtime-engine
SERVICE_HOME=$PLAINID_HOME/runtime
SERVICE_JAR=$(find "$SERVICE_HOME/lib/" -name $JAR_NAME'*.jar' )
LIB_JARS=$(find "$SERVICE_HOME/lib/" -name '*.jar' | sed 's/:$//')

export AGENT_URL="http://localhost:8080"

JAVA_OPTS="-server -XX:+AlwaysPreTouch"
JAVA_OPTS="$JAVA_OPTS -Xms1536m -Xmx1536m -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dinclude.apm=false"
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS="$JAVA_OPTS -XX:+UseStringDeduplication"
JAVA_OPTS="$JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20"
JAVA_OPTS="$JAVA_OPTS -XX:+ParallelRefProcEnabled"
JAVA_OPTS="$JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent"
JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceExpansion=64M"
JAVA_OPTS="$JAVA_OPTS -Dconf.format=json -Dconf.file=$PLAINID_HOME/runtime/conf/config.json -Dlog4j.configurationFile=$PLAINID_HOME/runtime/conf/log4j2.xml"

$JAVA_HOME/bin/java $JAVA_OPTS --add-exports java.base/sun.security.util=ALL-UNNAMED -cp "$SERVICE_JAR:${LIB_JARS%:}" com.plainid.runtime.Main
```

**PIP Start Script**

`sudo vi /opt/plainid/init/start_plainid_pip.sh`

```
#!/bin/bash
source /opt/plainid/init/env
JAR_NAME=pip-operator
SERVICE_HOME=$PLAINID_HOME/pip-operator
SERVICE_JAR=$(find "$SERVICE_HOME/lib/" -name $JAR_NAME'*.jar')

export PIP_SERVER_PORT=9595
export AGENT_URL="http://localhost:8080"

JAVA_OPTS="-server -XX:+AlwaysPreTouch"
JAVA_OPTS="$JAVA_OPTS -Xms1536m -Xmx1536m"
JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS="$JAVA_OPTS -XX:+UseStringDeduplication"
JAVA_OPTS="$JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20"
JAVA_OPTS="$JAVA_OPTS -XX:+ParallelRefProcEnabled"
JAVA_OPTS="$JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent"
JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceExpansion=64M"
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.cxf.transport.http.forceVersion=1.1"
JAVA_OPTS="$JAVA_OPTS -Dspring.config.location=$SERVICE_HOME/conf/application.yaml -Dlogging.config=$SERVICE_HOME/conf/logback-spring-text.xml"

$JAVA_HOME/bin/java $JAVA_OPTS -cp "$SERVICE_JAR"  -Dloader.main=com.plainid.pipoperator.Starter -Dloader.path=$SERVICE_HOME/lib/ org.springframework.boot.loader.launch.PropertiesLauncher --spring.config.location=$SERVICE_HOME/conf/application.yaml
```

```
sudo chown plainid:plainid /opt/plainid/init/env
sudo chmod +x /opt/plainid/init/env
sudo chown plainid:plainid /opt/plainid/init/*.sh
sudo chmod +x /opt/plainid/init/*.sh
```

1. Create the Service files for each service.  

The Requires and After settings below assume all services run on the same host. If services run on different hosts, remove cross-service dependencies.

- **Agent Service**

`sudo vi /etc/systemd/system/plainid_paa.service`

```
[Unit]
Description=PlainID Service PAA-AGENT
After=network.target redis.service
Requires=redis.service plainid_paa.service

[Service]
Type=simple
User=plainid
Group=plainid
ExecStart=/opt/plainid/init/start_plainid_agent.sh
ExecStop=/bin/kill -15 $MAINPID
TimeoutStopSec=10
KillMode=control-group
WorkingDirectory=/opt/plainid
Restart=on-failure

[Install]
WantedBy=multi-user.target
```

**Runtime Service**

`sudo vi /etc/systemd/system/plainid_runtime.service`

```
[Unit]
Description=PlainID Service PAA-RUNTIME
After=network.target redis.service plainid_paa.service
Requires=redis.service plainid_paa.service

[Service]
Type=simple
User=plainid
Group=plainid
ExecStart=/opt/plainid/init/start_plainid_runtime.sh
ExecStop=/bin/kill -15 $MAINPID
TimeoutStopSec=10
KillMode=control-group
WorkingDirectory=/opt/plainid
Restart=on-failure

[Install]
WantedBy=multi-user.target
```

**PIP Service**

`sudo vi /etc/systemd/system/plainid_pip.service`

```
[Unit]
Description=PlainID Service PAA-PIP
After=network.target redis.service plainid_paa.service
Requires=redis.service plainid_paa.service

[Service]
Type=simple
User=plainid
Group=plainid
ExecStart=/opt/plainid/init/start_plainid_pip.sh
ExecStop=/bin/kill -15 $MAINPID
TimeoutStopSec=10
KillMode=control-group
WorkingDirectory=/opt/plainid
Restart=on-failure

[Install]
WantedBy=multi-user.target
```

1. Run Daemon-reload commands and enable/start each service

- Reload, enabled, and start services:

```
sudo systemctl daemon-reload
sudo systemctl enable plainid_paa.service
sudo systemctl enable plainid_runtime.service
sudo systemctl enable plainid_pip.service
sudo systemctl start plainid_paa.service
sudo systemctl start plainid_runtime.service
sudo systemctl start plainid_pip.service
```

- Check the status:

```
sudo systemctl status plainid_paa.service
sudo systemctl status plainid_runtime.service
sudo systemctl status plainid_pip.service
```

- Stop Services

```

sudo systemctl stop plainid_paa.service
sudo systemctl stop plainid_runtime.service
sudo systemctl stop plainid_pip.service
```

#### Quick Start Example

This section is for development and trial purposes only. This is a quick-start guide for installing and testing the PlainID PAA on a RedHat Linux box. This does not go over setting up services, therefore ensure to source the `/opt/plainid/init/alias` file each time before running the start and stop commands.

1. Configure the PlaindID PAA:  

This example uses `/opt/plainid` and the JDK packaged with the services. Use an enterprise-managed JDK from the supportability matrix when possible, and follow your organization’s Java operational best practices (ie direct linking, symlink or java alternatives).

- Edit the `/opt/plainid/init/aliases` file, and add the following lines:

```
export PLAINID_HOME=/opt/plainid # The plainid folder path (or untar to /opt/plainid)
export JAVA_HOME=$PLAINID_HOME/jdk-17.0.5.8.1
export CLIENT_SECRET_KEY=9qfhbsUPC4vSDFTd03KgI8SDFDSasdfBmTyM1 # Agent secret key (Hybrid Agent Keys tab)
export TENANT_ID=TNT555R43QQQF9J4 # Tenant ID (Hybrid Agent Keys tab)
export PAA_ID=PAA4JM6BXD0OGZK # Policy Authorization Agent ID (Policy Authorization Agents tab)
export REDIS_HOST=localhost # Or your enterprise Redis hostname
export REDIS_PASS=redispass # Or your chosen password, or the enterprise Redis password
export REDIS_PORT=6379 # Or your enterprise Redis port
```

- If you run Redis as a local service (for example, via systemctl), **comment out** the Redis start and stop aliases in /opt/plainid/init/aliases so the package scripts do not try to start Redis:
  - line 20 `# alias start_redis_cache=$PLAINID_HOME'/redis/start_redis_cache.sh'`
  - line 27 `# alias stop_redis_cache=$PLAINID_HOME'/redis/stop_redis_cache.sh'`
  - line 32 `# start_redis_cache`
  - line 43 `# stop_redis_cache`

1. Start the Services  

If you created a PlainID User, run the following commands  

Note: You may want to simply add the source `/opt/plainid/init/aliases` to the user's bash_profile. If you did create a PlainID linux user, it must be created as a normal user, not as a system user used in the enterprise example above. Using a PlainID user is not required as you can run the services as yourself.

```
sudo su - plainid
source /opt/plainid/init/aliases start_plainid_paa
```

1. Check the status of the services by running

```
sudo su - plainid
source /opt/plainid/init/aliases start_plainid_paa
```

#### Aliases

| Alias | description |
| --- | --- |
| `start_plainid_paa` | Starts the PAA services |
| `stop_plainid_paa` | Stops the PAA services |
| `pid_status` | Shows the PAA's components health/status |

### Default Ports

| Service Name | Server Port | Management Port |
| --- | --- | --- |
| Runtime | 8010 | 8010 |
| PlainID-Agent | 8761 | 8082 |
| PIP-Operator | 8083 | 8089 |
| IDP-Webhook | 8020 | 8020 |
| Secrets-mgmt | 8072 | 8077 |

## Runtime SSL Configuration

1. Convert the private key and certificate to PKCS12 format using the following OpenSSL command:

```
openssl pkcs12 -export \
    -in "combined.pem" \
    -inkey "privkey.pem" \
    -out "certtemp.p12" -passout pass:"plainid" \
    -name "plainid"
```

1. Create a keystore.jks file using keytool from your JDK:

```
   $JAVA_HOME/bin/keytool -importkeystore \
    -srckeystore "certtemp.p12" -srcstoretype PKCS12 \
    -srcstorepass "plainid" \
    -destkeystore "keystore.jks" \
    -deststorepass "plainid" \
    -destkeypass "plainid" \
    -alias "plainid"
```

1. Update `/opt/plainid/init/env` or `/opt/plainid/init/alias` (Quick Start) with SSL Environment Variables:

```
export HTTP_SSL_ENABLED=true # to enable ssl over http
export HTTP_SSL_KEYSTORE_PATH="./keystore.jks" # - path to the keystore.jks file
export HTTP_SSL_KEYSTORE_PASSWORD=plainid # keystore password
```

### Other Important Environment Variables

Update `/opt/plainid/init/env` or `/opt/plainid/init/alias` (Quick Start) with the following Environment Variables as needed.

#### Provide UUID Attribute Type support

```
export RUNTIME_SUPPORT_UUID_ASSET_ATTRIBUTE=true # Enables UUID Asset Attribute support
export RUNTIME_SUPPORT_UUID_IDENTITY_ATTRIBUTE=true # Enables UUID identity Attribute support
```

#### Allow the IP and Time to be included in cache key

```
export RUNTIME_INCLUDE_IP_HEADER_IN_SCOPE_CACHE_KEY=false # Includes IP from header in scope cache calculation
export RUNTIME_INCLUDE_REQUEST_TIME_IN_SCOPE_CACHE_KEY=false # Includes current time in scope cache calculation
```

### Obtaining Private Keys from the Secret Management Service

The `secrets-mgmt` service is not enabled or deployed by default. Runtime parameters are required to configure the connection:

| Attribute | Environment Variable | Default value | Description |
| --- | --- | --- | --- |
| enableSecretsFetching | `ENABLE_SECRETS_FETCHING` | `false` | Indicates whether to fetch secrets from secret store |
| secretsProvider.connection.url | `SECRETS_LIST_URL` | `http://127.0.0.1:8072/1.0/secrets/list` | The URL to the secret-mgmt service. Update to your service URL/IP and add the /1.0/secrets/list as a suffix |

### Recommended System Requirements

| Item | Requirement |
| --- | --- |
| OS | RHEL 8 |
| CPU | 8 Core |
| RAM | 16 GB |
| Disk Space | 20 GB |

Consider increasing the available RAM, CPU, and disk space for more demanding use cases (e.g. Caching large amounts of data).

Note: As of January 2024, **Red Hat Enterprise Linux (RHEL)** has **deprecated** RHEL 7.z. Ensure that you meet the minimum requirements when installing the PAA Standalone.

#### FAQ

- Getting Error `-bash: ../plainid/**/bin/**.sh: Permission denied ` when running `plainid_paa_start`
  - Run the command `find . -type f -exec chmod 755 {} +` inside the plainid folder and try again

### Upgrading an Existing Installation to a New Version

Please note the upgrade from v2.x to v5.x is considered a minor upgrade due to a new, time-based versioning scheme

When upgrading to a new minor version (like v2.0.0 -> v5.2309.0) it is done without introducing breaking changes.

### Upgrade from 2.X to 5.2309.X

- Stop the currently installed PlainID PAA: `stop_plainid_paa`
- Delete the currently installed PAA directory
- Load the new alias file using `source` command
- Set the relevant environment variables according to the local environment, Tenant ID, and PAA ID.
  - Make sure to include any additional configurations made prior to the upgrade.
- Run `start_plainid_paa` to start the new PAA

## Upgrading an existing installation to a new major version

When upgrading to a new major version (like v1.2.3 -> v2.0.0) indicates that there is an incompatible breaking change that requires manual actions.

### Upgrade from 1.X to 2.X

- Stop the currently installed PlainID PAA: `stop_plainid_paa`
- Delete the currently installed PAA directory
- Load the new alias file using `source` command
- Set the relevant environment variables according to the local environment, Tenant ID, and PAA ID.
- Run `start_plainid_paa` to start the new PAA

The remote URL has been changed from:

| Parameter | old value | new value |
| --- | --- | --- |
| `remoteApi` | `[https://remote.us1.plainid.io/](https://remote.us1.plainid.io/)` / `[https://remote.eu1.plainid.io/](https://remote.eu1.plainid.io/)` | `[wss://remote.us1.plainid.io/wstunnel](wss://remote.us1.plainid.io/wstunnel)` / `[wss://remote.eu1.plainid.io/wstunnel](wss://remote.eu1.plainid.io/wstunnel)` |

### PAA Service Configurations

September 2024 PAA Update

For PAA updates after September 2024 (5.2439), the Agent and PIP-Operator configuration within your PAA package requires updates.

Ensure you make the following changes in *both* **applications.yaml** files in the Agent and PIP-Operator **"conf" files**:

- **Redis**

```
- spring:
    redis:
      username: ${REDIS_USER:}
```
  - Locate the Spring Redis service configuration and add the `username` parameter:
- **Secrets Management**

```
secretMgmtClient:
  url: ${SECRET_MGMT_CLIENT_URL:http://127.0.0.1:8072/1.0/secrets/list}
  apiClient:
    timeoutSeconds: ${SECRET_MGMT_CLIENT_API_CLIENT_TIMEOUT_SECONDS:30}
  cacheManager:
    durationSeconds: ${SECRET_MGMT_CLIENT_CACHE_MANAGER_DURATION_SECONDS:3600}
```
  - Add the following block to configure Secrets Management:
