fnox-configuration

Configuring secrets management with Fnox using fnox.toml files for secure, version-controlled secret storage.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "fnox-configuration" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-fnox-configuration

Fnox - Configuration

Configuring secrets management with Fnox using fnox.toml files for secure, version-controlled secret storage.

Basic Configuration

Initialize Project

Create fnox.toml in current directory

fnox init

Initialize with specific provider

fnox init --provider age

Basic fnox.toml Structure

fnox.toml

[providers.age] type = "age" public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]

[secrets] DATABASE_URL = { provider = "age", value = "age[...]" } API_KEY = { provider = "age", value = "age[...]", description = "Production API key" }

Secrets Definition

Simple Secret

[secrets] DATABASE_URL = "postgresql://localhost/myapp" # Plain text (dev only)

Encrypted Secret

[secrets] DATABASE_URL = { provider = "age", value = "age1encrypted-value-here", description = "Production database connection string" }

Secret with Default

[secrets] DEBUG_MODE = { provider = "age", value = "age[...]", default = "false", description = "Enable debug logging" }

Secret Behavior Options

[secrets] OPTIONAL_API_KEY = { provider = "age", value = "age[...]", if_missing = "warn" # Options: "error", "warn", "ignore" }

REQUIRED_SECRET = { provider = "age", value = "age[...]", if_missing = "error" # Fail if missing (default) }

Configuration Hierarchy

File Locations (Priority Order)

  • fnox.local.toml

  • Local overrides (gitignored)

  • fnox.$FNOX_PROFILE.toml

  • Profile-specific

  • fnox.toml

  • Project configuration

  • Parent directory fnox.toml files (recursive)

  • ~/.config/fnox/config.toml

  • Global configuration

Global Configuration

~/.config/fnox/config.toml

[providers.age] type = "age" identity = "~/.config/fnox/keys/identity.txt"

[settings] if_missing = "warn" # Global default for missing secrets

Project Configuration

project/fnox.toml

[providers.age] public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]

[secrets] DATABASE_URL = { provider = "age", value = "age[...]" } APP_NAME = "myapp"

Local Overrides

project/fnox.local.toml (gitignored)

[secrets] DATABASE_URL = "postgresql://localhost/myapp_dev" # Override for local dev DEBUG = "true"

Profiles

Define Profiles

fnox.toml

[secrets] DATABASE_URL = "postgresql://localhost/myapp" # Default

[profiles.production] [profiles.production.secrets] DATABASE_URL = { provider = "aws-sm", value = "prod/database-url" }

[profiles.staging] [profiles.staging.secrets] DATABASE_URL = { provider = "aws-sm", value = "staging/database-url" }

Use Profiles

Set profile via environment variable

export FNOX_PROFILE=production fnox get DATABASE_URL

Or use flag

fnox --profile staging get DATABASE_URL fnox -p production exec -- node app.js

Profile-Specific Files

fnox.production.toml

[providers.aws-sm] type = "aws-sm" region = "us-east-1"

[secrets] DATABASE_URL = { provider = "aws-sm", value = "prod/database-url" } API_KEY = { provider = "aws-sm", value = "prod/api-key" }

Use profile-specific file

export FNOX_PROFILE=production fnox get DATABASE_URL # Loads from fnox.production.toml

Configuration Imports

Import Other Configurations

fnox.toml

import = ["shared-secrets.toml", "../common/fnox.toml"]

[secrets] APP_SPECIFIC_SECRET = { provider = "age", value = "age[...]" }

Shared Configuration

shared-secrets.toml

[providers.age] public_keys = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"]

[secrets] SHARED_API_KEY = { provider = "age", value = "age[...]" }

Validation

Check Configuration

Show diagnostic information

fnox doctor

Verify secrets can be retrieved

fnox get DATABASE_URL

List all configured secrets

fnox list

Test specific provider

fnox provider test age

Common Validation Errors

Error: Missing provider definition

[secrets] API_KEY = { provider = "nonexistent", value = "..." }

Error: Invalid provider configuration

[providers.age]

Missing required fields

Error: Circular import

import = ["other.toml"] # other.toml imports this file

Best Practices

Separate Public and Private Config

fnox.toml (committed)

[providers.age] public_keys = ["age1ql3z..."] # Public key safe to commit

[secrets] DATABASE_URL = { provider = "age", value = "age[...]" } API_KEY = { provider = "age", value = "age[...]" }

fnox.local.toml (gitignored)

[providers.age] identity = "~/.ssh/age-identity.txt" # Private key, never commit

[secrets] DATABASE_URL = "postgresql://localhost/dev" # Local override

Document Secrets

[secrets] DATABASE_URL = { provider = "age", value = "age[...]", description = "PostgreSQL connection string for production database" }

STRIPE_API_KEY = { provider = "age", value = "age[...]", description = "Stripe secret key for payment processing" }

SENDGRID_API_KEY = { provider = "age", value = "age[...]", description = "SendGrid API key for transactional emails" }

Use Meaningful Names

Good: Clear, descriptive names

[secrets] POSTGRES_CONNECTION_STRING = { provider = "age", value = "age[...]" } STRIPE_SECRET_KEY = { provider = "age", value = "age[...]" } JWT_SIGNING_SECRET = { provider = "age", value = "age[...]" }

Avoid: Vague names

[secrets] DB = { provider = "age", value = "age[...]" } KEY1 = { provider = "age", value = "age[...]" } SECRET = { provider = "age", value = "age[...]" }

Set Appropriate Defaults

[secrets]

Good: Sensible defaults for non-sensitive config

LOG_LEVEL = { default = "info" } CACHE_TTL = { default = "3600" }

Avoid: Defaults for sensitive data

API_KEY = { default = "unsafe-default-key" } # Bad!

Common Patterns

Multi-Environment Setup

fnox.toml - Base configuration

[providers.age] public_keys = ["age1ql3z..."]

[secrets] APP_NAME = "myapp"

fnox.development.toml

[secrets] DATABASE_URL = "postgresql://localhost/myapp_dev" DEBUG = "true"

fnox.production.toml

[providers.aws-sm] type = "aws-sm" region = "us-east-1"

[secrets] DATABASE_URL = { provider = "aws-sm", value = "prod/db-url" } DEBUG = "false"

Feature Flags

[secrets] FEATURE_NEW_DASHBOARD = { default = "false" } FEATURE_BETA_API = { default = "false" } FEATURE_ROLLOUT_PERCENTAGE = { default = "0" }

Service Configuration

[secrets]

Database

DATABASE_HOST = { provider = "age", value = "age[...]" } DATABASE_PORT = { default = "5432" } DATABASE_NAME = { default = "myapp" } DATABASE_USER = { provider = "age", value = "age[...]" } DATABASE_PASSWORD = { provider = "age", value = "age[...]" }

Redis

REDIS_HOST = { provider = "age", value = "age[...]" } REDIS_PORT = { default = "6379" } REDIS_PASSWORD = { provider = "age", value = "age[...]" }

Anti-Patterns

Don't Commit Private Keys

Bad: Private key in committed config

[providers.age] identity = "AGE-SECRET-KEY-..." # NEVER DO THIS

Good: Reference gitignored location

[providers.age] identity = "~/.config/fnox/keys/identity.txt"

Don't Use Plain Text for Sensitive Data

Bad: Sensitive data in plain text

[secrets] DATABASE_PASSWORD = "super-secret-password" # Committed to git!

Good: Encrypted

[secrets] DATABASE_PASSWORD = { provider = "age", value = "age[...]" }

Don't Duplicate Secrets

Bad: Same secret defined multiple times

[secrets] API_KEY = { provider = "age", value = "age[...]" } STRIPE_KEY = { provider = "age", value = "age[...]" } # Same as API_KEY

Good: Use one secret, reference from code

[secrets] STRIPE_API_KEY = { provider = "age", value = "age[...]" }

Don't Mix Concerns

Bad: Secrets mixed with non-secret config

[secrets] DATABASE_PASSWORD = { provider = "age", value = "age[...]" } APP_NAME = "myapp" # Not a secret! LOG_LEVEL = "info" # Not a secret!

Good: Only secrets in fnox.toml

[secrets] DATABASE_PASSWORD = { provider = "age", value = "age[...]" }

Use separate config file for non-secrets

app.config.toml

APP_NAME = "myapp" LOG_LEVEL = "info"

Advanced Patterns

Template Values

[secrets] DATABASE_HOST = { provider = "age", value = "age[...]" } DATABASE_NAME = { default = "myapp" } DATABASE_USER = { provider = "age", value = "age[...]" } DATABASE_PASSWORD = { provider = "age", value = "age[...]" }

Constructed in application code from components above

DATABASE_URL = postgresql://{USER}:{PASSWORD}@{HOST}/{NAME}

Conditional Secrets

[secrets]

Base secrets always loaded

API_KEY = { provider = "age", value = "age[...]" }

[profiles.ci] [profiles.ci.secrets]

Additional secrets only for CI

CI_TOKEN = { provider = "age", value = "age[...]" } DEPLOY_KEY = { provider = "age", value = "age[...]" }

Related Skills

  • providers: Configuring encryption and secret storage providers

  • security-best-practices: Security guidelines for secrets management

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review
General

atomic-design-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review