PostgreSQL 18 pgAdmin
Overview
This image ships PostgreSQL 18 and pgAdmin 4 together on Ubuntu 24.04 LTS, configured and ready to use from the first boot of every deployed virtual machine. PostgreSQL 18 is installed from the official PGDG repository and runs as a single-node relational database on port 5432. pgAdmin 4 is the open source web administration console for PostgreSQL. Apache 2 serves it on port 80 and redirects the virtual machine's root URL to the pgAdmin 4 interface.
What you get:
- Per-VM credentials. On the very first boot, a one-time initialisation service generates a unique password for the postgres database role and a unique password for the pgAdmin 4 admin account. It writes them to a single credentials file that only root can read, and then permanently marks itself as done so that it never runs again. Two virtual machines launched from the same gallery image never share passwords.
- A pre-registered server. Open
http://<your-vm-public-ip>/pgadmin4/in any browser. The pgAdmin 4 console has the local PostgreSQL 18 server pre-registered. After you log in and expand the Servers tree, you are one password prompt away from a connected database session. - The psql client. The psql command-line client is installed and available over SSH for scripting, automation or direct SQL work without the browser.
The image is intended for developers, data engineers and database administrators who want a PostgreSQL 18 server with a browser-based management interface ready in minutes. You do not need to install packages, configure authentication or bootstrap credentials by hand. It is not a replicated cluster, and it does not ship with TLS on port 80. Step 14 covers TLS termination and the security steps to take before you expose the server to the public internet.
Prerequisites
Before you deploy this image, you need the following:
- A Microsoft Azure subscription with permissions to create resource groups, virtual networks and virtual machines.
- An SSH public key for the initial login to the azureuser admin account on the virtual machine.
- A virtual network and subnet in the eastus region, with an associated network security group.
- Inbound NSG rules that allow TCP 22 from your management IP and TCP 80 from the IPs that need pgAdmin 4 access.
- The Azure CLI (
azversion 2.50 or later), if you plan to use the CLI deployment path in Step 2.
Deploy the Virtual Machine from the Azure Portal
In the Azure Portal, go to Marketplace, search for PostgreSQL 18 pgAdmin, and select the SecureAnyCloud publisher entry. Click Create.
On the Basics tab, choose your subscription, target resource group and region, and set the virtual machine name. Choose SSH public key as the authentication type, enter a username, and paste your SSH public key. Standard_D2s_v3 is the recommended minimum size for PostgreSQL 18 with pgAdmin. For production workloads with significant query load or many concurrent connections, start with Standard_D4s_v3 or larger.
On the Disks tab, select Standard SSD for the OS disk. PostgreSQL data lives under /var/lib/postgresql/18/main. If you expect to store more than 20 GB of data, attach a separate Premium SSD data disk now, and configure the tablespace to use it after the server is running.
On the Networking tab, select your existing virtual network and subnet. Attach a network security group that opens TCP 22 from your management IP range and TCP 80 from the client IPs that need pgAdmin access. Do not expose port 80 to the entire public internet unless you have added TLS termination as described in Step 14.
On the Management, Monitoring and Advanced tabs, the defaults are appropriate. Click Review + create, wait for validation to pass, and then click Create. Deployment takes around two to three minutes.
Deploy the Virtual Machine from the Azure CLI
To deploy from the command line, accept the Marketplace terms once, and then deploy from the Marketplace image URN:
RG="postgresql-prod" LOCATION="eastus" VM_NAME="postgresql-01" ADMIN_USER="azureuser" IMAGE_URN="sac1647283583153:postgresql-18-pgadmin-ubuntu-24-04:standard:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create \
--resource-group "$RG" \
--name "${VM_NAME}-vnet" \
--address-prefix "10.0.0.0/16" \
--subnet-name default \
--subnet-prefix "10.0.1.0/24" az network nsg create \
--resource-group "$RG" \
--name "${VM_NAME}-nsg" az network nsg rule create \
--resource-group "$RG" \
--nsg-name "${VM_NAME}-nsg" \
--name AllowSSH \
--priority 100 \
--protocol Tcp \
--destination-port-ranges 22 az network nsg rule create \
--resource-group "$RG" \
--nsg-name "${VM_NAME}-nsg" \
--name AllowHTTP \
--priority 110 \
--protocol Tcp \
--destination-port-ranges 80
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:postgresql-18-pgadmin-ubuntu-24-04:standard:latest
az vm create \
--resource-group "$RG" \
--name "$VM_NAME" \
--image "$IMAGE_URN" \
--size Standard_D2s_v3 \
--admin-username "$ADMIN_USER" \
--ssh-key-value "$SSH_KEY" \
--vnet-name "${VM_NAME}-vnet" \
--subnet default \
--nsg "${VM_NAME}-nsg" \
--storage-sku StandardSSD_LRS \
--public-ip-sku StandardThe --storage-sku StandardSSD_LRS flag selects a Standard SSD OS disk. This tier is the right choice when the database itself is on an attached data disk, because the default Premium SSD costs more than the OS disk needs.
First Boot and Credentials
After deployment finishes, note the public IP address from the Azure Portal or from az vm show. Connect to the virtual machine over SSH:
ssh azureuser@<your-vm-public-ip>On first boot, a one-time initialisation service named postgresql-firstboot.service runs automatically. It generates unique passwords for the PostgreSQL postgres role and the pgAdmin 4 admin account, and writes them to a credentials file. The service typically completes within 15 seconds of the virtual machine reaching the login prompt. Read the credentials file:
sudo cat /root/postgresql-credentials.txtThe output looks like this:
# PostgreSQL 18 + pgAdmin 4 — generated on first boot
# These credentials are unique to this VM. Store them somewhere safe.
# pgAdmin 4 web console (use this to manage PostgreSQL via a browser) pgadmin.url=http://10.0.1.10/pgadmin4/ pgadmin.email=admin@example.com pgadmin.password=<unique-password>
# PostgreSQL 18 (use this from psql or any client driver) postgres.host=127.0.0.1 postgres.port=5432 postgres.role=postgres postgres.password=<unique-password> postgres.database=postgresSave these credentials. Only root can read the credentials file (0600), and it never leaves the virtual machine.
Verify that PostgreSQL 18 is running and confirm the installed version. The pg_lsclusters command lists the cluster status:
sudo -u postgres psql -c 'SELECT version();' pg_lsclusters systemctl is-active postgresql apache2The output confirms that PostgreSQL 18.3 is running on port 5432, the cluster is online, and both the postgresql and apache2 services are active.
Access pgAdmin 4
Open http://<your-vm-public-ip>/pgadmin4/ in a browser. Apache redirects the root URL, so http://<your-vm-public-ip>/ also lands on the pgAdmin 4 login page.
Enter the Email Address and Password from the credentials file (pgadmin.email and pgadmin.password), and click Login.
After you log in, the pgAdmin 4 dashboard opens. The Object Explorer panel on the left shows a Servers group. The local PostgreSQL 18 instance is pre-registered in it as PostgreSQL 18 (localhost).
Connect to PostgreSQL 18 Through pgAdmin
In the Object Explorer, click the expand arrow next to Servers. pgAdmin prompts for the PostgreSQL role password to connect to the pre-registered server.
Enter the postgres.password value from your credentials file and click OK.
pgAdmin connects to the PostgreSQL 18 instance and expands the server tree to show the Databases, Login/Group Roles and Tablespaces nodes. The Dashboard tab on the right updates to show live server activity charts for sessions, transactions per second, tuples and block I/O.
The server is now connected. You can browse databases, run queries, manage roles and inspect server statistics entirely through the browser.
Create a Database
Using pgAdmin 4: In the Object Explorer, expand Servers > PostgreSQL 18 (localhost) > Databases. Right-click Databases and select Create > Database. Enter a name in the Database field, optionally set an owner, and click Save. The new database appears in the tree immediately.
Using psql: Connect over SSH and run:
sudo -u postgres psqlThen, in the psql session, run:
CREATE DATABASE myapp; \l \qThe \l command lists all databases including the one you just created. The \q command exits psql.
Create a Database Role
Do not connect applications directly as the postgres superuser. Create a dedicated role for each application:
CREATE ROLE appuser WITH LOGIN PASSWORD 'choose-a-strong-password'; GRANT ALL PRIVILEGES ON DATABASE myapp TO appuser; \qTo verify that the role was created, list the roles:
\duThe command lists all roles with their attributes. The new appuser role appears with the Login attribute set.
Run a Query from pgAdmin
To open a query window in pgAdmin, expand the Servers tree and click the database you want to query. Then click the Query Tool button in the toolbar at the top, or select Tools > Query Tool.
Type a query in the editor pane and press F5 to run it, or use the Execute/Refresh button (the play triangle). Results appear in the data output panel below the editor.
For example, to confirm the current PostgreSQL version from inside pgAdmin, run:
SELECT version();To list all tables in the public schema of your database, run:
SELECT tablename FROM pg_tables WHERE schemaname = 'public';Connect with psql and a Connection String
You can use the PostgreSQL role password from the credentials file in any connection string. From the virtual machine itself, run:
PGPASSWORD='<postgres.password>' psql \
"postgresql://postgres@127.0.0.1:5432/postgres" \
-c 'SELECT current_database(), current_user;'From an application on the same virtual network, using the private IP:
postgresql://postgres:<password>@<private-ip>:5432/myappPostgreSQL 18 accepts remote connections from the same virtual network by default. Connections from outside the virtual network need NSG rule changes and pg_hba.conf updates, as described in Step 11.
Install PostgreSQL Client Libraries
The virtual machine has the full PostgreSQL 18 server package installed, which includes psql and all server utilities. You do not need to install a client on the VM.
For a separate application server that needs only the client libraries, run:
sudo apt-get install -y postgresql-client-18For language-specific drivers, use psycopg2 or psycopg3 for Python, pg for Node.js, the JDBC driver published at https://jdbc.postgresql.org for Java, and pgx for Go.
Allow Remote Connections
By default, PostgreSQL 18 listens on 127.0.0.1 only. To accept connections from other hosts on the virtual network, make the following configuration changes.
1. Edit postgresql.conf to listen on all interfaces:
sudo nano /etc/postgresql/18/main/postgresql.confFind the listen_addresses line, uncomment it if necessary, and set it to:
listen_addresses = '*'2. Edit pg_hba.conf to allow the virtual network CIDR:
sudo nano /etc/postgresql/18/main/pg_hba.confAdd a line for your virtual network. For example, if your subnet is 10.0.1.0/24, add:
host all all 10.0.1.0/24 scram-sha-2563. Reload PostgreSQL to apply both changes:
sudo systemctl reload postgresqlKeep this CIDR as narrow as possible. Do not use 0.0.0.0/0 unless you have TLS and a strong firewall policy in place.
Backup and Restore
Back up a single database with pg_dump:
sudo -u postgres pg_dump myapp > /tmp/myapp-backup.sqlTo compress the backup:
sudo -u postgres pg_dump -Fc myapp > /tmp/myapp-backup.dumpRestore from a plain SQL dump:
sudo -u postgres psql myapp < /tmp/myapp-backup.sqlRestore from a custom-format dump:
sudo -u postgres pg_restore -d myapp /tmp/myapp-backup.dumpBack up all databases with pg_dumpall:
sudo -u postgres pg_dumpall > /tmp/all-databases.sqlFor production workloads, schedule pg_dump as a cron job and copy the output to Azure Blob Storage with azcopy or the Azure CLI.
Monitor PostgreSQL Logs
PostgreSQL writes its logs to /var/log/postgresql/. The main log file for the running cluster is:
/var/log/postgresql/postgresql-18-main.logTo follow the log in real time:
sudo tail -f /var/log/postgresql/postgresql-18-main.logTo check the current log level and logging configuration, run:
sudo -u postgres psql -c "SHOW log_min_messages;"
sudo -u postgres psql -c "SHOW logging_collector;"The pgAdmin 4 Logs tab under the server node also shows recent log entries in the browser.
Security Hardening
Take the following steps before you expose PostgreSQL 18 or pgAdmin 4 to public traffic.
Change the postgres role password. The firstboot service generates a unique random password, but rotate it immediately to one you generate yourself:
sudo -u postgres psql -c "ALTER ROLE postgres WITH PASSWORD 'your-new-password';"Update the postgres.password value in any applications that use it, and then delete the credentials file:
sudo rm /root/postgresql-credentials.txtCreate application-specific roles. Follow the principle of least privilege. Create a role per application, grant it only the permissions it needs, and never hard-code the postgres superuser password in application code.
Restrict pg_hba.conf entries. Use the most specific CIDR possible for each host entry. Prefer scram-sha-256 over md5 for all new entries. Review and remove any trust entries.
Enable TLS for pgAdmin 4. Apache 2 is already installed. To add TLS, obtain a certificate (Let's Encrypt Certbot works on Ubuntu 24.04), install mod_ssl, and redirect port 80 to 443:
sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d <your-domain>The Certbot Apache plugin writes the SSL virtual host configuration and enables automatic renewal.
Enable TLS for PostgreSQL. PostgreSQL 18 supports native TLS on the server socket. Place a certificate and key at the paths set in ssl_cert_file and ssl_key_file in postgresql.conf, and then set ssl = on. The PGDG package ships with a self-signed certificate that activates TLS immediately. Replace it with a CA-signed certificate before you accept external connections.
Restrict NSG rules. Review your network security group after deployment. Allow port 22 only from your known management IP range. Allow port 80 (or 443 after TLS) only from the browsers and application servers that need access. Do not open PostgreSQL port 5432 in the NSG unless you specifically need direct TCP access from outside the virtual network.
Upgrade and Patch the Operating System
To apply Ubuntu 24.04 security updates, run:
sudo apt-get update
sudo apt-get upgrade -yTo upgrade PostgreSQL to a newer minor version (for example from 18.3 to a later 18.x release), run:
sudo apt-get update
sudo apt-get install -y postgresql-18
sudo systemctl restart postgresqlPostgreSQL minor version upgrades (18.x to 18.y) do not require a cluster dump and restore. Major version upgrades (18 to 19) require pg_upgrade or a dump-restore cycle.
Additional Resources
- PostgreSQL 18 documentation: https://www.postgresql.org/docs/18/
- pgAdmin 4 documentation: https://www.pgadmin.org/docs/pgadmin4/latest/
- PGDG APT repository: https://wiki.postgresql.org/wiki/Apt
- SecureAnyCloud Azure Marketplace products: https://secureanycloud.com/azure
- Support and feedback: https://secureanycloud.com/support
Deploy on Azure
Launch PostgreSQL 18 and pgAdmin 4 on Ubuntu 24.04 on Azure with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
This guide shows you how to connect to PostgreSQL and use the pgAdmin 4 web interface on an EC2 instance launched from the SecureAnyCloud AWS Marketplace AMI. The AMI ships with PostgreSQL 18 and pgAdmin 4 preinstalled. On the first boot, a one-shot service generates a unique set of credentials for that instance.
Prerequisites
- An EC2 instance launched from the SecureAnyCloud PostgreSQL with pgAdmin 4 Marketplace AMI.
- A security group that allows inbound TCP 22 (SSH) and TCP 80 (HTTP) to the instance.
- The
.pemkey file that you downloaded at launch time.
Connecting to your instance
Operating system variant SSH login user
AlmaLinux 9 ec2-user
ssh -i /path/to/key.pem ec2-user@<instance-public-ip>Retrieving generated credentials
On first boot, a systemd service generates a unique PostgreSQL superuser password and a unique pgAdmin 4 admin password. It writes them to /root/postgresql-credentials.txt. Only root can read the file.
sudo cat /root/postgresql-credentials.txtThe expected output looks like this:
# PostgreSQL 18 + pgAdmin 4 — generated on first boot
# These credentials are unique to this VM. Store them somewhere safe.
# PostgreSQL 18 superuser postgresql.superuser=postgres postgresql.superuser.password=x8rTLN1UQfUFEVi5C6rWduTJPofE2IO7
# pgAdmin 4 web console pgadmin.admin.email=admin@example.com pgadmin.admin.password=sHntLKWILHOHCzs1EV99A1! pgadmin.url=http://172.31.90.184/pgadmin4
# Quick check:
# PGPASSWORD=<set-at-first-boot> psql -U postgres -h 127.0.0.1 -c 'SELECT version();'Checking service status
/usr/pgsql-18/bin/psql --versionpsql (PostgreSQL) 18.4systemctl status postgresql-18 httpd* postgresql-18.service - PostgreSQL 18 database server Loaded: loaded (/usr/lib/systemd/system/postgresql-18.service; enabled) Active: active (running) since Wed 2026-05-27 19:54:28 UTC Main PID: 3108 (/usr/pgsql-18/bin/postgres -D /var/lib/pgsql/18/data/) * httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled) Active: active (running) since Wed 2026-05-27 19:55:23 UTC Status: "Total requests: 86; Idle/Busy workers 100/0"pgAdmin 4 web interface
Apache httpd serves pgAdmin 4 at /pgadmin4/. Browse to:
http://<instance-public-ip>/pgadmin4/The instance root URL redirects to this address automatically.
Sign in with the pgadmin.admin.email and pgadmin.admin.password values from /root/postgresql-credentials.txt.
The local PostgreSQL 18 server is pre-registered in pgAdmin. Expand Servers > PostgreSQL 18 (localhost) in the object browser on the left, and enter the postgresql.superuser.password when prompted. From there you can browse schemas, run queries in the Query Tool and monitor server activity in the Dashboard.
Connecting with psql
Connect with the PostgreSQL superuser password from the credentials file:
PGPASSWORD=<postgresql.superuser.password> psql -U postgres -h 127.0.0.1 -c 'SELECT version();'version ----------------------------------------------------------------------------------------------------------- PostgreSQL 18.4 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-14), 64-bit (1 row)You can also run psql as the postgres OS user, which uses local peer authentication and opens an interactive psql session:
sudo -u postgres psqlCreating a database and user
Run psql as the postgres superuser to create an application database and a dedicated user:
sudo -u postgres /usr/pgsql-18/bin/psql -c "CREATE DATABASE myapp;"
sudo -u postgres /usr/pgsql-18/bin/psql -c "CREATE USER appuser WITH PASSWORD 'securepass123';"
sudo -u postgres /usr/pgsql-18/bin/psql -c "GRANT ALL PRIVILEGES ON DATABASE myapp TO appuser;"
sudo -u postgres /usr/pgsql-18/bin/psql -lList of databases Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges -----------+----------+----------+-----------------+-------------+-------------+--------+-----------+----------------------- myapp | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =Tc/postgres + | | | | | | | | postgres=CTc/postgres+ | | | | | | | | appuser=CTc/postgres postgres | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | template0 | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =c/postgres + | | | | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | libc | en_US.UTF-8 | en_US.UTF-8 | | | =c/postgres + | | | | | | | | postgres=CTc/postgres (4 rows)Backing up a database with pg_dump
To create a compressed binary dump of a database, run:
sudo -u postgres /usr/pgsql-18/bin/pg_dump postgres -Fc -f /tmp/postgres_backup.dumpTo restore the dump with pg_restore, run:
sudo -u postgres /usr/pgsql-18/bin/pg_restore -d myapp -Fc /tmp/myapp_backup.dumpTo create a plain SQL dump instead, run:
sudo -u postgres /usr/pgsql-18/bin/pg_dump myapp > /tmp/myapp_backup.sqlData volume
The PostgreSQL data directory /var/lib/pgsql/18/data lives on a dedicated 30 GiB gp3 EBS volume mounted at /var/lib/pgsql. You can resize this volume independently. To expand it, increase the EBS volume size in the AWS console, and then run the following for an XFS file system:
sudo xfs_growfs /var/lib/pgsqlFor ext4, replace vol-YOURVOLID with your EBS volume ID from the AWS console and run:
sudo resize2fs /dev/$(lsblk -dno NAME,SERIAL | awk -v s=$(echo vol-YOURVOLID | tr -d -) '$2==s{print $1}')Enabling HTTPS
To serve pgAdmin over HTTPS, install Certbot and configure an SSL virtual host in Apache, or place an Application Load Balancer with an ACM certificate in front of the instance. After you obtain a certificate, update /etc/httpd/conf.d/000-sac-redirect.conf to redirect HTTP to HTTPS.
Screenshots
The pgAdmin 4 web interface login page, served by Apache httpd at the instance IP address with no manual setup.
The pgAdmin 4 object browser, showing the pre-registered local PostgreSQL 18 server and database tree.
Terminal output that shows the psql version and the running status of the postgresql-18 and httpd systemd services.
Support
SecureAnyCloud provides 24/7 technical support for this image. Contact details are on the SecureAnyCloud website.
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com