PostgreSQL

Bancos PostgreSQL no VPS com usuário próprio de privilégio mínimo, TLS e acesso externo limitado por lista de IP.

  • Categoria: Servidores e infraestrutura
  • Estado: Disponível
  • Requisitos: Um VPS ativo com a função postgresql disponível; Ser membro com acesso ao VPS para instalar; admin para revelar a credencial, abrir o acesso ou apagar dados
  • Ferramentas MCP (Só leem): ver_catalogo_apps, ver_preflight_app, ver_app, ver_acceso_app, ver_operacion_app, listar_motores_db_vps, listar_bases_db_vps
  • Ferramentas MCP (Escrevem ou modificam): instalar_app, revelar_credencial_app, cambiar_lista_ip_app, reintentar_operacion_app
  • Ferramentas MCP (Destrutivas): revocar_acceso_app, desinstalar_app

Markdown

O que permite fazer?

Cada banco PostgreSQL é um app: tem seu nome, seu usuário próprio com senha aleatória e, se pedido, acesso pela internet com TLS e lista de IP. O motor é instalado uma única vez por VPS e é compartilhado por todos os seus bancos.

  • Criar vários bancos no mesmo motor, cada um isolado dos outros.
  • Ver a credencial (usuário, senha e URI de conexão) quando necessário.
  • Abrir, alterar ou fechar o acesso pela internet por IP.
  • Explorar tabelas e dados pelo gerenciador de bancos de dados.
  • Pela aba PostgreSQL do VPS: listar e criar bancos, usuários e permissões.

Quando convém usar?

  • Uma aplicação publicada no mesmo VPS que precisa de um banco relacional (conecta por 127.0.0.1:5432).
  • Um serviço externo (BI, outra nuvem, um computador) que precisa ler o banco com TLS a partir de IPs conhecidos.

Como funciona na ArduMaker?

  1. Validar: VPS ativo e função postgresql do sistema.
  2. Motor: se não estiver instalado, é instalado uma única vez (pacotes postgresql e postgresql-contrib da distribuição, senha administrativa aleatória guardada criptografada). Se já estava, não é reinstalado nem muda de versão ou senha.
  3. Credencial: é gerado um usuário app<id>_<hex> com senha aleatória, criptografada na plataforma antes de tocar o VPS.
  4. Papel e banco: o papel é criado LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION; o banco é criado com esse papel como dono, tudo é revogado de PUBLIC e uma linha hostssl <banco> <papel> … scram-sha-256 é adicionada ao pg_hba.conf, com uma rejeição abaixo para qualquer outro banco.
  5. Verificação: o papel não pode ser superusuário nem criar bancos ou papéis, é dono do seu banco e PUBLIC não se conecta. Se algo não bater, falha permisos_no_verificados.
  6. Acesso externo: só se pedido com IPs. O TLS do motor é ativado e a abertura é pedida como operação separada; se ainda não puder abrir, o banco fica instalado assim mesmo e o motivo é registrado.

O SQL viaja codificado no ambiente e entra por stdin; a senha nunca aparece em uma linha de comando nem em um log.

config.external_access decide se o banco sai para a internet: {"ips": [...]} abre só para esses IPs; {"local": true} (ou false) o deixa só dentro do VPS. Se não for informado, pelo painel usa-se o IP de quem instala; via MCP o IP do agente não conta, então sem ips o banco fica local em vez de falhar.

O que muda realmente?

O quêDetalhe
MotorServiço postgresql habilitado, escutando em 127.0.0.1:5432
BancoNome [A-Za-z_][A-Za-z0-9_]{0,62}, com maiúsculas como estão (entre aspas)
Papel do appapp<id>_<hex>
pg_hba.confSeu bloco hostssl e um reject para os demais bancos
TLS (se houver acesso externo)Certificado próprio em /etc/ardumaker/tls/, ssl=on, TLS 1.2 no mínimo, recarga sem reinício

Acesso pela internet e lista de IP

Por padrão o motor escuta só dentro do VPS (5432 em 127.0.0.1). Para usar o banco de fora, a ArduMaker publica um endpoint próprio do motor: db-<id do VPS> dentro da zona da plataforma (registro DNS direto, sem proxy), em uma porta reservada entre 61000 e 64999. No host, um proxy leva essa porta ao 5432 do VPS e o firewall só deixa entrar os IPs da lista.

O certificado é próprio desse nome (não um curinga) e é instalado no motor: o PostgreSQL ativa ssl com TLS 1.2 no mínimo e recarrega a configuração sem reiniciar. O usuário do app só entra por TCP com TLS (hostssl) e só no seu banco.

Regra da listaDetalhe
FormatoIPv4 ou IPv6, com ou sem prefixo; um IP solto é /32 ou /128. Nada de nomes, loopback, link-local nem multicast
AmplitudePrefixo mínimo /24 em IPv4 e /48 em IPv6 por padrão; 0.0.0.0/0 e ::/0 são recusados na lista
TamanhoAté 20 entradas; vazia = fechado para todos
Nomes de hostAté 5 (allowed_hosts), com até 8 IPs públicos cada; são resolvidos de novo a cada 5 minutos e uma falha de DNS mantém o último conhecido
Aberto a todosSó com allow_any e confirm_open juntos; a resposta informa em open_to_any

A lista é do motor, não de cada banco: alterá-la a partir de qualquer banco PostgreSQL muda o acesso de todos os bancos desse motor nesse VPS (a resposta indica com shared_with_engine e affected_apps).

  1. As regras de firewall que faltam são adicionadas, uma por CIDR (ufw allow from <cidr> to any port <porta> proto tcp).
  2. Depois as que sobram são removidas e suas conexões abertas são cortadas.
  3. Só então o listener é criado e verificado: regras iguais à lista, nenhuma regra aberta a qualquer um, listener presente e handshake TLS com o nome correto.

Desinstalar, persistência e cópias

  • Sem delete_data (o normal): o acesso externo próprio é fechado e o app deixa de aparecer como instalado, mas o banco, seu usuário e seus dados ficam no VPS. A próxima reconciliação o mostra como detectado. Nada se perde.
  • Com delete_data: true (confirmado duas vezes, só admin): DROP DATABASE e, se o usuário foi criado pelo Apps (app<id>_<hex>), também o papel e sua senha guardada. Nunca um usuário do cliente nem o administrador do motor.
  • O motor nunca é desinstalado pelo Apps: fica instalado mesmo sem bancos.
  • Se o VPS ou o motor não responderem, desinstalar_app com forzar=true tenta cada passo uma vez, remove o app e lista em not_cleaned o que ficou no servidor.
  • Os dados vivem no disco do VPS e viajam na sua cópia semanal, feita com o VPS ligado. Para uma cópia consistente de um banco específico convém também um dump próprio pelo gerenciador de bancos de dados (exportar) ou com as ferramentas do motor.

Esquema

  1. App no mesmo VPS: 127.0.0.1:5432
  2. Cliente externo: db-<id>:<porta> com sslmode=verify-full
  3. Firewall do host: só os IPs da lista
  4. Proxy do host: porta 61000–64999 → 5432 do VPS
  5. PostgreSQL: hostssl + scram-sha-256, só o seu banco
Conexões a um banco PostgreSQL

Resultado esperado

O banco aparece em Apps pendurado no seu motor. ver_acceso_app mostra estado, host, porta, TLS e a lista aplicada; revelar_credencial_app devolve usuário, senha e a URI. A URI só existe quando o acesso externo está pronto:

postgresql://app<id>_<hex>@db-<vps>.<zona>:<puerto>/<base>?sslmode=verify-full

Erros e resolução

ErroCausaTentar de novo?
base_ya_existeJá existe um banco com esse nome de outro dono; não é sobrescrito nem adotadoNão
motor_detenido / motor_instalandose / motor_no_instaladoO motor está parado, instalando ou não pôde ser instaladoSim
base_no_creada / permisos_no_verificadosO SQL falhou ou as permissões do papel não verificaramSim
lista_ip_invalida / lista_ip_demasiado_ampliaEntrada malformada ou faixa mais ampla que o mínimo; data.invalid diz quaisCorrigindo a lista
credencial_legacy / cuentas_del_motor_sin_verificar / tls_no_disponibleO motor ainda não cumpre as condições para ser exposto (senhas antigas, contas do cliente não verificadas ou TLS pendente)Após resolver
acceso_externo_no_habilitadoO acesso externo não está habilitado para esse tipo na empresaNão
cierre_no_verificadoAo fechar ficou uma regra ou o listener; é informado o que realmente existeSim

Estado e passos de cada operação: ver_operacion_app (inclui se pode ser repetida). Uma operação falha que pode ser repetida é retomada do passo que falhou com reintentar_operacion_app, sem reinstalar o motor. Pedir a lista que já está aplicada não enfileira nada (idempotent: true).

Relação com MCP

Todo o ciclo do banco é operado via MCP com as permissões da pessoa que autorizou o agente. Referência em /mcp/docs e /mcp/bases-de-datos.

  • Leitura: ver_catalogo_apps, ver_preflight_app, listar_apps_empresa, ver_app, ver_acceso_app (host, porta, TLS e lista de IP, sem segredos), ver_operacion_app.
  • Modificam: instalar_app com app_type: postgres (exige idempotency_key), cambiar_lista_ip_app (só se o dono for admin; os IPs são informados explicitamente: o IP do agente não é o da pessoa), reintentar_operacion_app, refrescar_apps.
  • Sensível: revelar_credencial_app (só admin, não aceita idempotency_key; a resposta vem marcada sensible: true e a auditoria registra que foi revelado, nunca o valor).
  • Destrutivas: revocar_acceso_app (fecha o acesso externo de todo o motor) e desinstalar_app (com delete_data apaga os dados; exige confirm_delete_data).

Para ler e escrever dados dentro do banco, o agente usa as ferramentas do gerenciador de bancos de dados. Um agente autorizado como somente leitura não vê as ferramentas que modificam nem pode revelar credenciais.

Funcionalidades relacionadas