{"id":1825,"date":"2017-07-21T12:58:22","date_gmt":"2017-07-21T07:28:22","guid":{"rendered":"https:\/\/pheonixsolutions.com\/blog\/?p=1825"},"modified":"2026-09-09T16:17:05","modified_gmt":"2026-09-09T10:47:05","slug":"install-postgresql-ubuntu-16","status":"publish","type":"post","link":"https:\/\/pheonixsolutions.com\/blog\/install-postgresql-ubuntu-16\/","title":{"rendered":"PostgreSQL Installation Guide for Ubuntu 16.04"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This guide explains how to install PostgreSQL on Ubuntu, covering everything from the initial package installation through creating a dedicated database user and configuring access \u2014 not just the bare minimum needed to get the service running.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">PostgreSQL is a powerful, open-source object-relational database server, often compared to MySQL but known for stronger standards compliance, more advanced data types, and robust support for complex queries and concurrent transactions. It&#8217;s a common choice for applications that need reliability and advanced features beyond what simpler database engines offer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One quick note before starting: if you&#8217;re following this guide because you found an older tutorial referencing Ubuntu 16.04, be aware that Ubuntu 16.04 reached end of standard support in April 2021 and end of all support (including Extended Security Maintenance) in April 2024. The installation steps below apply equally to any current Ubuntu LTS release (22.04, 24.04, etc.) \u2014 Section II covers this in more detail before you proceed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">I. Prerequisites<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before you install PostgreSQL on Ubuntu, make sure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>An Ubuntu host (ideally a currently supported LTS release \u2014 see Section II)<\/li>\n\n\n\n<li>Root or sudo access<\/li>\n\n\n\n<li>Basic familiarity with the Linux command line<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">II. Important: Use a Currently Supported Ubuntu Version<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re setting this up on Ubuntu 16.04 specifically because an old tutorial recommended it, it&#8217;s worth stopping to reconsider. Ubuntu 16.04 no longer receives security updates from Canonical as of April 2024, which means:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The underlying OS carries unpatched vulnerabilities that will only accumulate over time<\/li>\n\n\n\n<li>PostgreSQL itself may not offer packages compatible with such an old Ubuntu release going forward<\/li>\n\n\n\n<li>Running any production database server on an unsupported OS is a real, compounding security risk, regardless of how well PostgreSQL itself is configured<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The commands in this guide work identically on Ubuntu 22.04, 24.04, or any current LTS release \u2014 there&#8217;s no reason to specifically target 16.04 today. If you&#8217;re maintaining an existing legacy 16.04 system, treat this as a strong signal to plan a migration to a supported release.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">III. Architecture Overview<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before installing anything, it helps to understand how PostgreSQL is structured once running:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <strong>PostgreSQL server process<\/strong> (<code>postgres<\/code>) runs continuously in the background, listening for connections<\/li>\n\n\n\n<li><strong>Client applications<\/strong> \u2014 whether that&#8217;s the <code>psql<\/code> command-line tool, a web application, or a GUI tool like pgAdmin \u2014 connect to this server process over a Unix socket (for local connections) or TCP\/IP (for network connections)<\/li>\n\n\n\n<li>Each client connection authenticates against PostgreSQL&#8217;s role-based permission system, which determines what that specific connection is allowed to see or modify<\/li>\n\n\n\n<li>The server manages all actual reads and writes to the underlying data files on disk \u2014 clients never touch the data files directly<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-scaled.png\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"512\" src=\"https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-1024x512.png\" alt=\"\" class=\"wp-image-11572\" srcset=\"https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-1024x512.png 1024w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-300x150.png 300w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-768x384.png 768w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-1536x768.png 1536w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2017\/07\/postgresql_architecture_v2-2048x1024.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This matters practically because PostgreSQL&#8217;s default authentication setup \u2014 covered in the next few steps \u2014 relies on this role system tightly, including a close relationship between Linux system users and PostgreSQL database roles that trips up a lot of newcomers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">IV. Update System Packages<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before installing anything new, update your package index:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt update\nsudo apt upgrade -y\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">V. Install PostgreSQL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Install PostgreSQL along with the <code>postgresql-contrib<\/code> package, which adds useful additional extensions and utilities not included in the base package:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt install postgresql postgresql-contrib -y\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This installs the PostgreSQL server, the <code>psql<\/code> command-line client, and creates a dedicated Linux system user named <code>postgres<\/code>, which PostgreSQL uses internally for its own administrative operations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">VI. Verify the PostgreSQL Service Is Running<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the service status:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl status postgresql\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should see <code>active (running)<\/code>. If it&#8217;s not running, start it manually:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl start postgresql\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">VII. Enable PostgreSQL to Start on Boot<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ensure PostgreSQL automatically starts whenever the server reboots:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl enable postgresql\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">VIII. Access the PostgreSQL Prompt<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is where a small but common mistake shows up in a lot of quick-reference guides. PostgreSQL&#8217;s default administrative Linux user is named <strong><code>postgres<\/code><\/strong> \u2014 not <code>postgresql<\/code>. Using the wrong username here will fail with a &#8220;role does not exist&#8221; or &#8220;user does not exist&#8221; error, since Linux and PostgreSQL both expect the exact system username that was created during installation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The correct command is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo -u postgres psql\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This switches to the <code>postgres<\/code> system user and opens the <code>psql<\/code> interactive prompt as PostgreSQL&#8217;s default superuser role, also named <code>postgres<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To exit the prompt at any time:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\q\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">IX. Create a New Database and User<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Rather than using the default <code>postgres<\/code> superuser role for applications, create a dedicated database and a scoped user \u2014 the same least-privilege principle that applies to any database system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From inside the <code>psql<\/code> prompt:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CREATE DATABASE example_db;\nCREATE USER app_user WITH ENCRYPTED PASSWORD 'Str0ng-Unique-Passw0rd!';\nGRANT ALL PRIVILEGES ON DATABASE example_db TO app_user;\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Security note:<\/strong> Replace both the username and password with real, strong, unique values. Avoid short or predictable passwords \u2014 PostgreSQL, like any database exposed to an application, is a common target if credentials are weak or reused elsewhere.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">X. Verify the New User Works<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Exit the current <code>psql<\/code> session:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\q\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then log in directly as the new user, connecting to the specific database:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">psql -U app_user -d example_db -h localhost\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The <code>-h localhost<\/code> flag matters here. By default, PostgreSQL&#8217;s local authentication method (<code>peer<\/code> authentication) expects the connecting Linux system username to exactly match the PostgreSQL role name \u2014 which won&#8217;t be true for an application-specific role like <code>app_user<\/code> unless a matching Linux user also exists. Specifying <code>-h localhost<\/code> forces a TCP connection instead, which uses password authentication (assuming it&#8217;s configured, covered in the next step) rather than relying on the Linux username matching.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">XI. Configure Password Authentication (If Needed)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the connection in Step X is rejected, PostgreSQL&#8217;s authentication configuration may need adjusting. Open the <code>pg_hba.conf<\/code> file, whose exact path varies by PostgreSQL version but is commonly:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo vi \/etc\/postgresql\/*\/main\/pg_hba.conf\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Look for a line matching local TCP connections, typically something like:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">host    all             all             127.0.0.1\/32            scram-sha-256\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If this line uses <code>peer<\/code> or <code>ident<\/code> instead of <code>scram-sha-256<\/code> (or <code>md5<\/code> on older PostgreSQL versions), change it to <code>scram-sha-256<\/code> for local TCP connections to use standard password authentication. After editing, restart PostgreSQL:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl restart postgresql\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> <code>scram-sha-256<\/code> is the modern, more secure password authentication method in current PostgreSQL versions, and is preferable to the older <code>md5<\/code> method where available.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">XII. Common PostgreSQL Administration Commands<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A few commands worth keeping on hand once your database and user are set up, run from inside <code>psql<\/code>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>List all databases:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\l\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>List all roles (users):<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\du\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Connect to a specific database:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\c example_db\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>List tables in the current database:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\\dt\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Change a user&#8217;s password:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ALTER USER app_user WITH ENCRYPTED PASSWORD 'NewStrongerPassword!';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Revoke privileges from a user:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">REVOKE ALL PRIVILEGES ON DATABASE example_db FROM app_user;\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">XIII. Troubleshooting Common Issues<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>&#8220;role does not exist&#8221; when running <code>sudo -u postgres psql<\/code>:<\/strong> Double-check the username is exactly <code>postgres<\/code>, not <code>postgresql<\/code> \u2014 this is the single most common typo, as covered in Step VIII.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>&#8220;Peer authentication failed&#8221; when connecting as an application user:<\/strong> This means you&#8217;re connecting via a Unix socket rather than TCP, and the Linux system username doesn&#8217;t match the PostgreSQL role. Add <code>-h localhost<\/code> to force a TCP connection, as shown in Step X, or adjust <code>pg_hba.conf<\/code> as covered in Step XI.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>PostgreSQL service fails to start after installation:<\/strong> Check the service logs for specifics:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo journalctl -u postgresql\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This usually points directly to a configuration file issue or a port conflict with another running service.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Changes to pg_hba.conf don&#8217;t seem to take effect:<\/strong> Confirm you restarted the PostgreSQL service after editing the file \u2014 a reload isn&#8217;t always sufficient for authentication method changes, depending on the specific setting changed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">XIV. Allowing Remote Connections (If Actually Needed)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">By default, PostgreSQL only listens for local connections. If you have a genuine need for a remote application server to connect to this database \u2014 for example, a separate application server in the same private network \u2014 two files need adjustment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. Allow PostgreSQL to listen on network interfaces<\/strong>, not just localhost. Edit <code>postgresql.conf<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo vi \/etc\/postgresql\/*\/main\/postgresql.conf\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Find the <code>listen_addresses<\/code> line and set it to either a specific IP or all interfaces:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">listen_addresses = '*'\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Using <code>*<\/code> listens on all network interfaces. For tighter control, specify the exact IP address of the interface you want PostgreSQL reachable on instead.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Add a rule permitting the specific remote host<\/strong> in <code>pg_hba.conf<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">host    example_db      app_user        192.168.1.50\/32         scram-sha-256\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This line permits connections to <code>example_db<\/code> from the specific role <code>app_user<\/code>, only from the IP address <code>192.168.1.50<\/code>, using password authentication.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>3. Restart PostgreSQL<\/strong> to apply both changes:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl restart postgresql\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>4. Update your firewall<\/strong> to allow the connection. If using <code>ufw<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo ufw allow from 192.168.1.50 to any port 5432\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Security note:<\/strong> Scope both the <code>pg_hba.conf<\/code> rule and firewall rule to the narrowest set of hosts and databases actually required. A broad rule like <code>0.0.0.0\/0<\/code> in <code>pg_hba.conf<\/code> combined with an open firewall port exposes your database to the entire internet \u2014 precisely the exposure the security best practices section above recommends avoiding.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">XV. Security Best Practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Avoid using the <code>postgres<\/code> superuser role for applications.<\/strong> Always create scoped, dedicated roles per application or use case, following the least-privilege principle covered in Step IX.<\/li>\n\n\n\n<li><strong>Restrict network exposure.<\/strong> Unless remote connections are genuinely required, keep PostgreSQL bound to <code>localhost<\/code> and use SSH tunneling or a VPN for any remote administrative access instead of exposing port 5432 directly to the internet.<\/li>\n\n\n\n<li><strong>Keep PostgreSQL updated.<\/strong> Like any database software, PostgreSQL receives periodic security patches \u2014 staying current is one of the most effective, low-effort security practices available.<\/li>\n\n\n\n<li><strong>Use strong, unique passwords for every role,<\/strong> and rotate them periodically, especially for roles with broad privileges.<\/li>\n\n\n\n<li><strong>Back up regularly using <code>pg_dump<\/code>,<\/strong> and periodically test that backups can actually be restored, since an untested backup provides false confidence rather than real protection.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">XVI. Conclusion<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You&#8217;ve now installed PostgreSQL on Ubuntu, verified the service is running and set to start on boot, and created a dedicated database and user rather than relying on the default superuser account for everyday use. Along the way, this guide corrected a common typo (<code>postgres<\/code>, not <code>postgresql<\/code>, as the system username) and covered the authentication quirks \u2014 particularly <code>peer<\/code> vs. TCP-based password authentication \u2014 that trip up a lot of newcomers on their first PostgreSQL setup. With that foundation in place, you&#8217;re ready to connect real applications to your database securely.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For deeper reference on roles, authentication methods, and configuration options, see the official PostgreSQL documentation.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Why do I get &#8220;role does not exist&#8221; even though I just installed PostgreSQL?<\/strong> This almost always means a typo in the username \u2014 the correct default administrative user is <code>postgres<\/code>, not <code>postgresql<\/code>. Double-check the exact spelling in your command.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What&#8217;s the difference between peer authentication and password authentication in PostgreSQL?<\/strong> Peer authentication (used by default for local Unix socket connections) trusts the connection based on the Linux system username matching the PostgreSQL role name, with no password required. Password-based authentication (like <code>scram-sha-256<\/code>) requires an actual password, and applies to TCP connections or when explicitly configured in <code>pg_hba.conf<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Can I use PostgreSQL and MySQL on the same server at the same time?<\/strong> Yes \u2014 the two use different default ports (5432 for PostgreSQL, 3306 for MySQL) and are otherwise independent, so running both simultaneously on the same host is common and generally not an issue, as long as the server has adequate resources for both.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Is it safe to expose PostgreSQL&#8217;s port directly to the internet?<\/strong> Generally not recommended. Keep PostgreSQL bound to <code>localhost<\/code> for local application connections, and use SSH tunneling, a VPN, or a properly firewalled private network for any legitimate remote access needs instead of exposing port 5432 publicly.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Talk to Our Technology Experts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Setting up or managing a PostgreSQL database? Our team can help with database administration and server security.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/pheonixsolutions.com\/contact\">Connect with our technology experts.<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Related Articles<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/pheonixsolutions.com\/blog\/how-to-setup-mysql-and-create-a-user-on-ubuntu-24-04\/\">Setup MySQL and Create a User on Ubuntu 24.04<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction This guide explains how to install PostgreSQL on Ubuntu, covering everything from the initial package installation through creating a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1022],"tags":[358,274],"class_list":["post-1825","post","type-post","status-publish","format-standard","hentry","category-web-architecture","tag-postgresql","tag-ubuntu","psol-cat-web-architecture"],"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/phn2x7-tr","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1825","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=1825"}],"version-history":[{"count":3,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1825\/revisions"}],"predecessor-version":[{"id":11574,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1825\/revisions\/11574"}],"wp:attachment":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=1825"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=1825"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=1825"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}