---
title: "Deploy PostgreSQL with Extensions"
description: "PostgreSQL with SSL and dynamic extensions."
category: "Storage"
url: https://railway.com/deploy/postgresql-with-extensions
---

# Deploy PostgreSQL with Extensions

PostgreSQL with SSL and dynamic extensions.

**[Deploy PostgreSQL with Extensions on Railway](https://railway.com/template/postgresql-with-extensions)**

- **Creator:** Nicolas's Projects
- **Category:** Storage
- **Total deploys:** 3

## Template content

### Postgres https://devicons.railway.app/postgres

- **Source:** ncontiero/postgres-ssl

## Documentation

# Deploy and Host PostgreSQL with Extensions and TLS on Railway

Build a customized PostgreSQL image on Railway with the APT packages, extension repositories, database extensions, and preload libraries your application requires. The template adds the same managed TLS and persistent-volume protections as the standard image.

## About Hosting PostgreSQL with Extensions

This template builds from the project source so Railway can install PostgreSQL extension packages before deployment. You provide comma-separated build arguments for Debian packages and optional third-party APT repositories, then choose which extensions to create when a new database is initialized. This supports packages such as PostGIS, pgvector, TimescaleDB, and pg_cron without maintaining a separate Dockerfile.

The resulting image generates a private CA and a CA-signed server certificate for Railway's private and public database hostnames. It validates and renews certificates on startup, preserves a healthy CA across deployments, validates the mounted PostgreSQL data version, and serializes access to the persistent volume during overlapping deployments.

## Common Use Cases

- **Geospatial applications:** Install PostGIS for spatial types, indexes, and queries.
- **AI and semantic search:** Install pgvector for vector storage and similarity search.
- **Time-series workloads:** Install TimescaleDB and preload its shared library.
- **Database automation:** Install pg_cron or other packaged PostgreSQL modules.

## Dependencies for PostgreSQL with Extensions Hosting

- A Railway persistent volume mounted at `/var/lib/postgresql` for PostgreSQL 18 or `/var/lib/postgresql/data` for PostgreSQL 17.
- APT package names compatible with the selected PostgreSQL major version and Debian base image.
- Reachable repository and signing-key URLs when using third-party APT repositories.

### Deployment Dependencies

- [Postgres SSL source repository](https://github.com/ncontiero/postgres-ssl)
- [Official PostgreSQL Docker image](https://hub.docker.com/_/postgres)

### Implementation Details

#### PostgreSQL version

- `POSTGRES_VERSION`: Selects the official PostgreSQL base image. The current generated templates use `18.6` in `with-extensions` and `17.11` in `with-extensions-older`.

Keep the selected major version aligned with the template directory. Changing this value does not migrate an existing PostgreSQL data directory to another major version.

#### Extension package build arguments

- `PG_APT_PACKAGES`: Comma-separated APT packages to install, such as `postgresql-18-postgis-3`.
- `PG_EXTENSION_REPOS`: Comma-separated third-party APT repository definitions.
- `PG_EXTENSION_REPO_KEYS`: Comma-separated signing-key URLs corresponding by position to `PG_EXTENSION_REPOS`.

Package installation happens while the image is built. PostgreSQL server and client packages are held during APT operations so dependency resolution does not replace the selected PostgreSQL minor release.

#### Extension initialization

- `PG_DB_EXTENSIONS`: Comma-separated extension names passed to `CREATE EXTENSION IF NOT EXISTS` when a new database is initialized, such as `postgis,vector`.
- `PG_SHARED_PRELOAD_LIBRARIES`: Comma-separated shared libraries loaded at PostgreSQL startup, such as `timescaledb,pg_cron`.

Initialization scripts only run when the persistent database directory is created for the first time. On an existing database, install the required package in a rebuilt image and run `CREATE EXTENSION` through a database connection when enabling a new extension.

#### TLS configuration

- `SSL_REQUIRE`: Set to `true` to reject plaintext TCP connections; defaults to `false`.
- `SSL_CERT_DAYS`: Server-certificate validity in days; defaults to `820`.
- `SSL_CA_CERT_DAYS`: CA-certificate validity in days; defaults to `3650`.
- `RUNTIME_LOCK_WAIT_SECONDS`: Volume-lock wait time during overlapping deployments; defaults to `300`.
- `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB`: Standard variables inherited from the official PostgreSQL image.

Use `sslmode=require` for encrypted connections without identity validation. For strict validation, export the service-specific public CA and use `sslmode=verify-full`:

```bash
railway ssh \
  --project your-project-id \
  --service your-service-id \
  --environment your-environment-id \
  -- export-ssl-ca > postgres-root.crt
```

The server certificate includes the Railway private domain and public TCP Proxy hostname. The exported CA certificate may be distributed to clients; private keys must remain inside the database service.

## Why Deploy PostgreSQL with Extensions on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying PostgreSQL with Extensions on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/postgresql-with-extensions
