Recipientes LXC não privilegiados são aqueles que usam os namespaces de usuário ( userns ). Ou seja de um recurso do kernel que permite mapear um intervalo de UIDs no host em um namespace dentro do qual um usuário com UID 0 pode existir novamente.
Ao contrário da minha percepção inicial de contêineres LXC não privilegiados por um tempo, isso não significa que o contêiner deva ser de propriedade de um usuário host não privilegiado. Essa é apenas uma possibilidade.
Relevante é:
- que um intervalo de UIDs e GIDs subordinados é definido para o usuário do host (
usermod [-v|-w|--add-sub-uids|--add-sub-gids]
) - ... e esse intervalo é mapeado na configuração do contêiner (
lxc.id_map = ...
)
Portanto, mesmo root
pode possuir contêineres sem privilégios, já que os UIDs efetivos dos processos de contêiner no host acabarão dentro do intervalo definido pelo mapeamento.
No entanto, para root
, você precisa definir primeiro os IDs subordinados. Ao contrário dos usuários criados por meio de adduser
, root
não terá um intervalo de IDs subordinados definidos por padrão.
Lembre-se também de que o intervalo completo que você fornece está à sua disposição. Portanto, você pode ter três contêineres com as seguintes linhas de configuração (somente o mapeamento de UID exibido):
-
lxc.id_map = u 0 100000 100000
-
lxc.id_map = u 0 200000 100000
-
lxc.id_map = u 0 300000 100000
assumindo que root
possui os UIDs subordinados entre 100000 e 400000. Toda a documentação que encontrei sugere o uso de 65536 IDs subordinados por contêiner, mas alguns usam 100000 para torná-lo mais legível para humanos.
Em outras palavras: você não precisa atribuir o mesmo intervalo a cada contêiner.
Com mais de 4 bilhões (~ 2^32
) IDs de subordinação possíveis, significa que você pode ser generoso ao lidar com as faixas subordinadas aos usuários do host.
Contêiner não privilegiado de propriedade e executado pela raiz
Para esfregar isso novamente. Um convidado LVC não privilegiado não precisa ser executado por um usuário não privilegiado no host.
Como configurar seu contêiner com um mapeamento de UID / GID subordinado assim:
lxc.id_map = u 0 100000 100000
lxc.id_map = g 0 100000 100000
em que o usuário root
no host possui esse determinado intervalo de IDs subordinadas, permite restringir ainda mais os convidados.
No entanto, há uma vantagem adicional importante em tal cenário (e sim, verifiquei que funciona): você pode iniciar automaticamente seu contêiner na inicialização do sistema.
Normalmente, ao vasculhar a Web em busca de informações sobre o LXC, você será informado de que não é possível iniciar automaticamente um convidado LVC sem privilégios. No entanto, isso é verdade apenas por padrão para os contêineres que não estão no armazenamento em todo o sistema para contêineres (geralmente algo como /var/lib/lxc
). Se eles são (o que geralmente significa que eles foram criados pelo root e são iniciados pelo root), é uma história totalmente diferente.
lxc.start.auto = 1
fará o trabalho muito bem, depois de colocá-lo em sua configuração de contêiner.
Obtendo permissões e configuração correta
Eu me esforcei um pouco com isso, então estou adicionando uma seção aqui.
Além do trecho de configuração incluído via lxc.include
, que normalmente é chamado de /usr/share/lxc/config/$distro.common.conf
(onde $distro
é o nome de uma distro), você deve verificar se há também /usr/share/lxc/config/$distro.userns.conf
em seu sistema e inclua isso também. Por exemplo:
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
Além disso, adicione os mapeamentos de ID subordinados:
lxc.id_map = u 0 100000 65535
lxc.id_map = g 0 100000 65535
que significa que o host UID 100000 é root
dentro do espaço de nome de usuário do convidado LXC.
Agora, verifique se as permissões estão corretas. Se o nome do seu convidado fosse armazenado na variável de ambiente $lxcguest
, você executaria o seguinte:
# Directory for the container
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest
chmod ug=rwX,o=rX $(lxc-config lxc.lxcpath)/$lxcguest
# Container config
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest/config
chmod u=rw,go=r $(lxc-config lxc.lxcpath)/$lxcguest/config
# Container rootfs
chown 100000:100000 $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
chmod u=rwX,go=rX $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
Isso deve permitir que você execute o contêiner após a primeira tentativa ter dado alguns erros relacionados à permissão.