O Vagrant permite o provisionamento de novas instâncias de convidado usando Shell, mas o script é sempre executado no root
contexto. Executar como root
é ótimo para configuração global sem ter que lidar com isso sudo
. Mas, o que você faz se também precisar configurar automaticamente o usuário de login do Vagrant durante o provisionamento? Isso não é tão simples quanto pode parecer.
O esqueleto de um projeto típico para mim se parece com:
.
├── Vagrantfile
└── vagrant
├── provision.sh
└── user-config.sh
O vagrant
diretório não é obrigatório, mas é uma convenção que adaptei para organizar todos os arquivos que estarei usando para o Vagrant, mas não estão relacionados à lógica do aplicativo. Mais importante ainda, existem dois arquivos presentes. A provision.sh
é o arquivo que contém toda a minha configuração global do sistema. O user-config.sh
mantém a configuração específica para o usuário vagrant de login.
Minha Vagrantfile
vontade, no mínimo, ser configurada para usar o provisionador Shell e começar com vagrant/provision.sh
:
Vagrant.configure('2') do |config|
# -- snipped --
config.vm.provision :shell do |s|
s.path = 'vagrant/provision.sh'
end
config.vm.synced_folder '.', '/home/vagrant/myapp'
# -- snipped --
end
O é responsável por todas as minhas ações de contexto, como instalação de bibliotecas ou serviços como Postgres, Redis, etc. Isso é bastante típico de configuração de um novo sistema. O que será diferente, porém, é que também invocará o como o usuário para definir a configuração personalizada para tudo o que estarei fazendo. Normalmente, eu uso o para instalar RVM, instalar meu Ruby, Bundling Rubygems e, em seguida, executar as tarefas Rails e Rake para configurar meu aplicativo.provision.sh
root
provision.sh
user-config.sh
vagrant
user-config.sh
Um exemplo de sistema mínimo para um convidado Ubuntu é parecido com:provision.sh
#!/bin/bash -x
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get -y install git
# install stuff, configure env, etc
su -c "source /home/vagrant/myapp/vagrant/user-config.sh" vagrant
Observe no final que o script contém um comando para executar o como o usuário.provision.sh
su
user-config.sh
vagrant
#!/bin/bash -x
echo "export EDITOR=vim" >> $HOME/.bashrc
# RVM
echo "rvm_install_on_use_flag=1" >> $HOME/.rvmrc
echo "rvm_project_rvmrc=1" >> $HOME/.rvmrc
echo "rvm_trust_rvmrcs_flag=1" >> $HOME/.rvmrc
curl -L https://get.rvm.io | bash -s stable --autolibs=4
source "$HOME/.rvm/scripts/rvm"
[[ -s "$rvm_path/hooks/after_cd_bundle" ]] && chmod +x $rvm_path/hooks/after_cd_bundle
rvm autolibs enable
rvm requirements
rvm reload
_RUBY_VERSION="ruby-1.9.3"
rvm install $_RUBY_VERSION
rvm gemset create myapp
rvm use $_RUBY_VERSION --default
rvm use $_RUBY_VERSION@myapp
cd ~/myapp
gem update --system && gem update bundler
bundle config --global jobs 3
bundle install
bundle exec rake db:setup
bundle exec rake db:test:prepare
Isso pode conter tudo o que você precisa para seu aplicativo. Este é apenas um exemplo do que estou usando para um aplicativo no qual estou trabalhando no momento.
Uma ressalva é que o provisionador Shell tentará executar sempre que você vagrant up
. Você precisará alterar a forma como inicializa o Vagrant se quiser pular a etapa de provisionamento.
vagrant up --no-provision