Skip to main content


Once you have established the Horizon database and have identified the Horizon runtime config per host, you're ready to run Horizon.

Bare-metal installation

Run the stellar-horizon binary with the appropriate environment parameters set (or stellar-horizon-cmd serve if you installed via the package manager, which will automatically import your configuration from /etc/default/stellar-horizon).

Containerized installation

You don't execute the Horizon binary directly, instead the stellar/stellar-horizon image has a pre-defined entrypoint that will start running Horizon at image startup time. The Horizon process will get all configuration settings from container environment variables.

Docker daemon

Use docker run stellar/stellar-horizon:<tag_version> --env-file <env_filename>, and specify each Horizon configuration flag identified during Configuring as a separate line in <env_filename> of HORIZON_CONFIG_PARAM=value.

Kubernetes using Helm Chart

Ensure you have followed the pre-requisite of installing the Helm CLI tool and added the Stellar chart repo to Helm client.

The Horizon process requires access to a Postgres 12 database. First use the common Kubernetes CLI tool kubectl from your workstation to create a Kubernetes secret on the intended namespace of the Kubernetes cluster which will hold the Horizon database URL.

# copy your horizon DATABASE_URL into a secure file, no line breaks.
echo -n 'database_url_here' > my_creds.txt

# now generate the kubernetes secret from the file
kubectl create secret generic \
-n my-namepsace\
my-db-secret \

Now deploy Horizon onto the cluster using the Helm Chart:

helm install my-horizon stellar/horizon \
--namespace my-horizon-namespace-on-cluster \
--set ingest.persistence.enabled=true \
--set web.replicaCount=1 \
--set web.enabled=true \
--set ingest.enabled=true \
--set ingest.replicaCount=1 \
--set web.existingSecret=my-db-secret \
--set global.image.horizon.tag=2.26.1 \
--set \
--set ingest.existingSecret=my-db-secret \
--set ingest.horizonConfig.captiveCoreUseDb=true \
--set ingest.resources.limits.cpu=1 \
--set ingest.resources.limits.memory=6Gi

This example of Helm Chart usage highlights some key aspects:

  • Uses the[testnet|pubnet] parameter, this automates generation of all the Horizon configuration parameters specific to the network such as archive urls, captive core config, and other parameters mentioned in Configuring.
  • global.image.horizon.tag should be set to one of the Docker Hub tags published on stellar/stellar-horizon
  • Enables all roles on the deployment instance: ingesting and web API (includes transaction submission). If you choose to have a multi-instance deployment with each instance performing a single role of just web API or ingestion, then you will do two Helm installations, one for each role: my-horizon-ingestion-installation and my-horizon-api-installation. Each of these Helm installations will set ingest.enabled, web.enabled, ingest.replicaCount, web.replicaCount respectively for the role they are performing.
  • To customize further, the best approach is to download the Horizon Helm Chart values.yaml, update the settings in your local copy of values.yaml, and pass to Helm install, rather than have many individual --set on Helm install:
helm install myhorizon stellar/horizon \
--namespace my-horizon-namespace-on-cluster \
--values values.yaml
  • Customizing network configuration parameters, If you want to connect to a network other than presets of testnet or pubnet, then you won't use, instead, use local copy of values.yaml and set ingest.coreConfig, and refer to _core-config.tpl for example of all the key/value pairs to include.

  • Minimum resource limits, verify whether LimitRange defaults are defined on the target namespace in Kubernetes for deployment, if so, ensure that the defaults provide at least minimum resource limits of 6Gi of memory and 1 cpu. Otherwise, define the limits explicitly on the helm install via the ingest.resources.limits.* shown in example, to ensure the deployed pods have adequate resources.

Once the Horizon process starts, it will emit logging to standard out. When run, you should see output similar to:

INFO[...] Starting horizon on :8000                     pid=29013

Note that the numbers may naturally be different for your installation. The log line above announces that Horizon is ready to serve client requests.

Next, you can confirm that Horizon is responding correctly by loading the root resource. In the example above, that URL would be, and simply running curl would show you that the root resource loads correctly:

"_links": {
"account": {
"href": "{account_id}",
"templated": true
"accounts": {
"href": "{?signer,sponsor,asset,cursor,limit,order}",
"templated": true
// etc.

Refer to Monitoring for more details on Horizon runtime logging and metrics available.