Instalar e configurar o PostgreSQL no Debian e no Ubuntu

Publicado a 18 min de leitura

Instalação a partir do pacote da distribuição ou do repositório PGDG, primeiro acesso através do utilizador postgres, criação da base de dados e do role, o pg_hba.conf explicado e um backup que aguenta mesmo.

No Debian e no Ubuntu, o PostgreSQL instala-se em dois minutos. As duas horas seguintes costumam ir-se embora porque ninguém consegue iniciar sessão. Este artigo leva a instalação até ao fim: escolha do pacote, primeiro acesso, base de dados e utilizador, as regras de acesso em pg_hba.conf e um backup que se sabe mesmo restaurável.

Todos os comandos correm como root. Se iniciar sessão com um utilizador normal, anteponha sudo. O número de versão 17 nos caminhos deve ser substituído pela versão que está realmente instalada no seu sistema.

Que versão do PostgreSQL vem em cada distribuição

A diferença mais importante entre os quatro sistemas habituais é a versão principal que vem do repositório da distribuição. Está fixada ao release e já não muda ao longo de todo o ciclo de vida da distribuição.

DistribuiçãoPostgreSQL do repositório da distribuição
Debian 13 (trixie)17
Debian 12 (bookworm)15
Ubuntu 24.04 LTS (noble)16
Ubuntu 22.04 LTS (jammy)14

Esta dispersão tem consequências práticas. Um dump feito no Debian 13 não se carrega sem mais no Ubuntu 22.04. E quem trabalha no Ubuntu 22.04 deve saber que, segundo a política de versões do PostgreSQL Global Development Group, o PostgreSQL 14 sai do suporte comunitário a 12 de novembro de 2026. O Ubuntu continua a fornecer atualizações de segurança para a 22.04 no âmbito do ciclo LTS, mas deixam de chegar correções upstream. Para projetos novos na 22.04, é um forte argumento para recorrer logo ao repositório PGDG.

O que está disponível no seu sistema mostra-se com uma olhadela à base de dados de pacotes, antes de instalar seja o que for:

apt update
apt-cache policy postgresql

A linha Candidato, ou Candidate num sistema em inglês, mostra um número de versão como 17+283. O número antes do sinal de mais é a versão principal do PostgreSQL, o resto é o número de versão do metapacote do Debian.

Instalação a partir do pacote da distribuição

Para a maioria dos casos, o pacote da distribuição é a escolha certa. Está integrado nas atualizações de segurança da distribuição, funciona com as bibliotecas do sistema e não cria problemas numa atualização de release.

apt install -y postgresql postgresql-contrib

O postgresql-contrib traz consigo as extensões incluídas, entre elas pgcrypto, uuid-ossp e pg_stat_statements. Sem esse pacote, muitas aplicações acabam por falhar mais tarde com um ERROR: could not open extension control file, e a procura da causa demora mais do que a instalação.

Durante a instalação, o Debian e o Ubuntu criam automaticamente um primeiro cluster chamado main e arrancam-no. Cluster significa aqui uma instância em execução com diretório de dados próprio, porta própria e configuração própria. Quem responde se isso resultou não é o código de saída do apt, mas sim isto:

pg_lsclusters

Na coluna Status, a saída tem de mostrar online:

Ver Cluster Port Status Owner    Data directory              Log file
17  main    5432 online postgres /var/lib/postgresql/17/main /var/log/postgresql/postgresql-17-main.log

Se ali estiver down, arranque o serviço à mão. O service postgresql start funciona nos quatro sistemas, incluindo em containers sem systemd. Num servidor normal, o systemctl start postgresql serve igualmente bem.

service postgresql start
pg_isready

O pg_isready responde com /var/run/postgresql:5432 - accepting connections e devolve o código de saída 0. Esta é a primeira prova sólida de que o servidor está acessível, e pode ser reaproveitada em scripts de monitorização.

Quando vale a pena o repositório PGDG e como integrá-lo corretamente

O repositório oficial em apt.postgresql.org disponibiliza em paralelo todas as versões principais suportadas para trixie, bookworm, noble e jammy. É a escolha certa quando precisa de uma versão principal concreta porque a aplicação a exige, quando precisa de extensões que o Debian não empacota, ou quando o estado da sua distribuição aponta para uma versão que sai do suporte em breve.

A chave pertence a um ficheiro próprio, já não ao chaveiro descontinuado do apt-key. O Debian 13 e o Ubuntu 24.04 preferem, além disso, o formato deb822 com a extensão .sources, que também funciona no Debian 12 e no Ubuntu 22.04:

apt install -y curl ca-certificates
install -d /usr/share/postgresql-common/pgdg
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
cat > /etc/apt/sources.list.d/pgdg.sources <<EOF
Types: deb
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: $(. /etc/os-release && echo $VERSION_CODENAME)-pgdg
Components: main
Signed-By: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
EOF

A linha com $(. /etc/os-release ...) insere automaticamente trixie-pgdg, bookworm-pgdg, noble-pgdg ou jammy-pgdg. A seguir:

apt update
apt-cache policy postgresql-18

O pacote postgresql-common traz, para o mesmo efeito, um script pronto a usar, o /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh. É uma alternativa à chave e ao pgdg.sources acima, não um complemento. Se executar as duas coisas, o script cria adicionalmente um /etc/apt/sources.list.d/pgdg.list, e a partir daí o apt avisa em cada execução: W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/pgdg.list:1 and /etc/apt/sources.list.d/pgdg.sources:1. Quem preferir o script aos passos manuais acima instala antes também o gnupg, ou seja, apt install -y curl ca-certificates gnupg. É que a versão mais antiga do script, no Ubuntu 22.04, ainda importa a chave através do apt-key e, sem o gnupg, termina com E: gnupg, gnupg2 and gnupg1 do not seem to be installed, but one of them is required for this operation e código de saída 255. No Debian 13, no Debian 12 e no Ubuntu 24.04, a versão mais recente guarda a chave diretamente como .asc e corre sem pacote adicional.

A armadilha: dois clusters, duas portas

Se instalar agora uma nova versão principal num sistema que já tem o pacote da distribuição instalado, surge um segundo cluster. Esse não fica com a porta 5432, mas com a seguinte que estiver livre, ou seja, a 5433. As aplicações continuam a ligar-se à versão antiga, sem que nenhuma mensagem de erro o denuncie. É a causa mais frequente da frase "mas eu instalei o PostgreSQL 18 e o SELECT version() mostra 15".

apt install -y postgresql-18
pg_lsclusters

Agora aparecem ali duas linhas com portas diferentes. Se quiser passar os dados para a nova versão, a ferramenta certa é o pg_upgradecluster, não um dump feito à mão. Exige que os dois pacotes de servidor estejam instalados e deixa o cluster antigo parado, em vez de o apagar:

pg_upgradecluster 15 main

Verifique depois com o pg_lsclusters qual é o cluster que ficou na porta 5432 e teste a aplicação antes de remover definitivamente o cluster antigo com pg_dropcluster --stop 15 main. Este comando apaga o diretório de dados sem perguntar nada.

O primeiro acesso, e porque é que o root não pode usar o psql

O tropeção clássico logo a seguir à instalação:

psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  role "root" does not exist

Isto não é um erro, é o comportamento esperado. O Debian e o Ubuntu configuram as ligações locais por socket com o método peer. O PostgreSQL pergunta então ao kernel sob que utilizador de sistema a ligação foi aberta e exige que exista um role de base de dados com o mesmo nome. Só existe o role postgres, por isso tem primeiro de mudar para esse utilizador de sistema.

su - postgres

A seguir, inicie o psql sem argumentos. Para sair da shell serve o exit. Para comandos avulsos a partir de um script, é mais prático mudar de utilizador em cada comando:

runuser -u postgres -- psql -c "SELECT version();"

Quem tiver o sudo instalado escreve antes sudo -u postgres psql -c "SELECT version();". As duas variantes são equivalentes. Com o sudo aparece muitas vezes o aviso could not change directory to "/root": Permission denied. Não tem consequências, porque o utilizador postgres não pode entrar no diretório de trabalho do root, mas o comando é executado à mesma.

Estas três consultas dizem-lhe com o que está a lidar, e são o primeiro passo em qualquer diagnóstico:

runuser -u postgres -- psql -c "SHOW server_version;"
runuser -u postgres -- psql -c "SHOW config_file;"
runuser -u postgres -- psql -c "SHOW hba_file;"

O último comando é particularmente útil. Indica o caminho que o servidor em execução lê de facto, tipicamente /etc/postgresql/17/main/pg_hba.conf. Se editar um ficheiro e nada mudar, quase sempre tem à sua frente a configuração de outro cluster.

Dentro do psql ajudam os meta-comandos: \l lista as bases de dados, \du os roles, \dt as tabelas da base de dados atual, \conninfo mostra com que identidade e a que servidor está ligado, e \q termina a sessão.

Criar a base de dados e o utilizador

Para cada aplicação deve criar-se um role próprio e uma base de dados própria. A ordem é importante, porque a base de dados deve pertencer diretamente ao role.

runuser -u postgres -- psql -c "CREATE ROLE appuser LOGIN PASSWORD 'ASuaPalavraPasseForte';"
runuser -u postgres -- psql -c "CREATE DATABASE appdb OWNER appuser;"

Desde o PostgreSQL 14 as palavras-passe são guardadas por omissão com scram-sha-256, o que vale portanto nos quatro sistemas aqui tratados. A palavra-passe não fica em texto simples na base de dados, mas fica no histórico da sua shell. Quem quiser evitar isso usa antes, dentro do psql, o \password appuser, que pergunta de forma interativa.

A armadilha desde o PostgreSQL 15: permission denied for schema public

Um comportamento que muitos guias mais antigos ainda não conhecem: a partir do PostgreSQL 15 já não é qualquer utilizador que pode criar objetos no esquema public. Isto afeta o Debian 12, o Debian 13 e o Ubuntu 24.04. Só o Ubuntu 22.04, com o PostgreSQL 14, ainda se comporta segundo o padrão antigo. O erro tem este aspeto:

ERROR:  permission denied for schema public
LINE 1: CREATE TABLE clientes (id serial primary key);

O caminho limpo é o que foi mostrado acima: a base de dados pertence ao role. Desde a versão 15, o esquema public pertence ao role pg_database_owner, e o proprietário da base de dados é implicitamente membro dele. Quem tiver criado a base de dados sem OWNER atribui a permissão a posteriori. Repare que esta instrução tem de ser executada na base de dados afetada, e não na postgres:

runuser -u postgres -- psql -d appdb -c "GRANT ALL ON SCHEMA public TO appuser;"

A prova de que as permissões estão certas

Um CREATE ROLE sem erros ainda não significa que a aplicação consiga iniciar sessão. A prova é um início de sessão real por TCP seguido de um acesso de escrita. O PGPASSWORD serve aqui apenas para o teste, para o funcionamento permanente veja mais abaixo:

PGPASSWORD='ASuaPalavraPasseForte' psql -h 127.0.0.1 -U appuser -d appdb -c "SELECT current_user, current_database();"
PGPASSWORD='ASuaPalavraPasseForte' psql -h 127.0.0.1 -U appuser -d appdb -c "CREATE TABLE teste (id int);"

Se os dois comandos passarem, a combinação de role, palavra-passe, base de dados e permissões de esquema está completa. A tabela teste fica de propósito, porque o teste de backup mais abaixo precisa de pelo menos um objeto na base de dados, caso contrário verifica o vazio. Para controlo, liste os objetos:

runuser -u postgres -- psql -c "\du"
runuser -u postgres -- psql -c "\l"

Uma palavra sobre a codificação de caracteres: se a definição regional do sistema não estava em UTF-8 quando o cluster foi criado, a base de dados modelo pode estar em SQL_ASCII. Um CREATE DATABASE ... ENCODING 'UTF8' falha então com ERROR: new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII). A saída é usar TEMPLATE template0 na criação, e a solução limpa é um sistema com definição regional UTF-8.

Compreender o pg_hba.conf, a fonte de erro mais frequente

O ficheiro pg_hba.conf (host-based authentication) decide, antes de qualquer verificação de palavra-passe, se uma ligação chega sequer a ser aceite. É lido de cima para baixo, e a primeira linha correspondente ganha. Se nenhuma corresponder, a ligação é recusada. Uma regra generosa mais abaixo não lhe serve de nada se uma mais restritiva, colocada acima, pegar primeiro. É de longe o erro de configuração mais frequente.

O estado de origem no Debian e no Ubuntu é este:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             postgres                                peer
local   all             all                                     peer
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256

É assim nos quatro sistemas aqui tratados. Em versões mais antigas, por exemplo o Debian 11 com o PostgreSQL 13, as duas linhas host ainda trazem md5 em vez de scram-sha-256. O início de sessão por TCP funciona nos dois casos, mas já não deve contar com o md5.

As colunas significam o seguinte: local corresponde ao socket Unix, host a TCP com ou sem TLS, hostssl apenas a ligações com TLS. Seguem-se a base de dados, o role, a gama de rede em notação CIDR e o método. São quatro os métodos importantes. O peer verifica o utilizador de sistema e só funciona através do socket. O scram-sha-256 é o método moderno de palavra-passe e a escolha certa para tudo o que passa por TCP. O md5 está descontinuado e não deve voltar a aparecer em configurações novas. O trust deixa entrar qualquer um sem verificação e não tem lugar num servidor acessível.

As mensagens de erro, palavra por palavra

Quem as consegue distinguir poupa muita adivinhação:

FATAL:  Peer authentication failed for user "appuser"

Está ligado através do socket, mas o seu utilizador de sistema tem um nome diferente do role. Ou muda de utilizador, ou liga-se com -h 127.0.0.1 para que a linha host passe a valer.

FATAL:  no pg_hba.conf entry for host "198.51.100.4", user "appuser", database "appdb", no encryption

O servidor está acessível, mas nenhuma regra corresponde a esta combinação de endereço de origem, role e base de dados. Falta uma linha, ou a rede indicada na linha existente não cobre o endereço.

FATAL:  password authentication failed for user "appuser"

A regra pega, mas a palavra-passe não está certa. Muitas vezes porque o role foi criado sem LOGIN, ou porque a palavra-passe ainda vem de uma instalação anterior.

psql: error: connection to server at "203.0.113.10", port 5432 failed: Connection refused

Aqui o pg_hba.conf nunca chegou a entrar em jogo. Ou o servidor não está a correr, ou não escuta neste endereço, ou uma firewall está a bloquear. Já a seguir há mais sobre isso.

Verificar as alterações antes de recarregar

O PostgreSQL oferece uma vista de sistema que mostra as regras já interpretadas, com número de linha e erros de sintaxe. Responde à pergunta de que regra o servidor vê realmente, em vez daquela que julga ter escrito:

runuser -u postgres -- psql -c "SELECT line_number, type, database, user_name, address, auth_method FROM pg_hba_file_rules;"

As alterações ao pg_hba.conf não precisam de reinício. Basta recarregar, e isso não corta nenhuma ligação existente:

runuser -u postgres -- psql -c "SELECT pg_reload_conf();"

Em alternativa, service postgresql reload. Um reinício a sério só é necessário se tiver alterado parâmetros como listen_addresses, port ou shared_buffers.

Permitir o acesso a partir do exterior

De origem, o PostgreSQL escuta apenas em localhost. É uma boa predefinição, e só deve abdicar dela quando for mesmo necessário. Duas coisas têm de coincidir: o servidor tem de escutar no endereço, e o pg_hba.conf tem de permitir a origem. Se faltar a primeira, obtém Connection refused; se faltar a segunda, obtém no pg_hba.conf entry.

A configuração fica em /etc/postgresql/17/main/postgresql.conf. O Debian traz para isso a ferramenta pg_conftool, que edita o ficheiro de forma mais fiável do que uma pesquisa no editor:

pg_conftool 17 main show listen_addresses
pg_conftool 17 main set listen_addresses '10.0.0.5,127.0.0.1'

Indique endereços concretos em vez de *. Num servidor com endereço público e endereço interno, fica assim ligado apenas à rede interna. A seguir acrescente uma regra no pg_hba.conf, tão restrita quanto possível:

host    appdb    appuser    10.0.0.0/24    scram-sha-256

Depois de um reinício com service postgresql restart, verifique primeiro em que endereços o processo escuta de facto. O ss -lntp | grep 5432 mostra os endereços associados. Se ali só constar 127.0.0.1:5432, a alteração não pegou, normalmente porque estava em causa um segundo cluster, ou porque um ficheiro em conf.d sobrepõe o valor.

A firewall precisa igualmente de uma regra, e com indicação de origem. Uma porta 5432 aberta sem restrições na Internet é apanhada por scanners em poucas horas:

ufw allow from 10.0.0.0/24 to any port 5432 proto tcp

Conselho honesto: na maioria dos casos a melhor solução é não abrir a porta de todo. Um túnel SSH com ssh -L 5432:127.0.0.1:5432 utilizador@servidor chega perfeitamente para acessos de manutenção. Para ligações permanentes entre vários servidores, uma rede WireGuard é a opção mais limpa, porque a base de dados continua então a escutar apenas num endereço privado. O Debian e o Ubuntu, aliás, ativam TLS por omissão com um certificado autoassinado, e por isso o sslmode=require funciona logo. Proteção real contra um atacante no caminho só a dá o sslmode=verify-full com um certificado em que o cliente confia.

Backup com o pg_dump, e a prova de que serve para alguma coisa

Para bases de dados individuais, o formato custom é a melhor escolha. É comprimido, permite um restauro seletivo e pode ser carregado em paralelo:

runuser -u postgres -- pg_dump -Fc -d appdb -f /var/lib/postgresql/appdb.dump

Um ponto que passa muitas vezes despercebido: o pg_dump não guarda roles nem palavras-passe. Estes existem ao nível de todo o cluster e têm de ser guardados à parte, senão, depois de um restauro, faltam exatamente os utilizadores de que a aplicação precisa:

runuser -u postgres -- pg_dumpall --globals-only -f /var/lib/postgresql/globals.sql

Quando as versões não combinam

pg_dump: error: server version: 17.5; pg_dump version: 15.10
pg_dump: error: aborting because of server version mismatch

A regra é esta: o pg_dump pode ser mais recente do que o servidor, nunca mais antigo. No Debian e no Ubuntu resolve-se facilmente, porque o /usr/bin/pg_dump é apenas um wrapper que escolhe a versão certa do programa. Instale o pacote postgresql-client-18 e a versão mais recente fica disponível. E com a extensão --cluster do Debian obriga o wrapper a usar um cluster concreto, aqui a versão 17, cluster main:

pg_dump --version
runuser -u postgres -- pg_dump --cluster 17/main -Fc -d appdb -f /var/lib/postgresql/appdb.dump

Manter as palavras-passe fora do script

Para backups automáticos, a palavra-passe pertence a um ficheiro .pgpass, no formato host:porta:base:utilizador:palavrapasse. O PostgreSQL ignora o ficheiro sem dizer nada se as permissões forem demasiado amplas. Igualmente importante é em que diretório pessoal ele se encontra, porque o ficheiro lido é sempre o do utilizador sob o qual o comando corre realmente. Um ~/.pgpass criado como root fica sem efeito enquanto o backup passar por runuser -u postgres, como neste artigo. Nesse caso conta a home do postgres:

touch /var/lib/postgresql/.pgpass
chown postgres:postgres /var/lib/postgresql/.pgpass
chmod 0600 /var/lib/postgresql/.pgpass

Vazio, o ficheiro fica igualmente sem efeito. Escreva uma linha por ligação, por exemplo 127.0.0.1:5432:appdb:appuser:ASuaPalavraPasseForte. Se, em vez disso, o seu job de backup correr diretamente como root, sem mudança de utilizador, o mesmo ficheiro pertence a /root/.pgpass.

Verificar o backup

Um ficheiro de backup que nunca foi restaurado não passa de uma suposição. O teste demora um minuto. Primeiro ver o índice, depois carregá-lo numa base de dados descartável e contar as tabelas:

runuser -u postgres -- pg_restore -l /var/lib/postgresql/appdb.dump | head -n 20
runuser -u postgres -- createdb appdb_restore_test
runuser -u postgres -- pg_restore -d appdb_restore_test /var/lib/postgresql/appdb.dump
runuser -u postgres -- psql -d appdb_restore_test -c "\dt"
runuser -u postgres -- dropdb appdb_restore_test

Se o \dt mostrar as mesmas tabelas do original, aqui pelo menos a tabela teste, o backup presta. Se, pelo contrário, o comando indicar Did not find any relations., a base de dados guardada estava vazia e o teste não prova nada. Na appdb, retire depois a tabela de teste com runuser -u postgres -- psql -d appdb -c "DROP TABLE teste;". Para o dia a dia basta uma entrada em /etc/cron.d que deixe os dois ficheiros com a data no nome e limpe os mais antigos. O importante é que os ficheiros saiam depois do servidor. Um backup no mesmo disco protege contra um DROP TABLE acidental, não contra uma avaria do hardware.

Quando o cluster não arranca

Se o serviço não arrancar, o estado do serviço costuma dizer apenas que algo falhou. A causa verdadeira está no log do cluster:

tail -n 30 /var/log/postgresql/postgresql-*-main.log

Há uma linha que pode ignorar sem receio. A mensagem já conhecida da primeira secção, FATAL: role "root" does not exist, vem quase sempre do pg_isready: a ferramenta monta a sua tentativa de ligação com o utilizador de sistema com sessão iniciada, ou seja, como root, e o servidor regista o role desconhecido. Ainda assim, o valor de retorno continua a ser 0, a saída diz accepting connections e o cluster está perfeitamente bem.

Em sistemas com systemd, o journalctl -u postgresql@17-main --no-pager -n 50 devolve as mesmas linhas. Repare na unit com número de versão: o postgresql.service é apenas um invólucro que arranca todos os clusters, e comunica sucesso mesmo quando um cluster isolado falhou. Por isso o pg_lsclusters é o controlo mais fiável.

Três mensagens cobrem a maioria dos casos. O could not bind IPv4 address "0.0.0.0": Address already in use significa que outro cluster está a ocupar a porta, veja a secção sobre os dois clusters. Uma mensagem de No space left on device ao escrever o postmaster.pid quer dizer simplesmente disco cheio, o que confirma com df -h. E os erros de permissões inválidas no diretório de dados surgem depois de execuções descuidadas de chmod ou chown: o /var/lib/postgresql/17/main tem de pertencer ao utilizador postgres e ter o modo 0700.

Para terminar, uma nota sobre a operação: na configuração de base, o PostgreSQL é conservador e está longe de aproveitar a memória de um servidor. Antes de mexer no shared_buffers e no work_mem, ative o pg_stat_statements do pacote contrib e veja que consultas custam tempo de facto. Na prática, o estrangulamento está quase sempre num índice em falta, e não nos parâmetros de memória.

Perguntas frequentes

Que versão do PostgreSQL recebo na minha distribuição?
A partir do repositório da distribuição, o Debian 13 fornece a versão 17, o Debian 12 a versão 15, o Ubuntu 24.04 a versão 16 e o Ubuntu 22.04 a versão 14. Esta correspondência está ligada a cada release e já não muda ao longo do seu ciclo de vida. Quem precisar de outra versão principal integra o repositório oficial PGDG em apt.postgresql.org, que suporta trixie, bookworm, noble e jammy.
Porque é que ao iniciar o psql aparece a mensagem "role root does not exist"?
O Debian e o Ubuntu usam o método peer para as ligações locais por socket. O PostgreSQL compara então o utilizador de sistema com o nome do role, e um role chamado root não existe. Mude para o utilizador de sistema postgres com su - postgres, ou execute comandos avulsos com runuser -u postgres -- psql; com sudo, o equivalente é sudo -u postgres psql.
O que significa "no pg_hba.conf entry for host" e como se resolve?
O servidor está acessível, mas nenhuma linha do pg_hba.conf corresponde à combinação de endereço de origem, role e base de dados. Acrescente uma linha host com a rede CIDR adequada e o método scram-sha-256. Como ganha a primeira linha correspondente, ela tem de ficar antes de qualquer recusa mais geral. Verifique o resultado com uma consulta à vista pg_hba_file_rules e recarregue a configuração com SELECT pg_reload_conf().
Porque é que o meu utilizador não consegue criar tabelas, apesar de poder usar a base de dados?
A partir do PostgreSQL 15 já não é qualquer utilizador que pode escrever no esquema public, e o erro é "permission denied for schema public". Isto afeta o Debian 12, o Debian 13 e o Ubuntu 24.04. O mais limpo é criar a base de dados logo com CREATE DATABASE appdb OWNER appuser, porque o esquema public pertence ao role pg_database_owner. A posteriori ajuda GRANT ALL ON SCHEMA public TO appuser, executado na base de dados afetada.
Tenho de reiniciar o PostgreSQL depois de alterar o pg_hba.conf?
Não, basta recarregar, e isso não corta nenhuma ligação existente. Faz-se com SELECT pg_reload_conf() ou com service postgresql reload. Um reinício a sério só é necessário para parâmetros que são lidos no arranque, como listen_addresses, port ou shared_buffers.
O pg_dump chega como backup completo?
Não. O pg_dump guarda uma base de dados isolada, mas não guarda roles nem palavras-passe, porque estes existem ao nível de todo o cluster. Acrescente por isso o pg_dumpall --globals-only. E verifique o backup, carregando-o com pg_restore numa base de dados descartável e comparando as tabelas com \dt. Para isso, a base de dados guardada tem mesmo de conter tabelas, senão o \dt indica apenas "Did not find any relations." e o teste não prova nada. Um backup que nunca foi restaurado não passa de uma suposição.

PostgreSQL Debian Ubuntu Base de dados pg_hba.conf pg_dump Linux Administração de servidores