Skip to content

Instantly share code, notes, and snippets.

@tdcosta100
Last active July 3, 2024 03:58
Show Gist options
  • Save tdcosta100/c5c206f8958e82e638fa0ea226351081 to your computer and use it in GitHub Desktop.
Save tdcosta100/c5c206f8958e82e638fa0ea226351081 to your computer and use it in GitHub Desktop.
Tutorial para utilizar interface gráfica no WSL2, substituindo XServer pelo Xvnc, permitindo ao WSL trabalhar como se fosse Linux nativo, incluindo tela de login

WSL2 com interface gráfica utilizando Xvnc

Note

Caso você queira utilizar o WSLg puro, você pode tentar o novo tutorial com o WSLg.

Nesse tutorial, iremos configurar a interface gráfica no WSL2, e acessá-la utilizando o VNC. Nenhum software adicional fora do WSL é necessário (como o VcXsrv), exceto, claro um VNC Viewer (RealVNC, TightVNC, TigerVNC, UVNC, etc, todos devem funcionar perfeitamente).

Os componentes-chave que precisamos instalar são o metapackage do desktop que você desejar (GNOME, KDE, Xfce, Budgie, etc) e o tigervnc-standalone-server.

Para essa configuração irei utilizar Ubuntu (20.04, 22.04 e 24.04 funcionam), e irei instalar o GNOME Desktop. Uma vez que os componentes-chave não são diretamente relacionados ou dependentes do Ubuntu ou do GNOME, você pode utilizar sua distribuição favorita e interface gráfica. Dê uma olhada na seção Telas de exemplo para exemplos.

Então vamos lá. Primeiro, precisamos do WSL2 instalado e funcionando.

Warning

O WSLg pode não funcionar da maneira esperada, uma vez que os seus sockets Wayland serão desabilitados para todos, e nem todo aplicativo consegue funcionar corretamente dessa maneira.

Antes de colocar a mão na massa, vamos nos certificar de que tudo está atualizado.

sudo apt update
sudo apt upgrade

Você também precisa verificar se o arquivo /etc/wsl.conf tem as seguintes linhas:

[boot]
systemd=true

Caso não tenha, crie/edite este arquivo, adicione essas linhas e reinicie o WSL (por exemplo, usando wsl --shutdown em um terminal do Windows PowerShell ou do Command Prompt, e reabrindo o terminal da sua distribuição).

Agora sim, estamos prontos para começar.

Instalando os componentes

Instalando a interface gráfica

  1. Primeiro você seleciona o metapackage do seu ambiente desktop favorito. Aqui está uma lista dos metapackages mais comuns:

    DistribuiçãoAmbiente DesktopMetapackage
    UbuntuGNOMEubuntu-desktop
    KDEkubuntu-desktop
    LXDElubuntu-desktop
    Xfcexubuntu-desktop
    Ubuntu/DebianCinnamontask-cinnamon-desktop
    GNOMEtask-gnome-desktop
    GNOME Flashbacktask-gnome-flashback-desktop
    KDE Plasmatask-kde-desktop
    LXDEtask-lxde-desktop
    LXQttask-lxqt-desktop
    MATEtask-mate-desktop
    Xfcetask-xfce-desktop
  2. Uma vez escolhido o metapackage, vamos instalá-lo. Por exemplo, se você escolheu o ubuntu-desktop, o comando será:

    sudo apt install \
    `[ ! -z "$(apt-cache search ^acpi-support$)" ] && echo "acpi-support-"` \
    tigervnc-standalone-server \
    ubuntu-desktop
    

    Isso irá instalar o ubuntu-desktop e o tigervnc-standalone-server, mas excluirá o acpi-support, caso seja incluído como dependência. Isto porque caso seja instalado, irá praticamente inutilizar a sua distribuição (detalhes em microsoft/WSL#10059), então o comando faz o apt não instalar esse pacote.

    A instalação irá demorar um pouco, então seja paciente.

  3. Caso esteja utilizando o Ubuntu, você deve querer instalar o snap-store. Mas se não precisa da loja de aplicativos, você pode pular esse passo:

    sudo snap install snap-store
    

Configurando o ambiente

Se você está utilizando o Debian, precisa configurar o locale (no Ubuntu isso não é necessário):

echo "LANG=en_US.UTF-8" | sudo tee -a /etc/default/locale

Criando e modificando serviços

  1. Agora que temos tudo instalado, precisamos ajustar o diretório /tmp/.X11-unix/, porque é montado como somente leitura por padrão. Criaremos uma nova unit do systemd:

    sudo systemctl edit --full --force wslg-fix.service
    
  2. Cole o código abaixo no editor:

    [Service]
    Type=oneshot
    ExecStart=-/usr/bin/umount /tmp/.X11-unix
    ExecStart=/usr/bin/rm -rf /tmp/.X11-unix
    ExecStart=/usr/bin/mkdir /tmp/.X11-unix
    ExecStart=/usr/bin/chmod 1777 /tmp/.X11-unix
    ExecStart=/usr/bin/ln -s /mnt/wslg/.X11-unix/X0 /tmp/.X11-unix/X0
    
    [Install]
    WantedBy=multi-user.target
    
  3. Saia do editor salvando as alterações do arquivo.

  4. Vamos habilitar o wslg-fix.service:

    sudo systemctl enable wslg-fix.service
    
  5. Também precisamos remover todas as referências ao Wayland, porque se não, alguns aplicativos (gnome-terminal, por exemplo) abrirão fora do desktop shell. Vamos editar o serviço user-runtime-dir@.service:

    sudo systemctl edit user-runtime-dir@.service
    
  6. Cole o código abaixo no editor:

    [Service]
    ExecStartPost=-/usr/bin/rm -f /run/user/%i/wayland-0 /run/user/%i/wayland-0.lock
    
  7. Reinicie o WSL usando wsl --shutdown em um terminal do Windows PowerShell ou Command Prompt, e então reabra o terminal da sua distribuição novamente.

Criando as senhas do VNC Server

Important

No Debian, o usuário do GDM é Debian-gdm, então você precisa substituir gdm por Debian-gdm nos comandos abaixo.

  1. Em algumas distribuições, o diretório /var/lib/gdm3/ tem um owner incorreto, então vamos corrigir isso antes de definir as senhas do VNC Server:

    sudo chown gdm:gdm /var/lib/gdm3/
    
  2. Nessa configuração, cada usuário tem uma senha do VNC diferente. Então você precisa configurar ao menos três senhas, uma para o usuário atual, uma para o root e uma para o GDM, que irá apresentar a tela de login. Se você não configurar a senha, não será capaz de acessar a tela de login, ou o desktop do usuário. Primeiro, vamos configurar a senha do VNC para o usuário atual:

    vncpasswd
    
  3. Agora, vamos configurar a senha do VNC do root (necessária se você utilizar o LightDM ao invés do GDM):

    sudo -H vncpasswd
    
  4. Finalmente, vamos configurar a senha do VNC para o GDM (pule esse passo se você não usa o GDM):

    sudo -H -u gdm vncpasswd
    

    Você pode repetir o processo para outros usuários existentes.

Substituindo o Xorg padrão pelo Xvnc

Por padrão, o display manager pode chamar várias instâncias do Xorg, uma para cada sessão de usuário, incluindo a tela de login, exibida pelo GDM. Então iremos substituir o script Xorg por uma nova versão que chama o Xvnc ao invés do Xorg clássico. Éssa é a verdadeira mágica que estamos tentando fazer.

  1. Primeiro, vamos fazer um backup do script Xorg original.

    sudo mv /usr/bin/Xorg /usr/bin/Xorg_old
    
  2. Agora, criamos um novo script Xorg.

    sudo nano /usr/bin/Xorg_new
    
  3. Cole o código abaixo no editor:

    #!/bin/bash
    for arg do
      shift
      case $arg in
        # Xvnc nao suporta o argumento vtxx, entao vamos converter para ttyxx
        vt*)
          set -- "$@" "${arg//vt/tty}"
          ;;
        # -keeptty nao e suportado pelo Xvnc
        -keeptty)
          ;;
        # -novtswitch nao e suportado pelo Xvnc
        -novtswitch)
          ;;
        # outros argumentos permanecem intactos
        *)
          set -- "$@" "$arg"
          ;;
      esac
    done
    
    # Encontrar um numero de display disponivel
    for displayNumber in $(seq 1 100)
    do
      [ ! -e /tmp/.X11-unix/X$displayNumber ] && break
    done
    
    # Aqui voce pode adequar ou adicionar as opcoes de acordo com as suas necessidades
    command=("/usr/bin/Xvnc" ":${displayNumber}" "-geometry" "1024x768" "-rfbport" "$((5900 + $displayNumber))" "-rfbauth" "${HOME:-/root}/.vnc/passwd" "$@")
    
    systemd-cat -t /usr/bin/Xorg echo "Starting Xvnc:" "${command[@]}"
    
    exec "${command[@]}"
    

    Note a resolução da tela virtual. Você pode modificá-la para outra que satisfaça suas necessidades (1366x768, 1920x1080, etc). Você também pode alterar a opção -rfbauth para apontar para um local fixo ao invés da home do usuário atual, para não precisar ter uma senha para cada usuário.

  4. Finalmente, definimos as permissões corretas para o arquivo e criamos um um link para ele:

    sudo chmod 0755 /usr/bin/Xorg_new
    sudo ln -sf Xorg_new /usr/bin/Xorg
    

Warning

Às vezes, atualizações do sistema substituem o link Xorg com a versão original. Basta repetir esse passo se isso ocorrer, e o Xvnc voltará a funcionar como substituição do Xorg.

Executando sua distribuição com interface gráfica habilitada

Agora você tem tudo pronto para começar. Abra um terminal do WindowsPowerShell ou Command Prompt e finalize o WSL:

wsl --shutdown

Então reabra o terminal da sua distribuição.

Fazer isso é como dar boot no Linux novamente, e o GDM irá inicializar automaticamente, e irá criar uma instância de Xorg para mostrar a interface de login. Mudamos esse processo para fazê-lo criar instâncias de Xvnc, então podemos acessá-las. A primeira instância abrirá a porta 5901, a segunda instância abrirá a porta 5902, e assim por diante.

Acessando a tela do VNC

Depois de um tempo (geralmente alguns segundos, mas pode demorar mais se você não tiver um SSD), você pode testar se está funcionando corretamente. Use seu VNC Viewer favorito para conectar no localhost porta 5901 (localhost:5901). Use a senha do VNC definida para o usuário gdm (ou Debian-gdm, se está utilizando o Debian). A tela de login deve aparecer.

Depois de fazer o login, a tela ficará em branco e eventualmente fechará automaticamente. Isso é porque uma nova instância do Xvnc foi criada para o desktop do usuário, abrindo a porta 5902. Conecte-se a essa porta agora. O desktop do usuário logado deve aparecer. Quando você deslogar, a tela da porta 5901 mostrará a interface de login novamente. Isso se aplica ao GDM (que é o caso se você instalou o Ubuntu Desktop). Você pode mudar esse comportamento alterando o arquivo de configuração dessa forma:

  1. sudo nano /etc/gdm3/custom.conf

  2. Descomente e edite as seguintes linhas:

     AutomaticLoginEnable=true
     AutomaticLogin=[seu username sem os colchetes]
    

Se você está utilizando o LightDM, a tela de desktop aparecerá na porta 5901, então não há necessidade de conectar na porta 5902.

Desligando

Uma coisa importante é: uma vez que você inicializa sua instância de WSL, você não pode simplesmente desligá-la do nada. Você deve realizar um desligamento padrão do Linux. Você pode utilizar uma das alternativas abaixo:

  • Opção de Desligar no menu da interface gráfica
  • sudo poweroff

Depois disso, você pode parar a sua instância de WSL com segurança, através do comando wsl --terminate ou wsl --shutdown. Não realizar o processo de desligamento poderá corromper sua instância de WSL, portanto tenha cuidado.

Dicas e truques

  • O VNC é um protocolo bastante adaptativo, e por padrão utiliza a maior taxa de compressão possível, para otimizar a utilização da rede. Mas no nosso caso, isso apenas desperdiça processamento, uma vez que você está se conectando ao próprio computador (largura de banda "infinita" e ping praticamente zero). Para não utilizar nenhum algoritmo de compressão e assim reduzir o delay, o ideal é forçar seu VNC Viewer a conectar-se utilizando a codificação RAW. O ganho de performance é perceptível, especialmente ao reproduzir vídeos (apesar de a performance não ser grande coisa nesse caso específico).

Solução de problemas

  1. Caso não funcione de primeira, tente checar os logs do journalctl:

    journalctl -b -t /usr/lib/gdm3/gdm-x-session -t /usr/bin/Xorg --no-pager
    

    Se você está utilizando o Debian, então o comando é:

    journalctl -b -t /usr/libexec/gdm-x-session -t /usr/bin/Xorg --no-pager
    

    Na saída gerada, você deve conseguir encontrar qual linha de comando foi gerada para o Xvnc, e quais mensagens de erro aparecem. E claro, mesmo que tudo funcione corretamente, ainda assim você pode checar os logs para ver o que está acontecendo, ou para fazer debug.

  2. Você deve verificar se o script customizado Xorg não foi substituído pela versão padrão dele. Se foi o caso, basta repetir os passos da seção Substituindo o Xorg padrão pelo Xvnc.

  3. Verifique se o Xorg é seu display server padrão, não Xephyr ou Wayland. Caso não seja, você precisa mudar o display server padrão para o Xorg.

  4. Se você está utilizando o LightDM, você também precisa verificar os logs em /var/log/lightdm (você vai precisar utilizar o sudo para ler os arquivos nesse diretório). A saída do Xvnc estará no arquivo /var/log/lightdm/x-0.log.

  5. Se você pode se conectar às portas 590XX, mas aparece um erro como Authentication failure: No password configured for VNC Auth, está faltando o arquivo $HOME/.vnc/passwd está faltando para aquele usuário em particular (na porta 5901, o usuário é gdm). Tente repetir os passos descritos na seção Criando as senhas do VNC Server e tente se conectar novamente.

  6. Caso ainda não funcione, você pode tentar reiniciar o WSL. Abra um terminal do Windows PowerShell ou Command Prompt, e execute o seguinte comando (não se esqueça de salvar tudo o que não foi salvo antes, porque o WSL será desligado completamente):

    PS > wsl --shutdown
    

    Depois disso, reabra o terminal da sua distribuição e repita os passos da seção Acessando a tela do VNC.

Telas de exemplo

GDM

GDM

LightDM

LightDM

GNOME

GNOME

KDE

KDE

Xfce

Xfce

Budgie Desktop

Budgie Desktop

Pessoas que contribuíram

Meu muito obrigado às pessoas abaixo, cujo feedback fez esse tutorial atingir o nível atual de qualidade e completitude (e ficará cada vez mais completo conforme mais feedback for sendo dado).

@tdcosta100
Copy link
Author

Poxa cara, valeu mesmo! Deu certo aqui =D

Se cuide,
André

Opa, que ótimo! Qualquer coisa, fale aí que corro atrás.

Abraços,
Tiago

@mlknservices
Copy link

Primeiro gostaria de agradecer o compartilhamento deste tutorial, segui todos os passos e funcionou tudo pra mim exceto o som, não consigo fazer que saia o som de jeito nenhum, já pesquisei e não consigo encontrar como corrigir, se alguém passou pelo mesmo problema e conseguiu resolver, se puder compartilhar agradeço.

Abraço a todo.

@tdcosta100
Copy link
Author

Valeu, @mlknservices! O som precisa de uma solução própria. Tem vários tutoriais e todos que conheço passam por um servidor de áudio rodando no Windows e daí você redireciona pra ele via TCP (mais ou menos a mesma coisa que o pessoal que usa X Server rodando no Windows faz). Um exemplo:

microsoft/WSL#4205

Espero que consiga fazer funcionar.

Abraços,
Tiago

@thiagozucarini
Copy link

Tiago, logo após colocar a senha do VNC, aparece a mensagem:

Would you like to enter a view-only password (y/n)?

Qual opção coloco?

@tdcosta100
Copy link
Author

Olá, @thiagozucarini. Essa é a mensagem para você criar uma segunda senha para o VNC, e quem utilizá-la conseguirá apenas ver a tela, não conseguirá mexer em nada. A segunda senha é opcional, você pode escolher tê-la ou não. No contexto do WSL, creio que não faz sentido você ter essa segunda senha. No meu setup, eu escolho N.

@davilos
Copy link

davilos commented Aug 18, 2022

Opa tdcosta100, parabéns pelo trabalho, tá sensacional. Só estou com uma dúvida, como faço pra desinstalar a interface Xubuntu e instala a do Ubuntu? Instalei a do Xubuntu porque pensei que talvez ficasse travando muito, mas tá rodando liso aqui.

@tdcosta100
Copy link
Author

Olá, @davilos. Perdão pela demora, estava de férias e fiquei meio off. Você instalou o Xubuntu pelo tasksel? Se sim, é só desmarcar as opções marcadas lá, e depois de tudo desinstalado, instalar o Ubuntu Desktop. Mas pra instalar a interface do Ubuntu eu acho que você não precisa desinstalar nada do Xubuntu, ele só vai perguntar pra você qual display manager você quer usar (e aí você escolhe o GDM), e na hora de fazer login, qual desktop você quer usar (e aí você escolhe o Ubuntu). Testa aí e me fala se funcionou :).

@1993nxv
Copy link

1993nxv commented Mar 9, 2023

Boa tarde! Segui os passos, estou com este erro. Pode da um help?

genie: WARNING: systemd default target is default.target; targets other than multi-user.target may not work
genie: WARNING: if you wish to use a different target, this warning can be disabled in the config file
genie: WARNING: if you experience problems, please change the target to multi-user.target
umount: /proc/sys/fs/binfmt_misc: not mounted.
genie: failed to unmount binfmt_misc filesystem; attempting to continue
Waiting for systemd....!
genie: systemd did not enter running state (degraded) after 240 seconds
genie: this may be due to a problem with your systemd configuration
genie: information on problematic units is available at https://github.com/arkane-systems/genie/wiki/Systemd-units-known-to-be-problematic-under-WSL
genie: a list of failed units follows:

UNIT LOAD ACTIVE SUB DESCRIPTION
● atd.service loaded failed failed Deferred execution scheduler
● ssh.service loaded failed failed OpenBSD Secure Shell server
● systemd-remount-fs.service loaded failed failed Remount Root and Kernel File Systems
● multipathd.socket loaded failed failed multipathd control socket

LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.

4 loaded units listed.
genie: WARNING: systemd is in degraded state, issues may occur!

@tdcosta100
Copy link
Author

Olá, @1993nxv. Muita coisa mudou desde que esse tutorial foi escrito. Agora existe suporte nativo ao systemd, e com isso as coisas ficaram um pouco diferentes. Eu vou reescrever o tutorial para abraçar essas mudanças. Enquanto isso, me conte qual é a distro que você está usando? Pergunto porque o Ubuntu 22.04 infelizmente tem coisas que não funcionam, aí a opção será usar o Ubuntu 20.04 mesmo. Me avise que aí consigo continuar te ajudando.

@cjannuzzi
Copy link

@tdcosta100 gostei da ideia de reescrever o tutorial atualizado. Já que o 22.04 ta bugado pode ser o 20.04 caso esteja rodando liso. De qualquer forma, agradeço desde já o empenho.

@tdcosta100
Copy link
Author

Olá, @cjannuzzi. Ainda não atualizei a versão em português, mas você já pode conferir a versão atualizada em inglês aqui.

@dpaes
Copy link

dpaes commented Jun 26, 2024

sudo apt install dotnet-runtime-5.0
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
dotnet-runtime-deps-5.0 : Depends: libssl1.0.0 but it is not installable or
libssl1.0.2 but it is not installable or
libssl1.1 but it is not installable
E: Unable to correct problems, you have held broken packages.

O que eu faço agora?

@tdcosta100
Copy link
Author

Olá, @dpaes. Muita coisa mudou desde que eu escrevi esse tutorial. Eu preciso reescrever ele, infelizmente minha vida está meio corrida então ainda não consegui. A versão 22.04 do Ubuntu está horrível pra funcionar dessa forma que o tutorial descreve. Mas as versões 24.04 e 20.04 funcionam melhor. O 24.04 inclusive eu consegui fazer funcionar mesmo com o WSLg ativado.

Enquanto não atualizo, resete sua distro WSL ou faça os tutoriais seguindo a versão em inglês.

@dpaes
Copy link

dpaes commented Jun 28, 2024

entendi, obrigado @tdcosta100, mas o erro ocorreu usando o Ubuntu 20.04 mesmo só pra informar.

@tdcosta100
Copy link
Author

Opa, obrigado pela informação. Então, como falei, agora muita coisa mudou, e esse tutorial está desatualizado, o systemd-genie não é mais necessário, então você não precisa mais instalar o dotnet-runtime-5.0. Com isso, esse erro não vai acontecer se você seguir o tutorial em inglês. No momento estou fazendo alguns testes com o WSLg, e tenho tido resultados bastante interessantes. Quando finalizar, reescrevo o tutorial em português e atualizo o tutorial em inglês.

@tdcosta100
Copy link
Author

Pessoal, finalmente atualizei o tutorial em português. Agora não é mais necessário desativar o WSLg, e agora funciona no Ubuntu 22.04 e também no Ubuntu 24.04.

@tdcosta100
Copy link
Author

E pra quem quiser utilizar somente o WSLg, também tem um tutorial novo para o WSLg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment