MySQL

Bancos MySQL 8 ou MariaDB no VPS com conta própria que exige TLS, permissões só no seu banco e acesso externo por IP.

  • Categoria: Servidores e infraestrutura
  • Estado: Disponível
  • Requisitos: Um VPS ativo com a função mysql disponível; Se o motor já existir: MySQL 8.x ou MariaDB 10.4 ou superior; Ser membro com acesso ao VPS para instalar; admin para revelar, abrir 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 MySQL é um app com conta própria. O motor (MySQL ou MariaDB) é um por VPS e compartilhado pelos seus bancos; se não existir, o MySQL é instalado a partir dos pacotes da distribuição.

  • Criar vários bancos utf8mb4, cada um com sua conta e suas permissões.
  • Revelar usuário, senha e URI de conexão.
  • Abrir o motor para a internet só para certos IPs, com TLS.
  • Pela aba MySQL do VPS: bancos, usuários, permissões e tabelas.

Quando convém usar?

  • Aplicações que esperam MySQL (PHP, Laravel, muitas ferramentas de terceiros).
  • Um WordPress usa este mesmo motor, com banco e conta próprios por site.

Como funciona na ArduMaker?

  1. Motor: se o agente disser que não está instalado, é instalado uma vez (mysql-server e mysql-client); se já existir, nunca é reinstalado nem muda de versão.
  2. Variante: lê-se mysql --version. Só MySQL 8.x ou MariaDB 10.4+; outra coisa falha motor_no_soportado sem executar SQL.
  3. Credencial app<id>_<hex> com senha aleatória, guardada criptografada antes de tocar o VPS.
  4. Entra-se como administrador pelo socket, com a senha em um arquivo de opções efêmero, nunca na linha de comando.
  5. Conta 'app<id>_<hex>'@'127.0.0.1' com REQUIRE SSL, e GRANT ALL PRIVILEGES só sobre <banco>.*, sem GRANT OPTION, antes de criar o banco.
  6. CREATE DATABASE <banco> CHARACTER SET utf8mb4 só se não existia.
  7. Verificação: TLS exigido, sem privilégios globais e permissões sobre um único banco, o seu.

A conta é @'127.0.0.1' de propósito: não % (abriria a conta para qualquer origem) nem localhost (socket, sem TLS). Quando o servidor não tem partial_revokes (ou é MariaDB), o _ do nome é escapado no GRANT, porque ali é um curinga.

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
MotorMySQL ou MariaDB escutando em 127.0.0.1:3306
Bancoutf8mb4; um nome igual com outras maiúsculas conta como o mesmo
Conta'app<id>_<hex>'@'127.0.0.1' REQUIRE SSL
TLS no MySQL 8SET PERSIST + ALTER INSTANCE RELOAD TLS, sem reinício
TLS no MariaDBArquivo 90-ardumaker-tls.cnf; na primeira vez exige reiniciar o motor

Acesso pela internet e lista de IP

Por padrão o motor escuta só dentro do VPS (3306 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 3306 do VPS e o firewall só deixa entrar os IPs da lista.

O certificado é próprio do nome db-<id> e é terminado pelo mysqld: o proxy do host só passa TCP. A conta do app exige SSL venha de onde vier.

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 MySQL 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): o banco é apagado e, se a conta foi criada pelo Apps, também a conta e sua senha guardada. Nunca uma conta do cliente nem root.
  • 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:3306
  2. Cliente externo: db-<id>:<porta> com verificação de identidade TLS
  3. Firewall e proxy do host: só IPs da lista → 3306 do VPS
  4. mysqld: termina o TLS; a conta exige SSL e vê só o seu banco
Conexões a um banco MySQL

Resultado esperado

A URI (sem senha) aparece quando o acesso externo está pronto; a completa é obtida com revelar_credencial_app.

mysql://app<id>_<hex>@db-<vps>.<zona>:<puerto>/<base>?ssl-mode=VERIFY_IDENTITY
mysql://app<id>_<hex>@db-<vps>.<zona>:<puerto>/<base>?sslMode=verify-full   (MariaDB)

Erros e resolução

ErroCausaTentar de novo?
motor_no_soportadoNão é MySQL 8.x nem MariaDB 10.4+; nada é tocadoNão
base_ya_existeExiste um banco com esse nome (sem distinguir maiúsculas) sobre o qual a conta não tem permissõesNão
motor_detenido / base_no_creada / permisos_no_verificadosMotor parado, SQL com falha ou permissões que não verificaramSim
requiere_reinicioO MariaDB precisa reiniciar para o primeiro TLS; o acesso não abre até resolverApós reiniciar
Acesso externo não pedidoO motor tem contas anônimas ou sem senha que o listener exporiaApós limpar essas contas

As demais causas (lista de IP, TLS, credenciais antigas, fechamento não verificado) são as mesmas do PostgreSQL. O acompanhamento é com ver_operacion_app e reintentar_operacion_app.

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: mysql (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