# How to Configure Security for API Keys and Authentication in OpenViking

> Secure your OpenViking API with robust authentication. Learn to configure API keys and manage secrets in YAML for safe runtime operations.

- Repository: [Volcengine/OpenViking](https://github.com/volcengine/OpenViking)
- Tags: how-to-guide
- Published: 2026-03-08

---

**OpenViking stores runtime secrets in a YAML configuration file parsed by `config.LoadConfig`, where each plugin declares required authentication parameters via `GetConfigParams`, validates them through the `Validate` method using helpers like `config.RequireString`, and injects them into HTTP headers at request time without logging sensitive values.**

OpenViking is an open-source agentic filesystem that requires secure handling of third-party API credentials for services like OpenAI and AWS. To configure security for API keys and authentication in OpenViking, administrators define secrets in a structured YAML file that the server loads at startup, ensuring credentials are validated before any plugin becomes active.

## Declaring Secret Parameters in Plugin Configuration

OpenViking's plugin architecture requires each component to advertise its configuration schema through the `GetConfigParams` method. This declarative approach ensures that sensitive values like API keys are explicitly marked as required strings before the server initializes.

### GPTFS Plugin Example

In [`third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs.go), the GPTFS plugin defines its authentication parameter as follows:

```go
{
    Name:        "api_key",
    Type:        "string",
    Required:    true,
    Description: "API key for OpenAI‑compatible service",
},

```

This declaration signals to the configuration loader that the plugin cannot function without this specific secret.

## Validating API Keys at Startup

When the server loads a plugin, it invokes the `Validate` method to ensure all required secrets are present and properly formatted. The GPTFS implementation in [`gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/gptfs.go) uses validation helpers from the config package:

```go
allowedKeys := []string{"api_host", "api_key", "mount_path", "workers"}
if err := config.ValidateOnlyKnownKeys(cfg, allowedKeys); err != nil {
    return err
}
if _, err := config.RequireString(cfg, "api_key"); err != nil {
    return err
}

```

The `config.RequireString` function, defined in [`third_party/agfs/agfs-server/pkg/config/config.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/config/config.go), aborts startup with an error if the `api_key` field is missing or empty. This prevents the plugin from running with invalid or undefined credentials.

### Unit Test Verification

The validation logic is verified in [`third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs_test.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs_test.go):

```go
func TestGptfsValidateRequiresApiKey(t *testing.T) {
    cfg := map[string]interface{}{
        "api_host":   "https://example.com",
        "mount_path": "/tmp/gptfs",
        // "api_key" omitted on purpose
    }
    g := &Gptfs{}
    if err := g.Validate(cfg); err == nil {
        t.Fatalf("expected error for missing api_key")
    }
}

```

## Runtime Injection and Request Security

After validation, the plugin stores the secret in memory and injects it into outbound HTTP requests. The GPTFS driver constructs the Authorization header in [`gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/gptfs.go) without exposing the value in logs:

```go
req.Header.Set("Authorization", "Bearer "+d.apiKey)

```

This implementation ensures the bearer token never appears in error messages or log files—only the HTTP client receives the credential.

## YAML Configuration File Structure

The server reads runtime settings from a YAML file specified via the `-c` flag. Secrets reside under the `plugins` section, nested within each plugin's `config` object.

### Basic Configuration Example

```yaml
server:
  address: ":8080"
  log_level: "info"

plugins:
  gptfs:
    enabled: true
    config:
      api_host: "https://api.openai.com/v1"
      api_key:  "YOUR_OPENAI_API_KEY"
      mount_path: "/agents/gptfs"
      workers: 4

```

Only the `api_key` field requires protection as a secret value.

### Environment Variable Substitution

While OpenViking does not natively expand environment variables inside the YAML parser, deployment pipelines can substitute placeholders before startup:

```yaml
plugins:
  gptfs:
    enabled: true
    config:
      api_key: "${GPT_API_KEY}"   # placeholder for substitution

```

Deploy with an environment variable:

```bash
export GPT_API_KEY="sk-abcdef1234567890"
./agfs-server -c ./config.yaml

```

## Multi-Provider Authentication: S3FS Example

The S3FS plugin demonstrates alternative secret handling patterns for AWS credentials. Located in [`third_party/agfs/agfs-server/pkg/plugins/s3fs/s3fs.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/plugins/s3fs/s3fs.go), this implementation accepts explicit configuration values while falling back to standard AWS environment variables.

The plugin declares optional fields in `GetConfigParams`:

```go
{
    Name:        "access_key_id",
    Type:        "string",
    Required:    false,
    Description: "AWS access key ID (uses env AWS_ACCESS_KEY_ID if not provided)",
},
{
    Name:        "secret_access_key",
    Type:        "string",
    Required:    false,
    Description: "AWS secret access key (uses env AWS_SECRET_ACCESS_KEY if not provided)",
},

```

When `access_key_id` or `secret_access_key` are omitted from the YAML, the plugin reads from `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` at runtime, providing flexibility for hybrid deployment scenarios.

## Security Best Practices

To harden authentication in production environments:

- **Never commit real secrets** – Store the YAML file outside version control or use placeholder syntax like `${API_KEY}` that your CI/CD pipeline populates at deployment time.
- **Restrict file permissions** – Set the configuration file to be readable only by the user account running the `agfs-server` process (e.g., `chmod 600 config.yaml`).
- **Rotate credentials regularly** – Update the `api_key` value in the YAML file and restart the server; the `Validate` step guarantees the new key is present before the plugin accepts traffic.
- **Audit logging behavior** – The OpenViking source code explicitly avoids logging secret values (see `log.Infof` usage in [`gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/gptfs.go)), but verify that custom plugins follow this pattern.

## Summary

- OpenViking uses a centralized YAML configuration loaded by `config.LoadConfig` in [`third_party/agfs/agfs-server/pkg/config/config.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/config/config.go) to manage secrets.
- Plugins declare required authentication parameters via `GetConfigParams` and enforce presence through `config.RequireString` during the `Validate` phase.
- Secrets are injected into HTTP headers at request time (e.g., `Authorization: Bearer`) without appearing in server logs.
- The GPTFS plugin ([`gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/gptfs.go)) requires explicit `api_key` values, while S3FS ([`s3fs.go`](https://github.com/volcengine/OpenViking/blob/main/s3fs.go)) supports both YAML-defined credentials and environment variable fallbacks.
- External secret management is achieved through placeholder substitution in the YAML file during deployment, not through native environment variable expansion.

## Frequently Asked Questions

### How does OpenViking validate that an API key is present before starting?

OpenViking invokes the `Validate` method on each plugin after loading the configuration. For the GPTFS plugin, this method calls `config.RequireString(cfg, "api_key")` in [`third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs.go), which returns an error and aborts server startup if the key is missing or empty. This ensures no plugin runs without proper authentication credentials.

### Can I use environment variables instead of hardcoding API keys in the YAML file?

OpenViking does not natively evaluate environment variables inside the YAML parser. However, you can use placeholder syntax like `${GPT_API_KEY}` in your [`config.yaml`](https://github.com/volcengine/OpenViking/blob/main/config.yaml) and expand these values using your shell or CI/CD pipeline before startup. The S3FS plugin alternatively reads standard AWS environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`) at runtime if the YAML configuration omits these fields.

### Where are API keys stored once the server loads them?

After validation, the API key is stored as a private field in the plugin struct (e.g., `d.apiKey` in the GPTFS driver). The value persists in memory and is injected into the `Authorization` header for each outbound HTTP request in [`third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs.go`](https://github.com/volcengine/OpenViking/blob/main/third_party/agfs/agfs-server/pkg/plugins/gptfs/gptfs.go). The secret never appears in log files or error messages returned to clients.

### What is the recommended way to rotate API keys in a running OpenViking deployment?

To rotate credentials, update the `api_key` value in your YAML configuration file and restart the `agfs-server` process. The server re-runs the `Validate` method during startup, confirming the new key is present and properly formatted before activating the plugin. There is no hot-reload mechanism; a restart is required to apply new secrets.