Notebook (Jupyter) — Guia do Administrador
Dar Python aos analistas costumava significar instalar ambientes locais, distribuir credenciais por e-mail e perder o controle de onde os dados vão parar. Com o ambiente de Notebook do DATTA, cada analista ganha um Jupyter completo dentro da própria plataforma — mesma identidade, mesmo visual, acesso pronto às fontes de dados — e você mantém as credenciais e o isolamento sob controle central. Este guia cobre como habilitar o ambiente, o modelo de segurança das credenciais e o diagnóstico dos problemas mais comuns.
Público: administração e operação. Para o uso do notebook pelo analista, veja o Guia do Notebook e o
O que o analista recebe
- Jupyter Lab completo (notebook + terminal), acessível em , sem nenhuma instalação local.
- Ambiente individual e isolado por usuário, criado sob demanda pelo JupyterHub.
- Conectores prontos para as fontes da plataforma — Neo4j, OpenSearch, Trino, cache da plataforma, MinIO e Spark Connect — com as credenciais de dados já injetadas no ambiente.
- Identidade única: não existe login separado. Quem está autenticado no DATTA entra no Notebook automaticamente.
Como a identidade viaja
O portal do Notebook pede à plataforma um cookie de sessão HttpOnly (datta_jwt), restrito ao caminho /jupyter. O autenticador do JupyterHub valida esse token (HS256, HS384 ou HS512), exige o perfil ANALISTA ou ADMIN e cria o usuário do hub a partir do e-mail normalizado — @ e . viram -. O endpoint que emite esse cookie está descrito na referência de API.
O tráfego de /jupyter/ vai direto ao proxy público do JupyterHub, na porta 8000; ele não passa pelo proxy de entrada da plataforma, que mantém uma rota equivalente apenas como contingência interna. Vale a atenção ao endereço interno correto: é jupyterhub-proxy-public:8000 — não existe um endereço chamado apenas jupyterhub. A variável de configuração JUPYTER_URL e o padrão usado pelo Copilot apontam para o proxy público.
Como habilitar em produção
1. Imagem do ambiente individual
A imagem jupyter-datta é construída a partir de docker/jupyter-datta/ (base quay.io/jupyter/minimal-notebook, mais os drivers de Neo4j, OpenSearch, Trino, cache da plataforma e MinIO, o Spark Connect e o tema DATTA). Ela é identificada pelo último commit que alterou essa pasta (SHA curto de 7 caracteres), desacoplada do SHA do release Java: um release que não toca o Notebook não reconstrói a imagem nem a troca nos ambientes já abertos, e git show <tag> mostra exatamente o que está no ar.
Você não calcula nem fixa essa tag à mão. O instalador e o script de release derivam a tag, constroem e publicam a imagem só quando ela ainda não existe no registro (a construção leva ~10 min e 3 GB) e passam a tag ao chart (jupyter.singleuser.image.tag) a cada implantação. Para construir ou reconstruir fora do release:
./scripts/datta-build-jupyter.sh # tag derivada do git
./scripts/datta-build-jupyter.sh --force # reconstrói mesmo existindoChamado de fora do servidor com o registro do on-prem, o script constrói no servidor, a partir do commit publicado no GitHub — o registro só aceita conexão de dentro do cluster, e o commit precisa estar publicado.
A imagem passa por varredura de vulnerabilidades antes de ser publicada; um resultado HIGH/CRITICAL com correção disponível bloqueia o push.
O Spark do notebook é só cliente: a imagem traz o cliente Spark Connect 4.2.0, sem a distribuição Java embutida. Duas consequências práticas:
- a versão tem de ser a mesma do servidor Spark Connect (
k8s/jupyter/spark-connect.yml) — cliente e servidor falam o mesmo protocolo dentro de uma linha maior, então subir um sem o outro derrubaria a conexãosc://; - não há Spark local dentro do notebook: uma sessão criada com
master("local")não existe mais. O caminho édatta_clients.spark, que conecta ao servidor. Isso tira da imagem 2 GB de bibliotecas Java que vinham com falhas críticas impossíveis de corrigir isoladamente — elas viajam dentro do pacote do Spark, e é o pacote que deixou de vir.
Nunca use um latest flutuante.
Com jupyter.prepull.enabled: true (o padrão da instalação), cada máquina do cluster baixa a imagem logo após a implantação. Sem isso, a primeira abertura do Notebook em cada máquina paga o download inteiro dentro do tempo limite de criação do ambiente — a tela fica minutos em "Iniciando…" ou falha.
2. Configuração da instalação
values-onprem-local.yaml traz jupyter.enabled: true. As credenciais (jupyter.serviceToken, as chaves de MinIO e os demais segredos) vêm do arquivo .env — ou do release atual, por contingência — e são injetadas pelo script de release.
3. Implantação
Rode ./scripts/datta-release.sh (release uniforme). Ele sobe o hub, o proxy, os endereços internos, o cofre dedicado jupyter-user-secrets e a regra de roteamento de /jupyter/.
Modelo de segurança das credenciais
O ambiente de Notebook executa código arbitrário do analista. Por isso ele recebe credenciais de um cofre dedicado (jupyter-user-secrets), nunca o cofre de segredos da plataforma inteiro (datta-secrets).
O cofre dedicado contém somente o escopo "Dados + MinIO", e cada valor é de um usuário próprio, de menor privilégio (auditoria de 2026-09-04):
NEO4J_PASSWORD— do usuáriojupyter_reader(papelreader: só leitura em todo banco), criado pelo job de inicialização do Neo4j. Nunca a senha do superusuárioneo4j.MINIO_ACCESS_KEY=jupytereMINIO_SECRET_KEY— usuário com a políticadatta-jupyter: leitura nos buckets de warehouse e documentos, leitura e escrita só no bucket de staging. Nunca as chaves root.- OpenSearch: sem credencial enquanto o plugin de segurança estiver desligado; quando for ligado, um usuário de leitura entra aqui como
OPENSEARCH_PASSWORD.
As senhas dos dois usuários são geradas e preservadas no cofre da plataforma (JUPYTER_NEO4J_PASSWORD, JUPYTER_MINIO_PASSWORD) e chegam ao ambiente do notebook por referência a essas duas chaves específicas, nunca ao cofre inteiro. O cofre dedicado passa a guardar apenas o nome do usuário MinIO.
Por que isso importa: o cofre da plataforma carrega JWT_SECRET, DATTA_VAULT_MASTER_KEY, GEMINI_API_KEY, DATTA_INTERNAL_TOKEN, ADMIN_DEFAULT_PASSWORD e outros. Um analista leria qualquer um deles com um os.environ de dentro de uma célula — expor o cofre inteiro seria vazamento de segredos da plataforma.
Duas decisões complementam o isolamento:
- Cofre estreito injetado por bloco, não chave a chave. O criador de ambientes não consegue mesclar listas de variáveis de ambiente: uma referência por chave apagaria a lista de variáveis que ele mesmo define. Por isso o cofre é estreito e injetado inteiro.
- Sem token de infraestrutura. O ambiente individual sobe sem montar automaticamente o token de conta de serviço do cluster — de dentro do notebook não há credencial de administração da infraestrutura.
Copilot cria notebooks (recurso opcional)
O Copilot do chat consegue criar notebooks .dattanb prontos no ambiente do usuário, usando a Contents API do Jupyter. Isso exige um service token do JupyterHub, registrado no hub com o escopo access:servers — um token do DATTA não é um token válido do JupyterHub.
- O token vem de
JUPYTER_SERVICE_TOKEN, gerado pelosetup-datta.she persistido no.env. - Sem ele, o hub não registra o serviço e a criação de notebook pelo Copilot fica desativada com aviso amigável — todo o restante do Notebook funciona normalmente.
- O script de release preserva
jupyter.serviceTokenentre releases, então a habilitação não se perde a cada implantação.
Diagnóstico rápido
| Sintoma | Causa provável | Ação |
|---|---|---|
| "Notebook indisponível" (estado de erro, com o código HTTP quando houver) | o hub não respondeu — pode estar reiniciando ou estar com jupyter.enabled=false; do navegador as duas causas são indistinguíveis | Aguarde alguns segundos e recarregue a página (F5); se persistir, confirme jupyter.enabled: true na configuração da instalação e verifique a saúde do hub pelo console da plataforma |
| "Verificando…" que nunca termina | Já corrigido: a tela tinha saídas sem estado (sessão ausente, perfil sem acesso, cookie recusado, hub mudo) e nenhum tempo limite | A tela é uma máquina de estados: cada verificação tem tempo limite e toda saída pinta a barra (indisponível, sem sessão, sem permissão, parado, iniciando com percentual, ativo, erro com "Tentar de novo"); force a recarga do asset no navegador |
| Iframe vazio / "refused to connect" | Política frame-ancestors do hub ou do ambiente individual | Já tratado: o hub e os argumentos do criador de ambientes definem frame-ancestors 'self' |
Erro de permissão em /home/jovyan | O volume do diretório pessoal nasce com dono root | Já tratado: um passo de inicialização ajusta a propriedade para o usuário do notebook, e ele faz parte da instalação |
| Copilot não cria notebook | JUPYTER_SERVICE_TOKEN ausente | Defina no .env e reimplante — recurso opcional, o Notebook segue funcionando sem ele |
| Notebook não conecta a Neo4j/OpenSearch/MinIO | Credencial ausente no cofre dedicado | Confira que jupyter-user-secrets tem as quatro chaves de dados |
| "Iniciando…" por minutos na primeira abertura | A imagem (~3 GB) ainda não estava na máquina | Ative jupyter.prepull.enabled (padrão da instalação) — o aquecimento acontece logo após a implantação, não no primeiro clique |
| Ambiente não sobe e o hub registra imagem não encontrada | A tag da imagem passada ao chart não existe no registro | Rode ./scripts/datta-build-jupyter.sh (constrói e publica a tag derivada do git) e reimplante |
Para separar em qual porta o acesso para (hub, emissão do cookie, aceite do cookie pelo hub, criação do ambiente), siga o runbook Notebook — diagnóstico E0, que traz as quatro chamadas na ordem.
Para saber mais
- Guia do Notebook — uso do notebook pelo analista. de notebooks.
- Perfis e permissões — de onde vêm os perfis
ANALISTAeADMIN.