PostgreSQL, apesar de ser um RDBMS moderno e versátil, não é o mais fácil de configurar e executar enquanto você procura desenvolver um aplicativo. Leia para saber como você pode começar com a versão mais recente do PostgreSQL na versão LTS do Ubuntu.
Instalação
O Ubuntu 18.04 vem com o PostgreSQL 10, mas podemos usar o repositório APT hospedado pela equipe do PostgreSQL para instalar a versão mais recente, o PostgreSQL 11.
Você pode configurar o repositório usando estes comandos:
# add the repository
sudo tee /etc/apt/sources.list.d/pgdg.list <<END
deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main
END
# get the signing key and import it
wget https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo apt-key add ACCC4CF8.asc
# fetch the metadata from the new repo
sudo apt-get update
E, em seguida, instale o próprio software, usando:
sudo apt-get install postgresql-11
A instalação faz algumas coisas:
- Instala o servidor PostgreSQL, utilitários e um cliente de linha de comando chamadopsql .
- Cria um usuário do sistema Linux chamado postgres . Todos os arquivos de dados são de propriedade deste usuário e todos os processos são executados como este usuário.
- Cria um banco de dados, também chamado de postgres .
- Cria um usuário PostgreSQL (não o usuário do sistema Linux), também chamado depostgres .
Você pode ver que isso está começando a ficar confuso!
Clusters de banco de dados
Seu servidor PostgreSQL recém-instalado consiste em um conjunto de processos que gerenciam o que é conhecido como “cluster de banco de dados”. Você pode ver os processos aqui:
alice@devbox:~$ ps axfww | grep postgres
4737 ? S 0:00 /usr/lib/postgresql/11/bin/postgres -D /var/lib/postgresql/11/main -c config_file=/etc/postgresql/11/main/postgresql.conf
4749 ? Ss 0:00 \_ postgres: 11/main: checkpointer
4750 ? Ss 0:00 \_ postgres: 11/main: background writer
4751 ? Ss 0:00 \_ postgres: 11/main: walwriter
4752 ? Ss 0:00 \_ postgres: 11/main: autovacuum launcher
4753 ? Ss 0:00 \_ postgres: 11/main: stats collector
4754 ? Ss 0:00 \_ postgres: 11/main: logical replication launcher
O processo principal (aqui com o PID 4737) é o processo principal que gera ainda mais os processos filhos – isso é convencionalmente chamado de processo “postmaster”.
O uso do termo “cluster” pelo PostgreSQL é anterior ao jargão moderno de cluster distribuído – aqui significa apenas um conjunto de bancos de dados gerenciados em uma única máquina por um único postmaster. Leia mais sobre clusters aqui.
Um cluster contém bancos de dados (por enquanto temos apenas um, “postgres”) e usuários do PostgreSQL (novamente, apenas um por enquanto, também chamado de “postgres”) entre outras coisas. Só para você saber, o cluster está associado a um monte de arquivos de dados, todos em um único diretório - neste caso, em/var/lib/postgresql/11/main . Você notou esse caminho na linha de comando do postmaster acima?
Quando seu aplicativo, ou psql, se conecta ao Postgres, ele deve fazer isso no contexto de um usuário do PostgreSQL. Há sempre um usuário do PostgreSQL associado a uma conexão. Mas, como você já deve ter adivinhado, um usuário do PostgreSQL pode ou não corresponder a um usuário do sistema.
Usuários do sistema e usuários do PostgreSQL
Os usuários do PostgreSQL podem ser criados usando comandos SQL como CREATE ROLE ou ferramentas agrupadas como createdb.
Quando qualquer aplicativo tenta se conectar ao Postgres, ele precisa fornecer um nome de usuário do PostgreSQL. Vamos ver o que acontece quando você inicia um cliente PostgreSQL como o psql:
alice@devbox:~$ psql
psql: FATAL: role "alice" does not exist
Aqui, “alice” é o seu nome de usuário do sistema Linux. O psql recebe este nome e usa como nome de usuário Postgres. Uma função (funções são um nome genérico de classificação para “usuário” ou “grupo”, BTW) com esse nome não existe, que é o que o Postgres está reclamando.
Sabemos que existe um papel com o nome “postgres”, então vamos tentar isso. Podemos usar o parâmetro “-U” do psql para especificar o nome de usuário:
alice@devbox:~$ psql -U postgres
psql: FATAL: Peer authentication failed for user "postgres"
OK, estamos chegando mais perto – a função/usuário “postgres” existe, mas a “peerauthentication” falhou. O que é essa “autenticação de pares”?
Autenticação de peer e senha
Clientes PostgreSQL como psql ou seu aplicativo podem se conectar ao servidor PostgreSQL por meio de um destes mecanismos IPC:
- Soquetes de domínio Unix
- Soquetes TCP
Ao contrário dos soquetes TCP, os soquetes de domínio Unix oferecem a possibilidade de validar o ID do usuário do sistema da conexão do cliente. O servidor Postgres pode examinar uma conexão de entrada em um soquete de domínio Unix e determinar o ID de usuário do sistema do cliente e então decidir se concede acesso ou não.
Por padrão, seu servidor apenas escuta conexões em soquetes de domínio unix e não em TCP/IP.
Vamos ver o que acontece se tentarmos iniciar o psql como usuário do sistema postgres:
alice@devbox:~$ sudo -u postgres psql
psql (11.0 (Ubuntu 11.0-1.pgdg18.04+2))
Type "help" for help.
postgres=#
Isso funcionou! (Use “\q”, “\quit” ou
^D
para sair do psql, BTW.) Na autenticação peer, se a conexão do cliente for feita usando um soquete de domínio Unix e o processo cliente tiver o mesmo nome de usuário do sistema que o usuário PostgreSQL com o qual está tentando se conectar, a autenticação será considerada bem-sucedida.
Os usuários do PostgreSQL também podem receber uma senha opcionalmente, e você pode pedir ao PostgreSQL para validar as conexões de entrada usando a senha. Mas como? Essa é a próxima peça do quebra-cabeça.
pg_hba.conf
Agora é hora de abrir o (in)famoso arquivo de configuração pg_hba.conf, localizado em
/etc/postgresql/11/main/pg_hba.conf
:sudo vim /etc/postgresql/11/main/pg_hba.conf
HBA significa autenticação baseada em host. Basicamente, este arquivo é usado para controlar como os usuários do PostgreSQL são autenticados. Este arquivo é provavelmente a parte menos intuitiva da curva de aprendizado do PostgreSQL. A documentação de referência está aqui, você deve lê-la mais tarde.
A primeira linha (sem comentários) aqui é:
local all postgres peer
que diz ao Postgres para aceitar conexões “locais” (domínio unix) para “todos” os bancos de dados, autenticando como usuário “postgres” usando autenticação “peer”. É por isso que conectar como o usuário do sistema “postgres” funciona imediatamente.
A ordem das linhas neste arquivo é importante, a primeira linha correspondente vence. Vamos ver outra linha:
host all all 127.0.0.1/32 md5
Esta linha permite que “todos” os usuários façam login usando TCP/IP (“host”) do localhost (“127.0.0.1/32”) para “todos” os bancos de dados, caso tenham sucesso na autenticação de senha usando o método “md5”.
Existem mais métodos de autenticação de senha (md5, scram-sha-256, gss,ldap, …) do que podemos cobrir, então vamos voltar aos exemplos mais simples.
Mas primeiro, precisamos ter certeza de que o PostgreSQL também aceita conexões TCP/IP. Para isso, precisamos editar o arquivo de configuração principal.
postgresql.conf
O arquivo /etc/postgresql/11/main/postgresql.conf é o arquivo de configuração principal para seu cluster PostgreSQL. Este arquivo contém um lote de configurações, e entender o que tudo isso significa não é tarefa fácil. Por enquanto, vamos ver a primeira configuração:
#listen_addresses = 'localhost'
Esta linha é comentada por padrão, vamos descomentá-la para torná-la lida:
listen_addresses = 'localhost'
Isso permitirá que o PostgreSQL escute as conexões TCP/IP de entrada no host local, porta 5432 (o padrão). Salve as alterações (você terá que ser “root” para fazer isso) e reinicie o servidor Postgres para que as alterações tenham efeito:
sudo systemctl restart postgresql
(Observe que, para a maioria das alterações de configurações, você só precisa “recarregar”, não “reiniciar”, mas isso requer uma “reinicialização”).
Agora podemos ver o Postgres escutando na porta 5432, vinculada a 127.0.0.1:
alice@devbox:~$ sudo netstat -tnlp | grep 5432
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 8408/postgres
Agora vamos configurar um novo usuário e banco de dados para uso por um aplicativo.
Configuração do aplicativo
Vamos nos conectar como o superusuário “postgres” para fazer as alterações:
alice@devbox:~$ sudo -u postgres psql
psql (11.0 (Ubuntu 11.0-1.pgdg18.04+2))
Type "help" for help.
postgres=# create user myapp_user password 's3cr3t';
CREATE ROLE
postgres=# create database myapp owner myapp_user;
CREATE DATABASE
postgres=#
Agora criamos um banco de dados chamado
myapp
e um usuário chamado myapp_user
,com a senha s3cr3t
. O banco de dados está vazio e será de propriedade do usuáriomyapp_user
, o que significa que, conectando-se como myapp_user
o cliente poderá executar quase todos os comandos DDL/DML. Vamos nos conectar ao banco de dados do aplicativo como este usuário do aplicativo agora:
alice@devbox:~$ psql -h 127.0.0.1 -d myapp -U myapp_user
Password for user myapp_user:
psql (11.0 (Ubuntu 11.0-1.pgdg18.04+2))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
myapp=>
Funcionou! Agora você está conectado a “myapp” (veja o prompt), usando SSL sobre uma conexão TCP/IP para 127.0.0.1. Observe que especificamos o nome do banco de dados também na linha de comando do psql. Por razões históricas, se isso for omitido, o nome do banco de dados também será considerado o mesmo que o nome de usuário do sistema (“alice” aqui), o que não é o que queremos. O nome de usuário do PostgreSQL também é especificado ("-U myapp_user").
Se você precisar se conectar de outras máquinas, precisará editar
pg_hba.conf
para adicionar linhas assim:# existing entry, allows connections from localhost
host all all 127.0.0.1/32 md5
# new entry to allow connections from 10.1.2.0/24 subnet,
# only to myapp database for myapp_user
host myapp myapp_user 10.1.2.0/24 md5
e recarregue o PostgreSQL (“sudo systemctl reload postgresql”) para que as alterações tenham efeito.
Com isso em vigor, agora você pode usar strings de conexão de banco de dados como estas em seus aplicativos:
# URL format
postgresql://myapp_user:[email protected]/myapp
# connection string format
host=127.0.0.1 user=myapp_user dbname=myapp password=s3cr3t
Pronto!
Isso deve fazer com que você configure um banco de dados e um usuário dedicados para seu aplicativo. Seu framework de desenvolvimento de aplicativos (como Django, Drupal etc.) deve ser capaz de criar objetos (como tabelas, visualizações) e gerenciar os dados neste banco de dados.