CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sails

API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration

Sails.js provides a unified configuration system that merges settings from multiple sources, enabling flexible environment-specific configuration with runtime access and validation. The configuration system supports .sailsrc files, environment variables, command-line arguments, and programmatic overrides.

Configuration Access

getRc()

Load configuration from .sailsrc files, environment variables, and command-line arguments:

sails.getRc(namespace?: String): Dictionary

Parameters:

  • namespace (String, optional) - Configuration namespace (default: 'sails')

Returns: Dictionary - Merged configuration object from all sources

Configuration Sources (in precedence order):

  1. Command-line arguments (parsed with minimist)
  2. Environment variables with namespace prefix
  3. Local .sailsrc files (current directory and upward)
  4. Global .sailsrc files (home directory)
  5. Default configuration values

Example:

// Get default Sails configuration
const config = sails.getRc();
console.log('Port:', config.port);
console.log('Environment:', config.environment);
console.log('Log level:', config.log?.level);

// Get custom namespace configuration
const appConfig = sails.getRc('myapp');
console.log('Custom config:', appConfig);

// Programmatic configuration access
console.log('Database URL:', sails.getRc().datastores?.default?.url);

Runtime Configuration Access

sails.config  // Dictionary - Complete merged configuration

Example:

// Access configuration at runtime
console.log('Current port:', sails.config.port);
console.log('Environment:', sails.config.environment);
console.log('Database config:', sails.config.datastores);

// Check feature flags
if (sails.config.myapp?.featureFlags?.newUI) {
  console.log('New UI enabled');
}

// Access hook configurations
console.log('Blueprint settings:', sails.config.blueprints);
console.log('Security settings:', sails.config.security);

Configuration Sources

Environment Variables

Environment variables with the SAILS_ prefix are automatically parsed using rttc.parseHuman:

# Basic configuration
export SAILS_PORT=3000
export SAILS_ENVIRONMENT=production

# Nested configuration (use double underscores for nesting)
export SAILS_LOG__LEVEL=verbose
export SAILS_MODELS__MIGRATE=drop  
export SAILS_DATASTORES__DEFAULT__URL=mysql://user:pass@host:3306/db

# Array configuration  
export SAILS_CORS__ALLOW_ORIGINS='["https://app.com", "https://admin.com"]'

# Boolean configuration
export SAILS_BLUEPRINTS__REST=true
export SAILS_SECURITY__CSRF=false

Environment Variable Parsing Examples:

// SAILS_PORT=3000 → config.port = 3000 (number)
// SAILS_LOG__LEVEL=verbose → config.log.level = 'verbose' (string)
// SAILS_MODELS__MIGRATE=drop → config.models.migrate = 'drop'
// SAILS_CORS__ALLOW_ORIGINS='["https://app.com"]' → config.cors.allowOrigins = ['https://app.com']
// SAILS_BLUEPRINTS__REST=true → config.blueprints.rest = true (boolean)

.sailsrc Files

JSON configuration files loaded automatically:

Local .sailsrc (project directory):

{
  "port": 1337,
  "environment": "development",
  "log": {
    "level": "verbose"
  },
  "models": {
    "migrate": "alter"  
  },
  "datastores": {
    "default": {
      "adapter": "sails-mysql",
      "host": "localhost",
      "port": 3306,
      "user": "root",
      "database": "myapp_dev"
    }
  }
}

Global .sailsrc (home directory):

{
  "generators": {
    "modules": {}
  },
  "commands": {
    "generate": {
      "templatesDirectory": "~/.sails-templates"
    }
  }
}

Command-Line Arguments

Configuration via command-line arguments using minimist:

# Basic arguments
sails lift --port=4000 --environment=staging

# Nested arguments
sails lift --log.level=silly --models.migrate=safe

# Boolean flags
sails lift --prod --verbose

# Array arguments
sails lift --cors.allowOrigins=https://app.com,https://admin.com

Argument Parsing:

// --port=4000 → config.port = 4000
// --log.level=silly → config.log.level = 'silly'
// --prod → config.environment = 'production'
// --verbose → config.log.level = 'verbose'

Configuration Files

Sails applications use configuration files in the config/ directory:

Core Configuration Files

config/env/development.js:

module.exports = {
  port: 1337,
  
  models: {
    migrate: 'alter'
  },
  
  datastores: {
    default: {
      adapter: 'sails-mysql',
      host: 'localhost',
      user: 'root',
      password: '',
      database: 'myapp_dev'
    }
  },
  
  log: {
    level: 'verbose'
  }
};

config/env/production.js:

module.exports = {
  port: process.env.PORT || 80,
  
  models: {
    migrate: 'safe'
  },
  
  datastores: {
    default: {
      adapter: 'sails-mysql',
      url: process.env.DATABASE_URL
    }
  },
  
  log: {
    level: 'error'
  },
  
  security: {
    cors: {
      allowOrigins: process.env.ALLOWED_ORIGINS?.split(',') || []
    }
  },
  
  session: {
    secret: process.env.SESSION_SECRET,
    cookie: {
      secure: true,
      maxAge: 24 * 60 * 60 * 1000 // 24 hours
    }
  }
};

Feature-Specific Configuration

config/datastores.js:

module.exports.datastores = {
  default: {
    adapter: 'sails-mysql',
    host: 'localhost',
    port: 3306,
    user: 'myapp',
    password: 'secret',
    database: 'myapp'
  },
  
  redis: {
    adapter: 'sails-redis',
    host: 'localhost', 
    port: 6379,
    db: 0
  },
  
  mongodb: {
    adapter: 'sails-mongo',
    url: 'mongodb://localhost:27017/myapp'
  }
};

config/routes.js:

module.exports.routes = {
  // Static routes
  'GET /': 'PageController.home',
  'GET /about': { view: 'pages/about' },
  
  // API routes
  'POST /api/login': 'AuthController.login',
  'DELETE /api/logout': 'AuthController.logout',
  
  // RESTful routes
  'GET /api/users': 'UserController.find',
  'POST /api/users': 'UserController.create',
  'GET /api/users/:id': 'UserController.findOne',
  'PUT /api/users/:id': 'UserController.update',
  'DELETE /api/users/:id': 'UserController.destroy',
  
  // Catch-all route
  '/*': { view: '404', skipAssets: true }
};

config/models.js:

module.exports.models = {
  // Default datastore
  datastore: 'default',
  
  // Migration strategy  
  migrate: 'alter', // 'alter', 'drop', or 'safe'
  
  // Model settings
  attributes: {
    id: { type: 'string', columnName: 'id' },
    createdAt: { type: 'number', autoCreatedAt: true },
    updatedAt: { type: 'number', autoUpdatedAt: true }
  },
  
  // Validation
  schema: true
};

Hook Configuration

HTTP Hook Configuration

config/http.js:

module.exports.http = {
  port: process.env.PORT || 1337,
  
  middleware: {
    order: [
      'cookieParser',
      'session', 
      'bodyParser',
      'compress',
      'methodOverride',
      'router',
      'www',
      'favicon'
    ],
    
    // Custom middleware
    requestLogger: (req, res, next) => {
      console.log(`${req.method} ${req.url}`);
      next();
    },
    
    // Built-in middleware configuration
    bodyParser: {
      urlencoded: { extended: true },
      json: { limit: '10mb' }
    }
  },
  
  // SSL configuration  
  ssl: {
    key: require('fs').readFileSync('./ssl/private-key.pem'),
    cert: require('fs').readFileSync('./ssl/certificate.pem')
  },
  
  // Trust proxy
  trustProxy: true,
  
  // Static file caching
  cache: 365.25 * 24 * 60 * 60 * 1000 // 1 year
};

Security Configuration

config/security.js:

module.exports.security = {
  cors: {
    allRoutes: true,
    allowOrigins: [
      'http://localhost:3000',
      'https://myapp.com',
      'https://admin.myapp.com'
    ],
    allowCredentials: false,
    allowRequestMethods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    allowRequestHeaders: 'content-type,authorization'
  },
  
  csrf: {
    grantTokenViaAjax: true,
    origin: 'https://myapp.com',
    routesDisabled: ['/api/webhook/*']
  }
};

Blueprints Configuration

config/blueprints.js:

module.exports.blueprints = {
  // Action routes (e.g. GET /user/find)
  actions: false,
  
  // RESTful routes (e.g. GET /user, POST /user)  
  rest: true,
  
  // Shortcut routes (e.g. GET /user/create?name=John)
  shortcuts: true,
  
  // Route prefix
  prefix: '/api/v1',
  
  // Pluralize model names in URLs
  pluralize: true,
  
  // Auto-subscribe to model changes
  autoWatch: true,
  
  // Default limit for find operations
  defaultLimit: 30
};

Custom Configuration

Application-Specific Configuration

config/custom.js:

module.exports.custom = {
  // API keys
  stripeSecretKey: process.env.STRIPE_SECRET_KEY,
  sendgridApiKey: process.env.SENDGRID_API_KEY,
  
  // Feature flags
  featureFlags: {
    newUserInterface: process.env.NEW_UI === 'true',
    betaFeatures: false,
    maintenanceMode: false
  },
  
  // Business logic configuration
  pagination: {
    defaultLimit: 25,
    maxLimit: 100
  },
  
  // File upload settings
  uploads: {
    maxBytes: 10 * 1024 * 1024, // 10MB
    allowedTypes: ['image/jpeg', 'image/png', 'image/gif'],
    uploadPath: './assets/uploads'
  },
  
  // Email settings
  email: {
    from: 'noreply@myapp.com',
    templates: {
      welcome: 'email-welcome',
      passwordReset: 'email-password-reset'
    }
  }
};

Environment-Specific Overrides

config/env/staging.js:

module.exports = {
  // Inherit from production but override specific settings
  
  log: {
    level: 'verbose' // More verbose logging for staging
  },
  
  models: {
    migrate: 'alter' // Allow schema changes in staging
  },
  
  custom: {
    featureFlags: {
      betaFeatures: true // Enable beta features in staging
    }
  }
};

Configuration Validation

Runtime Validation

// Validate required configuration at startup
module.exports = {
  // config/bootstrap.js
  fn: async function() {
    // Check required environment variables
    const required = ['DATABASE_URL', 'SESSION_SECRET', 'STRIPE_SECRET_KEY'];
    const missing = required.filter(key => !process.env[key]);
    
    if (missing.length > 0) {
      throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
    }
    
    // Validate configuration values
    if (sails.config.custom.pagination.maxLimit > 1000) {
      throw new Error('Maximum pagination limit cannot exceed 1000');
    }
  }
};

Configuration Schema

// Define configuration schema for validation
const configSchema = {
  port: { type: 'number', min: 1, max: 65535 },
  environment: { type: 'string', isIn: ['development', 'staging', 'production'] },
  log: {
    type: 'dictionary',
    properties: {
      level: { type: 'string', isIn: ['silly', 'verbose', 'info', 'warn', 'error', 'silent'] }
    }
  }
};

// Validate configuration
const rttc = require('rttc');
try {
  rttc.validate(configSchema, sails.config);
  console.log('Configuration is valid');
} catch (err) {
  console.error('Configuration validation failed:', err);
}

Configuration Best Practices

Development Configuration

// Use local environment for development
module.exports = {
  port: 1337,
  environment: 'development',
  
  // Detailed logging
  log: { level: 'verbose' },
  
  // Schema migration
  models: { migrate: 'alter' },
  
  // Local database
  datastores: {
    default: {
      adapter: 'sails-disk' // File-based for development
    }
  },
  
  // Development-friendly settings
  blueprints: {
    shortcuts: true,
    rest: true
  }
};

Production Configuration

// Secure production configuration
module.exports = {
  port: process.env.PORT || 80,
  environment: 'production',
  
  // Minimal logging
  log: { level: 'error' },
  
  // Safe database migration
  models: { migrate: 'safe' },
  
  // Production database
  datastores: {
    default: {
      adapter: 'sails-mysql',
      url: process.env.DATABASE_URL,
      ssl: true
    }
  },
  
  // Security settings
  security: {
    cors: {
      allowOrigins: process.env.ALLOWED_ORIGINS.split(',')
    }
  },
  
  // Disable development features
  blueprints: {
    shortcuts: false
  }
};

The Sails.js configuration system provides comprehensive flexibility for managing application settings across different environments, with multiple configuration sources, runtime access, and validation capabilities.

Install with Tessl CLI

npx tessl i tessl/npm-sails

docs

actions.md

application-lifecycle.md

cli.md

configuration.md

events.md

hooks.md

index.md

routing.md

tile.json