{"id":179,"date":"2024-01-06T21:56:35","date_gmt":"2024-01-06T21:56:35","guid":{"rendered":"https:\/\/www.ccsgeo.com\/?p=179"},"modified":"2024-01-06T22:51:06","modified_gmt":"2024-01-06T22:51:06","slug":"deploying-an-open-source-gis-stack-part-2-installing-postgresql-with-postgis","status":"publish","type":"post","link":"https:\/\/www.ccsgeo.com\/index.php\/2024\/01\/06\/deploying-an-open-source-gis-stack-part-2-installing-postgresql-with-postgis\/","title":{"rendered":"Deploying an Open Source GIS Stack (Part 2: Installing PostgreSQL with PostGIS)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The foundation of any open source GIS stack is PostgreSQL with the PostGIS extension. In <a href=\"https:\/\/www.ccsgeo.com\/index.php\/2023\/12\/23\/deploying-an-open-source-gis-stack-part-1-the-plan-and-deploying-the-name-server\/\" data-type=\"link\" data-id=\"https:\/\/www.ccsgeo.com\/index.php\/2023\/12\/23\/deploying-an-open-source-gis-stack-part-1-the-plan-and-deploying-the-name-server\/\">part 1 of this series<\/a>, I laid out the deployment architecture and spun up some Ubuntu Server virtual machines on VMWare ESXI. There are a few steps to deploy the database so that it can be used as a GIS database in QGIS and Geoserver. <\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Install PostgreSQL.<\/li>\n\n\n\n<li>Install PostGIS.<\/li>\n\n\n\n<li>Configure PostgreSQL connections.<\/li>\n\n\n\n<li>Set up postgres user.<\/li>\n\n\n\n<li>Configure allowed authentication.<\/li>\n\n\n\n<li>Create GIS database <\/li>\n\n\n\n<li>Activate PostGIS on database.<\/li>\n\n\n\n<li>Create new GIS user and GIS data schema.<\/li>\n\n\n\n<li>Ensure connection from QGIS are successful.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">So let&#8217;s get started! <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install PostgreSQL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Installing <a href=\"https:\/\/ubuntu.com\/server\/docs\/databases-postgresql\" data-type=\"link\" data-id=\"https:\/\/ubuntu.com\/server\/docs\/databases-postgresql\">PostgreSQL on Ubuntu<\/a> is pretty straightforward: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">$ sudo apt install postgresql<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install PostGIS<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Installing PostGIS is also pretty straightforward: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">$ sudo apt install postgresql-14-postgis-3<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configure PostgreSQL Connections<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once we have installed PostgreSQL, we have to configure it to allow connections from other machines. This is done through the postgresql.conf file. Using nano, a built-in command line text editor, we can modify the file: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>$ sudo nano \/etc\/postgresql\/14\/main\/postgresql.conf<\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"975\" height=\"342\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image.png\" alt=\"postgresql.conf configuration\" class=\"wp-image-189\" style=\"width:850px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image.png 975w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-300x105.png 300w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-768x269.png 768w\" sizes=\"auto, (max-width: 975px) 100vw, 975px\" \/><figcaption class=\"wp-element-caption\">postgresql.conf configuration.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Here we can set the listen_address to &#8216;*&#8217; so that the PostgreSQL server listens for all incoming ip addresses. You can modify this for your own network configuration but this is an easy catch-all for a development environment. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setup Postgres User <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">By default, when PostgreSQL is installed on Linux, it creates a user called postgres at the OS level. This user has access to the database via <a href=\"https:\/\/www.atlassian.com\/data\/admin\/how-to-set-the-default-user-password-in-postgresql\" data-type=\"link\" data-id=\"https:\/\/www.atlassian.com\/data\/admin\/how-to-set-the-default-user-password-in-postgresql\">peer authentication<\/a>, which allows a user logged in at the OS level to log in to the database if there is a corresponding user present. Initially there is no password required and you can access the database on the local machine via: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>$ sudo -u postgres psql <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can then set a password for the database user using the ALTER ROLE sql command: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"963\" height=\"98\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-1.png\" alt=\"Adding a password for postgres user.\" class=\"wp-image-191\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-1.png 963w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-1-300x31.png 300w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-1-768x78.png 768w\" sizes=\"auto, (max-width: 963px) 100vw, 963px\" \/><figcaption class=\"wp-element-caption\">Adding a password for postgres user.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">This password will not be required to sign in when accessing the database from the local machine, but we will need it later on when accessing the database from a remote machine (such as where QGIS is installed). <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modify pg_hba.conf<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Our final configuration step is to modify the pg_hba.conf file which allows us to connect to the database using the postgres user configured with a password from a remote machine: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>$sudo nano \/etc\/postgresql\/14\/main\/pg_hba.conf<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At the bottom, I added <strong>hostssl all all 0.0.0.0\/0 scram-sha-256<\/strong>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"969\" height=\"445\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-2.png\" alt=\"pg_hba.conf configuration\" class=\"wp-image-194\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-2.png 969w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-2-300x138.png 300w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-2-768x353.png 768w\" sizes=\"auto, (max-width: 969px) 100vw, 969px\" \/><figcaption class=\"wp-element-caption\">pg_hba.conf configuration.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">You can narrow the IP range down to reflect your local network subnet. The hostssl parameter only allows for ssl connections and uses the scram-sha-256 method for authentication. Now, we can restart the PostgreSQL service to lock in our changes: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>$ sudo systemctl restart postgresql.service<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To test the connection, I installed <a href=\"https:\/\/www.pgadmin.org\/download\/\">pgAdmin<\/a> on my desktop. You can then right-click on Servers > Register and enter in the database information: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"702\" height=\"551\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-3.png\" alt=\"Register the database server in pgAdmin\" class=\"wp-image-197\" style=\"width:457px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-3.png 702w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-3-300x235.png 300w\" sizes=\"auto, (max-width: 702px) 100vw, 702px\" \/><figcaption class=\"wp-element-caption\">Register the database server in pgAdmin.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Success! <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"325\" height=\"192\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-4.png\" alt=\"Successful connection\" class=\"wp-image-199\" style=\"width:332px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-4.png 325w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-4-300x177.png 300w\" sizes=\"auto, (max-width: 325px) 100vw, 325px\" \/><figcaption class=\"wp-element-caption\">Successful connection.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create GIS Database <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can create a database where we will store our geographic data. You can do this easily through pgAdmin (Right-click Databases &gt; New Database) or through the command prompt on the database machine. First, sign in: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>$sudo -u postgres psql<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then use the CREATE DATABASE command: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CREATE DATABASE gisgdb2;<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we have a look at pgAdmin, we should be able to see the new database: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"320\" height=\"318\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-5.png\" alt=\"New database visible in pgAdmin.\" class=\"wp-image-200\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-5.png 320w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-5-300x298.png 300w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-5-150x150.png 150w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><figcaption class=\"wp-element-caption\">New database visible in pgAdmin.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">In order to enable our database to store geographic information, we also need to add the PostGIS extension to the database. You can do this by using the CREATE EXTENSION command: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"266\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-6-1024x266.png\" alt=\"Adding the PostGIS extension to the gisgdb2 database.\" class=\"wp-image-202\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-6-1024x266.png 1024w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-6-300x78.png 300w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-6-768x200.png 768w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-6.png 1069w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Adding the PostGIS extension to the gisgdb2 database.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now we have a PostGIS enabled PostgreSQL database we can use for all of our mapping needs! There are just a few other things to take care of. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create new GIS user and GIS data schema<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You could technically just use the postgres user and the default public schema to store and access your geographic data. However, I want to model this a bit more like an organization would. So I am going to create a specific GIS user that has their own schema for storing and accessing data. On the PostgreSQL machine, log in to the database: <br><br><strong>$ sudo -u postgres psql <\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new user:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CREATE USER ccsgeoprod WITH encrypted password &#8216;ccsgeoprod&#8217;;<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Switch into the database created in the step above: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>postgres=# \\c gisgdb2<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Grant all privileges to the new user on this database: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>gisgdb2=# GRANT ALL PRIVILEGES ON DATABASE gisgdb2 TO ccsgeoprod;<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a schema with the same name as the user: <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CREATE SCHEMA AUTHORIZATION ccsgeoprod;<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Be sure to test your new user by connecting to the database via pgAdmin. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Connect to the Database in QGIS<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The final step is to make sure that we can actually make a connection to the new database with the ccsgeoprod user and load some data! To create a database connection in QGIS, navigate to the PostgreSQL option in the Browser &gt; Right-click &gt; New Connection: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"453\" height=\"533\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-7.png\" alt=\"QGIS database connection.\" class=\"wp-image-207\" style=\"width:411px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-7.png 453w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-7-255x300.png 255w\" sizes=\"auto, (max-width: 453px) 100vw, 453px\" \/><figcaption class=\"wp-element-caption\">QGIS database connection.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">As my hba_conf file is configured with the hostssl option, I had to set the SSL mode to &#8216;allow&#8217;. In the Authentication section, I chose basic and entered in the username and password for ccsgeoprod. The test connection was successful and I can now see the two available schemas in the Browser: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"479\" height=\"442\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-8.png\" alt=\"The database and schema visible in the QGIS Browser.\" class=\"wp-image-210\" style=\"width:431px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-8.png 479w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-8-300x277.png 300w\" sizes=\"auto, (max-width: 479px) 100vw, 479px\" \/><figcaption class=\"wp-element-caption\">The database and schema visible in the QGIS Browser.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">I then used the Export to PostgreSQL data loading tool to load a shapefile to my new database: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"689\" height=\"581\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-9.png\" alt=\"Export to PostgreSQL tool. \" class=\"wp-image-211\" style=\"width:378px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-9.png 689w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-9-300x253.png 300w\" sizes=\"auto, (max-width: 689px) 100vw, 689px\" \/><figcaption class=\"wp-element-caption\">Export to PostgreSQL tool. <\/figcaption><\/figure>\n<\/div>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"465\" height=\"444\" src=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-10.png\" alt=\"The loaded data. \" class=\"wp-image-212\" style=\"width:357px;height:auto\" srcset=\"https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-10.png 465w, https:\/\/www.ccsgeo.com\/wp-content\/uploads\/2024\/01\/image-10-300x286.png 300w\" sizes=\"auto, (max-width: 465px) 100vw, 465px\" \/><figcaption class=\"wp-element-caption\">The loaded data. <\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Success! <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this part of deploying an open source GIS stack, we stepped through downloading PostgreSQL, configuring connections, creating a database, enabling PostGIS, creating users and schemas, and loading data through QGIS. This database will give us a solid platform for being able to publish and serve out web services via Geoserver, as well as manage and work with our geographic data through QGIS. Stay tuned for part three &#8211; deploying Geoserver. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The foundation of any open source GIS stack is PostgreSQL with the PostGIS extension. In part 1 of this series, I laid out the deployment architecture and spun up some Ubuntu Server virtual machines on VMWare ESXI. There are a few steps to deploy the database so that it can be used as a GIS [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":218,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[13,7,12],"tags":[],"class_list":["post-179","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-foss","category-technology","category-workflow"],"_links":{"self":[{"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/posts\/179","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/comments?post=179"}],"version-history":[{"count":24,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/posts\/179\/revisions"}],"predecessor-version":[{"id":217,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/posts\/179\/revisions\/217"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/media\/218"}],"wp:attachment":[{"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/media?parent=179"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/categories?post=179"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ccsgeo.com\/index.php\/wp-json\/wp\/v2\/tags?post=179"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}