Railway

Deploy Postiz | (Just Updated) Buffer Alternative, Admin Seeded and API Actually Works

Self-hosted social scheduler. Admin seeded, API works, media persists

Deploy Postiz | (Just Updated) Buffer Alternative, Admin Seeded and API Actually Works

Just deployed

/var/lib/postgresql

/usr/share/elasticsearch/data

Just deployed

/data

Just deployed

/uploads

Just deployed

/var/lib/postgresql

Deploy and Host Postiz on Railway

Postiz is an open-source social media scheduling tool — a self-hosted Buffer / Hootsuite alternative. One calendar for ~20 platforms (X, LinkedIn, Instagram, Threads, TikTok, YouTube, Bluesky, Mastodon, Reddit, Discord, Slack, Telegram and more), an AI copilot for drafting, a media library, analytics, a team workspace and a public API.

This template deploys Postiz v2.23.0 with its whole Temporal stack wired up, an admin account that already exists when the URL goes live, and the Railway-specific defects that break the other listings in this category already fixed. Every claim below was reproduced against the upstream image before this template was published.

About Hosting

The API works. Postiz's own nginx has a hardcoded listen 5000; and no templating; its backend binds process.env.PORT || 3000. Railway injects PORT, so on a stock deploy the backend takes the edge port and nginx is unreachable. Measured on v2.23.0 with PORT=8080:

GET /                          -> 200  App is running!     <- the backend, not the app UI
GET /api/                      -> 404  Cannot GET /api/
GET /uploads/            -> 404  Cannot GET /uploads/…

The instance is green, the healthcheck passes, and there is no product. This template's image rewrites nginx's listener to the injected port at boot and pins the backend back to 3000, then health-checks /api/ — with the trailing slash, because location /api/ does not match /api.

Nobody else can claim your instance. Postiz's canRegister() returns true for every caller until an organization exists, so a fresh deploy is claimable by whoever loads the URL first — anonymous POST /api/auth/register returns 200 with an auto-activated account. This template generates an admin password, seeds the organization and its SUPERADMIN through Postiz's own registration handler on loopback while nginx is still down, verifies the login, and only then opens the port. On the live deploy:

[railway-entrypoint] seeded organization 'My Workspace' with SUPERADMIN admin@postiz.local
[railway-entrypoint] verified: admin@postiz.local can log in with the current POSTIZ_ADMIN_PASSWORD
[railway-entrypoint] registration open to the public: {"register":false}

POST /api/auth/register (anonymous)  -> 400 Registration is disabled
POST /api/auth/login (admin)         -> 200 {"login":true}

Log in with POSTIZ_ADMIN_EMAIL (default admin@postiz.local) and the generated POSTIZ_ADMIN_PASSWORD, both in the service's variables.

Brute force gets throttled. Postiz applies no rate limit to its auth routes: 20 wrong passwords answer 400 twenty times. This deployment answers 400 x4 then 429 x16 on the same burst, keyed on the real client address (the first entry of X-Forwarded-For, because Railway's edge hop rotates per request).

Your media survives a redeploy. Uploads live on a volume at /uploads, and nginx serves them from there. Verified end to end on this template: an image uploaded through the app was still served with the same bytes after a full redeploy.

No unauthenticated Temporal console. Postiz 2.x schedules through Temporal, and Temporal's web UI has no authentication of its own. Other listings publish it on a public domain, which exposes every workflow — scheduled post bodies and connected accounts included — to anyone with the URL. This template simply does not ship it; scheduling does not need it.

Also: every image is pinned (Postiz v2.23.0 by digest, Temporal 1.28.1, Elasticsearch 7.17.27), because Postiz runs prisma db push --accept-data-loss on every boot and a floating tag makes each redeploy an unrequested schema change. Elasticsearch's JVM heap is sized from the container's cgroup limit instead of a fixed -Xmx512m.

Why Deploy Postiz on Railway?

Scheduling is an always-on workload: a Temporal worker per platform, a poller for analytics, and a media store that has to be there when a post fires. Railway gives it private networking between the six services, persistent volumes, and per-second usage billing instead of a fixed VPS — without asking you to run docker compose on a box you have to patch. Deploys are one click, the public domain and TLS come with it, and every service scales on its own.

Common Use Cases

  • Run your own Buffer/Hootsuite replacement for a personal brand or a client roster, with no per-seat or per-channel pricing.
  • Give an agency team one shared calendar and approval workflow across every client account.
  • Drive scheduling from code or an AI agent through Postiz's public API, using the deployment as the posting backend for a product of your own.

Dependencies for Postiz Hosting

Postiz needs Postgres, Redis and — from 2.x onward, where BullMQ was removed — a Temporal server, which itself needs a database and Elasticsearch. This template provisions all of it: postiz, postgres, redis, temporal, temporaldb and elasticsearch.

Deployment Dependencies

Implementation Details

The admin account is seeded through Postiz's own /auth/register handler on 127.0.0.1 before nginx starts, so the bcrypt hash, the organization row, the SUPERADMIN role and the encrypted API key are exactly what the application would have written itself:

[railway-entrypoint] gateway will listen on 8080, auth throttle 10r/m burst 5
[railway-entrypoint] temporal reachable at temporal.railway.internal:7233
[railway-entrypoint] backend answering on 127.0.0.1:3000
[railway-entrypoint] seeded organization 'My Workspace' with SUPERADMIN admin@postiz.local
[railway-entrypoint] gateway up on 8080

On any later boot it leaves the existing organization alone and re-verifies the login. To connect social channels, add the relevant provider's client ID and secret to the postiz service's variables (X_API_KEY, LINKEDIN_CLIENT_ID, …) as documented in Postiz's docs — the template deliberately does not publish them as empty required fields.


Template Content

More templates in this category

View Template
N8N Main + Worker
Deploy and Host N8N with Inactive worker.

jakemerson
120
View Template
Evolution API with n8n
[Jul'26] WhatsApp automation platform using Evolution API, n8n & PostgreSQL

codestorm
67
View Template
Postgres Backup
Cron-based PostgreSQL backup to bucket storage

Railway Templates
870