Configuration Reference

⚠️ Documentation Under Review: This documentation is currently being updated and verified against the actual implementation. Some information may be incorrect or incomplete. Please verify all code examples against the actual source code before use.

Overview

The Neuron CMS uses YAML configuration files located in the config/ directory. Configuration is managed through the SettingManager component and can be accessed at runtime.

Configuration Files

The CMS uses a hierarchical configuration structure supporting environment-specific overrides and encrypted secrets:

Base Configuration

Environment-Specific Configuration

Encrypted Secrets

Note: The neuron.yaml file is created during installation via php neuron cms:install from the template at vendor/neuron-php/cms/resources/config/neuron.yaml.example.

neuron.yaml

Primary application configuration file containing system, logging, caching, views, site, theme, database, and email settings.

System Configuration

Controls system-level behavior and paths.

system:
  timezone: UTC                    # PHP timezone identifier
  base_path: resources             # Base path for resources (relative or absolute)
  routes_path: resources/config    # Path to route configuration files

Options:

Routing Configuration

Defines controller paths for autoloading.

routing:
  controller_paths:
    - path: 'vendor/neuron-php/cms/src/Cms/Controllers'
      namespace: 'Neuron\Cms\Controllers'

Options:

Logging Configuration

Controls application logging behavior.

logging:
  destination: \Neuron\Log\Destination\File    # Log destination class
  format: \Neuron\Log\Format\PlainText         # Log format class
  file: storage/logs/app.log                   # Log file path
  level: info                                  # Minimum log level

Available Destinations:

Available Formats:

Options:

Cache Configuration

Controls view and content caching.

cache:
  enabled: false                # Enable caching
  storage: file                 # Storage driver
  path: storage/cache/views     # Cache directory
  ttl: 3600                     # Time-to-live in seconds
  html: true                    # Cache HTML output
  markdown: true                # Cache markdown rendering
  json: false                   # Cache JSON output
  xml: false                    # Cache XML output

Options:

Views Configuration

Controls view template location.

views:
  path: resources/views    # Path to view templates

Options:

Site Configuration

Site metadata and branding.

site:
  name: 'Neuron CMS'                                        # Site name
  url: 'https://localhost'                                  # Base URL
  description: 'A modern content management system built with Neuron.'
  title: 'Neuron CMS'                                       # Default page title

Options:

Theme Configuration

Bootswatch theme selection for different user roles.

theme:
  admin: vapor          # Admin portal theme (for admin role users)
  subscriber: sandstone # Member portal theme (for subscriber, editor, author roles)
  guest: sandstone      # Guest theme (for public website and login/registration)

Available Themes:

cerulean, cosmo, cyborg, darkly, flatly, journal, litera, lumen, lux, materia, minty, morph, pulse, quartz, sandstone, simplex, sketchy, slate, solar, spacelab, superhero, united, vapor, yeti, zephyr

View themes at bootswatch.com

Database Configuration

Database connection settings supporting SQLite, MySQL, and PostgreSQL.

# SQLite
database:
  adapter: sqlite
  name: storage/database.sqlite3

# MySQL/MariaDB
database:
  adapter: mysql
  host: localhost
  port: 3306
  name: cms_database
  user: cms_user
  pass: secure_password
  charset: utf8mb4

# PostgreSQL
database:
  adapter: pgsql
  host: localhost
  port: 5432
  name: cms_database
  user: cms_user
  pass: secure_password

# URL Format (Alternative)
database:
  url: mysql://user:pass@localhost:3306/dbname?charset=utf8mb4
  # or
  url: postgresql://user:pass@localhost:5432/dbname
  # or
  url: sqlite:///storage/database.sqlite3

Options:

Migration Configuration

Database migration and schema export settings.

migrations:
  path: db/migrate                 # Migration files directory
  seeds_path: db/seed              # Seed files directory
  table: phinx_log                 # Migration tracking table
  schema_file: db/schema.yaml      # Schema export file path
  auto_dump_schema: false          # Auto-export schema after migrations

Options:

Email Configuration

Email delivery configuration using PHPMailer.

email:
  driver: smtp                      # Transport driver
  host: smtp.gmail.com              # SMTP server hostname
  port: 587                         # SMTP server port
  username: [email protected]    # SMTP username
  password: your-app-password       # SMTP password
  encryption: tls                   # Encryption method
  from_address: [email protected] # Default from address
  from_name: My Website             # Default from name
  test_mode: false                  # Log emails instead of sending

Driver Options: smtp, sendmail, mail

SMTP Options:

Common Options:

Cloudinary Configuration

Cloud-based image management service (optional).

cloudinary:
  cloud_name: your-cloud-name
  api_key: your-api-key
  api_secret: your-api-secret
  folder: neuron-cms/images
  max_file_size: 5242880
  allowed_formats: [jpg, jpeg, png, gif, webp]

If not configured, image uploads will be disabled in the admin interface.

Maintenance Mode Configuration

System maintenance mode settings.

maintenance:
  default_message: 'Site is currently under maintenance. Please check back soon.'
  allowed_ips: ['127.0.0.1', '::1']
  retry_after: 3600
  custom_view: null
  show_countdown: false

Note: Maintenance mode is managed via CLI commands (cms:maintenance:enable/disable) rather than configuration.

auth.yaml

Authentication and member registration configuration.

Authentication Settings

auth:
  default: session    # Default authentication driver

  session:
    lifetime: 120                # Session lifetime in minutes
    expire_on_close: false       # Expire session when browser closes
    cookie_name: neuron_session  # Session cookie name
    cookie_httponly: true        # Prevent JavaScript access to cookie
    cookie_secure: true          # Require HTTPS
    cookie_samesite: Lax         # CSRF protection

  remember:
    enabled: true     # Enable "remember me" functionality
    lifetime: 43200   # Remember token lifetime in minutes (30 days)

  passwords:
    min_length: 8                 # Minimum password length
    require_uppercase: true       # Require uppercase letter
    require_lowercase: true       # Require lowercase letter
    require_numbers: true         # Require number
    require_special_chars: false  # Require special character
    hash_algorithm: argon2id      # Password hash algorithm

  throttle:
    enabled: true        # Enable brute force protection
    max_attempts: 5      # Maximum failed login attempts
    lockout_duration: 15 # Account lockout duration in minutes

  storage:
    type: file              # User storage type
    path: storage/users     # Storage path (not actively used)

Member Registration Settings

member:
  registration_enabled: true           # Enable public registration
  require_email_verification: true     # Require email verification
  default_role: subscriber             # Default role for new members
  verification_token_expiration_minutes: 60
  verification_url: /verify-email
  resend_throttle_seconds: 60

Note: Member settings are in auth.yaml, not neuron.yaml.

routes.yaml

HTTP route definitions (typically in resources/config/routes.yaml).

home:
  method: GET
  route: /
  controller: Neuron\Cms\Controllers\Home@index

admin_dashboard:
  method: GET
  route: /admin/dashboard
  controller: Neuron\Cms\Controllers\Admin\Dashboard@index
  filter: auth

Route Structure:

event-listeners.yaml

Event system configuration (typically in resources/config/event-listeners.yaml).

events:
  user.created:
    class: 'Neuron\Cms\Events\UserCreatedEvent'
    listeners:
      - 'Neuron\Cms\Listeners\SendWelcomeEmailListener'
      - 'Neuron\Cms\Listeners\LogUserActivityListener'

Structure:

Runtime Configuration Access

Using SettingManager

use Neuron\Patterns\Registry;

// Get SettingManager from Registry
$settings = Registry::getInstance()->get( 'Settings' );

// Get single value
$timezone = $settings->get( 'system', 'timezone' );
$dbAdapter = $settings->get( 'database', 'adapter' );
$sessionLifetime = $settings->get( 'auth.session', 'lifetime' );

// Get entire section
$dbConfig = $settings->getSection( 'database' );
$authConfig = $settings->getSection( 'auth' );
$memberConfig = $settings->getSection( 'member' );

// Check if setting exists
if( $settings->has( 'email', 'test_mode' ) )
{
    $testMode = $settings->get( 'email', 'test_mode' );
}

Available Sections

From neuron.yaml:

From auth.yaml:

Environment-Specific Configuration

The CMS automatically loads environment-specific configuration based on the APP_ENV environment variable.

Directory Structure

config/
├── neuron.yaml                          # Base configuration
├── routing.yaml                         # URL rewrites and controller paths
├── auth.yaml                            # Authentication settings
├── event-listeners.yaml                 # Event system configuration
├── services.yaml                        # DI container services
├── master.key                           # Base secrets key (gitignored)
├── secrets.yml.enc                      # Base secrets (committed)
└── environments/
    ├── local.yaml                       # Local development config
    ├── local.key                        # Local secrets key (gitignored)
    ├── local.secrets.yml.enc            # Local secrets (committed)
    ├── testing.yaml                     # Testing environment config
    ├── testing.key                      # Testing secrets key (gitignored)
    ├── testing.secrets.yml.enc          # Testing secrets (committed)
    ├── production.yaml                  # Production config overrides
    ├── production.key                   # Production secrets key (gitignored)
    └── production.secrets.yml.enc       # Production secrets (committed)

Setting the Environment

Set the APP_ENV environment variable to determine which configuration is loaded:

Apache (.htaccess or VirtualHost):

SetEnv APP_ENV local

Docker Compose:

environment:
  APP_ENV: production

Command Line:

export APP_ENV=local
php index.php

Railway/Cloud Platform: Set APP_ENV=production in your platform's environment variables.

Configuration Loading Priority

Configuration is loaded in the following order (later sources override earlier ones):

  1. config/neuron.yaml - Base application configuration
  2. config/environments/{env}.yaml - Environment-specific overrides (e.g., local.yaml)
  3. config/secrets.yml.enc - Encrypted base secrets (shared across environments)
  4. config/environments/{env}.secrets.yml.enc - Encrypted environment-specific secrets
  5. Environment variables - Highest priority (e.g., DATABASE_URL, NEURON_MASTER_KEY)

Example: If APP_ENV=local, the system loads:

  1. neuron.yaml
  2. environments/local.yaml (overrides neuron.yaml values)
  3. secrets.yml.enc (if exists)
  4. environments/local.secrets.yml.enc (if exists, overrides secrets.yml.enc)
  5. Environment variables (override everything)

Example Environment Override

config/neuron.yaml (base):

logging:
  level: error
  file: storage/logs/app.log

cache:
  enabled: true

config/environments/local.yaml (development override):

logging:
  level: debug  # Override: more verbose logging in development

cache:
  enabled: false  # Override: disable caching for faster iteration

The local environment automatically gets debug logging and caching disabled, while production uses the base configuration.

Secrets Management

The CMS provides a Rails-inspired encrypted secrets system for storing sensitive configuration data (API keys, passwords, tokens) securely in version control.

Why Use Encrypted Secrets?

Benefits:

What Should Go in Secrets:

What Should Stay in Plain Config:

Base Secrets vs Environment-Specific Secrets

Base Secrets (config/secrets.yml.enc):

Environment-Specific Secrets (config/environments/{env}.secrets.yml.enc):

Priority: Environment-specific secrets override base secrets, which override plain configuration files.

Encryption Keys

master.key (config/master.key):

Environment Keys (config/environments/{env}.key):

Production Deployment: For production, store the encryption key as an environment variable instead of a file:

# Railway, Heroku, etc.
NEURON_MASTER_KEY=your-64-character-hex-key

# Or environment-specific
NEURON_PRODUCTION_KEY=your-64-character-hex-key

Managing Secrets via CLI

Generate Encryption Key

Create a new encryption key (32 bytes, 64 hex characters):

# Generate base master key
php neuron secrets:key:generate

# Generate environment-specific key
php neuron secrets:key:generate --env=production
php neuron secrets:key:generate --env=local

# Show the generated key (for copying to environment variables)
php neuron secrets:key:generate --show

# Force overwrite existing key
php neuron secrets:key:generate --force

Edit Secrets

Edit encrypted secrets in your default editor (set via EDITOR environment variable or defaults to vi):

# Edit base secrets
php neuron secrets:edit

# Edit environment-specific secrets
php neuron secrets:edit --env=production
php neuron secrets:edit --env=local

# Use specific editor
php neuron secrets:edit --editor=nano
php neuron secrets:edit --editor=code --wait  # VS Code

Editor Opens Decrypted YAML:

# config/secrets.yml (decrypted temporarily)
database:
  password: my_secure_password

stripe:
  api_key: sk_test_123456789
  webhook_secret: whsec_abcdefghij

smtp:
  username: [email protected]
  password: smtp_password_here

When you save and close the editor, the file is automatically encrypted and saved to .secrets.yml.enc.

View Secrets

Display decrypted secrets without editing:

# Show all base secrets
php neuron secrets:show

# Show environment-specific secrets
php neuron secrets:show --env=production

# Show a specific key
php neuron secrets:show --key=database.password
php neuron secrets:show --env=production --key=stripe.api_key

# Skip confirmation for production (dangerous!)
php neuron secrets:show --env=production --force

Security Note: The secrets:show command requires confirmation before displaying production secrets to prevent accidental exposure.

Accessing Secrets in Code

Secrets are automatically loaded into the SettingManager during bootstrap. Access them like any other configuration:

use Neuron\Patterns\Registry;

$settings = Registry::getInstance()->get( 'Settings' );

// Access secrets using dot notation
$dbPassword = $settings->get( 'database', 'password' );
$stripeKey = $settings->get( 'stripe', 'api_key' );
$smtpPassword = $settings->get( 'smtp', 'password' );

// Check if secret exists
if( $settings->has( 'stripe', 'webhook_secret' ) )
{
    $webhookSecret = $settings->get( 'stripe', 'webhook_secret' );
}

Best Practices

Security:

  1. Never commit .key files - Always add to .gitignore
  2. Rotate keys periodically - Especially after team member changes
  3. Use environment-specific secrets - Don't share production keys across environments
  4. Store production keys externally - Use NEURON_MASTER_KEY environment variable
  5. Limit access to production keys - Only CI/CD and senior team members
  6. Be careful with secrets:show - Production secrets should require confirmation

Organization:

  1. Group related secrets - Use YAML sections (database, smtp, apis)
  2. Use descriptive keys - stripe.api_key not stripe_key
  3. Document secret requirements - Comment what each secret is for
  4. Don't duplicate - Use base secrets for shared values, override only when needed

Development Workflow:

  1. Generate keys first - Run secrets:key:generate before secrets:edit
  2. Edit locally - Use secrets:edit --env=local for development
  3. Share encrypted files - Commit .secrets.yml.enc but not .key files
  4. Distribute keys securely - Share keys via password manager, not email/Slack
  5. Test encryption - Verify secrets decrypt correctly after editing

Example .gitignore:

# Encryption keys (NEVER commit these)
config/master.key
config/environments/*.key

# Keep encrypted secrets (safe to commit)
!config/secrets.yml.enc
!config/environments/*.secrets.yml.enc

Troubleshooting

"Encryption key not found" error:

"Invalid encryption key" error:

Secrets not loading in application:

Editor doesn't open:

Configuration Best Practices

Security

  1. Never commit credentials - Use environment variables for passwords
  2. Use HTTPS in production - Set cookie_secure: true
  3. Enable CSRF protection - Use csrf filter on state-changing routes
  4. Strong passwords - Require all character types and minimum length
  5. Enable throttling - Prevent brute force attacks

Performance

  1. Enable caching in production - Set cache.enabled: true
  2. Use appropriate log level - error in production, debug in development
  3. Configure session lifetime - Balance security vs user experience

Development

  1. Use test mode for email - Set test_mode: true to log emails
  2. Disable cache - Set cache.enabled: false for faster iteration
  3. Enable debug logging - Set level: debug for detailed logs
  4. Use SQLite locally - Simpler than MySQL/PostgreSQL

Troubleshooting

Configuration Not Loading

Check:

  1. Files are in config/ directory
  2. YAML syntax is valid
  3. File permissions are readable
  4. SettingManager is initialized

Database Connection Fails

Check:

  1. database: section exists in neuron.yaml
  2. Credentials are correct
  3. Database server is accessible
  4. Adapter name is correct (sqlite, mysql, pgsql)

Session Not Persisting

Check:

  1. Set cookie_secure: false for HTTP development
  2. Session directory is writable
  3. Use cookie_samesite: Lax for compatibility
  4. HTTPS matches cookie_secure setting

Email Not Sending

Check:

  1. test_mode: false in production
  2. SMTP credentials are correct
  3. Port matches encryption (587 for TLS, 465 for SSL)
  4. Firewall allows outbound SMTP

Additional Resources