Trocar a logo do GLPI parece um ajuste de cinco minutos - até a próxima atualização apagar tudo. Personalizar a identidade visual editando o CSS do core ou o template de login funciona no dia, mas é uma dívida que vence sozinha: some no update e, no salto do GLPI 10 para o 11, o DOM da tela de login mudou de nome, então o hack antigo para de aplicar sem lançar erro nenhum. Este guia mostra como fazer branding que sobrevive à atualização, onde cada peça vive no GLPI 11 e as armadilhas que só aparecem em ambiente de cliente.
Branding no GLPI não é só estética
Um GLPI com a cara da organização reduz atrito: o usuário final reconhece que aquilo é o Service Desk da empresa, e não um sistema estranho pedindo login. Mas o custo escondido não está em escolher a cor certa - está em como a customização é aplicada. Existem três caminhos, e dois deles cobram caro depois.
- Editar o core (CSS, imagens ou templates dentro de
glpi/css,glpi/picsoutemplates/): funciona, mas o próximogit pullou o descompactar do release sobrescreve os arquivos. A personalização evapora e ninguém lembra por quê. - Tema/CSS injetado por fora: sobrevive ao update dos arquivos, mas fica preso aos seletores da versão. Quando o GLPI muda a estrutura HTML - como fez do 10 para o 11 - o seletor deixa de existir e o CSS vira letra morta, silenciosamente.
- Hook de plugin: o GLPI expõe pontos de injeção oficiais (
display_login,add_javascript). O módulo aplica a marca por esses hooks, sem tocar em um único arquivo do core. É o único caminho que sobrevive à atualização por design.
O que dá para personalizar - e onde cada peça vive
Cada elemento visual do GLPI mora em um lugar diferente do DOM, e trocar sem saber o alvo certo é o que gera a maioria dos chamados de "mudei e não apareceu". A matriz abaixo mapeia cada peça à sua chave de configuração e ao mecanismo real no GLPI 11:
| Peça | Chave de config | Mecanismo no GLPI 11 | Armadilha comum |
|---|---|---|---|
| Favicon | favicon_picture | <link rel="icon"> reescrito via JS | Cache agressivo do navegador segura o ícone antigo |
| Título da aba | page_title | document.title | Telas que definem o próprio título revertem |
| Logo do login | login_picture | span.glpi-logo via content: url(...) | Mirar .login-logo, que não existe no 11 |
| Fundo do login | login_background | body.welcome-anonymous / .page-anonymous | Mirar body.login-page, que não existe no 11 |
| Logo do cabeçalho | internal_picture | Header interno via add_javascript | Confundir com o logo de login (são alvos distintos) |
| Rodapé | footer_mode / footer_text | .copyright (tema padrão do 11) | Colar HTML não sanitizado no texto customizado |
| Cores da interface | color_* | Variáveis CSS Tabler (--tblr-*) | Passar valor que não é hex e injetar CSS quebrado |
A armadilha do GLPI 11: o logo de login não é background
Na sustentação de ambientes de clientes, o chamado clássico é: "atualizamos o GLPI e a tela de login voltou ao padrão". Quase sempre a causa é uma customização feita direto no core ou num CSS que mirava os seletores do GLPI 10. No salto para o 11, o template da tela de login (page_card_notlogged.html.twig) foi reescrito: o <body> virou body.welcome-anonymous, o container virou .page-anonymous e o logo deixou de ser uma imagem de fundo - agora é um <span class="glpi-logo"> renderizado por content: var(--logo). Descobrimos isso na prática em 2026-06-10, depurando por que o fundo de login de um cliente simplesmente não aplicava após o upgrade: o seletor antigo body.login-page não existia mais no DOM. Não havia erro no log - o CSS estava correto para uma versão que não rodava mais. Por isso passamos a emitir os seletores certos por hook, versionados junto do módulo. Este é o CSS real que o módulo injeta - e os seletores mortos que explicam o sumiço:
/* GLPI 11 - seletores REAIS da tela de login (page_card_notlogged.html.twig) */
/* O logo NAO e background: e um <span class="glpi-logo"> com content: var(--logo) */
.page-anonymous .glpi-logo {
content: url("/plugins/nextool/front/module_assets.php?module=branding&file=...") !important;
width: 240px !important;
height: 130px !important;
object-fit: contain !important; /* preserva a proporcao da imagem */
}
/* O fundo vai no body.welcome-anonymous / .page-anonymous - NUNCA em body.login-page */
body.welcome-anonymous,
.page-anonymous {
background-image: url("...") !important;
background-size: cover !important;
background-position: center center !important;
}
/* Seletores do GLPI 10 que NAO existem mais no 11 (por isso o hack antigo some sem erro):
.login-logo -> agora e span.glpi-logo
body.login-page -> agora e body.welcome-anonymous */
Como o módulo aplica sem tocar no core
Na tela de login não há sessão, então o módulo se pendura no hook display_login e injeta um bloco <style>/<script> inline. As imagens (favicon, logo, fundo) são servidas por um endpoint stateless que não exige login, com três proteções que valem citar porque são onde plugins descuidados vazam: a extensão passa por uma whitelist (png, jpg, jpeg, gif, ico, svg, webp), o caminho é resolvido com realpath() e conferido contra o prefixo do diretório de upload (bloqueio de path traversal), e o arquivo é gravado com nome único via uniqid() para não colidir nem sobrescrever. Nas páginas internas, já autenticadas, a customização entra pelo hook add_javascript.
Um detalhe de performance que só aparece medindo: o JS interno vai com Cache-Control: private, max-age=86400 e as imagens com public, max-age=604800 (uma semana), mas sem ETag. A razão é concreta - com ETag e max-age juntos, o Chrome revalidava (HTTP 304) a cada carregamento de página, e cada 304 ainda pagava o bootstrap completo do GLPI no servidor. Um hash da configuração entra no parâmetro fv= da URL, então salvar a config muda a URL e invalida o cache na hora, sem precisar de revalidação.
Configuração em cinco passos
- Ative o módulo Branding no catálogo de módulos do NexTool.
- Na aba Configurações, envie o favicon, a logo de login e a logo do cabeçalho; defina largura e altura de cada logo (aceita
px,em,rem,%,vw,vh). - Envie o fundo da tela de login e ajuste o título da aba do navegador.
- Escolha o comportamento do rodapé: manter o original, ocultar ou substituir por texto (HTML limitado a tags seguras).
- Opcional: defina as cores da interface por variáveis CSS (o módulo valida cada valor como hex antes de emitir, evitando CSS injection). Recarregue o GLPI para ver o resultado.
Auditoria: quem mudou o quê
Toda ação - ativar, desativar, salvar config, enviar ou apagar imagem - é gravada em uma tabela de log do módulo. Em ambiente com mais de um administrador, essa trilha responde "quem trocou a logo na sexta à noite" sem depender de memória. A consulta de diagnóstico:
-- Trilha de auditoria do modulo Branding: quem mudou a identidade visual e quando
SELECT l.date_creation AS quando,
u.name AS usuario,
l.action AS acao, -- save_config, upload_picture, delete_picture, toggle_enable/disable
l.detail AS detalhe
FROM glpi_plugin_nextool_branding_log l
LEFT JOIN glpi_users u ON u.id = l.users_id
ORDER BY l.date_creation DESC
LIMIT 20;
Armadilhas de campo
- Favicon que não troca - o navegador cacheia favicon de forma agressiva, por aba e por sessão. Depois de subir o novo ícone, um hard refresh (Ctrl+Shift+R) ou fechar e reabrir a aba resolve; não é bug do módulo.
- SVG de fonte confiável - SVG é ótimo para logo (escala sem perder nitidez), mas pode carregar script embutido. Use SVG apenas de arte que você mesmo gerou; o endpoint serve o arquivo com o Content-Type correto, mas a higiene começa no upload.
- Rodapé com HTML colado - o texto customizado do rodapé passa por sanitização que só permite um punhado de tags (
a, b, strong, i, em, span, br). Colar um bloco inteiro de HTML de marketing simplesmente não renderiza o que você espera. - Proporção da logo - definir largura e altura fixas sem respeitar a proporção original distorce a imagem. O módulo aplica
object-fit: containjustamente para não esticar, mas vale conferir na tela. - Upgrade 10 para 11 - se o cliente já tinha branding manual no GLPI 10, ele vai sumir no 11 pelos seletores trocados. Trate o branding como parte do plano de upgrade, não como surpresa pós-migração.
Quer padronizar a identidade visual do GLPI em todos os ambientes que você administra, sem reabrir o assunto a cada atualização? O módulo Branding é gratuito e aplica a marca por hooks nativos. E, se preferir terceirizar a implantação e a sustentação do GLPI, a NexTool mantém ambientes de clientes com branding versionado e à prova de update.
Este conteúdo foi produzido com auxílio de inteligência artificial e revisado pela equipe Nextool Solutions.