PostgreSQL, pur essendo un RDBMS moderno e versatile, non è il più facile da configurare e iniziare mentre stai cercando di sviluppare un'applicazione. Continua a leggere per scoprire come iniziare con l'ultima versione di PostgreSQL sulla versione LTS di Ubuntu.
Installazione
Ubuntu 18.04 viene fornito con PostgreSQL 10, ma possiamo invece utilizzare il repository APT ospitato dal team PostgreSQL per installare l'ultima versione, PostgreSQL 11.
Puoi configurare il repository usando questi comandi:
# 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 quindi installa il software stesso, utilizzando:
sudo apt-get install postgresql-11
L'installazione fa alcune cose:
- Installa il server PostgreSQL, le utility e un client a riga di comando chiamatopsql .
- Crea un utente di sistema Linux chiamato postgres . Tutti i file di dati sono di proprietà di questo utente e tutti i processi vengono eseguiti come questo utente.
- Crea un database, chiamato anche postgres .
- Crea un utente PostgreSQL (non l'utente del sistema Linux), chiamato anchepostgres .
Puoi vedere che questo sta cominciando a creare confusione!
Cluster di database
Il server PostgreSQL appena installato è costituito da un insieme di processi che gestiscono ciò che è noto come "cluster di database". Puoi vedere i processi qui:
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
Il processo principale (qui con PID 4737) è il processo principale che genera ulteriormente i processi figlio – questo è convenzionalmente chiamato processo "postmaster".
L'uso del termine "cluster" da parte di PostgreSQL precede il moderno gergo dei cluster distribuiti:qui significa semplicemente un insieme di database gestiti su una singola macchina da un singolo postmaster. Leggi di più sui cluster qui.
Un cluster contiene database (per ora ne abbiamo solo uno, "postgres") e utenti PostgreSQL (di nuovo, solo uno per ora, chiamato anche "postgres") tra le altre cose. Solo perché tu sappia, il cluster è associato a un intero gruppo di file di dati, che risiedono tutti in un'unica directory, in questo caso in /var/lib/postgresql/11/main . Hai notato questo percorso nella riga di comando postmaster sopra?
Quando la tua app, o psql, si connette a Postgres, deve farlo nel contesto di un utente PostgreSQL. C'è sempre un utente PostgreSQL associato a unaconnessione. Ma, come avrai già intuito, un utente PostgreSQL può corrispondere o meno a un utente di sistema.
Utenti di sistema e utenti PostgreSQL
Gli utenti PostgreSQL possono essere creati utilizzando comandi SQL come CREATE ROLE o strumenti in bundle come createb.
Quando un'applicazione tenta di connettersi a Postgres, deve fornire un nome utente PostgreSQL. Vediamo cosa succede quando avvii un client PostgreSQL come psql:
alice@devbox:~$ psql
psql: FATAL: role "alice" does not exist
Qui, "alice" è il nome utente del tuo sistema Linux. psql prende questo nome e usa it come nome utente di Postgres. Un ruolo (i ruoli sono una sorta di nome generico per "utente" o "gruppo", BTW) con quel nome non esiste, che è ciò di cui si lamenta Postgres.
Sappiamo che esiste un ruolo chiamato "postgres", quindi proviamolo. Possiamo usare il parametro “-U” di psql per specificare il nome utente:
alice@devbox:~$ psql -U postgres
psql: FATAL: Peer authentication failed for user "postgres"
OK, ci stiamo avvicinando:il ruolo/utente "postgres" esiste, ma la "peerauthentication" non è riuscita. Che cos'è questa "autenticazione peer"?
Autenticazione peer e password
I client PostgreSQL come psql o la tua app possono connettersi al server PostgreSQL tramite uno di questi meccanismi IPC:
- Socket di dominio Unix
- Prese TCP
A differenza dei socket TCP, i socket di dominio Unix offrono la possibilità di convalidare l'ID utente di sistema della connessione client. Il server Postgres può esaminare una connessione in entrata su un socket di dominio Unix e determinare l'ID utente di sistema del client e quindi decidere se concedergli l'accesso o meno.
Per impostazione predefinita, il tuo server ascolta solo le connessioni su socket di dominio unix e non TCP/IP.
Vediamo cosa succede se proviamo ad avviare psql come utente di sistema postgres:
alice@devbox:~$ sudo -u postgres psql
psql (11.0 (Ubuntu 11.0-1.pgdg18.04+2))
Type "help" for help.
postgres=#
Ha funzionato! (Usa “\q”, “\quit” o ^D
per uscire da psql, BTW.)
Nell'autenticazione peer, se la connessione client viene effettuata utilizzando un socket di dominio Unix e il processo client ha lo stesso nome utente di sistema dell'utente PostgreSQL con cui sta tentando di connettersi, l'autenticazione viene considerata riuscita.
Agli utenti di PostgreSQL può anche essere assegnata una password facoltativa e puoi chiedere a PostgreSQL di convalidare le connessioni in entrata usando la password. Ma come? Questo è il prossimo pezzo del puzzle.
pg_hba.conf
Ora è il momento di aprire il (in)famoso file di configurazione pg_hba.conf, che si trova in/etc/postgresql/11/main/pg_hba.conf
:
sudo vim /etc/postgresql/11/main/pg_hba.conf
HBA sta per autenticazione basata su host. Fondamentalmente, questo file viene utilizzato per controllare il modo in cui gli utenti PostgreSQL vengono autenticati. Questo file è probabilmente la parte più non intuitiva della curva di apprendimento di PostgreSQL. La documentazione di riferimento è qui, dovresti leggerla più tardi.
La prima riga (senza commenti) qui è:
local all postgres peer
che dice a Postgres di accettare connessioni "locali" (dominio unix) a "tutti" i database, autenticandosi come utente "postgres" utilizzando l'autenticazione "peer". Questo è il motivo per cui la connessione come utente di sistema "postgres" funziona immediatamente.
L'ordine delle righe in questo file è importante, vince la prima riga corrispondente. Vediamo un'altra riga:
host all all 127.0.0.1/32 md5
Questa riga consente a "tutti" gli utenti di accedere utilizzando TCP/IP ("host") dal localhost ("127.0.0.1/32") ai database "tutti", se riescono nell'autenticazione con password utilizzando il metodo "md5".
Esistono più metodi di autenticazione della password (md5, scram-sha-256, gss,ldap, …) di quanti ne possiamo coprire, quindi torniamo a esempi più semplici.
Ma prima, dobbiamo assicurarci che PostgreSQL accetti anche connessioni TCP/IP. Per questo, dobbiamo modificare il file di configurazione principale.
postgresql.conf
Il file /etc/postgresql/11/main/postgresql.conf è il file di configurazione principale per il tuo cluster PostgreSQL. Questo file contiene un lotto di impostazioni, e capire cosa significano tutti questi non è affatto un compito facile. Per ora, vediamo la primissima impostazione:
#listen_addresses = 'localhost'
Questa riga è commentata per impostazione predefinita, decommentiamola per farla leggere:
listen_addresses = 'localhost'
Ciò consentirà a PostgreSQL di ascoltare le connessioni TCP/IP in entrata su localhost, porta 5432 (l'impostazione predefinita). Salva le modifiche (dovrai essere "root" per farlo) e riavvia il server Postgres affinché le modifiche abbiano effetto:
sudo systemctl restart postgresql
(Nota che alcune per la maggior parte delle modifiche alle impostazioni devi solo "ricaricare", non "riavviare", ma questo richiede un "riavvio").
Ora possiamo vedere Postgres in ascolto sulla porta 5432, legato 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
Ora configuriamo un nuovo utente e database per l'utilizzo da parte di un'app.
Impostazione app
Connettiamoci come superutente "postgres" per apportare le modifiche:
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=#
Ora abbiamo creato un database chiamato myapp
e un utente chiamato myapp_user
,con la password s3cr3t
. Il database è vuoto e sarà di proprietà dell'utentemyapp_user
, il che significa che ci si connette come myapp_user
il client sarà in grado di eseguire quasi tutti i comandi DDL/DML.
Connettiamoci al database dell'app come utente dell'app ora:
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=>
Ha funzionato! Ora sei connesso a "myapp" (vedi il prompt), usando SSL su una connessione TCP/IP a 127.0.0.1. Nota che abbiamo specificato il nome del database anche sulla riga di comando per psql. Per ragioni storiche, se questo viene omesso, si presume che anche il nome del database sia lo stesso del nome utente del sistema ("alice"qui), che non è quello che vogliamo. Viene anche specificato il nome utente di PostgreSQL(“-U myapp_user”).
Se devi connetterti da altre macchine, dovrai modificare pg_hba.conf
per aggiungere righe in questo modo:
# 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 ricarica PostgreSQL ("sudo systemctl reload postgresql") per rendere effettive le modifiche.
Con questa impostazione, ora puoi utilizzare stringhe di connessione al database come queste nelle tue app:
# URL format
postgresql://myapp_user:[email protected]/myapp
# connection string format
host=127.0.0.1 user=myapp_user dbname=myapp password=s3cr3t
Pronto!
Questo dovrebbe consentirti di configurare un database e un utente dedicati per la tua app. Il tuo framework di sviluppo delle app (come Django, Drupal ecc.) dovrebbe essere in grado di creare oggetti (come tabelle, viste) e gestire i dati in questo database.