Hoewel PostgreSQL een modern en veelzijdig RDBMS is, is het niet de gemakkelijkste om in te stellen en aan de slag te gaan terwijl je een applicatie wilt ontwikkelen.Lees verder om te leren hoe je aan de slag kunt met de nieuwste versie van PostgreSQL op de LTS-versie van Ubuntu.
Installatie
Ubuntu 18.04 wordt geleverd met PostgreSQL 10, maar we kunnen in plaats daarvan de APT-repository gebruiken die wordt gehost door het PostgreSQL-team om de nieuwste versie, PostgreSQL 11, te installeren.
U kunt de repository instellen met behulp van deze opdrachten:
# 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
En installeer vervolgens de software zelf, met behulp van:
sudo apt-get install postgresql-11
De installatie doet een paar dingen:
- Het installeert de PostgreSQL-server, hulpprogramma's en een opdrachtregelclient met de naam psql .
- Het maakt een Linux-systeemgebruiker aan met de naam postgres . Alle gegevensbestanden zijn eigendom van deze gebruiker en alle processen worden uitgevoerd als deze gebruiker.
- Het creëert één database, ook wel postgres . genoemd .
- Het maakt één PostgreSQL-gebruiker aan (niet de Linux-systeemgebruiker), ook wel postgres . genoemd .
Je kunt zien dat dit verwarrend begint te worden!
Databaseclusters
Uw nieuw geïnstalleerde PostgreSQL-server bestaat uit een reeks processen die een zogenaamd "databasecluster" beheren. Je kunt de processen hier zien:
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
Het hoofdproces (hier met PID 4737) is het hoofdproces dat verder de onderliggende processen voortbrengt - dit wordt gewoonlijk het "postmaster" -proces genoemd.
Het gebruik van de term "cluster" door PostgreSQL dateert van vóór het moderne fancy gedistribueerde clustering-jargon - hier betekent het gewoon een set databases die op één enkele machine wordt beheerd door een enkele postmaster. Lees hier meer over clusters.
Een cluster bevat onder andere databases (voor nu hebben we er maar één, "postgres") en PostgreSQL-gebruikers (nogmaals slechts één voor nu, ook wel "postgres" genoemd). Voor de duidelijkheid:het cluster is gekoppeld aan een hele reeks gegevensbestanden, die allemaal onder één enkele map leven - in dit geval onder/var/lib/postgresql/11/main . Heb je dit pad opgemerkt in de postmaster-commandoregel hierboven?
Wanneer uw app, of psql, verbinding maakt met Postgres, moet deze dit doen in de context van een PostgreSQL-gebruiker. Er is altijd een PostgreSQL-gebruiker die is gekoppeld aan een verbinding. Maar, zoals je misschien al geraden had, kan een PostgreSQL-gebruiker wel of niet overeenkomen met een systeemgebruiker.
Systeemgebruikers en PostgreSQL-gebruikers
PostgreSQL-gebruikers kunnen worden gemaakt met SQL-commando's zoals CREATE ROLE of gebundelde tools zoals createdb.
Wanneer een toepassing verbinding probeert te maken met Postgres, moet deze een PostgreSQL-gebruikersnaam opgeven. Laten we eens kijken wat er gebeurt als je een PostgreSQL-client zoals psql start:
alice@devbox:~$ psql
psql: FATAL: role "alice" does not exist
Hier is "alice" de gebruikersnaam van uw Linux-systeem. psql neemt deze naam en gebruikt het als de gebruikersnaam van Postgres. Een rol (rollen zijn een soort generieke naam voor "gebruiker" of "groep", BTW) met die naam bestaat niet, en dat is waar Postgres over klaagt.
We weten dat er een rol is met de naam "postgres", dus laten we dat proberen. We kunnen de “-U” parameter van psql gebruiken om de gebruikersnaam te specificeren:
alice@devbox:~$ psql -U postgres
psql: FATAL: Peer authentication failed for user "postgres"
OK, we komen dichterbij - de rol/gebruiker "postgres" bestaat, maar "peerauthenticatie" is mislukt. Wat is deze "peer-authenticatie"?
Peer- en wachtwoordverificatie
PostgreSQL-clients zoals psql of uw app kunnen via een van deze IPC-mechanismen verbinding maken met de PostgreSQL-server:
- Unix-domein-sockets
- TCP-sockets
In tegenstelling tot TCP-sockets bieden Unix-domeinsockets de mogelijkheid om de systeemgebruikers-ID van de clientverbinding te valideren. De Postgres-server kan een inkomende verbinding via een Unix-domeinsocket onderzoeken en de systeemgebruikers-ID van de client bepalen en vervolgens beslissen of deze toegang wordt verleend of niet.
Uw server luistert standaard alleen naar verbindingen via unix-domeinsockets en niet naar TCP/IP.
Laten we eens kijken wat er gebeurt als we psql proberen te starten als de systeemgebruiker postgres:
alice@devbox:~$ sudo -u postgres psql
psql (11.0 (Ubuntu 11.0-1.pgdg18.04+2))
Type "help" for help.
postgres=#
Dat werkte! (Gebruik “\q”, “\quit” of ^D
om psql af te sluiten, btw.)
Als bij peer-authenticatie de clientverbinding wordt gemaakt met een Unix-domeinsocket en het clientproces dezelfde systeemgebruikersnaam heeft als de PostgreSQL-gebruiker waarmee het verbinding probeert te maken, wordt de authenticatie als geslaagd beschouwd.
PostgreSQL-gebruikers kunnen ook optioneel een wachtwoord worden toegewezen en u kunt PostgreSQL vragen om inkomende verbindingen te valideren met behulp van het wachtwoord. Maar hoe? Dat is het volgende stukje van de puzzel.
pg_hba.conf
Het is nu tijd om het (in)beroemde pg_hba.conf configuratiebestand te openen, te vinden op/etc/postgresql/11/main/pg_hba.conf
:
sudo vim /etc/postgresql/11/main/pg_hba.conf
HBA staat voor host-based authenticatie. In principe wordt dit bestand gebruikt om te bepalen hoe PostgreSQL-gebruikers worden geverifieerd. Dit bestand is waarschijnlijk het meest niet-intuïtieve deel van de PostgreSQL-leercurve. De referentiedocumentatie is hier, u zou het later moeten lezen.
De eerste regel (zonder commentaar) hier is:
local all postgres peer
die Postgres vertelt om "lokale" (unix-domein) verbindingen met "alle" databases te accepteren, authenticatie als gebruiker "postgres" met behulp van "peer"-authenticatie. Dit is de reden waarom verbinding maken als systeemgebruiker "postgres" direct werkt.
De volgorde van regels in dit bestand is belangrijk, de eerste overeenkomende regel wint. Laten we een andere regel bekijken:
host all all 127.0.0.1/32 md5
Met deze regel kunnen "alle" gebruikers inloggen met behulp van TCP/IP ("host") van de localhost ("127.0.0.1/32") naar "alle" databases, als ze slagen in wachtwoordauthenticatie met behulp van de "md5"-methode.
Er zijn meer methoden voor wachtwoordverificatie (md5, scram-sha-256, gss,ldap, ...) dan we kunnen behandelen, dus laten we teruggaan naar eenvoudigere voorbeelden.
Maar eerst moeten we ervoor zorgen dat PostgreSQL ook TCP/IP-verbindingen accepteert. Daarvoor moeten we het hoofdconfiguratiebestand bewerken.
postgresql.conf
Het bestand /etc/postgresql/11/main/postgresql.conf is het hoofdconfiguratiebestand voor uw PostgreSQL-cluster. Dit bestand bevat een lot van instellingen, en begrijpen wat al deze betekenen, is helemaal geen gemakkelijke taak. Laten we nu eens kijken naar de allereerste instelling:
#listen_addresses = 'localhost'
Deze regel wordt standaard becommentarieerd, laten we het commentaar verwijderen om het te laten lezen:
listen_addresses = 'localhost'
Hierdoor kan PostgreSQL luisteren naar inkomende TCP/IP-verbindingen op localhost, poort 5432 (de standaard). Sla de wijzigingen op (u moet hiervoor "root" zijn) en start de Postgres-server opnieuw om de wijzigingen door te voeren:
sudo systemctl restart postgresql
(Merk op dat voor de meeste wijzigingen in de instellingen je gewoon moet "herladen", niet "opnieuw opstarten", maar dit vereist een "herstart").
Nu kunnen we Postgres zien luisteren op poort 5432, gebonden aan 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
Laten we nu een nieuwe gebruiker en database instellen voor gebruik door een app.
App-configuratie
Laten we verbinding maken als de supergebruiker "postgres" om de wijzigingen aan te brengen:
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=#
We hebben nu een database gemaakt met de naam myapp
en een gebruiker genaamd myapp_user
,met het wachtwoord s3cr3t
. De database is leeg en is eigendom van de gebruikermyapp_user
, wat betekent dat door verbinding te maken als myapp_user
de client zal de meeste DDL/DML-commando's kunnen uitvoeren.
Laten we nu als deze app-gebruiker verbinding maken met de app-database:
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=>
Het werkte! U bent nu verbonden met "myapp" (zie de prompt), via SSL via een TCP/IP-verbinding met 127.0.0.1. Merk op dat we de databasenaam ook op de opdrachtregel voor psql hebben opgegeven. Om historische redenen, als dit wordt weggelaten, wordt aangenomen dat de databasenaam hetzelfde is als de systeemgebruikersnaam (“alice” hier), wat niet is wat we willen. De gebruikersnaam van PostgreSQL is ook gespecificeerd ("-U myapp_user").
Als u verbinding moet maken vanaf andere machines, moet u pg_hba.conf
bewerken om regels als volgt toe te voegen:
# 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
en herlaad PostgreSQL (“sudo systemctl reload postgresql”) om de wijzigingen door te voeren.
Als dit op zijn plaats is, kunt u nu databaseverbindingsreeksen zoals deze gebruiken in uw apps:
# URL format
postgresql://myapp_user:[email protected]/myapp
# connection string format
host=127.0.0.1 user=myapp_user dbname=myapp password=s3cr3t
Klaar!
Dit zou u moeten instellen met een speciale database en gebruiker voor uw app. Uw app-ontwikkelingsframework (zoals Django, Drupal enz.) zou in staat moeten zijn om objecten (zoals tabellen, views) te creëren en de gegevens in deze database te beheren.