Virtual host (host virtual, ou simplesmente vhost) é a configuração do servidor web que permite hospedar vários sites na mesma máquina, muitas vezes no mesmo endereço IP. O servidor olha qual domínio o navegador pediu e entrega a pasta, os logs e o certificado SSL daquele site, e não de outro.

É assim que um único servidor Apache ou NGINX atende dezenas ou centenas de domínios. A seguir você vê como o servidor escolhe o site certo, os três tipos de virtual host, exemplos prontos para Apache e NGINX, o que o cPanel faz por você e os erros que mais aparecem na prática.


O que é virtual host

Pense no servidor web como um prédio com um só endereço na rua. O virtual host é a lista da portaria que diz em qual apartamento mora cada visitante esperado: chegou alguém procurando loja.com.br, vai para uma pasta; chegou alguém procurando blog.com.br, vai para outra.

No Apache, cada site é um bloco <VirtualHost>. No NGINX, o mesmo papel é de um bloco server. Em ambos, cada virtual host costuma definir:

  • o domínio principal e os apelidos (por exemplo, com e sem www);
  • a pasta onde estão os arquivos do site (DocumentRoot no Apache, root no NGINX);
  • arquivos de log separados, o que facilita achar o erro de um site sem vasculhar os outros;
  • o certificado SSL usado na porta 443;
  • regras próprias: redirecionamentos, versão do PHP, permissões de pasta, cabeçalhos.
Notebook com código na tela e monitor ao fundo, representando a configuração de um servidor web

Não confunda: virtual host não é máquina virtual. A máquina virtual divide um computador físico em vários servidores independentes, cada um com sistema operacional próprio (veja o que é virtualização). O virtual host é só uma configuração dentro do servidor web, que reparte um mesmo Apache ou NGINX entre vários sites.


Como o servidor escolhe o site certo

Quando alguém digita um endereço no navegador, acontece esta sequência:

  1. O DNS traduz o domínio para o IP do servidor. Se o domínio acabou de ser apontado, essa etapa pode demorar por causa da propagação de DNS.
  2. O navegador se conecta a esse IP na porta 80 (HTTP) ou 443 (HTTPS).
  3. Junto com o pedido, o navegador informa o nome do site no cabeçalho Host. Em HTTPS, o nome também segue antes da criptografia começar, numa extensão chamada SNI, para o servidor saber qual certificado apresentar.
  4. O servidor compara esse nome com o ServerName e os ServerAlias (Apache) ou o server_name (NGINX) de cada virtual host daquele IP e porta.
  5. Achou o par, entrega os arquivos da pasta configurada. Não achou nenhum, usa o virtual host padrão: no Apache, o primeiro da lista; no NGINX, o marcado com default_server.

Esse último passo explica um susto comum: o domínio novo abre o site de outro cliente ou a página padrão do Apache. Quase sempre o nome não bateu com nenhum virtual host e o servidor caiu no padrão.


Baseado em nome, em IP ou em porta

Existem três jeitos de o servidor separar um site do outro. Na hospedagem atual, o baseado em nome é o padrão; os outros dois resolvem casos específicos.

TipoComo o servidor diferenciaExemploQuando usar
Baseado em nomePelo domínio enviado pelo navegador (cabeçalho Host e SNI)<VirtualHost *:443> com ServerName loja.com.brPraticamente sempre: vários sites dividindo um único IP
Baseado em IPPelo endereço IP em que a conexão chegou<VirtualHost 203.0.113.10:443>Quando um site precisa de IP exclusivo, por exigência de firewall de parceiro, reputação de envio ou cliente muito antigo sem SNI
Baseado em portaPela porta usada na conexão<VirtualHost *:8080>Painéis internos, ambientes de teste e serviços que não precisam de domínio próprio

Por muito tempo, quem queria HTTPS precisava de um IP por site, porque o servidor não sabia qual certificado mostrar antes de a conexão ser cifrada. O SNI resolveu isso, e hoje todos os navegadores atuais o suportam. Por isso o modelo por nome vale também para a porta 443.

No Apache 2.4, não é preciso declarar NameVirtualHost, como em tutoriais antigos: basta ter mais de um bloco no mesmo IP e porta que o Apache já trabalha por nome. A documentação oficial de virtual hosts do Apache traz exemplos de cada tipo.


Como configurar virtual host no Apache

Mesa com dois monitores exibindo código, usada para configurar um servidor Apache

O exemplo usa Ubuntu ou Debian, com acesso root ou sudo, e o domínio fictício exemplo.com.br. Troque pelo seu domínio em todos os comandos.

1. Crie a pasta do site e uma página de teste

sudo mkdir -p /var/www/exemplo.com.br/public_html
sudo chown -R $USER:$USER /var/www/exemplo.com.br/public_html
echo '<h1>exemplo.com.br funcionando</h1>' > /var/www/exemplo.com.br/public_html/index.html

O Apache lê os arquivos como o usuário www-data, então as pastas precisam de permissão de leitura para todos (755 em pastas e 644 em arquivos resolve na maioria dos casos).

2. Escreva o arquivo do virtual host

Crie o arquivo /etc/apache2/sites-available/exemplo.com.br.conf. O bloco da porta 80 só redireciona para HTTPS; o site de verdade fica no bloco da porta 443:

<VirtualHost *:80>
    ServerName exemplo.com.br
    ServerAlias www.exemplo.com.br
    Redirect permanent / https://exemplo.com.br/
</VirtualHost>

<VirtualHost *:443>
    ServerName exemplo.com.br
    ServerAlias www.exemplo.com.br
    ServerAdmin admin@exemplo.com.br
    DocumentRoot /var/www/exemplo.com.br/public_html

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/exemplo.com.br/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/exemplo.com.br/privkey.pem

    <Directory /var/www/exemplo.com.br/public_html>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/exemplo.com.br-error.log
    CustomLog ${APACHE_LOG_DIR}/exemplo.com.br-access.log combined
</VirtualHost>

AllowOverride All libera o uso de .htaccess, que o WordPress e muitos sistemas usam para URLs amigáveis. Se o site não precisa disso, deixe None, que é um pouco mais rápido.

Ainda sem certificado? Se os arquivos de certificado não existirem, o Apache não sobe. Comece só com o bloco da porta 80 (com DocumentRoot no lugar do Redirect), ative o site e rode sudo certbot --apache -d exemplo.com.br -d www.exemplo.com.br. O Certbot emite o certificado gratuito e cria o bloco da porta 443 sozinho.

3. Ative o site, teste a sintaxe e recarregue

sudo a2enmod ssl
sudo a2ensite exemplo.com.br.conf
sudo a2dissite 000-default.conf
sudo apachectl configtest
sudo systemctl reload apache2

O a2ensite cria um atalho do arquivo em sites-enabled, que é a pasta que o Apache realmente lê. Desativar o 000-default.conf é opcional, mas evita que a página padrão do Apache apareça para domínios não configurados. Só recarregue depois que o configtest responder Syntax OK: um erro de digitação derruba todos os sites do servidor, não só o novo.

4. Confira se funcionou

O comando sudo apachectl -S lista todos os virtual hosts carregados, com o arquivo e a linha de cada um, e mostra qual é o padrão de cada porta. Para testar antes de apontar o DNS, peça a página direto ao IP informando o domínio:

curl -I -H "Host: exemplo.com.br" http://IP-DO-SERVIDOR/

Em outras distribuições: no AlmaLinux e no Rocky Linux o Apache se chama httpd, não há a2ensite e os virtual hosts ficam em /etc/httpd/conf.d/, em arquivos terminados em .conf. O teste é o mesmo (apachectl configtest) e o recarregamento é systemctl reload httpd.

Para testar no próprio computador, sem DNS, acrescente uma linha como 127.0.0.1 exemplo.test ao arquivo hosts (/etc/hosts no Linux e no macOS, C:\Windows\System32\drivers\etc\hosts no Windows) e use esse nome no ServerName. A terminação .test é reservada para testes e nunca vai existir na internet.


Virtual host no NGINX: server blocks

O NGINX não usa o termo virtual host, mas a ideia é idêntica. Cada site é um bloco server, e a escolha é feita pelo server_name. No Ubuntu e no Debian, crie o arquivo /etc/nginx/sites-available/exemplo.com.br:

server {
    listen 80;
    listen [::]:80;
    server_name exemplo.com.br www.exemplo.com.br;
    return 301 https://exemplo.com.br$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name exemplo.com.br www.exemplo.com.br;

    root /var/www/exemplo.com.br/public_html;
    index index.html index.php;

    ssl_certificate     /etc/letsencrypt/live/exemplo.com.br/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exemplo.com.br/privkey.pem;

    access_log /var/log/nginx/exemplo.com.br-access.log;
    error_log  /var/log/nginx/exemplo.com.br-error.log;

    location / {
        try_files $uri $uri/ =404;
    }
}

Depois, ative, teste e recarregue:

sudo ln -s /etc/nginx/sites-available/exemplo.com.br /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

O que muda em relação ao Apache:

  • Não existe a2ensite: você cria o link simbólico à mão. Em instalações fora do Debian, os arquivos vão em /etc/nginx/conf.d/.
  • O site padrão de cada porta é definido com listen 80 default_server;, não pela ordem dos arquivos.
  • Não há .htaccess. Regras de reescrita entram no próprio bloco server.
  • O server_name aceita curingas (*.exemplo.com.br) e expressões regulares, como explica a documentação do NGINX sobre server names.

O mesmo cuidado com o certificado vale aqui: se ele ainda não existe, suba primeiro só o bloco da porta 80 e rode sudo certbot --nginx.


Como o cPanel cria um virtual host para cada domínio

Em servidores com cPanel, ninguém escreve virtual host à mão. Quando o administrador cria uma conta no WHM ou o cliente adiciona um domínio na tela Domínios do cPanel, o sistema gera os blocos das portas 80 e 443, aponta a pasta (o public_html do domínio principal ou a pasta escolhida para os demais) e pede um certificado gratuito pelo AutoSSL.

Esses blocos ficam em /etc/apache2/conf/httpd.conf, mas o arquivo é reconstruído a partir dos dados de cada conta sempre que algo muda. Quem edita o httpd.conf direto perde a alteração na próxima atualização. O caminho certo para personalizar um virtual host é um arquivo de inclusão:

# HTTP (porta 80)
/etc/apache2/conf.d/userdata/std/2_4/USUARIO/DOMINIO/minhas-regras.conf
# HTTPS (porta 443)
/etc/apache2/conf.d/userdata/ssl/2_4/USUARIO/DOMINIO/minhas-regras.conf

# depois de criar ou editar:
/usr/local/cpanel/scripts/rebuildhttpdconf
/usr/local/cpanel/scripts/restartsrv_httpd

Os detalhes, incluindo como aplicar uma regra a todos os domínios de uma vez, estão no guia do cPanel Modify Apache Virtual Hosts with Include Files. Isso exige acesso root, ou seja, um servidor próprio. Em hospedagem compartilhada, o que você ajusta por site fica no .htaccess e nas telas do cPanel.

Na SAN: no Cloud Server você tem acesso root para montar seus virtual hosts no Apache ou no NGINX, ou pode usar cPanel/WHM e deixar que o painel crie um para cada domínio. Se a ideia é só publicar sites, a hospedagem de sites com cPanel já entrega tudo configurado.


Erros comuns e como resolver

Antes de mexer em qualquer coisa, rode apachectl -S ou nginx -T e leia o log de erro do site. Metade dos problemas aparece ali. Os casos abaixo são os que mais se repetem:

O que aconteceCausa provávelComo resolver
Abre a página padrão do Apache ou o site de outro domínioNenhum ServerName/ServerAlias bateu, ou o site não foi ativadoConfira o nome com e sem www, rode a2ensite e veja em apachectl -S qual é o virtual host padrão
Funciona pelo IP, mas não pelo domínioO DNS ainda aponta para outro servidorConsulte o registro A do domínio e aguarde a propagação
403 ForbiddenPermissão de pasta ou falta de Require all granted quando a pasta fica fora de /var/wwwAjuste para 755/644 e acrescente o bloco <Directory>
HTTPS mostra certificado de outro siteFalta o virtual host da porta 443 para aquele nomeCrie o bloco *:443 com o certificado certo ou rode o Certbot/AutoSSL
Syntax error no configtest ao usar SSLEngineMódulo SSL desativadosudo a2enmod ssl e teste de novo
Aviso AH00558 sobre o nome do servidorFalta um ServerName globalÉ só um aviso; some ao definir ServerName no apache2.conf
NGINX avisa conflicting server nameO mesmo domínio está em dois blocos serverRemova a duplicata; o NGINX ignora a segunda ocorrência
Alteração some depois de um tempo (cPanel)O httpd.conf foi editado diretoUse os arquivos de inclusão e o rebuildhttpdconf

Perguntas frequentes

O que significa vhost?

Vhost é a abreviação de virtual host (host virtual): a configuração do servidor web que define qual pasta, logs e certificado SSL respondem por cada domínio hospedado na mesma máquina.

Preciso de um IP diferente para cada site com HTTPS?

Não. Com virtual hosts baseados em nome e o SNI, que todos os navegadores atuais suportam, vários sites com certificados diferentes dividem o mesmo IP na porta 443. IP exclusivo só é necessário em casos específicos, como exigência de firewall de um parceiro.

Onde ficam os arquivos de virtual host do Apache?

No Ubuntu e no Debian, em /etc/apache2/sites-available (os ativos aparecem em sites-enabled). No AlmaLinux e no Rocky Linux, em /etc/httpd/conf.d. Em servidores com cPanel, o painel gera tudo em /etc/apache2/conf/httpd.conf, que não deve ser editado à mão.

Virtual host é a mesma coisa que servidor virtual (VPS)?

Não. O VPS é uma máquina virtual com sistema operacional próprio. O virtual host é uma configuração dentro do servidor web, e um mesmo VPS pode ter vários virtual hosts, um para cada site. Entenda a diferença no post sobre virtualização.

Como ver quais virtual hosts estão ativos no servidor?

No Apache, rode sudo apachectl -S: ele lista cada virtual host, o arquivo onde está e o padrão de cada porta. No NGINX, sudo nginx -T mostra a configuração completa carregada.