Environment Variables and Secrets in Vagrant
Hardcoding passwords and sensitive values in Vagrantfiles is a security risk — especially if you commit to version control. Vagrant provides several methods to pass secrets and configuration safely into VMs without exposing them in your Vagrantfile.
Methods Overview
| Method | How | Best for |
|---|---|---|
| ENV variables | Read from shell environment | CI/CD, personal dev |
| .env file + vagrant-env plugin | Load from .env file | Team projects (gitignored) |
| Provisioner env: option | Pass to shell provisioner | Script-specific secrets |
| Synced secrets folder | Share secrets/ folder into VM | Certificates, keys, config files |
| HashiCorp Vault | Fetch at runtime from Vault | Enterprise / production-like labs |
Method 1 — Shell Environment Variables
Ruby — ENV Variables in Vagrantfile
# Vagrantfile reads variables from your shell environment
Vagrant.configure("2") do |config|
config.vm.box = "generic/oracle8"
config.vm.provider "virtualbox" do |vb|
vb.memory = ENV["VM_MEMORY"] || "4096"
vb.cpus = (ENV["VM_CPUS"] || "2").to_i
end
config.vm.provision "shell",
env: {
"ROOT_PASS" => ENV["DB_ROOT_PASSWORD"] || "Root@123!",
"ORACLE_PASS" => ENV["ORACLE_PASSWORD"] || "Oracle@123!"
},
inline: <<-SHELL
echo "Setting up DB with password from environment"
mysql -u root -p"$ROOT_PASS" -e "SELECT 1;"
SHELL
end
BASH — Set ENV Before vagrant up
# Set before vagrant up
export DB_ROOT_PASSWORD="MySecurePass@2026!"
export VM_MEMORY="8192"
export VM_CPUS="4"
vagrant up
# Or inline
DB_ROOT_PASSWORD="MySecurePass@2026!" vagrant up
# For Parallels
VAGRANT_DEFAULT_PROVIDER=parallels DB_ROOT_PASSWORD="MySecurePass!" vagrant up
Method 2 — .env File with vagrant-env Plugin
BASH — Create .env File
# Install plugin
vagrant plugin install vagrant-env
# Create .env file in project directory
cat > .env << EOF
DB_ROOT_PASSWORD=MySecurePass@2026!
ORACLE_PASSWORD=Oracle@2026!
VM_MEMORY=8192
VM_CPUS=4
MYSQL_VERSION=8.0
ORACLE_SID=ORCL
EOF
# IMPORTANT — add to .gitignore
echo ".env" >> .gitignore
echo "*.box" >> .gitignore
echo "secrets/" >> .gitignore
Ruby — vagrant-env Usage
# Vagrantfile
Vagrant.configure("2") do |config|
config.env.enable # Load .env file automatically
config.vm.box = "generic/oracle8"
config.vm.provider "virtualbox" do |vb|
vb.memory = ENV["VM_MEMORY"]
vb.cpus = ENV["VM_CPUS"].to_i
end
config.vm.provision "shell",
path: "scripts/install_mysql.sh",
env: {
"ROOT_PASS" => ENV["DB_ROOT_PASSWORD"],
"MYSQL_VERSION" => ENV["MYSQL_VERSION"]
}
end
Method 3 — Secrets Folder (Files and Certificates)
Ruby — Secrets Folder
# Share a local secrets/ folder into the VM
# This folder is gitignored on host but accessible inside VM
Vagrant.configure("2") do |config|
config.vm.box = "generic/oracle8"
# Mount secrets folder read-only inside VM
config.vm.synced_folder "./secrets", "/home/vagrant/secrets",
mount_options: ["ro"]
config.vm.provision "shell", inline: <<-SHELL
# Use files from secrets folder
cp /home/vagrant/secrets/my.cnf /etc/my.cnf.d/custom.cnf
cp /home/vagrant/secrets/ssl/ca-cert.pem /etc/mysql/ssl/
chmod 600 /etc/mysql/ssl/*.pem
SHELL
end
BASH — Create Secrets Folder
# On host — create secrets directory (gitignored)
mkdir -p secrets/ssl
echo "secrets/" >> .gitignore
# Place your sensitive files
cp ~/my-database-config.cnf secrets/my.cnf
cp ~/ssl/ca-cert.pem secrets/ssl/
cp ~/ssl/server-cert.pem secrets/ssl/
cp ~/ssl/server-key.pem secrets/ssl/
# Vagrant up — secrets are mounted into VM
vagrant up
Method 4 — Provisioner env: Option
Ruby — Provisioner env:
Vagrant.configure("2") do |config|
config.vm.box = "generic/oracle8"
# Pass environment variables directly to shell provisioner
config.vm.provision "shell",
path: "scripts/setup_mysql.sh",
env: {
"MYSQL_ROOT_PASSWORD" => "SecurePass@123!",
"MYSQL_DATABASE" => "labdb",
"MYSQL_USER" => "appuser",
"MYSQL_USER_PASSWORD" => "AppPass@123!",
"MYSQL_SERVER_ID" => "1",
"REPLICATION_PASSWORD" => "ReplPass@123!"
}
# Multiple provisioners can have different env sets
config.vm.provision "shell",
path: "scripts/setup_oracle.sh",
env: {
"ORACLE_SID" => "ORCL",
"ORACLE_PASSWORD" => "Oracle@123!",
"ORACLE_BASE" => "/u01/app/oracle"
}
end
Best Practices for Secrets
- Always add .env, secrets/ and *.box to .gitignore
- Never hardcode passwords in Vagrantfile — use ENV variables
- Share a .env.example file with dummy values in git so teammates know what variables are needed
- Use different passwords for lab VMs than production systems
- Rotate secrets regularly even in lab environments
BASH — .env.example Pattern
# Create .env.example (safe to commit — dummy values)
cat > .env.example << EOF
# Copy this file to .env and fill in real values
DB_ROOT_PASSWORD=change_me
ORACLE_PASSWORD=change_me
VM_MEMORY=4096
VM_CPUS=2
MYSQL_VERSION=8.0
ORACLE_SID=ORCL
EOF
# Team setup workflow
cp .env.example .env
# Edit .env with real values
vagrant up
💡 Note: Never commit .env files or secrets folders to git. Use .env.example with placeholder values to document what variables are required without exposing real credentials.