Kubernetes Dashboard com proxy reverso e SSL é a publicação da interface web do cluster por trás de um proxy (como o Nginx) que termina o HTTPS, enquanto o serviço do Dashboard continua acessível só localmente. Isso não dispensa um ServiceAccount com poucas permissões nem restrição de acesso por IP ou VPN. Para instalar e proteger o Dashboard em um VPS Linux, siga estes passos:
- Confirme que o cluster (por exemplo K3s) responde com
kubectl get nodese que o Helm está instalado. - Instale o chart oficial do kubernetes-dashboard em um namespace próprio.
- Crie um ServiceAccount com a role
viewe gere um token temporário. - Exponha o Dashboard apenas em 127.0.0.1 com
kubectl port-forwardgerenciado pelo systemd. - Configure o Nginx como proxy reverso HTTPS para essa porta local e emita o certificado com o Certbot.
- Restrinja o acesso por IP, ative o firewall e teste o login e a renovação do certificado.
Pré-requisitos
- VPS Linux com Ubuntu 24.04 LTS (os comandos de pacote abaixo usam
apt), acesso root ou sudo e pelo menos 2 GB de RAM livres para o cluster e o Dashboard. - Cluster Kubernetes funcionando. Em um VPS único, o K3s é uma opção leve; veja Otimizar Kubernetes em VPS Linux: recursos e custos eficientes.
kubectlconfigurado para o cluster e Helm 3 instalado.- Um subdomínio (neste artigo,
dashboard.seudominio.com.br) com registro A apontando para o IP do VPS (exemplo: 203.0.113.10). - Portas 80 e 443 liberadas no firewall do VPS.
- Nginx e Certbot disponíveis no repositório padrão do Ubuntu 24.04 ou via snap.
Checklist de instalação do Dashboard com Helm
Atenção: o repositório do Kubernetes Dashboard foi arquivado e o projeto não recebe manutenção ativa. Antes de expor um painel administrativo do cluster, avalie alternativas mantidas, como o Headlamp, preferencialmente acessível apenas por VPN. Se precisar usar o Dashboard legado, fixe a versão no Helm, verifique a compatibilidade com a versão exata do Kubernetes em uso e nunca o exponha em rede pública sem VPN ou restrição de IP estrita.
A instalação por Helm é o método documentado pelo projeto, pois o chart já traz os componentes de autenticação, API e interface web. Nas versões recentes do chart (7.x), o Dashboard é composto por vários pods e o acesso é feito por um serviço chamado kubernetes-dashboard-kong-proxy, que usa HTTPS interno com certificado autoassinado.
Se você usa K3s, o kubectl já vem junto, mas o arquivo de configuração fica em /etc/rancher/k3s/k3s.yaml. Exporte a variável antes de continuar:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get nodes
A saída deve mostrar o nó com status Ready. Se o Helm ainda não estiver instalado, use o método oficial do projeto Helm e confirme com helm version.
Adicione o repositório e instale o chart:
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm repo update
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard \
--create-namespace --namespace kubernetes-dashboard
Aguarde os pods e confirme o estado:
kubectl -n kubernetes-dashboard get pods
kubectl -n kubernetes-dashboard get svc
Todos os pods devem estar em Running. Na lista de serviços, localize kubernetes-dashboard-kong-proxy, do tipo ClusterIP, na porta 443. Esse tipo de serviço não é acessível de fora do cluster, o que é exatamente o desejado: nenhuma porta do Dashboard fica aberta na internet.
Os nomes dos serviços podem variar conforme a versão do chart. Sempre confira a saída de kubectl get svc antes de apontar qualquer coisa para ele.
Criar ServiceAccount e token de acesso com menor privilégio
O login do Dashboard por token depende de um ServiceAccount, e as permissões dele definem o que quem entra pode fazer no cluster. Comece com a role view, que dá apenas leitura e já vem pronta no Kubernetes.
kubectl -n kubernetes-dashboard create serviceaccount leitor-dashboard
kubectl -n meu-namespace create rolebinding leitor-dashboard-view \
--clusterrole=view \
--serviceaccount=kubernetes-dashboard:leitor-dashboard
O comando acima concede a role view apenas no namespace meu-namespace. Se precisar de visibilidade em múltiplos namespaces, crie um RoleBinding separado em cada um deles com o mesmo comando, trocando o namespace. Usar um ClusterRoleBinding daria leitura em todos os namespaces do cluster de uma vez, o que costuma ser mais do que o necessário para um operador com escopo limitado.
Gere o token temporário:
kubectl -n kubernetes-dashboard create token leitor-dashboard
O comando imprime uma string longa (JWT). Ela expira; por padrão, a validade é curta e você pode ajustar com --duration, por exemplo --duration=2h. Prefira tokens de vida curta a tokens permanentes.
Atenção: evite associar o ServiceAccount à role cluster-admin, comum em tutoriais antigos. Com ela, qualquer pessoa com o token administra todo o cluster. A role view não permite ler Secrets, o que reduz o impacto de um vazamento. Se precisar de escrita, crie uma role específica por namespace em vez de liberar tudo.
Guarde o token apenas em um gerenciador de senhas e não o cole em chats ou tickets.
Expor o serviço apenas em localhost
Para o proxy reverso alcançar o Dashboard sem abrir uma porta pública, uma opção simples em VPS único é o kubectl port-forward ligado em 127.0.0.1. O Nginx, rodando no mesmo servidor, encaminha para essa porta local. O Dashboard continua sem exposição direta na internet.
Teste primeiro manualmente:
kubectl -n kubernetes-dashboard port-forward \
--address 127.0.0.1 svc/kubernetes-dashboard-kong-proxy 8443:443
Em outro terminal, valide com curl. O -k é necessário porque o certificado interno é autoassinado:
curl -k -I https://127.0.0.1:8443/
Você deve ver uma resposta HTTP com código 200, ou um redirecionamento, vinda do Dashboard. Interrompa o teste com Ctrl+C e torne o encaminhamento permanente com uma unidade do systemd:
sudo nano /etc/systemd/system/k8s-dashboard-forward.service
[Unit]
Description=Port-forward do Kubernetes Dashboard para localhost
After=network-online.target k3s.service
Wants=network-online.target
[Service]
Environment=KUBECONFIG=/etc/rancher/k3s/k3s.yaml
ExecStart=/usr/local/bin/kubectl -n kubernetes-dashboard port-forward --address 127.0.0.1 svc/kubernetes-dashboard-kong-proxy 8443:443
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now k8s-dashboard-forward.service
ss -tlnp | grep 8443
O ss deve mostrar a porta 8443 escutando em 127.0.0.1, e nunca em 0.0.0.0. Se o kubectl estiver em outro caminho no seu servidor (confira com which kubectl), ajuste o ExecStart. Se você não usa K3s, remova a referência ao k3s.service e aponte o KUBECONFIG para o seu arquivo.
Como alternativa mais robusta, é possível usar um Ingress Controller dentro do cluster. Aqui seguimos com o Nginx no host porque é o caso mais comum em VPS único e o que já aparece em Como Configurar um Servidor Proxy Reverso com Nginx no VPS Linux.
Configurar o Nginx como proxy reverso
O Nginx recebe as conexões na porta 443 e repassa o tráfego para o Dashboard em 127.0.0.1:8443. Como o backend usa HTTPS com certificado autoassinado, o proxy deve falar HTTPS com ele. Nesta etapa, crie apenas a configuração necessária para validar o domínio com o Certbot; o bloco de proxy será adicionado depois, somente no servidor HTTPS, após o certificado estar emitido.
sudo apt update
sudo apt install -y nginx
sudo mkdir -p /var/www/certbot
Para recursos que usam WebSocket (como logs e terminal de pods), o Nginx precisa de um bloco map no contexto http. Crie um arquivo de configuração separado que o Nginx inclui automaticamente:
sudo nano /etc/nginx/conf.d/connection-upgrade.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
Agora crie o virtual host inicial. Nesta primeira versão, a porta 80 serve apenas o desafio ACME e retorna 404 para todo o restante — o Dashboard não fica exposto em HTTP em nenhum momento:
sudo nano /etc/nginx/sites-available/dashboard.conf
server {
listen 80;
server_name dashboard.seudominio.com.br;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 404;
}
}
Ative o site e valide a sintaxe antes de recarregar:
sudo ln -s /etc/nginx/sites-available/dashboard.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Emitir o certificado SSL com Certbot
O certificado SSL Let's Encrypt criptografa o login e o token entre o navegador e o servidor. Antes, confirme que o DNS já aponta para o VPS. O utilitário dig requer o pacote dnsutils:
sudo apt install -y dnsutils
dig +short dashboard.seudominio.com.br
O resultado deve ser o IP do seu VPS (por exemplo, 203.0.113.10). Instale o Certbot e emita o certificado com validação webroot — esse método usa o diretório criado na etapa anterior e não expõe o Dashboard:
sudo apt install -y certbot
sudo certbot certonly --webroot -w /var/www/certbot -d dashboard.seudominio.com.br
O Certbot pede um e-mail e solicita aceite dos termos. Ao final, os arquivos do certificado ficam em /etc/letsencrypt/live/dashboard.seudominio.com.br/.
Com o certificado emitido, substitua o conteúdo de /etc/nginx/sites-available/dashboard.conf pela configuração completa, que inclui o redirecionamento HTTP e o proxy HTTPS:
server {
listen 80;
server_name dashboard.seudominio.com.br;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name dashboard.seudominio.com.br;
ssl_certificate /etc/letsencrypt/live/dashboard.seudominio.com.br/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dashboard.seudominio.com.br/privkey.pem;
location / {
proxy_pass https://127.0.0.1:8443;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 300s;
}
}
O proxy_ssl_verify off está explícito porque o certificado interno é autoassinado; como a conexão ocorre dentro do próprio servidor, em 127.0.0.1, o risco é baixo. A variável $connection_upgrade é definida pelo bloco map criado na etapa anterior e garante que Connection: upgrade seja enviado apenas em requisições WebSocket, e close nas demais. Aplique e recarregue:
sudo nginx -t
sudo systemctl reload nginx
Teste a renovação automática:
sudo certbot renew --dry-run
A mensagem final deve indicar que a simulação de renovação foi bem-sucedida. Para entender certificados para vários subdomínios, consulte Como Instalar e Configurar o Let's Encrypt Wildcard SSL no VPS Linux.
Após confirmar que o HTTPS funciona (veja a seção de testes a seguir), acrescente cabeçalhos de segurança no bloco server da porta 443 e recarregue:
add_header Strict-Transport-Security "max-age=300" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
Recarregue com sudo nginx -t && sudo systemctl reload nginx. O valor inicial max-age=300 (5 minutos) permite reverter rapidamente caso algo esteja errado. Depois de validar que o HTTPS funciona de forma estável por alguns dias, aumente para max-age=31536000 (um ano). O HSTS instrui o navegador a converter automaticamente qualquer requisição HTTP para HTTPS nesse host; se o endpoint HTTPS deixar de funcionar ou apresentar certificado inválido, o acesso falhará até o max-age expirar.
Restringir acesso por IP e autenticação extra
Mesmo com HTTPS, o painel de administração não deve ficar aberto a qualquer visitante. Uma camada extra no proxy reduz o risco de exploração de falhas e de força bruta no token. A forma mais direta é limitar por IP dentro do bloco location / do servidor HTTPS:
location / {
allow 198.51.100.25;
deny all;
proxy_pass https://127.0.0.1:8443;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
Substitua 198.51.100.25 pelo seu IP fixo. Quem tentar acessar de outro endereço recebe 403. Se o seu IP muda, a opção mais segura é acessar por VPN e liberar só o IP da VPN; veja Como Instalar e Configurar o OpenVPN no VPS Linux para Acesso Seguro Remoto.
Não use autenticação básica do Nginx (auth_basic) na frente do Dashboard. O frontend do Dashboard envia o token de acesso no cabeçalho Authorization: Bearer em todas as chamadas à API. O auth_basic usa o mesmo cabeçalho Authorization, e os dois entram em conflito: o login por token deixa de funcionar de forma consistente. Se precisar de uma barreira adicional além da restrição por IP, use VPN ou soluções que não disputem o cabeçalho Authorization, como oauth2-proxy ou autenticação por certificado de cliente no Nginx.
Por fim, configure o firewall com UFW. Em um nó K3s, as faixas de pods e de serviços precisam ser liberadas explicitamente para que a comunicação interna do cluster (CoreDNS, pods, serviços) continue funcionando. Configure a política padrão e adicione as regras antes de ativar:
sudo ufw default deny incoming
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 10.42.0.0/16 to any
sudo ufw allow from 10.43.0.0/16 to any
sudo ufw enable
sudo ufw status numbered
Os CIDRs 10.42.0.0/16 (pods) e 10.43.0.0/16 (serviços) são os padrões do K3s; ajuste se o seu cluster usar faixas diferentes. Em cluster multi-nó, libere também 6443/tcp, 8472/udp e 10250/tcp entre os nós. A porta 8443 não precisa de regra: ela escuta só em localhost e não é acessível de fora. Após ativar, audite as regras com sudo ufw status numbered e remova as que não forem necessárias; regras criadas pelo runtime do Kubernetes para NodePort ou LoadBalancer podem não estar representadas pelo UFW e precisam ser verificadas separadamente com sudo nft list ruleset ou sudo iptables -L -n.
Testar o acesso e validar a segurança
Com tudo configurado, o teste final confirma que o HTTPS funciona, que o backend não vaza e que o login por token entra. Do seu computador:
curl -I https://dashboard.seudominio.com.br
Você deve receber uma resposta HTTP/2 ou HTTP/1.1 com status 200. Verifique também o redirecionamento do HTTP:
curl -I http://dashboard.seudominio.com.br
Deve voltar um status 301 com o cabeçalho Location apontando para a versão HTTPS. Em seguida, acesse a URL no navegador, escolha a opção de login por Token e cole o token gerado.
Checklist final de validação:
- Pods do namespace
kubernetes-dashboardemRunning. - Porta 8443 escutando apenas em 127.0.0.1 (
ss -tlnp). - Certificado válido e renovação testada com
certbot renew --dry-run. - Acesso restrito por IP ou VPN.
- ServiceAccount com role
viewpor namespace, semcluster-admin. - Firewall ativo: política padrão
deny incoming, CIDRs do K3s liberados, regras auditadas comsudo ufw status numbered.
Para acompanhar consumo de CPU e memória do servidor depois da instalação, o monitoramento de recursos com Netdata no VPS Linux ajuda a perceber excesso de uso cedo.
Problemas comuns e como resolver
Sintoma: erro 502 Bad Gateway ao abrir o subdomínio
Causa: o Nginx não consegue falar com 127.0.0.1:8443, normalmente porque o port-forward caiu ou o serviço tem outro nome.
Solução: verifique sudo systemctl status k8s-dashboard-forward.service e ss -tlnp | grep 8443. Confirme o nome do serviço com kubectl -n kubernetes-dashboard get svc. Veja também /var/log/nginx/error.log. Se o proxy_pass usa http:// em vez de https://, corrija: o backend só responde em HTTPS.
Sintoma: o Certbot falha na validação do domínio
Causa: o DNS ainda não aponta para o VPS, a porta 80 está bloqueada no firewall ou outro serviço ocupa a porta 80.
Solução: confira com dig +short dashboard.seudominio.com.br, libere a porta 80 no UFW e no firewall do provedor, e verifique se há um único Nginx escutando com ss -tlnp | grep ':80'. Se o DNS passa por um proxy como a Cloudflare, o ideal é desativar o proxy durante a emissão ou usar validação por DNS.
Sintoma: o login com token é rejeitado ou volta à tela inicial
Causa: o token expirou, foi copiado com quebra de linha, o ServiceAccount não tem as permissões esperadas ou há conflito com autenticação adicional na camada do proxy.
Solução: gere um novo token com kubectl -n kubernetes-dashboard create token leitor-dashboard, copie-o em uma única linha e verifique os logs dos componentes de autenticação do Dashboard. Para diagnosticar loops de redirecionamento ou URLs geradas com esquema incorreto, investigue se os cabeçalhos proxy_set_header X-Forwarded-Proto estão presentes no bloco HTTPS. Se alguma camada de autenticação adicional estiver ativa na frente do Dashboard, remova-a para isolar a causa.
Sintoma: o Dashboard abre, mas mostra "forbidden" nas listas
Causa: o ServiceAccount não tem permissão para o recurso, o que é esperado com a role view em itens como Secrets.
Solução: confirme com kubectl auth can-i list pods --as=system:serviceaccount:kubernetes-dashboard:leitor-dashboard -n meu-namespace. Se precisar de mais acesso, crie uma role específica para o namespace necessário em vez de usar cluster-admin.
Sintoma: erro 403 ao acessar de casa ou do celular
Causa: seu IP mudou e não está mais na diretiva allow.
Solução: atualize o IP no virtual host, rode sudo nginx -t e recarregue. Para evitar manutenção constante, acesse por VPN com IP fixo.
Perguntas frequentes
Como instalar o Kubernetes Dashboard em um VPS Linux?
Com um cluster funcionando (por exemplo K3s) e o Helm instalado, adicione o repositório oficial do kubernetes-dashboard e execute helm upgrade --install em um namespace próprio. Depois crie um ServiceAccount com a permissão desejada, gere um token e valide que os pods estão em Running. O acesso externo deve ser feito por proxy reverso com HTTPS, nunca expondo o serviço diretamente.
Por que usar proxy reverso com SSL no Kubernetes Dashboard?
O Dashboard permite administrar o cluster, então o tráfego e o token de login precisam ser criptografados. O proxy reverso, como o Nginx, centraliza o certificado SSL, permite restringir IPs, adicionar autenticação extra e esconder o serviço interno. Assim a porta do Dashboard fica acessível apenas localmente.
Posso expor o Kubernetes Dashboard diretamente na internet?
Não é recomendado. Um Dashboard exposto com permissões amplas dá controle sobre o cluster a quem obtiver o token ou explorar uma falha. Prefira publicá-lo atrás de proxy reverso com HTTPS, restrição por IP ou VPN e um ServiceAccount com o mínimo de permissões necessárias.
Como gerar o token de acesso do Kubernetes Dashboard?
Crie um ServiceAccount e um RoleBinding adequado no namespace que deseja visualizar, depois execute kubectl -n kubernetes-dashboard create token nome-do-serviceaccount. O token é temporário e deve ser colado na tela de login. Use permissões somente leitura sempre que possível, como a role view.
Como emitir o certificado SSL para o Dashboard com Nginx?
Aponte o DNS do subdomínio para o IP do VPS, configure um virtual host Nginx que sirva apenas o desafio ACME na porta 80 e execute certbot certonly --webroot -w /var/www/certbot -d dashboard.seudominio.com.br. Após a emissão, atualize o virtual host com o bloco HTTPS completo incluindo proxy_pass. Confirme a renovação automática com certbot renew --dry-run.
Conclusão
Publicar o Dashboard com segurança depende de camadas: serviço só em localhost, HTTPS no proxy, acesso restrito e token com poucas permissões. Cada camada reduz o risco de alguém assumir o controle do cluster.
- Revise o ServiceAccount: mantenha a role
viewpor namespace comRoleBindinge gere tokens de curta duração com--duration. - Restrinja o subdomínio por IP ou VPN e confirme que a porta 8443 escuta apenas em 127.0.0.1.
- Teste a renovação com
certbot renew --dry-rune acompanhe o servidor com monitoramento de recursos.
Leia também
- Checklist de SSL: erros comuns ao renovar certificado no cPanel
- Checklist para configurar SSL Let's Encrypt no VPS Linux
- Como Instalar e Configurar o Let's Encrypt Wildcard SSL no VPS Linux
Precisa de ajuda com Kubernetes em VPS?
Um VPS com recursos dedicados facilita rodar K3s, Nginx e o Dashboard com HTTPS e firewall sob seu controle. Se precisar de apoio para dimensionar o servidor, nossa equipe pode orientar.