> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/integrations/resource-integrations/ssh/self-hosted.md).

# Self-hosted

Install the P0 SSH Agent on an on-premises or self-managed server and grant developers just-in-time, certificate-based SSH access with no standing credentials.

The P0 SSH Agent brings just-in-time (JIT) SSH access to servers that don't run on a cloud provider's managed compute: on-premises machines, bare-metal hosts and virtual machines you manage yourself. The agent runs on each server and holds a persistent outbound connection to P0 Security. When a request is approved, P0 tells the agent to provision the access: it creates the user, installs a short-lived SSH certificate and grants sudo if the request asked for it. When the grant expires, the certificate stops working, so no standing credentials remain on the host.

This guide is for administrators. It walks through registering a self-hosted environment in P0, installing and registering the agent on a Linux server, and making a first access request.

{% hint style="info" %}
If an administrator has already onboarded your server and you only need to connect to it, skip to [Request and connect to a server](#step-5-request-and-connect-to-a-server).
{% endhint %}

{% hint style="info" %}
The self-hosted SSH connector may need to be enabled for your organization. If **Self-hosted** does not appear under **Integrations**, contact P0 at <support@p0.dev>.
{% endhint %}

## How it works

```mermaid
flowchart LR
  DEV["Requestor<br/>(P0 CLI)"]
  P0["P0 SaaS<br/>(policy + approvals)"]
  AGENT["P0 SSH Agent<br/>(on your server)"]
  HOST["Self-hosted server"]

  DEV -->|"p0 ssh request"| P0
  P0 -->|"provision (outbound WSS)"| AGENT
  AGENT -->|"create user, install cert, grant sudo"| HOST
  DEV -->|"SSH with short-lived cert"| HOST
```

1. Register a **self-hosted environment** in P0.
2. Install and register the **P0 SSH Agent** on each server. The agent opens an outbound WebSocket connection to P0, so no inbound ports are required.
3. A requestor asks for access through the P0 CLI, Slack, Microsoft Teams or the web app. P0 evaluates the request against your [access policies](/access-management/just-in-time-access/access-policies.md).
4. On approval, P0 instructs the agent to create the user, install a short-lived SSH certificate and grant sudo if requested.
5. The requestor connects with `p0 ssh`. P0 logs the session.
6. When the approved duration ends, or the requestor relinquishes access, the certificate is invalidated and the access is revoked.

## Prerequisites

Before you start, confirm the following.

**In P0:**

* An existing P0 account at [p0.app](https://p0.app/), with permission to install integrations and generate API keys.

**On the target server:**

* A Linux server (for example Ubuntu, RHEL or CentOS) with an SSH server installed and running.
* A non-root user with `sudo` privileges. The `register` command refuses to run as `root`.
* Outbound HTTPS and WebSocket (WSS) access to P0. The agent initiates all connections outbound, so no inbound firewall rules are needed.

{% hint style="warning" %}
The P0 SSH Agent currently supports Linux only. Windows is not supported.
{% endhint %}

**On the requestor's workstation:**

* The [P0 CLI installed](/p0-cli/installing-p0-cli.md).

## Step 1: Create a self-hosted environment in P0

1. Go to [p0.app](https://p0.app/) and select **Integrations**.
2. Under **Resources**, select **Self-hosted**.
3. Select **Add environment**.
4. (Optional) Fill in the environment details:
   * **Environment label**: a user-friendly name for this group of servers.
   * **User suffix**: a suffix appended to the Linux user name P0 creates. Use it to avoid conflicts with existing users managed outside P0.
5. Select **Finish**.

Keep this environment's page open. You need its registration URL in [Step 3](#step-3-install-and-register-the-agent-on-the-server).

## Step 2: Generate an API key

The agent authenticates its registration request with a P0 API key.

1. Navigate to **P0 Management**, then follow [Generating an API key](/p0-management/generating-an-api-key.md).
2. Copy the key and store it somewhere secure.

{% hint style="warning" %}
A P0 API key carries the full permissions of the Owner role. Treat it as a secret, and delete it when the agent is registered if you no longer need it.
{% endhint %}

## Step 3: Install and register the agent on the server

Run these commands on the target server, signed in as the non-root user with `sudo` privileges.

1. Download the P0 SSH Agent binary for your server's operating system and architecture from the [P0 SSH Agent releases](https://github.com/p0-security/p0-agent), then make it executable:

   ```bash
   chmod +x p0-ssh-agent
   ```
2. Register the agent. Provide the API key from [Step 2](#step-2-generate-an-api-key) as `--auth` and your environment's registration URL from [Step 1](#step-1-create-a-self-hosted-environment-in-p0) as `--url`:

   ```bash
   ./p0-ssh-agent register \
     --auth "<API_KEY>" \
     --url "<registration-url-from-console>"
   ```

   The `register` command:

   * Installs the binary to a system location (for example `/usr/local/bin`).
   * Generates an ECDSA key pair for JWT authentication under `/etc/p0-ssh-agent/keys`.
   * Registers the host with P0 and saves the returned configuration to `/etc/p0-ssh-agent/config.yaml`.
   * Creates a `systemd` service named `p0-ssh-agent` (it does not start it yet).

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><code>register</code> does not configure the SSH daemon to trust the P0 certificate authority. Confirm with P0 how CA trust is established for your environment before relying on certificate-based SSH access.</p></div>

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>To give the host a recognizable name or attach labels, add <code>--hostname &#x3C;name></code> and one or more <code>--label key=value</code> flags. Labels let requestors group and target hosts.</p></div>

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Run <code>register</code> as a regular user with <code>sudo</code>, not as <code>root</code>. If you must bypass this check, pass <code>--allow-root</code>, though this is not recommended.</p></div>
3. Start the service and enable it to run on boot:

   ```bash
   sudo systemctl enable --now p0-ssh-agent
   ```

## Step 4: Verify the agent is connected

1. On the server, confirm the service is running and healthy:

   ```bash
   sudo systemctl status p0-ssh-agent
   p0-ssh-agent status
   ```

   To follow the agent's logs:

   ```bash
   sudo journalctl -f -u p0-ssh-agent
   ```
2. From the requestor's workstation, sign in and confirm the host appears as an SSH session destination:

   ```bash
   p0 login <your-p0-organization-name>
   p0 ls ssh session destination
   ```

   The registered host appears in the list. If it does not, see [Troubleshooting](#troubleshooting).

## Step 5: Request and connect to a server

{% hint style="info" %}
This step is for requestors. Anyone who needs access to the server can follow it once the agent is connected.
{% endhint %}

1. Sign in to the P0 CLI, replacing `<your-p0-organization-name>` with your organization name:

   ```bash
   p0 login <your-p0-organization-name>
   ```
2. Request access and connect in one step. Replace `<hostname>` with the host name or identifier from `p0 ls ssh session destination`:

   ```bash
   p0 ssh <hostname> --provider self-hosted --reason "Investigating a failing service"
   ```

   To request sudo access, add the `--sudo` flag:

   ```bash
   p0 ssh <hostname> --provider self-hosted --sudo
   ```

   P0 submits the request, evaluates it against your access policies and waits for approval. Once access is provisioned, P0 opens the SSH session using a short-lived certificate.
3. Access ends automatically when the approved duration expires. To end it early, relinquish access from your P0 message.

{% hint style="info" %}
Use [access policies](/access-management/just-in-time-access/access-policies.md) to route self-hosted SSH requests to approvers, pre-approve access or restrict which hosts a requestor can reach. See [SSH filtering](/access-management/just-in-time-access/access-policies/ssh-filtering.md) for host-level rules.
{% endhint %}

## Troubleshooting

| Problem                                                     | Solution                                                                                                                                                                                                                              |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `register` exits with "should not be run as root"           | Run the command as a regular user with `sudo` privileges, not as `root`.                                                                                                                                                              |
| The host does not appear in `p0 ls ssh session destination` | Confirm the service is running with `sudo systemctl status p0-ssh-agent`, and check the agent connected successfully with `sudo journalctl -u p0-ssh-agent`.                                                                          |
| The agent logs a WebSocket handshake failure                | Verify the API key is valid, that the server allows outbound WSS to P0 on port 443 and that the JWT keys exist under `/etc/p0-ssh-agent/keys`. Restart with `sudo journalctl -f -u p0-ssh-agent` open to watch reconnection attempts. |
| Access is approved but `p0 ssh` fails to connect            | Confirm the server's SSH server is running and the agent is connected. Check the agent logs for the user-provisioning result.                                                                                                         |

## What's next

* [Configure access policies](/access-management/just-in-time-access/access-policies.md) to govern who can request self-hosted SSH access.
* [SSH filtering](/access-management/just-in-time-access/access-policies/ssh-filtering.md) to scope requests to specific hosts.
* [`p0 ssh` command reference](/p0-cli/p0-commands-and-usage/p0-ssh.md) for all connection options.
