---
title: "Deploy Wordpress"
description: "Host WordPress [Oct'26]— MySQL, persistent media, HTTPS behind the proxy"
category: "CMS"
url: https://railway.com/deploy/wordpress-dedicated-hosting
---

# Deploy Wordpress

Host WordPress [Oct'26]— MySQL, persistent media, HTTPS behind the proxy

**[Deploy Wordpress on Railway](https://railway.com/template/wordpress-dedicated-hosting)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/wordpress-dedicated-hosting/manifest.json

- **Creator:** SB
- **Category:** CMS

## Template content

### MariaDB https://img.icons8.com/color/48/maria-db.png

- **Image:** mariadb

### wordpress https://img.icons8.com/color/48/000000/wordpress.png

- **Image:** wordpress

## Documentation

# Deploy and Host WordPress on Railway

WordPress is the CMS behind a large share of the web — a PHP application with the deepest plugin and theme ecosystem anywhere. This template runs it on dedicated infrastructure rather than a shared host: managed MySQL over private networking, a volume for media and plugins, and the proxy and cron configuration container deployments normally get wrong.

## What This Template Deploys

| Service | Purpose |
| --- | --- |
| `wordpress` | Official PHP/Apache image on port `80` behind Railway's HTTPS proxy. Public domain. |
| `MySQL` | Posts, pages, users, settings, plugin data. Volume at `/var/lib/mysql`. |
| Volume | `wp-content` — media, installed themes and plugins. |

Both services talk over Railway's private network, so the database has no public port. Two things are stateful: MySQL holds your content, the volume holds your files, and a backup of one without the other restores a site with no images.

## About Hosting

WordPress assumes a server it controls — writable filesystem, cron daemon, a web server terminating its own TLS. A container behind a proxy gives it none of those, and the failures look like WordPress bugs rather than configuration.

**TLS terminates at the edge, and WordPress does not know it.** Railway handles HTTPS and forwards plain HTTP to PHP. WordPress sees an insecure request, compares it to an `https://` site URL and redirects — the proxy forwards HTTP again, and you have an infinite loop. Turn on `FORCE_SSL_ADMIN` and it locks you out of `/wp-admin` specifically. The fix is reading `X-Forwarded-Proto` in `wp-config.php` before `wp-settings.php` loads.

**A volume at the web root cancels your pinned image.** Mount a volume over `/var/www/html` and it shadows the directory the image ships core in. From the second boot the pinned tag no longer decides your version — the copy on the volume does, and WordPress's auto-updates have been editing it. Mounting `wp-content` instead keeps core in the image where the tag means something, and media and plugins on the volume where they belong.

**WP-Cron fires on page loads, not on a schedule.** WordPress has no scheduler; it checks for due tasks when someone visits. On a quiet site, scheduled posts publish late, backups skip and plugin tasks stall. Set `DISABLE_WP_CRON=true` and drive `wp-cron.php` from a real scheduled job.

**One volume means one instance.** A Railway volume attaches to a single service, so `wp-content` cannot be shared across replicas. This scales vertically only — fine for most sites, and a hard ceiling worth knowing before you plan around traffic you do not have yet.

**Your site URL lives in the database, not your config.** `siteurl` and `home` are rows in `wp_options`. Change your domain without updating them and the site redirects to the old one from the first request, login page included. Set `WP_HOME` and `WP_SITEURL` as constants so the environment wins.

Typical cost: **~$15–25/month** for WordPress, MySQL and volumes at $10/GB/month RAM, $20/vCPU/month CPU and $0.15/GB/month volumes. Be clear-eyed: shared hosting starts around $4/month and will be cheaper for a small blog. You are paying for isolated resources, a real database and infrastructure you control.

## How It Compares

| | WordPress on Railway | Shared hosting | WordPress.com | Managed WP host |
| --- | --- | --- | --- | --- |
| Resources | Dedicated | Shared, throttled | Managed | Dedicated |
| Entry cost | ~$15–25/month | ~$4/month | Free tier | ~$20–30/month |
| Horizontal scaling | No, one instance | No | Managed | Yes |

The honest edge: for a personal blog, shared hosting is cheaper and does the job — take it. Managed WordPress hosts handle updates, caching and backups for roughly what this costs, and if you want none of that work they are the better buy. Railway earns its place when WordPress is one service among several — a headless backend feeding a Next.js front end, or a marketing site beside your application — where you want the whole stack on one platform with private networking between the parts.

## Deploy in Under 5 Minutes

1. Click **Deploy** and pick a workspace. WordPress and MySQL come up wired over private networking, all eight security salts generated.
2. Open the generated domain. WordPress runs its install wizard — create your admin account here.
3. Confirm `WP_HOME` and `WP_SITEURL` match the domain you intend to keep — changing them later means editing the database.
4. Install a theme and upload one image to confirm the volume is writable.
5. Set `DISABLE_WP_CRON=true` and point a scheduled job at `wp-cron.php` if you publish on a schedule.

> Verify before you rely on it: load `/wp-admin` over HTTPS. Endless redirects or mixed-content warnings mean the forwarded-protocol handling is wrong — fix it before building anything on the site.

## Common Use Cases

- **Marketing site beside your app** — run WordPress in the same project as your product, with private networking between them.
- **Headless CMS** — serve content via the REST API to a Next.js or Astro front end while editors keep the admin they know.
- **Client sites with real isolation** — one project per client, each with its own database, volume and budget.

## Configuration

| Variable | Required | Description |
| --- | --- | --- |
| `WORDPRESS_DB_HOST`, `_NAME`, `_USER`, `_PASSWORD` | Auto | MySQL connection as reference variables on the private hostname. |
| `WP_HOME`, `WP_SITEURL` | Required | Your public HTTPS domain. Overrides the values stored in the database. |
| `WORDPRESS_AUTH_KEY` plus seven more salts | Generated | Sign cookies and sessions. Changing one logs every user out. |
| `WORDPRESS_CONFIG_EXTRA` | Pre-set | Carries the forwarded-protocol handling that stops the HTTPS redirect loop. |
| `DISABLE_WP_CRON` | Recommended | `true`, with a real scheduled job calling `wp-cron.php`. |
| Storage volume | Pre-set | Mounted on `wp-content` for media, themes and plugins. |

> **Decide your domain before publishing anything.** The site URL is stored in the database as well as config, and changing it later means a search-and-replace across post content for hardcoded links.

> **Do not point WordPress at the MySQL root user.** Railway's managed MySQL hands out root credentials; create a database-scoped user for WordPress so a compromised plugin cannot reach anything else.

## Dependencies for WordPress Hosting

- **Railway account** — ~$15–25/month for WordPress, MySQL and both volumes.
- **Bundled services** — managed MySQL 8.0+ or MariaDB 10.6+, wired over private networking.
- **Volumes** — one on `wp-content` for media and plugins, one on MySQL. Both required.
- **Optional** — S3 offload if the media library outgrows a volume, Redis for object caching, an external scheduler for cron.

### Deployment Dependencies

- [WordPress on GitHub](https://github.com/WordPress/WordPress)
- [WordPress documentation](https://wordpress.org/documentation/)
- [Official WordPress Docker image](https://hub.docker.com/_/wordpress)
- [Railway volumes](https://docs.railway.com/volumes)

### Implementation Details

WordPress runs the official PHP/Apache image on a pinned tag, serving port `80` behind Railway's HTTPS edge. The volume mounts on `wp-content` rather than the whole web root, deliberately: a volume over `/var/www/html` shadows the core files the image provides, so the pinned tag stops describing what is running once the volume has content. Core in the image and user content on the volume means upgrading is a tag change, and so is rolling back.

The proxy handling lives in `WORDPRESS_CONFIG_EXTRA`, which the official image injects into `wp-config.php` before `wp-settings.php` runs — the only point early enough to matter. It inspects `HTTP_X_FORWARDED_PROTO` and sets `$_SERVER['HTTPS']`, so WordPress knows the request arrived over TLS. Without it every generated URL is `http://`, admin redirects loop against the proxy, and plugins checking for a secure connection take the wrong branch.

For backups you need both halves. A `mysqldump` captures posts, pages, users, settings and plugin configuration; the volume holds the media those posts reference plus the plugin and theme code. Restore the database alone into a fresh deployment and you get a site full of broken images. Past a few gigabytes of media, move to S3 rather than enlarging the volume — cheaper per gigabyte, and it decouples media from a single service.

## Frequently Asked Questions

**Why does `/wp-admin` redirect forever?** Railway terminates TLS, so PHP sees HTTP while your site URL says HTTPS and WordPress loops. The forwarded-protocol handling in `wp-config.php` fixes it; this template ships it.

**Do media and plugins survive a redeploy?** Yes, with the volume on `wp-content` and MySQL on its own. Content is in the database, files are on the volume; you need both.

**Why didn't my scheduled post publish?** WP-Cron runs on visitor requests, not on a clock. On a quiet site nothing triggers it. Disable it and call `wp-cron.php` from a real scheduled job.

**Can I run more than one instance?** No. A volume attaches to one service, so `wp-content` cannot be shared across replicas. Scale vertically, or move media to S3 first.

**Is this cheaper than managed WordPress hosting?** Not necessarily, and shared hosting is cheaper still. The reason to run it here is control, and keeping WordPress alongside the rest of your stack.

## Why Deploy WordPress 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 WordPress on Railway you get the container details that usually bite — forwarded-protocol handling that stops the HTTPS redirect loop, a volume on `wp-content` so your pinned version still means something, cron on a clock, and a database on the private network with no public port.

## Similar templates

- [Libredesk - Complete Setup](https://railway.com/deploy/libredesk-complete-setup) — Complete self-hosted omnichannel customer support desk.
- [Paperless-ngx](https://railway.com/deploy/paperless-ngx-3) — Paperless-ngx — document management with OCR and full-text search
- [Instatic CMS - Postgres](https://railway.com/deploy/instatic-cms-postgres) — Design, build and manage powerful static sites from state-of-the-art CMS

Open this page in a browser: https://railway.com/deploy/wordpress-dedicated-hosting
