Deploy PostgreSQL Server with Security on GPU Cloud (2026 Guide) banner image

Deploy PostgreSQL Server with Security on GPU Cloud (2026 Guide)

Deploy a production-ready PostgreSQL 16 server with enterprise-grade security defaults. This guide covers localhost binding, firewall configuration, and least-privilege database roles on Massed Compute infrastructure.

PostgreSQL
Database
Security
Ubuntu 24.04
Cloud Infrastructure
AI Agent Shortcut

Skip the manual setup. This guide exists as a tested, machine-readable recipe in the Massed Compute MCP. Connect an AI agent to provision and configure your PostgreSQL server automatically.

PostgreSQL remains the world’s most advanced open-source database, but default installations often lack production-grade security. This guide deploys PostgreSQL 16 with defense-in-depth: localhost-only binding, UFW firewall protection, revoked public schema access, and a non-superuser application role.

You’ll provision a secure database server that follows PostgreSQL security best practices from day one, eliminating common attack vectors while maintaining full functionality for your applications.

Tech Stack
Component Version Purpose
PostgreSQL 16.x Primary database engine
Ubuntu Server 24.04 LTS Base operating system
UFW Latest Uncomplicated firewall
Massed Compute API v1 Cloud infrastructure
System Requirements
Resource Minimum Recommended Notes
vCPU 2 cores 4+ cores For moderate workloads
RAM 4 GiB 8+ GiB PostgreSQL shared_buffers tuning
Storage 400 GB 800+ GB SSD recommended for IOPS
Network SSH access SSH + private network Secure administration

Massed Compute VM Pricing

Choose a CPU-optimized VM that meets your database workload requirements. PostgreSQL benefits from additional CPU cores and RAM for concurrent connections and query processing.

Pricing fetched from the Massed Compute inventory API on June 11, 2026.
SKU Description vCPU RAM Storage Price Capacity
cpu_mini_amd_epyc Mini AMD EPYC 8 32 GiB 400 GB $0.12/hr 31
cpu_small_amd_epyc Small AMD EPYC 14 40 GiB 800 GB $0.22/hr 31
cpu_medium_amd_epyc Medium AMD EPYC 28 80 GiB 1600 GB $0.44/hr 17
cpu_large_amd_epyc Large AMD EPYC 52 160 GiB 3200 GB $0.82/hr 7
cpu_x_large_amd_epyc X-Large AMD EPYC 100 320 GiB 6400 GB $1.56/hr 3
cpu_dedicated_amd_epyc Dedicated AMD EPYC 126 440 GiB 10000 GB $1.98/hr 2
Cost optimization tip: The cpu_mini_amd_epyc provides excellent value for development and small production databases. Scale up to cpu_medium_amd_epyc or larger for high-throughput workloads.

Step-by-Step Deployment

1

Provision Your VM

Launch a new VM in the Massed Compute dashboard or via API:

  • Image: Ubuntu Server 24.04 LTS
  • Product: cpu_mini_amd_epyc or larger CPU instance
  • Region: Any region with available capacity
  • SSH key: Attach a key you can access from your workstation

Wait until the VM status shows Running and SSH is reachable on port 22.

2

Set Database Credentials

Define your database configuration. Replace these placeholders with your actual values:

  • YOUR_SSH_USER: SSH username (usually ubuntu)
  • YOUR_VM_IP: Public IP of your VM
  • YOUR_SSH_KEY_PATH: Path to your SSH private key
  • your_app_db: Database name for your application
  • app_user: Non-superuser database role
  • secure_password_16_chars: Strong password (16+ characters)

3

Install and Configure PostgreSQL

Run this command from your workstation to install PostgreSQL with security hardening:

ssh -i YOUR_SSH_KEY_PATH YOUR_SSH_USER@YOUR_VM_IP 'bash -s' <<'REMOTE'
set -euo pipefail

DB_NAME='your_app_db'
DB_USER='app_user'
DB_PASSWORD='secure_password_16_chars'

export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get install -y postgresql postgresql-contrib ufw

# Configure UFW firewall
sudo ufw allow OpenSSH
sudo ufw --force enable

# Configure PostgreSQL for localhost-only access
PG_CONF=$(sudo -u postgres psql -Atc "SHOW config_file;")
sudo sed -i "s/^#\?listen_addresses.*/listen_addresses = 'localhost'/" "$PG_CONF"
sudo systemctl enable --now postgresql
sudo systemctl restart postgresql

echo POSTGRESQL_INSTALL_OK
REMOTE

4

Create Database and User

Set up your application database with a least-privilege user role:

ssh -i YOUR_SSH_KEY_PATH YOUR_SSH_USER@YOUR_VM_IP 'bash -s' <<'REMOTE'
set -euo pipefail

DB_NAME='your_app_db'
DB_USER='app_user'
DB_PASSWORD='secure_password_16_chars'

sudo -u postgres psql <-- Create application role
DO \$\$ BEGIN
  CREATE ROLE $DB_USER LOGIN PASSWORD '$DB_PASSWORD';
EXCEPTION WHEN duplicate_object THEN
  ALTER ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASSWORD';
END \$\$;

-- Create application database
SELECT 'CREATE DATABASE $DB_NAME OWNER $DB_USER'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$DB_NAME')\gexec

-- Revoke public access and grant to app user
REVOKE ALL ON DATABASE $DB_NAME FROM PUBLIC;
\c $DB_NAME
REVOKE ALL ON SCHEMA public FROM PUBLIC;
GRANT USAGE, CREATE ON SCHEMA public TO $DB_USER;
SQL

echo DATABASE_SETUP_OK
REMOTE

5

Verify Installation

Test the database connection and security configuration:

ssh -i YOUR_SSH_KEY_PATH YOUR_SSH_USER@YOUR_VM_IP 'bash -s' <<'REMOTE'
set -euo pipefail

DB_NAME='your_app_db'
DB_USER='app_user'
DB_PASSWORD='secure_password_16_chars'

# Test application database connection
PGPASSWORD="$DB_PASSWORD" psql -h 127.0.0.1 -U "$DB_USER" -d "$DB_NAME" -c \
  "CREATE TABLE IF NOT EXISTS recipe_smoke(id int primary key);
   INSERT INTO recipe_smoke VALUES (1) ON CONFLICT DO NOTHING;
   SELECT count(*) FROM recipe_smoke;"

# Verify non-superuser role
if sudo -u postgres psql -Atc "SELECT rolsuper FROM pg_roles WHERE rolname='$DB_USER';" | grep -q '^t$'; then
  echo "PostgreSQL app role must not be a superuser" >&2
  exit 1
fi

# Check service and firewall status
sudo systemctl is-active --quiet postgresql
sudo ufw status | grep -q '^Status: active'
sudo ss -ltnp | grep -E '127\.0\.0\.1:5432|\[::1\]:5432'

echo POSTGRESQL_VERIFICATION_OK
REMOTE

Troubleshooting

Connection Refused

If you see psql: connection refused, check the PostgreSQL service status and configuration:

sudo systemctl status postgresql
sudo grep listen_addresses /etc/postgresql/*/main/postgresql.conf

Ensure listen_addresses = 'localhost' is set and PostgreSQL has restarted.

Authentication Failure

Reset the application role password if authentication fails:

sudo -u postgres psql -c "ALTER ROLE app_user WITH PASSWORD 'new_secure_password';"
REMOTE

Remote Access Requirements

For production applications, prefer application proxies or private networks over exposing PostgreSQL directly. If you must allow remote connections, add specific CIDR blocks to pg_hba.conf and create matching UFW rules.

Skip All of This: Deploy with an AI Agent

This entire guide exists as a tested, machine-readable recipe in the Massed Compute MCP. Recipe last tested: June 10, 2026.

Add this MCP server to your AI client:

{
  "mcpServers": {
    "massed-compute": {
      "type": "http",
      "url": "https://vm.massedcompute.com/api/mcp",
      "headers": { "Authorization": "Bearer MC_TOKEN" }
    }
  }
}

Then say:

“Deploy a secure PostgreSQL 16 server on Massed Compute with a database called ‘my_app_prod’ and user ‘api_service’. Use localhost binding and UFW firewall protection.”

The agent matches your request against the recipe catalog, provisions a cpu_mini_amd_epyc VM, runs the installation and security hardening steps above, creates your specified database and user, and reports back with connection details. If any step fails, the agent stops and reports the exact error.

Deploy Your Database Infrastructure

Launch secure, production-ready PostgreSQL servers in minutes. Massed Compute provides enterprise-grade cloud infrastructure with transparent pricing and instant provisioning.

Think it. Build it. Scale it.

Quick Setup Guide

For experienced developers who want the essential commands:

# 1. Provision Ubuntu 24.04 VM with cpu_mini_amd_epyc
# 2. SSH and run:

sudo apt-get update && sudo apt-get install -y postgresql postgresql-contrib ufw
sudo ufw allow OpenSSH && sudo ufw --force enable

# 3. Configure localhost binding
PG_CONF=$(sudo -u postgres psql -Atc "SHOW config_file;")
sudo sed -i "s/^#\?listen_addresses.*/listen_addresses = 'localhost'/" "$PG_CONF"
sudo systemctl restart postgresql

# 4. Create database and user
sudo -u postgres psql <# 5. Test connection
PGPASSWORD='secure_password' psql -h 127.0.0.1 -U app_user -d app_db -c 'SELECT version();'

Frequently Asked Questions

01Why bind PostgreSQL to localhost only?

Localhost binding prevents direct internet access to your database server, eliminating network-based attacks. Applications should connect through secure tunnels, private networks, or application proxies rather than exposing PostgreSQL directly to the internet.

02How do I connect my application to the database?

Applications running on the same VM can connect using host=127.0.0.1. For external applications, set up SSH tunneling, use private networking between VMs, or configure a connection proxy with proper authentication and encryption.

03Can I upgrade this setup to PostgreSQL 17 later?

Yes, but plan for a maintenance window. PostgreSQL major version upgrades require data migration using pg_dump and pg_restore or pg_upgrade. Test the upgrade process in a staging environment first and ensure your applications are compatible with PostgreSQL 17.

04What’s the recommended backup strategy?

Implement automated daily backups using pg_dump with compression and remote storage. For high-availability setups, consider continuous archiving with Write-Ahead Logging (WAL) shipping. Test restore procedures regularly to ensure backup integrity.

05How do I monitor PostgreSQL performance?

Enable PostgreSQL’s built-in statistics collector and use pg_stat_* views for query analysis. Consider tools like pg_stat_statements for query performance tracking, and monitor key metrics like connection count, cache hit ratio, and slow query logs.