Instalando o Ubuntu em um ambiente chroot jail no Archlinux – parte 2
Continuando o artigo anterior, vou descrever como ficou a versão final de minha instalação Ubuntu dentro do ambiente chroot e mostrar as configurações que haviam ficado pendentes:
- D-Bus
- PulseAudio
Mudanças desde a última versão
Eu estava enfrentando alguns problemas com o debconf/apt-get, então resolvi pegar a instalação de minha máquina virtual e transferir para o ambiente chroot. Para transferir a partição, que estava em um arquivo vdi, reconhecido somente pelo VirtualBox, eu coloquei a ISO de um livecd na VM, e a partir da VM usei o comando (onde o remote.host era meu próprio ip):
dd if=/dev/sda1 | ssh user@remote.host "cat > /remote/file" |
NOTA: Antes de transferir a sua instalação Ubuntu, eu recomendo fortemente que instale todos os pacotes que você irá utilizar antes de transferir a partição. Isso vai lhe poupar bastante trabalho.
Para montar a imagem gerada com o comando anterior você pode usar o comando:
mount -o loop -t ext4 /path/to/chrootbuntu.sda1.ext4.img /srv/chroot/lucid/ |
Você pode alterar o arquivo /etc/rc.d/chrootbuntu para que ele faça a montagem dessa imagem para você. Ele ficaria então assim:
#!/bin/bash | |
. /etc/rc.conf | |
. /etc/rc.d/functions | |
dirs=(/dev /dev/pts /dev/shm /tmp) | |
case $1 in | |
start) | |
stat_busy "Starting Ubuntu chroot" | |
mount -o loop -t ext4 /path/to/chrootbuntu.sda1.ext4.img /srv/chroot/lucid | |
for d in "${dirs[@]}"; do | |
mount -o bind $d /srv/chroot/lucid$d | |
done | |
mount -t proc none /srv/chroot/lucid/proc | |
mount -t sysfs none /srv/chroot/lucid/sys | |
add_daemon chrootbuntu | |
stat_done | |
;; | |
stop) | |
stat_busy "Stopping Ubuntu chroot" | |
for (( i = ${#dirs[@]} - 1; i >= 0; i-- )); do | |
umount "/srv/chroot/lucid${dirs[i]}" | |
done | |
umount /srv/chroot/lucid/{proc,sys} | |
umount /srv/chroot/lucid | |
rm_daemon chrootbuntu | |
stat_done | |
;; | |
restart) | |
$0 stop | |
sleep 1 | |
$0 start | |
;; | |
*) | |
echo "usage: $0 {start|stop|restart}" | |
esac | |
exit 0 |
Nova configuração do ambiente chroot
Um processo interessante é também copiar certos arquivos de configuração que recriem o ambiente Archlinux dentro do ambiente Ubuntu, como arquivos de usuários e grupos. Isso é importante porque em sistemas Linux, um processo qualquer herda as configurações de ambiente do processo-pai, e dessa forma o comando chroot herdará as configurações de ambiente do processo bash, que está rodando dentro do seu Archlinux. Quando iniciar o bash do sistema Ubuntu, ele utilizará os arquivos de configuração que estão inconsistentes com as variáveis de ambiente herdadas. Abaixo um simples teste que mostra sobre sobre o quê eu estou discutindo:
[root@vinipsmaker-desktop ~]# groups | |
root bin daemon sys adm disk wheel log | |
[root@vinipsmaker-desktop ~]# chroot /srv/chroot/lucid/ | |
groups: cannot find name for group ID 19 | |
root@vinipsmaker-desktop:/# groups | |
root daemon bin sys adm disk uucp groups: cannot find name for group ID 19 | |
19 |
Você pode resolver o problema dessa inconsistência copiando arquivos importantes do sistema. Apenas execute os comandos abaixo:
# você também pode usar o comando "ln -f" no lugar de cp | |
cp /etc/passwd* /srv/chroot/lucid/etc | |
cp /etc/group* /srv/chroot/lucid/etc | |
# se você também usa sudo no seu Archlinux | |
# vai lhe poupar o trabalho de configurar o sudo do ambiente chroot | |
cp /etc/sudoers /srv/chroot/lucid/etc | |
# se você quiser o mesmo conjunto de senhas | |
cp /etc/shadow* /srv/chroot/lucid/etc | |
# opcional, somente para resolução de DNS | |
cp /etc/resolv.conf /srv/chroot/lucid/etc | |
cp /etc/localtime /srv/chroot/lucid/etc | |
cp /etc/mtab /srv/chroot/lucid/etc |
Agora que o ambiente chroot está consistente com o ambiente Archlinux instalado, podemos também tornar o comando xhost mais seguro, restringindo os usuários com acesso ao seu servidor X:
xhost +SI:localuser:seu_username | |
xhost +SI:localuser:root |
D-Bus + PulseAudio
Para configurar uma única instância do D-Bus para todo o sistema, use os comandos abaixo antes de iniciar qualquer serviço D-Bus do ambiente chroot (lembrando que você também pode colocá-los no arquivo /etc/rc.d/chrootbuntu):
mount --bind /var/lib/dbus/ /srv/chroot/lucid/var/lib/dbus/ | |
mount --bind /var/run/dbus/ /srv/chroot/lucid/var/run/dbus/ |
Para permitir que aplicativos que façam uso do PulseAudio reproduzam som, utilizaremos as capacidades do PulseAudio de transmitir som através da rede. Para tal, edite o arquivo /etc/pulse/default.pa (tanto no Ubuntu quanto no Archlinux), adicionando/descomentando a linha:
load-module module-native-protocol-tcp |
Essa mudança irá garantir que o seu PulseAudio carregue o módulo tcp durante a inicialização, mas caso ele já esteja rodando, abra o console do pulseaudio (usando o comando pacmd), e use a mesma linha anterior como um comando nesse console.
Agora que o módulo está carregado, precisamos autorizar o usuário do ambiente chroot a acessar o servidor PulseAudio rodando localmente. Para tal, copie o arquivo de cookie que está na sua pasta de usuário (~/.pulse-cookie) para a pasta dos usuários irão usar o PulseAudio dentro do ambiente chroot.
Para finalizar, crie/edite o arquivo /etc/asound.conf do Ubuntu adicionando o conteúdo a seguir:
pcm.pulse { | |
type pulse | |
} | |
ctl.pulse { | |
type pulse | |
} | |
pcm.!default { | |
type pulse | |
} | |
ctl.!default { | |
type pulse | |
} |
Isso irá garantir que aplicações que façam uso diretamente do ALSA utilizem o PulseAudio.
Script facilitador
Um script que você pode colocar na sua pasta de usuário para automatizar a tarefa de configuração do X11 + PulseAudio é:
USER=$(whoami) | |
COOKIE=${HOME}/.pulse-cookie | |
xhost +SI:localuser:${USER} | |
xhost +SI:localuser:root | |
cp ${COOKIE} /srv/chroot/lucid/home/${USER} | |
sudo cp ${COOKIE} /srv/chroot/lucid/root | |
#sudo chroot /srv/chroot/lucid/ su ${USER} |
É isso.
EDIT:
Alguns programas (como o ROS, discutido na parte anterior do artigo), não irão funcionar corretamente se você configurou hostnames diferentes para a sua instalação Archlinux e sua instalação Ubuntu. Caso você tenha feito isso, não se desespere, basta editar o arquivo /etc/hosts e tudo vai funcionar normalmente.
EDIT2:
Alterei a linha:
umount /path/to/remote/file |
Para:
umount /srv/chroot/lucid |
Pois quando eu atualizei para o Linux 3.0 no Archlinux o comando antigo parou de funcionar.
EDIT3 (2014/02/10):
Hoje em dia eu não faria a abominação de copiar os arquivos da pasta /etc que definem usuários e grupos do ambiente hospedeiro para o ambiente convidado (ainda mais quando são baseados em distribuições completamente diferentes). Tal solução… tão vulgar… e pedindo para dores de cabeça no futuro. Só não apago o artigo, porque suas outras partes são úteis.
Hoje em dia eu só iria usar chroot para aplicações mínimas que não exigem comunicação com outros serviços do sistema. Se a aplicação precisar se comunicar com D-Bus, o Apache ou qualquer outro serviço do sistema, eu optaria por usar containers (chroot on steroids) no lugar. E a não ser que haja um meio fácil de atualizar a aplicação (e suas dependências) do chroot mínimo, eu acabaria optando por um ambiente completo no lugar de mínimo só para ter a facilidade de atualizar os pacotes facilmente (gerenciadores de pacotes ftw). Na verdade, eu provavelmente ainda acabaria optando por um container caso o ambiente convidado possuísse systemd, só para usufruir de suas funcionalidades legais como reiniciar serviços mortos, ativação por socket, monitoração de watchdog, interface unificada e bem documentada, …
E a “solução muito esperta” do D-Bus está com os dias contados com o pessoal querendo mover o D-Bus para o kernel.
Não sei se mais alguém teve esse problema, mas ao tentar instalar algo me deparei com o seguinte erro:
dpkg: unrecoverable fatal error, aborting:
syntax error: unknown group ‘mlocate’ in statoverride file
E: Sub-process /usr/bin/dpkg returned an error code (2)
resolvi rodando os seguintes comandos (precisa ser super user):
# cat /dev/null > /var/lib/dpkg/statoverride-old
# cat /dev/null > /var/lib/dpkg/statoverride
$ sudo dpkg --configure -a
;D