# Environment Variable Expansion in PostgreSQL DSN Configuration for AgentsView

> Discover how AgentsView handles PostgreSQL DSN configuration. Learn that automatic environment variable expansion is not supported; the pgx driver receives the AGENTSVIEW_PG_URL variable directly.

- Repository: [Kenn Software/agentsview](https://github.com/kenn-io/agentsview)
- Tags: how-to-guide
- Published: 2026-06-15

---

**AgentsView does not perform automatic environment variable expansion in PostgreSQL DSN strings; the application reads the `AGENTSVIEW_PG_URL` environment variable verbatim and passes it directly to the pgx driver without processing `${VAR}` or `$VAR` placeholders.**

When configuring database connections for the kenn-io/agentsview repository, understanding how the PostgreSQL connection string is processed is critical for secure credential management. The application relies on the `AGENTSVIEW_PG_URL` environment variable to establish database connectivity, but unlike some frameworks, it does not interpolate environment variables within the DSN itself. This behavior impacts how you structure your deployment configuration and handle sensitive credentials.

## How AgentsView Loads the PostgreSQL DSN

### Configuration Loading in internal/config/config.go

The configuration loading flow begins in [`internal/config/config.go`](https://github.com/kenn-io/agentsview/blob/main/internal/config/config.go), where the environment is inspected during initialization. According to the source code, lines 998–1000 assign the raw value of `AGENTSVIEW_PG_URL` directly to the configuration struct:

```go
func (c *Config) loadEnv() {
    // …other env vars…
    if v := os.Getenv("AGENTSVIEW_PG_URL"); v != "" {
        c.PG.URL = v          // stored exactly as provided
    }
    // …
}

```

Notice that `os.Getenv` retrieves the string as-is, with no transformation or expansion logic applied.

### Connection Initialization in internal/postgres/connect.go

When the server starts, the `postgres.Open` function in [`internal/postgres/connect.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/connect.go) (lines 45–47) receives the DSN string directly from `c.PG.URL`. The implementation passes this string unchanged to the underlying driver:

```go
func Open(dsn, schema string, allowInsecure bool) (*sql.DB, error) {
    // dsn is the raw string from AGENTSVIEW_PG_URL
    // No environment expansion here – the DSN is used as‑is.
    connStr, err := appendConnParams(dsn, map[string]string{
        "search_path": quoted,
        "TimeZone":    "UTC",
    })
    // pgx driver parses connStr internally.
    db, err := sql.Open("pgx", connStr)
    // …
}

```

The `appendConnParams` helper only appends runtime parameters such as `search_path` and `TimeZone`; it does not scan for or expand environment variable references.

## Why Environment Variables Are Not Expanded Automatically

The AgentsView codebase deliberately avoids automatic expansion to prevent side effects and maintain predictable configuration behavior. Specifically:

- **No `os.ExpandEnv` calls**: Neither [`internal/config/config.go`](https://github.com/kenn-io/agentsview/blob/main/internal/config/config.go) nor [`internal/postgres/connect.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/connect.go) invokes `os.ExpandEnv` or equivalent helpers on the DSN string.
- **Direct pgx handoff**: The DSN is passed directly to `pgconn.ParseConfig` within the pgx driver, which expects a fully-formed connection string.
- **Verbatim preservation**: Any `${VAR}` or `$VAR` placeholders remain literal characters in the connection string, likely causing authentication failures if unexpanded.

This design choice means that if you set `AGENTSVIEW_PG_URL` to `postgres://user:${PG_PASS}@host/db`, the application attempts to connect using the literal username `user:${PG_PASS}@host` rather than substituting the value of the `PG_PASS` environment variable.

## Implementing Manual Environment Variable Expansion

To use dynamic values in your PostgreSQL DSN, you must expand the environment variables before setting `AGENTSVIEW_PG_URL`. This pre-processing can occur in your shell wrapper, init script, or a Go program that prepares the environment.

Here is a standalone example that demonstrates the expansion pattern:

```go
package main

import (
    "os"
    "log"
)

func main() {
    // Assume PG_PASS holds the password.
    raw := os.Getenv("AGENTSVIEW_PG_URL") // "postgres://user:${PG_PASS}@host/db"
    dsn := os.ExpandEnv(raw)              // expands ${PG_PASS}
    if err := os.Setenv("AGENTSVIEW_PG_URL", dsn); err != nil {
        log.Fatalf("cannot set expanded DSN: %v", err)
    }

    // Proceed to start AgentsView (e.g. exec.Command or import the server package)
}

```

Alternatively, in a bash deployment script:

```bash
export AGENTSVIEW_PG_URL="postgres://user:${PG_PASS}@localhost:5432/agentsview"
./agentsview-server

```

In this approach, the shell performs the expansion before the process starts, ensuring AgentsView receives the fully materialized connection string.

## Summary

- AgentsView reads the PostgreSQL DSN exclusively from the `AGENTSVIEW_PG_URL` environment variable.
- The configuration loader in [`internal/config/config.go`](https://github.com/kenn-io/agentsview/blob/main/internal/config/config.go) stores the value verbatim without calling `os.ExpandEnv`.
- The connection opener in [`internal/postgres/connect.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/connect.go) passes the raw DSN directly to the pgx driver.
- To embed dynamic credentials or hostnames, expand environment variables before exporting `AGENTSVIEW_PG_URL`, either via shell substitution or programmatically using `os.ExpandEnv`.

## Frequently Asked Questions

### Does AgentsView support ${VAR} syntax in AGENTSVIEW_PG_URL?

No. AgentsView does not parse or expand `${VAR}` or `$VAR` syntax within the `AGENTSVIEW_PG_URL` value. The string is read literally from the environment and passed directly to the PostgreSQL driver. Any variable references must be resolved by your shell or a pre-processing script before the application starts.

### How can I securely inject passwords into the PostgreSQL DSN?

You should expand the password variable in your deployment environment before setting `AGENTSVIEW_PG_URL`. For example, use shell expansion (`export AGENTSVIEW_PG_URL="postgres://user:${PG_PASS}@host/db"`) or a secrets management tool that injects fully-formed connection strings. Avoid committing DSNs with placeholder syntax to version control.

### Where does the DSN parsing happen in the codebase?

The DSN is initially captured in [`internal/config/config.go`](https://github.com/kenn-io/agentsview/blob/main/internal/config/config.go) (lines 998–1000) and subsequently processed in [`internal/postgres/connect.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/connect.go) (lines 45–47). However, "parsing" in the context of connection parameters occurs inside the pgx driver via `pgconn.ParseConfig`, which AgentsView invokes indirectly through `sql.Open("pgx", connStr)`.

### Can I use multiple environment variables in the DSN string?

You can include multiple variable references (e.g., `postgres://${DB_USER}:${DB_PASS}@${DB_HOST}/db`), but AgentsView will not expand them. You must ensure all variables are substituted by your shell or a wrapper script before the application reads `AGENTSVIEW_PG_URL`. The final value exported to the environment must contain the actual credentials and hostnames, not placeholder syntax.