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

# Configuring

> You are now ready to identify the configuration parameters needed to perform three important roles.

## Prerequisites

* You have identified the [installation](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/installing.md) method for the host system:
  * For bare-metal, you have two executables installed on the host operation system path: `stellar-horizon` and `stellar-core`.
  * For running Horizon image with Docker daemon, you will use the [stellar/stellar-horizon](https://hub.docker.com/r/stellar/stellar-horizon) hosted on Docker Hub. You have already pulled the stellar/stellar-horizon image via `docker pull stellar/stellar-horizon:<tag_version>` onto host. This image contains the `stellar-horizon` and `stellar-core` within.
  * For Kubernetes with [Horizon Helm Chart](https://github.com/stellar/helm-charts/tree/main/charts/horizon), you have followed the [Install Horizon with Helm Chart](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/installing.md#helm-chart-installation).

* [Initialize database](#initialize-horizon-database)

You are now ready to identify the configuration parameters needed to perform three important roles:

* **Serving read-only API requests** via a regular web-based HTTP API;
* **Ingesting ledgers** from Core nodes of the Stellar network to keep its world-view up to date;
* **Submitting transactions** via a regular web-based HTTP API, forwarding the transaction submission request to the Stellar network.

To perform these roles, you can choose from one of two deployment modes below (single instance deployment or multiple instance deployment). Each has its own configuration parameters.

## Single Instance Deployment

Run `stellar-horizon` in a single o/s process and it will perform all three roles simultaneously.

| environment variable | example |
| - | - |
| `DATABASE_URL` | postgres\://localhost/horizon\_pubnet |
| `NETWORK` | pubnet |
| `HISTORY_RETENTION_COUNT` | 518400 |

## Multiple Instance Deployment

In this scalable deployment variant, you run multiple instances of `stellar-horizon`, each performing a subset of the roles. This allows you to horizontally scale each of the role functions independently.

### Ingestion Role Instance

You must allocate **at least** one instance to perform ongoing ingestion to capture network activity. Set `HISTORY_RETENTION_COUNT` explicitly to limit storage of ingested network activity in the database — we recommend a sliding window of the last 30 days (518400 ledgers). By default (`HISTORY_RETENTION_COUNT=0`), Horizon retains all ingested history and never purges it.

| environment variable | example |
| - | - |
| `DATABASE_URL` | postgres\://localhost/horizon\_pubnet |
| `NETWORK` | pubnet |
| `HISTORY_RETENTION_COUNT` | 518400 |
| `DISABLE_TX_SUB` | true |

### API Role Instance

You can run none or multiple instances to serve read-only API requests. Notice there is no need to define network settings here, as Horizon only reads from database.

| environment variable | example |
| - | - |
| `DATABASE_URL` | postgres\://localhost/horizon\_pubnet |
| `INGEST` | false |
| `DISABLE_TX_SUB` | true |

### Transaction Submission Role Instance

You can run none or multiple instances to serve transaction submission requests. If you run an instance with transaction submission enabled, the Horizon deployment is required to have at least one instance perform the ingestion role on the same database. Horizon transaction submission depends on this **live** ingestion taking place against the database in order to confirm tx submission status.

If ingestion is planned to be done on a separate instance, add `INGEST=false` on this instance, otherwise don't include the parameter, Horizon will default to `INGEST=true`. When a transaction submission enabled instance has `INGEST=true` effective, it will configure the related `STELLAR_CORE_URL` parameter automatically to use the internally launched captive core instance and the deployment does not need to set the configuration value explicitly.

If setting `INGEST=false`, then **must** define the `STELLAR_CORE_URL` variable on this transaction submission enabled instance, since there will be no internally hosted captive core instance as part of ingestion available to reference, instead the `STELLAR_CORE_URL` provides the ability to define the URL of a core instance HTTP port which Horizon will send transaction submissions towards.

| environment variable | example |
| - | - |
| `DATABASE_URL` | postgres\://localhost/horizon\_pubnet |
| `STELLAR_CORE_URL` | [http://example.watcher.core:11626](http://example.watcher.core:11626) |
| `INGEST` | false |

## Notes

### Ingestion

If you have configured your deployment to perform the ingestion role, then it is **strongly** recommended to review [Ingestion](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/ingestion.md) first and [Filtering](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/ingestion-filtering.md) second and factor that into configuration parameters to achieve best performance related to your application requirements before proceeding further.

* Horizon will create a sub-directory under the current working directory of the o/s process to store captive core runtime data files. Refer to [Prerequisites](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/prerequisites.md) for the type and amount of storage recommended. You can override this location with the optional `CAPTIVE_CORE_STORAGE_PATH` environment variable, set to a directory on the file system where captive core will store the runtime files.

### `DISABLE_TX_SUB`

This config parameter is optional, set as FALSE by default. Controls whether Horizon will accept HTTP requests to the `/tx` API endpoint and forward to the network. Refer to [Channel Accounts](https://developers.stellar.org/docs/build/guides/transactions/channel-accounts.md) for some recommendations on optional client transaction submission optimizations.

* When set to FALSE, it requires **live** ingestion process to be running on the same database because Horizon depends on new ledgers from the network to confirm a transaction submission status, Horizon will report a startup error if it detects no **live** ingestion. Requires `INGEST=true` or `STELLAR_CORE_URL` to be defined for access to a Core instance.
* When transaction submission is disabled by setting it to TRUE, Horizon will return 405 on POSTs to /tx.

### `NETWORK`

This config parameter is optional, can be one of Stellar's public networks, 'pubnet', or 'testnet'. Triggers Horizon to automatically set configurations for remaining Horizon settings and generate the correct core toml/cfg settings. If you only need Horizon to connect to one of those public Stellar networks, this will take care of all related configurations.

* If you want to connect Horizon to a different Stellar network other than pubnet or testnet or override any of the defaults that `NETWORK` usage will initiate, the key environment variables that can be set are: `HISTORY_ARCHIVE_URLS`, `CAPTIVE_CORE_CONFIG_PATH`, `NETWORK_PASSPHRASE`, `CAPTIVE_CORE_STORAGE_PATH`, `STELLAR_CORE_URL`.

### `DB_URL`

This config parameter is required, specifies the Horizon database. It's value follows this format: `dbname=<pg_dbname> user=<pg_user_name> password=<pg_user_pwd> host=<host_address>`

### `LOG_LEVEL`

This config parameter is optional, can be one of 'info', 'error', 'debug'.

### `HISTORY_RETENTION_COUNT`

This config parameter is optional, it determines the maximum sliding window of historical network data to retain on the database from ingestion. The value is expressed as absolute ledger count, which is an indirect way to define a duration of time, each ledger being approximately 5 seconds. It is defaulted to 0, which means it will not purge any history from the database. To enact the recommended sliding window of one month, set this to 518400, which is the approximate number of ledgers in 30 days. Refer to [Compute Resources](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/prerequisites.md) for how database storage space is closely related to this setting.

## Passing Configurations to Horizon

The `stellar-horizon` binary searches process environment variables for configuration. Depending on how Horizon was installed, the method you perform to configure the process environment will differ:

### Bare-metal

* Non-package manager: use O/S environment variables to pass configurations. There are many tools you can use to manage them, such as [direnv](http://direnv.net) or [dotenv](https://github.com/bkeepers/dotenv).
* [Package manager](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/installing.md#package-manager): the provided `stellar-horizon-cmd` wrapper will start a new process and create environment variables in the process from `/etc/default/stellar-horizon` and then launch the 'stellar-horizon'. To set configurations, edit the file at `/etc/default/stellar-horizon`.

  > [!NOTE]
  >
  > This script invokes Horizon with the `stellar` user, so make sure that permissions for the user are set up accordingly. The current working directory should be writable for this user and the user should be able to execute the `stellar-horizon` and `stellar-core` binaries; etc.

### Containerized

* Non-Helm: pass all configuration parameters to the horizon docker image as [docker environment variables](https://docs.docker.com/engine/reference/commandline/run/#env).
* Helm: pass all configuration parameters in the [Helm install command](https://helm.sh/docs/helm/helm_install) as a values file.

## Initialize Horizon Database

Before running the Horizon server for the first time, you must initialize the Horizon database. This database will be used for all of the information produced by Horizon, most notably historical information about transactions that have occurred on the Stellar network.

To prepare a database for Horizon's use, first ensure it is blank. It's easiest to create a new database on your PostgreSQL server specifically for Horizon's use. We recommend creating a new user(role) in postgres dedicated to Horizon's database and assigning that user(role) as the owner of this database.

To illustrate an example using `psql`, first login to the database server using the `psql` command-line tool as a superuser, and then create the new user(role) and database for Horizon:

```
postgres=#
postgres=# CREATE ROLE horizon WITH LOGIN;
CREATE ROLE
postgres=#
postgres=# CREATE DATABASE horizon OWNER horizon;
CREATE DATABASE
postgres=#
```

Additionally, you can set a password on your new `horizon` postgres user with `ALTER USER`.

Once completed, you can compose the full value of the configuration parameter for db access `DATABASE_URL="dbname=horizon user=horizon password=<value_here> host=<address_of_pg_server>"`.

Next, execute the Horizon binary to install the schema onto the empty db from the command line. In this example, assume the current shell doesn't have `DATABASE_URL` in environment yet, so export it first into shell:

```
$ export DATABASE_URL="dbname=horizon user=horizon password=<value_here> host=<address_of_pg_server>"
$ stellar-horizon db init
```

### Optional Postgres Configurations

Based on performance observations over time, we recommend additional Postgres configuration settings(postgresql.conf), but these are not required:

* Set `random_page_cost=1` if you are using SSD storage. With this setting, Query Planner will make a better use of indices, especially for `JOIN` queries. We've noticed a huge speed improvement for some queries with this setting.

\_ To improve availability of ingestion, api, transaction submission servers it's recommended to set the following values:

* `tcp_keepalives_idle`: 10 seconds
* `tcp_keepalives_interval`: 1 second
* `tcp_keepalives_count`: 5

With the config above, if there are no queries from a given client for 10 seconds, Postgres should start sending TCP keepalive packets. It will retry 5 times every second. If there is no response from the client after that time it will drop the connection.

## Next Step

After configuration is complete, you are now ready to proceed to [Running Horizon](https://developers.stellar.org/docs/data/apis/horizon/admin-guide/running.md)!
