BLOG POSTS
    MangoHost Blog / Moving a PostgreSQL Data Directory to a New Location on Ubuntu 24
Moving a PostgreSQL Data Directory to a New Location on Ubuntu 24

Moving a PostgreSQL Data Directory to a New Location on Ubuntu 24

Moving a PostgreSQL data directory to a new location is a common system administration task that becomes crucial when you’re dealing with limited disk space, performance optimization, or storage architecture changes. Whether you’re migrating to faster SSDs, relocating to a mounted network drive, or simply need more space than your current partition allows, understanding how to safely relocate PostgreSQL’s data directory can save you from potential data loss and extended downtime. This guide walks you through the complete process on Ubuntu 24, covering everything from pre-migration planning to post-move verification and troubleshooting common issues.

How PostgreSQL Data Directory Relocation Works

PostgreSQL stores all database files, configuration files, and logs in what’s called the data directory (PGDATA). By default on Ubuntu 24, this directory is located at /var/lib/postgresql/16/main for PostgreSQL 16. The relocation process involves stopping the PostgreSQL service, copying the entire data directory to the new location, updating configuration files to point to the new path, and adjusting file permissions and ownership.

The key components that need to be moved include:

  • Database cluster files (base directory)
  • Write-Ahead Logging (WAL) files
  • Configuration files (postgresql.conf, pg_hba.conf)
  • Server log files
  • Tablespace directories

Unlike some database systems that allow hot migration, PostgreSQL requires a complete service shutdown for data directory relocation to ensure data integrity.

Prerequisites and Planning

Before starting the migration, verify your current setup and plan the move carefully:

# Check PostgreSQL version and status
sudo systemctl status postgresql

# Identify current data directory location
sudo -u postgres psql -c "SHOW data_directory;"

# Check disk space usage
df -h /var/lib/postgresql/
du -sh /var/lib/postgresql/16/main

# Verify destination has sufficient space
df -h /new/postgresql/path

Create a backup before proceeding. Even though we’re moving files rather than modifying data, having a backup provides safety:

# Create a full backup
sudo -u postgres pg_dumpall > /backup/postgresql_backup.sql

# Or use pg_basebackup for a binary backup
sudo -u postgres pg_basebackup -D /backup/pg_basebackup -Ft -z -P

Step-by-Step Migration Process

Step 1: Stop PostgreSQL Service

# Stop PostgreSQL service
sudo systemctl stop postgresql

# Verify it's completely stopped
sudo systemctl status postgresql
ps aux | grep postgres

Step 2: Create New Data Directory Location

# Create the new directory structure
sudo mkdir -p /new/postgresql/data/16/main

# Set proper ownership
sudo chown postgres:postgres /new/postgresql/data/16/main

# Set appropriate permissions
sudo chmod 700 /new/postgresql/data/16/main

Step 3: Copy Data Directory

Use rsync to preserve permissions, timestamps, and handle large files efficiently:

# Copy the entire data directory
sudo rsync -av /var/lib/postgresql/16/main/ /new/postgresql/data/16/main/

# Verify the copy completed successfully
sudo du -sh /var/lib/postgresql/16/main
sudo du -sh /new/postgresql/data/16/main

# Check critical files exist
sudo ls -la /new/postgresql/data/16/main/PG_VERSION
sudo ls -la /new/postgresql/data/16/main/postgresql.conf

Step 4: Update PostgreSQL Configuration

Ubuntu 24 uses systemd service files that specify the data directory. Update the PostgreSQL cluster configuration:

# Update the PostgreSQL cluster configuration
sudo pg_dropcluster 16 main
sudo pg_createcluster -d /new/postgresql/data/16/main 16 main

# Alternative method: Edit the systemd service file
sudo systemctl edit postgresql@16-main

# Add the following content:
[Service]
Environment="PGDATA=/new/postgresql/data/16/main"

For manual configuration, edit the PostgreSQL configuration file:

# Edit postgresql.conf in the new location
sudo nano /new/postgresql/data/16/main/postgresql.conf

# Ensure data_directory points to the new location
data_directory = '/new/postgresql/data/16/main'

Step 5: Update File Permissions and SELinux Context

# Ensure proper ownership recursively
sudo chown -R postgres:postgres /new/postgresql/data/16/main

# Set correct permissions
sudo chmod -R 700 /new/postgresql/data/16/main

# If SELinux is enabled, update context
sudo setsebool -P postgresql_can_rsync on
sudo restorecon -R /new/postgresql/data/16/main

Step 6: Start and Verify PostgreSQL

# Start PostgreSQL service
sudo systemctl start postgresql

# Check service status
sudo systemctl status postgresql

# Verify the new data directory is being used
sudo -u postgres psql -c "SHOW data_directory;"

# Test database connectivity
sudo -u postgres psql -c "SELECT version();"

# Check that all databases are accessible
sudo -u postgres psql -l

Performance Considerations and Benchmarking

Different storage types can significantly impact PostgreSQL performance. Here’s a comparison of typical performance characteristics:

Storage Type Random Read IOPS Sequential Read MB/s Write Latency (ms) Best Use Case
Traditional HDD 100-200 100-200 10-15 Archive, backup storage
SATA SSD 30,000-50,000 500-600 0.1-0.3 General purpose databases
NVMe SSD 100,000-500,000 2,000-7,000 0.01-0.1 High-performance OLTP
Network Storage (NFS) 1,000-10,000 100-1,000 1-5 Shared storage, HA setups

Test your new storage performance with pgbench:

# Initialize pgbench database
sudo -u postgres createdb pgbench
sudo -u postgres pgbench -i -s 50 pgbench

# Run read-write benchmark
sudo -u postgres pgbench -c 10 -j 2 -t 1000 pgbench

# Run read-only benchmark
sudo -u postgres pgbench -c 10 -j 2 -t 1000 -S pgbench

Common Issues and Troubleshooting

Permission Problems

The most common issue after relocation is incorrect file permissions:

# Error: "FATAL: data directory has wrong ownership"
# Solution: Fix ownership
sudo chown -R postgres:postgres /new/postgresql/data/16/main
sudo chmod 700 /new/postgresql/data/16/main

# Error: "FATAL: could not open file... Permission denied"
# Check parent directory permissions
ls -la /new/postgresql/data/16/
sudo chmod 755 /new/postgresql/data/16/

Service Configuration Issues

# If PostgreSQL fails to start, check systemd configuration
sudo systemctl status postgresql -l

# Check which data directory systemd is trying to use
sudo systemctl show postgresql@16-main | grep Environment

# Reset systemd configuration if needed
sudo systemctl daemon-reload
sudo systemctl restart postgresql

Path and Symlink Issues

Some administrators prefer using symlinks instead of reconfiguration:

# Alternative approach: Use symbolic links
sudo systemctl stop postgresql

# Backup original directory
sudo mv /var/lib/postgresql/16/main /var/lib/postgresql/16/main.backup

# Create symlink to new location
sudo ln -s /new/postgresql/data/16/main /var/lib/postgresql/16/main

# Start service
sudo systemctl start postgresql

Real-World Use Cases and Examples

Scenario 1: Moving to High-Performance NVMe Storage

A development team noticed slow query performance during peak hours. They moved their PostgreSQL data directory from a traditional RAID array to NVMe SSDs:

# Mount new NVMe drive
sudo mkfs.ext4 /dev/nvme0n1
sudo mkdir /nvme/postgresql
sudo mount /dev/nvme0n1 /nvme/postgresql

# Add to fstab for persistent mounting
echo "/dev/nvme0n1 /nvme/postgresql ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab

# Follow migration steps to move data to /nvme/postgresql/data

Results: Query response times improved by 60%, and concurrent user capacity increased from 50 to 200 users.

Scenario 2: Network Storage for High Availability

For a high-availability setup with failover capabilities:

# Mount shared NFS storage
sudo apt install nfs-common
sudo mkdir /shared/postgresql
sudo mount -t nfs nfs-server:/postgresql /shared/postgresql

# Configure for proper PostgreSQL permissions on NFS
sudo mount -o remount,rw,hard,intr,rsize=8192,wsize=8192,timeo=14 /shared/postgresql

Best Practices and Security Considerations

  • Always test on non-production systems first – Practice the migration process on development or staging environments
  • Schedule maintenance windows – Plan for 2-3x the estimated downtime for unexpected issues
  • Monitor disk space during migration – Ensure you have enough space for both old and new directories during the process
  • Use filesystem snapshots when available – LVM or ZFS snapshots provide quick rollback options
  • Update monitoring systems – Modify disk space monitoring to watch the new location
  • Document the change – Update system documentation and runbooks with the new paths

Security Checklist

# Verify no world-readable permissions
find /new/postgresql/data/16/main -type f -perm /o+r

# Check for proper SELinux contexts (if applicable)
ls -lZ /new/postgresql/data/16/main

# Ensure backup files are properly secured
chmod 600 /backup/postgresql_backup.sql
chown postgres:postgres /backup/postgresql_backup.sql

Alternative Approaches and Tools

While manual migration provides full control, several tools can simplify the process:

Method Complexity Downtime Risk Level Best For
Manual rsync Medium 15-60 minutes Low Most scenarios
Symbolic links Low 5-15 minutes Medium Quick migrations
pg_basebackup High 30-120 minutes Low Large databases
Logical replication High Near-zero Medium Production systems

Using pg_basebackup for Large Databases

For databases larger than 100GB, consider using pg_basebackup to minimize downtime:

# Create base backup to new location while server is running
sudo -u postgres pg_basebackup -D /new/postgresql/data/16/main -Fp -Xs -P -v

# Stop PostgreSQL
sudo systemctl stop postgresql

# Update configuration and start with new location

Post-Migration Optimization

After successfully moving the data directory, optimize PostgreSQL for the new storage:

# Update postgresql.conf for new storage characteristics
sudo nano /new/postgresql/data/16/main/postgresql.conf

# For SSD storage, consider these optimizations:
random_page_cost = 1.1
effective_io_concurrency = 200
checkpoint_completion_target = 0.9
wal_buffers = 16MB
shared_buffers = 25% of RAM

Run VACUUM and ANALYZE to update statistics:

# Update database statistics
sudo -u postgres psql -c "VACUUM ANALYZE;"

# Check for any corrupted indexes
sudo -u postgres psql -c "REINDEX DATABASE your_database_name;"

Moving PostgreSQL data directories requires careful planning and execution, but the process is straightforward when following proper procedures. The key to success lies in thorough preparation, having reliable backups, and testing the process in non-production environments first. Whether you’re moving to faster storage, increasing capacity, or implementing high-availability architecture, this systematic approach ensures data integrity while minimizing downtime.

For additional information, consult the official PostgreSQL documentation on database clusters and the PostgreSQL wiki on shared database hosting for advanced configuration scenarios.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked