---
title: "Load configuration from remote sources | Grafana Alloy documentation"
description: "Learn how to load Grafana Alloy configuration from remote sources"
---

# Load configuration from remote sources

Alloy provides several methods to load an Alloy configuration from remote sources. Loading a configuration from a remote source doesn’t mean you point Alloy directly at a URL for a complete configuration file. You always start with a local configuration file. From that file, you import modules from remote sources or connect to a remote configuration API, such as Fleet Management in Grafana Cloud. The method you choose depends on your use case and infrastructure.

## Before you begin

You should have a basic understanding of [Alloy configuration syntax](../../get-started/syntax/) and [modules](../../get-started/modules/).

## How remote configuration works

Alloy supports two patterns for remote configuration.

- **Module imports:** `import.http`, `import.git`, and `import.file` load Alloy modules into your local root configuration. Alloy fetches or watches the source. It reads the returned Alloy text as module content. It reevaluates the local configuration when the module changes.
- **Remote configuration API:** `remotecfg` connects to a compatible remote configuration API. Alloy identifies the collector, sends its attributes, and polls the API for updates. The server decides which configuration to return.

If you want to read Alloy configuration text from a generic HTTP endpoint, use `import.http`. If you want a server to choose configuration based on collector identity or attributes, use `remotecfg`.

## Choose a method

Use the following table to choose the appropriate method for your use case:

Expand table

| Method                                                      | Use case                                                                               |
|-------------------------------------------------------------|----------------------------------------------------------------------------------------|
| [`import.http`](../../reference/config-blocks/import.http/) | Load configuration from an HTTP server hosting static files.                           |
| [`import.git`](../../reference/config-blocks/import.git/)   | Load configuration from a Git repository with version control.                         |
| [`import.file`](../../reference/config-blocks/import.file/) | Load configuration from a local file or directory.                                     |
| [`remotecfg`](../../reference/config-blocks/remotecfg/)     | Dynamically manage configuration through a remote configuration management API server. |

## Load from an HTTP server

Use `import.http` to load configuration modules from an HTTP server. This is the recommended approach when you have configuration modules hosted on a web server.

Alloy periodically makes HTTP requests to the configured URL and treats the response body as Alloy module content. The response doesn’t need a special API, a standard HTTP server that returns Alloy text is enough.

Alloy loads remote content with `import.http` and treats it as a module, not as a complete top-level configuration file. Modules define reusable components in `declare` blocks. After you import a module, add the components you need in your local configuration, or they won’t run.

> Note
> 
> You can’t point Alloy directly at a remote URL on startup. At a minimum, you must have a local configuration file that uses `import.http` to import modules from the remote server.
> 
> The HTTP response body must contain Alloy module content, not a complete top-level configuration file.

Alloy periodically polls the URL to detect and apply configuration changes.

### Module requirements

Modules can contain top-level `declare` blocks and nested `import.*` blocks. They can’t contain top-level configuration blocks such as `logging` or `remotecfg`. Set CLI flags when you start Alloy. You can’t set CLI flags inside modules.

The following example shows an **invalid** module. It includes a `logging` block, which isn’t allowed in modules:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
logging {
  level = "debug"
}

declare "pipeline" {
  prometheus.scrape "default" {
    targets = [{"__address__" = "localhost:9090"}]
  }
}
```

The following module is **valid** because it only contains `declare` blocks which is the simplest module pattern:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
declare "pipeline" {
  prometheus.scrape "default" {
    targets = [{"__address__" = "localhost:9090"}]
  }
}
```

Global configuration such as `logging` must remain in the local configuration file that imports the module.

### Create the remote configuration file

Create a configuration file on your HTTP server. The file must be a valid Alloy module, using top-level `declare` blocks to define a reusable configuration that you import and instantiate locally.

The following example creates a reusable Prometheus scrape configuration:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
declare "scrape" {
  argument "targets" {}
  argument "forward_to" {}

  prometheus.scrape "default" {
    targets    = argument.targets.value
    forward_to = argument.forward_to.value
  }
}
```

### Import the remote configuration

In your local configuration, import the remote file and use the declared component:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
import.http "remote" {
  url            = "http://<CONFIG_SERVER_ADDRESS>/prometheus_scrape.alloy"
  poll_frequency = "5m"
}

prometheus.remote_write "default" {
  endpoint {
    url = "http://<MIMIR_ADDRESS>/api/v1/push"
  }
}

remote.scrape "app" {
  targets    = [{"__address__" = "localhost:8080"}]
  forward_to = [prometheus.remote_write.default.receiver]
}
```

Replace the following:

- *`<CONFIG_SERVER_ADDRESS>`* : The address of your HTTP server hosting the configuration file.
- *`<MIMIR_ADDRESS>`* : The address of your Prometheus-compatible remote write endpoint.

You can load multiple remote modules by defining multiple `import.http` blocks in your local configuration file. Each block can point to a different module file on the remote server.

For example:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
import.http "metrics" {
  url = "http://config-server.example.com/metrics.alloy"
}

import.http "logs" {
  url = "http://config-server.example.com/logs.alloy"
}
```

Each imported module can define its own `declare` blocks and components.

If you need to manage many configuration files or directories, consider using [`import.git`](../../reference/config-blocks/import.git/) to load modules from a version-controlled repository.

Refer to [`import.http`](../../reference/config-blocks/import.http/) for more information.

## Load from a Git repository

Use `import.git` to load configuration from a Git repository. This approach provides version control and supports authentication for private repositories. Alloy periodically pulls the repository to detect and apply configuration changes.

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
import.git "modules" {
  repository     = "https://github.com/<ORGANIZATION>/<REPOSITORY>.git"
  revision       = "main"
  path           = "modules/prometheus.alloy"
  pull_frequency = "5m"
}

modules.scrape "app" {
  targets    = [{"__address__" = "localhost:8080"}]
  forward_to = [prometheus.remote_write.default.receiver]
}

prometheus.remote_write "default" {
  endpoint {
    url = "http://<MIMIR_ADDRESS>/api/v1/push"
  }
}
```

Replace the following:

- *`<ORGANIZATION>`* : Your GitHub organization or username.
- *`<REPOSITORY>`* : The name of your Git repository.
- *`<MIMIR_ADDRESS>`* : The address of your Prometheus-compatible remote write endpoint.

Refer to [`import.git`](../../reference/config-blocks/import.git/) for more information.

## Load from a local file

Use `import.file` to load configuration from a local file or directory. This is useful when you want to organize your configuration into separate files on the local filesystem. Alloy watches the file for changes and automatically applies updates.

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
import.file "modules" {
  filename = "/etc/alloy/modules/prometheus.alloy"
}

modules.scrape "app" {
  targets    = [{"__address__" = "localhost:8080"}]
  forward_to = [prometheus.remote_write.default.receiver]
}

prometheus.remote_write "default" {
  endpoint {
    url = "http://<MIMIR_ADDRESS>/api/v1/push"
  }
}
```

Replace *`<MIMIR_ADDRESS>`* with the address of your Prometheus-compatible remote write endpoint.

Refer to [`import.file`](../../reference/config-blocks/import.file/) for more information.

## Use dynamic remote configuration management

Use `remotecfg` when you need a configuration management server that can serve different configurations based on collector identity and attributes. This approach requires implementing or using a server that supports the [alloy-remote-config API](https://github.com/grafana/alloy-remote-config).

> Note
> 
> The `remotecfg` block isn’t for loading static configuration files from an HTTP server. If you want to load a static configuration file from an HTTP server, use `import.http` instead.

The `remotecfg` block sends the collector’s `id` and `attributes` to the server, allowing the server to dynamically decide which configuration to serve.

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
remotecfg {
  url            = "http://<REMOTECFG_SERVER_ADDRESS>"
  id             = constants.hostname
  attributes     = {"cluster" = "production", "environment" = "us-east-1"}
  poll_frequency = "5m"
}

logging {
  level  = "info"
  format = "logfmt"
}
```

Replace *`<REMOTECFG_SERVER_ADDRESS>`* with the address of your remote configuration management server.

Refer to [`remotecfg`](../../reference/config-blocks/remotecfg/) for more information.
