Development Setup
This guide walks through setting up a local Vulcan development environment.
Prerequisites
Required Software
- Ruby 3.4.9 (use rbenv or rvm for version management)
- Node.js 24 LTS and Yarn package manager
- PostgreSQL 18 database server
- Git version control
Recommended Tools
- VSCode or RubyMine for IDE
- Docker Desktop for containerized development
- Postman or HTTPie for API testing
- pgAdmin or TablePlus for database management
Quick Start
1. Clone Repository
git clone https://github.com/mitre/vulcan.git
cd vulcan2. Install Dependencies
Ruby Dependencies
# Install bundler
gem install bundler
# Install gems
bundle installJavaScript Dependencies
# Install yarn if not present
npm install -g yarn
# Install packages
yarn install3. Database Setup
Option A: Docker PostgreSQL (Recommended)
# Start PostgreSQL container
docker compose -f docker-compose.dev.yml up db -d
# Wait for healthy status
docker compose ps db # should show "healthy"
# Create and migrate development database
bin/rails db:prepare
# Seed development data (optional — creates demo users, projects, SRGs, STIGs)
bin/rails db:seedOption B: Local PostgreSQL
# macOS
brew install postgresql@18
brew services start postgresql@18
# Create and migrate
bin/rails db:prepare
bin/rails db:seedSetting Up Parallel Test Databases
parallel_rspec uses one database per CPU core. Set them up once after initial database creation:
# 1. Create parallel test databases (vulcan_vue_test, vulcan_vue_test2, ..., vulcan_vue_testN)
bundle exec rake parallel:create
# 2. Migrate the primary test database (loads schema_migrations)
bin/rails db:migrate RAILS_ENV=test
# 3. Load schema into all parallel test databases
bundle exec rake parallel:load_schemaAfter schema changes (new migrations), re-sync parallel databases:
bin/rails db:migrate RAILS_ENV=test
bundle exec rake parallel:load_schema4. Start Development Server
# Using Foreman (recommended)
foreman start -f Procfile.dev
# Or manually in separate terminals:
# Terminal 1: Rails server
rails server
# Terminal 2: JavaScript bundler
yarn build:watchVisit http://localhost:3000
Detailed Setup
Ruby Environment
Using rbenv
# Install rbenv
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
# Install ruby-build
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
# Install Ruby
rbenv install 3.4.9
rbenv local 3.4.9Using rvm
# Install RVM
\curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby
rvm install 3.4.9
rvm use 3.4.9
# Create gemset (optional)
rvm gemset create vulcan
rvm use 3.4.9@vulcanDatabase Configuration
PostgreSQL Installation
# macOS
brew install postgresql@18
brew services start postgresql@18
# Ubuntu/Debian
sudo apt-get install postgresql postgresql-contrib
sudo systemctl start postgresql
# Create user and database
createuser -d vulcan_devDatabase Configuration File
The project's config/database.yml supports DB_SUFFIX for worktree isolation:
development:
database: vulcan_vue_development<%= ENV['DB_SUFFIX'] %>
test:
database: vulcan_vue_test<%= ENV['DB_SUFFIX'] %><%= ENV['TEST_ENV_NUMBER'] %>Worktree Database Isolation
When working with multiple git worktrees (e.g., v2.x and v3.x branches), set DB_SUFFIX in each worktree's .env to prevent migration conflicts:
# v2.x worktree
DB_SUFFIX=_v2 # → vulcan_vue_development_v2
# v3.x worktree
DB_SUFFIX=_v3 # → vulcan_vue_development_v3To set up a new worktree database, clone from the existing one:
# Clone the development database for a new worktree
docker exec <postgres-container> psql -U postgres -c \
"CREATE DATABASE vulcan_vue_development_v2 WITH TEMPLATE vulcan_vue_development OWNER postgres;"Environment Variables
Create .env.development:
# Database
DATABASE_URL=postgresql://vulcan_dev:password@localhost/vulcan_development
# Application
SECRET_KEY_BASE=development_secret_key_minimum_30_characters_long
RAILS_ENV=development
# Email (optional)
VULCAN_ENABLE_SMTP=false
VULCAN_CONTACT_EMAIL=dev@localhost # Also used as default SMTP username when SMTP enabled
# Authentication (optional)
VULCAN_ENABLE_USER_REGISTRATION=true
VULCAN_ENABLE_LOCAL_LOGIN=true
VULCAN_SESSION_TIMEOUT=1h # Accepts: 30s, 15m, 1h, or plain numbers
# Development features
RAILS_LOG_LEVEL=debug
VULCAN_WELCOME_TEXT="Development Environment"Authentication Setup
Local Authentication
Enabled by default. Create test users:
# Rails console
rails console
User.create!(
email: 'admin@example.com',
password: 'S3cure!#Pass001',
admin: true,
confirmed_at: Time.now
)
User.create!(
email: 'user@example.com',
password: 'S3cure!#Pass001',
confirmed_at: Time.now
)GitHub OAuth (Development)
Create GitHub OAuth App:
- Go to GitHub Settings > Developer settings > OAuth Apps
- Set callback URL:
http://localhost:3000/users/auth/github/callback
Add to
config/vulcan.ymlunder theproviderskey:
providers:
- { name: 'github',
app_id: 'your_client_id',
app_secret: 'your_client_secret',
args: { scope: 'user:email' } }Development Workflow
Branch Strategy
# Create feature branch
git checkout -b feature/your-feature-name
# Make changes and commit
git add specific_files
git commit -m "feat: Add new feature"
# Push to GitHub
git push origin feature/your-feature-nameCode Style
Ruby Style
# Run RuboCop
bundle exec rubocop
# Auto-fix issues
bundle exec rubocop --autocorrect-allJavaScript Style
# Run ESLint
yarn lint
# Auto-fix issues
yarn lint --fix
# CI mode (fails on warnings)
yarn lint:ciTesting
Run All Tests
# Ruby tests (use parallel_rspec for full suite — 3-4x faster)
bundle exec parallel_rspec spec/
# JavaScript tests
yarn test:unit
# Specific test file
bundle exec rspec spec/models/user_spec.rb
# Specific test line
bundle exec rspec spec/models/user_spec.rb:42Test Coverage
# Generate coverage report
COVERAGE=true bundle exec rspec
# View report
open coverage/index.htmlDatabase Tasks
# Reset database
rails db:reset
# Run specific migration
rails db:migrate VERSION=20240101000000
# Rollback migration
rails db:rollback
# Database console
rails dbconsoleAsset Management
# Compile assets
rails assets:precompile
# Clean assets
rails assets:clean
# Watch for changes
yarn build:watchIDE Configuration
VSCode
Recommended extensions:
- Ruby LSP
- Rails
- ESLint
- Prettier
- GitLens
.vscode/settings.json:
{
"ruby.useBundler": true,
"ruby.rubocop.executePath": "bundle exec rubocop",
"editor.formatOnSave": true,
"editor.tabSize": 2,
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
}RubyMine
- Set Ruby SDK to 3.4.9
- Configure Rails project
- Enable RuboCop inspection
- Set JavaScript version to ES6+
Common Issues
Bundle Install Failures
# Missing native extensions
sudo apt-get install libpq-dev # Linux
brew install postgresql # macOS
# Permission issues
bundle config set --local path 'vendor/bundle'
bundle installDatabase Connection Issues
# Check PostgreSQL is running
pg_isready
# Check connection
psql -U vulcan_dev -d vulcan_development -h localhost
# Reset database
rails db:drop db:create db:migrateAsset Compilation Issues
# Clear cache
rails tmp:clear
yarn cache clean
# Reinstall dependencies
rm -rf node_modules yarn.lock
yarn install
# Rebuild
yarn buildPort Already in Use
# Find process using port 3000
lsof -i :3000
# Kill process
kill -9 <PID>
# Or use different port
rails server -p 3001Docker Development
Database-Only (Recommended for Local Dev)
Use Docker for PostgreSQL while running Rails natively for faster iteration:
# Start PostgreSQL only
docker compose -f docker-compose.dev.yml up db -d
# Verify healthy
docker compose ps db
# Set up databases (dev + parallel test)
bin/rails db:prepare
bundle exec rake parallel:create
bin/rails db:migrate RAILS_ENV=test
bundle exec rake parallel:load_schema
# Run Rails natively
foreman start -f Procfile.devFull Docker Stack (Production-Like Testing)
# Generate secrets
./setup-docker-secrets.sh
# Build and start everything
docker compose up --build
# Database setup runs automatically via docker-entrypoint
# First user becomes admin when VULCAN_FIRST_USER_ADMIN=true (default in Docker)Multi-Project Setup
When running multiple MITRE projects simultaneously, assign unique ports to avoid conflicts. See docs/development/port-registry.md for port assignments.
# Example .env for vulcan-v2.x alongside other projects
DATABASE_PORT=5435
POSTGRES_PORT=5435
PORT=3000
DATABASE_GSSENCMODE=disableDocker Tips
- Use
docker compose -f docker-compose.dev.yml up db -d(database-only) for fastest development cycle - Use
.dockerignorefor faster builds (excludes docs/, downloads/, coverage/) - Production image uses multi-stage build with jemalloc (~596MB)
docker-compose.ymlsupports Caddy or nginx reverse proxy profiles
Performance Optimization
Development Speed
- Bootsnap (enabled by default):
# config/boot.rb
require 'bootsnap/setup'- Parallel Testing:
bundle exec parallel_rspec spec/Database Performance
-- Add indexes for slow queries
CREATE INDEX index_rules_on_project_id ON rules(project_id);
-- Analyze query performance
EXPLAIN ANALYZE SELECT * FROM rules WHERE project_id = 1;Debugging
Rails Console
# Start console
rails console
# With sandbox (rollback on exit)
rails console --sandbox
# Production console (careful!)
RAILS_ENV=production rails consoleDebugging Tools
# Add to Gemfile
group :development do
gem 'pry-rails'
gem 'better_errors'
gem 'binding_of_caller'
gem 'letter_opener'
endDebug in Code
# Using pry
binding.pry
# Rails logger
Rails.logger.debug "Variable value: #{variable}"
# JavaScript console
console.log('Debug output:', variable);Security in Development
Credentials Management
# Edit credentials
EDITOR=nano rails credentials:edit
# Access in code
Rails.application.credentials.secret_keySecurity Scanning
# Ruby security audit
bundle exec bundler-audit check --update
# Brakeman for Rails
bundle exec brakeman
# JavaScript audit
yarn auditUseful Commands
Rails Generators
# Generate model
rails generate model User name:string email:string
# Generate controller
rails generate controller Users index show
# Generate migration
rails generate migration AddAdminToUsers admin:booleanDatabase Seeds
# db/seeds.rb
10.times do |i|
User.create!(
email: "user#{i}@example.com",
password: '1qaz!QAZ1qaz!QAZ'
)
endRails Tasks
# List all tasks
rails -T
# Custom tasks in lib/tasks/
rails vulcan:custom_task