# Installation

This document describes how to set up a deployment of Inrupt Enterprise Solid Server (ESS). To set up a deployment, ESS provides various [Kustomize](https://github.com/kubernetes-sigs/kustomize) [overlays](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#bases-and-overlays) that can act as the base configuration for your deployment.

{% hint style="warning" %}
**Important**\
ESS uses **three-element** version descriptors for its Kubernetes images, corresponding to the release versions (i.e., semantic versions of Major.Minor.Patch). For example **`docker.software.inrupt.com/inrupt-kustomizer:2.7.0`** .
{% endhint %}

{% hint style="info" %}
**PodSpaces (Developer Preview)** Inrupt provides hosted versions of the Enterprise Solid Server, eliminating the installation overhead. For more information, see [Inrupt PodSpaces](https://docs.inrupt.com/podspaces/podspaces)
{% endhint %}

## Prerequisites

{% hint style="info" %}
**Note**\
The tutorial follows the Infrastructure as Code (IaC) practice for managing the system and assumes the installation directory is under source control.
{% endhint %}

{% hint style="danger" %}
**CRITICAL SECURITY REQUIREMENT**

NEVER commit files containing secrets such as **`.env`** or **`JWT`** to version control. These files must be managed securely.

As part of updating the inputs for your deployment:

1. **Review** the template secret files
2. **Set strong secrets** for the values, such as strong passwords
3. **Store the secret securely** outside your repository using one of these methods:
   * Cloud secrets management service
   * Enterprise secrets vault solution
   * Kubernetes Secrets with encryption at rest
   * Secure file system with restricted access (development only)
4. **Configure your deployment** to retrieve credentials from your secure storage at runtime
5. **Add the secrets files to your `.gitignore` file immediately**
   {% endhint %}

### Entitlement Token

To login to Inrupt’s private Docker registry and download the ESS Docker images, your enterprise needs to obtain an entitlement token from Inrupt.

For inquiries (including pricing inquiries) about obtaining the token, you can either:

* Contact your Inrupt representative; or
* Contact Inrupt’s [Business Development](https://www.inrupt.com/contact) team.

### Docker

The installation uses Linux Docker images. If Docker is not installed, refer to its [official documentation](https://docs.docker.com/get-docker/) to install.

### Kubernetes Version

ESS supports Kubernetes versions **`1.21+`**.

### Kubernetes Management Tool

To deploy and manage the Kubernetes cluster, install a Kubernetes deployment tool (if not already installed).

This tutorial uses **`kubectl`** . To install **`kubectl`** , use the directions at <https://kubernetes.io/docs/tasks/tools/>

### Kubernetes Environment

For your Kubernetes Environment, ensure that the following features are enabled:

* [Certificate management controller](https://cert-manager.io/docs/installation/)

To enable these features for your Kubernetes environment, refer to your Kubernetes-specific documentation.

For an example, see [appendix-setup-local-kubernetes](https://docs.inrupt.com/ess/latest/installation/appendix/appendix-setup-local-kubernetes "mention") to set up a local Kubernetes environment.

### OIDC-Compliant Identity Provider

ESS integrates with your OpenID Connect (OIDC) compliant Identity Provider (IdP). In addition, as part of the provided **`standalone`** overlay, ESS includes [Keycloak](https://www.keycloak.org/). When using the provided Keycloak, your usernames should be alphanumeric.

To use your OIDC-compliant IdP, refer to your IdP’s official site to set up an OIDC application. When configuring the OIDC application:

| Callback/Redirect URL | Set to **`https://openid.<ESS Domain>/callback`**.                                                                                                                  |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OAuth 2.0 Flow        | Set to **`Authorization code grant`**. For more information, see [The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1) |
| OIDC Scopes           | Must include **`openid`** and **`profile`**.                                                                                                                        |

{% hint style="info" %}
**Tip**\
Contact [Inrupt Support Center](https://inrupt.atlassian.net/servicedesk/customer/portals) for guidance setting up an OIDC application with your IdP.
{% endhint %}

### Initial Service Account

{% hint style="warning" %}
**Required for ESS 2.7.0+**

The Platform Management service requires a Service Account to be configured before deployment. This Service Account enables the Platform Management API for user provisioning operations.
{% endhint %}

Before deploying ESS, you must:

1. **Create a user account in your IdP** for the Platform Management Service Account
   * Choose a username (e.g., `platform-service`, `provision-service`)
   * This account will be used exclusively by the Platform Management service
   * The account does not require special privileges in the IdP
2. **Configure the Service Account username** in your deployment
   * The username must be set in the `INRUPT_PLATFORM_ACCOUNT_PROVISION_SERVICE_USERNAME` environment variable
   * This configuration is stored in the `inputs/platform-management-secrets.env` file
   * **The service will fail to start if this configuration is not set**

{% hint style="danger" %}
**Critical Security Requirement**

The Service Account username creates the binding between ESS and your IdP. You **must** create the corresponding user account in your IdP before deploying ESS.

Failing to do this could allow malicious users to claim the Service Account username, leading to unauthorized administrative access to your ESS deployment.
{% endhint %}

**Example Configuration**:

```bash
# In inputs/platform-management-secrets.env
INRUPT_PLATFORM_ACCOUNT_PROVISION_SERVICE_USERNAME=provision-service
```

For more information about the Platform Management service and Service Accounts, see [Platform Management API](https://docs.inrupt.com/ess/latest/services/service-platform-management/platform-management-api).

### Publicly Accessible

ESS services are designed to be accessible from and have access to the Internet. For example,

* JSON Web Key Set (JWKS) may be hosted on external services, and ESS services would need access to those when running in an open Solid ecosystem.
* If running ESS with certificates from LetsEncrypt, common [LetsEncrypt validation challenges](https://letsencrypt.org/docs/challenge-types/) require Internet access.
* With Internet access, ESS can also integrate with third-party services such as Identity Providers, Cloud Logging, Metrics, Telemetry systems.

## Installation

### Step 1: Initialize the Installation Directory

1. Start Docker.
2. Open a terminal shell and login to Inrupt’s private Docker registry. When prompted for your password, enter your entitlement token:

   ```sh
   docker login  --username <userid> docker.software.inrupt.com
   ```
3. Get the latest **`2.7`** version of the **`inrupt-kustomizer`** :

{% hint style="info" %}
ESS uses **three-element** version descriptors for its Kubernetes images, corresponding to the release versions(i.e., semantic versions of Major.Minor.Patch). As such, to get the latest version, you must use the specific patch version.
{% endhint %}

```sh
docker pull docker.software.inrupt.com/inrupt-kustomizer:2.7.0
```

4\. Initialize an empty installation directory with a base [overlay](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#bases-and-overlays) for your environment:

{% hint style="warning" %}
The tutorial follows the Infrastructure as Code (IaC) practice for managing the system and assumes the installation directory is under source control. Specifically, since secrets are stored in the configuration files, the tutorial assumes the directory is stored in a private repository and kept secure.

As such, the steps include committing the directory and its files to your source control.
{% endhint %}

{% hint style="danger" %}
**CRITICAL SECURITY REQUIREMENT**

**NEVER commit files containing secrets such as** **`.env`** **or** **`JWT`** **to version control.** These files must be managed securely.

As part of updating the inputs for your deployment:

1. **Review** the template secret files
2. **Set strong secrets** for the values, such as strong passwords
3. **Store the secret securely** outside your repository using one of these methods:
   * Cloud secrets management service
   * Enterprise secrets vault solution
   * Kubernetes Secrets with encryption at rest
   * Secure file system with restricted access (development only)
4. **Configure your deployment** to retrieve credentials from your secure storage at runtime
5. **Add the secrets files to your** **`.gitignore`** **file immediately**
   {% endhint %}

a. Run the **`inrupt-kustomizer`** , specifying the absolute path to the installation directory.

{% hint style="info" %}
**Note**

* If the specified directory does not exist, the operation creates the directory.
* If the specified directory exists, ensure that the directory is empty. If the directory is not empty, the **`inrupt-kustomizer`** does not attempt to initialize the directory with the base configuration files.
  {% endhint %}

```sh
docker run -it -v ${HOME}/ess:/kustomize docker.software.inrupt.com/inrupt-kustomizer:2.7.0
```

The operation prompts you to select from one of the available overlays provided by Inrupt as a base overlay:

```none
It appears that this environment hasn't been initialized.
You can choose an overlay that you'd like to base this environment on.
For more details please see: https://docs.inrupt.com/ess/2.7/installation/
The available overlays are:
scalable-cloud
    ESS Scalable Cloud with external storage, queues and identity provider
standalone
    WARNING! ESS Standalone comes bundled with in-cluster storage, queues and identity provider for specific evaluation purposes only. DO NOT deploy ESS Standalone in production environments. Unexpected issues may arise. Inrupt disclaims all liability and responsibility for use of ESS Standalone in a production environment. Contact support@inrupt.com for assistance or inquiries. Your understanding is appreciated.
```

b. Enter the overlay to use. For example, to use the Scalable Cloud overlay as the base, enter scalable-cloud:

```
Please enter the overlay you would like to use [scalable-cloud]: scalable-cloud
```

{% hint style="info" %}
You may choose to run ESS on other Kubernetes environments. To install ESS as a standalone on a local environment, contact Inrupt for technical assistance.
{% endhint %}

The operation populates the specified installation directory with various files needed to set up your environment.

```
Extracting inputs required for overlay "scalable-cloud"...
The inputs for "scalable-cloud" are now in the "inputs" folder
Generating "kustomization.yaml" to allow you to fine-tune your environment...
Please refer to the **`readme.txt`** file that was generated. It contains instructions on how to set up your environment.
```

c. Place the directory under source control in a **private** repo.

{% hint style="warning" %}
Ensure that the directory is in a **private** repo for best security
{% endhint %}

### Step 2: Update Inputs and Build

{% hint style="warning" %}
Inputs may change per versions. For example, a new input file may be added or new input may be required in an existing input file. Always review the contents of the **`inputs`** folder when performing the installation/upgrades.
{% endhint %}

During the initialization, Inrupt generates a **`readme.txt`** file in the installation directory. The file provides instructions on updating inputs for your deployment and building the deployment file.

1. Go to the installation directory.

   ```sh
   cd ${HOME}/ess
   ```
2. Using the instructions in the **`readme.txt`** file, update the inputs in the base overlay for your deployment.

{% hint style="danger" %}
**WarningCRITICAL SECURITY REQUIREMENT**

**NEVER commit files containing secrets such as** **`.env`** **or** **`JWT`** **to version control.** These files must be managed securely.

As part of updating the inputs for your deployment:

1. **Review** the template secret files
2. **Set strong secrets** for the values, such as strong passwords
3. **Store the secret securely** outside your repository using one of these methods:
   * Cloud secrets management service
   * Enterprise secrets vault solution
   * Kubernetes Secrets with encryption at rest
   * Secure file system with restricted access (development only)
4. **Configure your deployment** to retrieve credentials from your secure storage at runtime
5. **Add the secrets files to your** **`.gitignore`** **file immediately**
   {% endhint %}

{% hint style="warning" %}
**Important**\
Inputs may change per versions. For example, a new input file may be added or new input may be required in an existing input file. Review the contents of your **`inputs/`** folder for your installation/upgrades.
{% endhint %}

{% hint style="warning" %}
**Kafka Message Encryption**

ESS’ services communicate with each other by sending messages through Kafka.

By default, Inrupt enables data encryption for all data that pass through the Kafka messaging system.

{% hint style="danger" %}
You **MUST** set the data encryption key values to a strong password.
{% endhint %}

Update any other input(s) as specified in the **`kafka-credentials.env`** file.

For more information on the Kafka configurations in the **`kafka-credentials.env`** file, see [appendix-kafka-configuration](https://docs.inrupt.com/ess/latest/services/appendix/appendix-kafka-configuration "mention")
{% endhint %}

3. After updating the inputs, build the deployment file per the instructions in the **`readme.txt`** file.
4. Commit all changes in the directory to source control.

{% hint style="warning" %}
Ensure that the repo is **private**
{% endhint %}

### Step 3: Optional. Customize Your Deployment Configuration

Optionally, you can further customize your ESS deployment using Kustomize [overlays](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#bases-and-overlays) , such as to use certificates from an official Certificate Authority (CA).

{% hint style="info" %}
You can opt to customize after setting up a base deployment.
{% endhint %}

For examples on customizing your deployment with overlays, see [customize-configurations](https://docs.inrupt.com/ess/latest/installation/customize-configurations "mention")

### Step 4: Deploy

After you have built the deployment file, you can deploy.

1. If not already, go to the installation directory:

   ```sh
   cd ${HOME}/ess
   ```
2. Deploy to your Kubernetes environment:

   ```sh
   kubectl apply -f kustomized.yaml
   ```

{% hint style="info" %}
The deploy operation is idempotent. If the deploy operation does not complete successfully, you can safely retry the operation.
{% endhint %}

{% hint style="danger" %}
**Warning: Self-signed Certificates**\
The provided base overlays create self-signed certificates. These self-signed certificates are for **development purposes only** . In production, ESS should be run with certificates from an official Certificate Authority (CA). For an example of how you can customize your deployment to use your production certificates, see [Use Official Certificate Authority](https://docs.inrupt.com/ess/latest/installation/customize-configurations/customization-security/use-production-lets-encrypt).
{% endhint %}

3. You can view the ESS components and services that are running:

   ```sh
   kubectl -n ess get all
   ```
4. **For local standalone deployments** , add the ESS service domains to the **`/etc/hosts`** file on your local machine.

   ```
    The following steps are specific to Linux operating system.
   ```

   1. Get your local Kubernetes cluster IP address:

      ```sh
      K8_IP=$(kubectl get nodes -o jsonpath="{.items[*].status.addresses[?(@.type=='InternalIP')].address}")
      ```
   2. Get a list of the ESS service domains:

      ```sh
      ESS_DOMAINS=$(grep "host: " kustomized.yaml | awk '{print $3}' | sort -u | tr -d '\r' | tr '\n' ' ')
      ```
   3. Backup your **`/etc/hosts`** file:

      ```sh
      sudo cp /etc/hosts /etc/hosts.bak
      ```
   4. Update the **`/etc/hosts`** :

      ```sh
      sudo sed -n -e '/# ESS-DOMAINS-BEGIN/,/# ESS-DOMAINS-END/!p' -e '$a# ESS-DOMAINS-BEGIN\n'"$K8_IP $ESS_DOMAINS"'\n# ESS-DOMAINS-END' -i /etc/hosts
      ```
5. To verify, go to **`https://start.{ESS DOMAIN}/`** .

## Appendix

### Delete ESS

Because ESS deploys to a namespace ( **`ess`** ), you can delete ESS by deleting the **`ess`** namespace:

```sh
kubectl delete namespace ess
```

{% hint style="danger" %}
Ensure that no other components have been deployed to the namespace.
{% endhint %}
