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 and modules.
How remote configuration works
Alloy supports two patterns for remote configuration.
- Module imports:
import.http,import.git, andimport.fileload 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:
remotecfgconnects 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:
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.httpto 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:
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:
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:
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:
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:
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 to load modules from a version-controlled repository.
Refer to 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.
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 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.
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 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.
Note
The
remotecfgblock isn’t for loading static configuration files from an HTTP server. If you want to load a static configuration file from an HTTP server, useimport.httpinstead.
The remotecfg block sends the collector’s id and attributes to the server, allowing the server to dynamically decide which configuration to serve.
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 for more information.


