Engineering · Postiz series, part 1 of 2
X, LinkedIn, Reddit, and Mastodon
A fresh self-hosted Postiz can't post anywhere — every channel is a bring-your-own OAuth app. The exact portal clicks, callback URLs, and environment variables for the four platforms you can finish in an afternoon.
This is part 1 of a two-part series on running Postiz, the open-source social scheduler, on your own server — written while wiring up the marketing for Remotype, Remotext, and Foldyni.
- Part 1: X, LinkedIn, Reddit, and Mastodon (you are here)
- Part 2: Facebook, Instagram, and TikTok
The blank-slate problem
Here is the first thing nobody tells you about self-hosting Postiz: a fresh install cannot post to anything. You log in, the dashboard looks great, you click Add channel — and every platform fails. X says "could not connect to platform." LinkedIn says "passed in client_id is invalid." Nothing is broken. Nothing is configured.
The hosted Postiz service ships with its own platform credentials. Your server has none, and no platform will talk to an anonymous client. Every channel you want is a bring-your-own OAuth app: you register an application on the platform's developer portal, the portal gives you a client ID and secret, and Postiz presents those when it asks a user (you) to connect an account.
The good news: it is the same dance seven times, and four of the seven finish in minutes. That's this post. The three that involve review queues and business-account plumbing — Facebook, Instagram, TikTok — get part 2.
The pattern, once
Every platform below reduces to four moves:
- Register an app on the platform's developer portal.
- Set the callback URL to your Postiz domain:
https://postiz.example.com/integrations/social/<provider>— substitute yourFRONTEND_URLand the provider slug (x,linkedin,reddit,mastodon). - Copy the client ID and secret into Postiz's
.env. - Recreate the container. Postiz reads its environment at boot, so
docker compose up -dafter every edit. A restart is not enough if you usedocker compose restartwith anenv_file— recreation is what re-reads the file.
If a channel errors after this, the message usually names the layer: "client_id is invalid" means the env var is empty, misspelled, or has a stray quote; a redirect error means the callback URL in the portal doesn't byte-for-byte match your domain and path.
| Platform | Env vars | Callback path |
|---|---|---|
| X | X_API_KEY, X_API_SECRET |
/integrations/social/x |
LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET |
/integrations/social/linkedin |
|
REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET |
/integrations/social/reddit |
|
| Mastodon | MASTODON_URL, MASTODON_CLIENT_ID, MASTODON_CLIENT_SECRET |
/integrations/social/mastodon |
X
X's free API tier allows enough writes for a scheduling workload — the caps bite scrapers, not marketers posting a few times a day.
- Go to developer.x.com and sign in as the account that will post. Sign up for the free tier; you'll get a default Project with one App.
- In the App's settings, find User authentication settings → Set up:
- App permissions: Read and write
- Type of App: Web App, Automated App or Bot
- Callback URI:
https://postiz.example.com/integrations/social/x - Website URL: any real page you own — the portal requires one.
- Under Keys and tokens, copy the API Key and API Key Secret (the consumer keys, not the bearer token) into
X_API_KEYandX_API_SECRET.
One operational note: X is notoriously suspicious of datacenter IP ranges. If your credentials are right but connections still fail intermittently from a cloud VM, that's not you — some self-hosters end up routing just the Postiz container through a VPN. Try the straight path first; add plumbing only when the platform makes you.
- Go to linkedin.com/developers → Create app. LinkedIn requires attaching a company Page to the app — a personal profile won't do, so create the Page first if your product doesn't have one.
- On the Products tab, request "Sign In with LinkedIn using OpenID Connect" and "Share on LinkedIn." Both are self-serve and approved instantly.
- On the Auth tab, add the redirect URL:
https://postiz.example.com/integrations/social/linkedin, and copy the Client ID and Primary Client Secret into the env.
That combination posts to your personal profile. Posting as the company Page needs one more product — the Community Management API — which has an actual review process with actual waiting. Request it when you need it; don't block the other six channels on it.
Reddit's portal is the most old-fashioned of the four, and the ID is hidden in plain sight.
- Go to reddit.com/prefs/apps → create another app...
- Type: web app. Redirect URI:
https://postiz.example.com/integrations/social/reddit. - The client ID is the unlabeled string under the app's name — there is no field caption. The secret is labeled. Copy both.
Self-promotion on Reddit is a cultural question, not an API one — the credentials just make posting possible. Where and how often is a strategy for another day.
Mastodon
The easiest of the seven, because there's no central gatekeeper — your instance is the platform.
- On the instance your account lives on, go to Preferences → Development → New application.
- Name it, leave scopes at
read write, set the redirect URI tohttps://postiz.example.com/integrations/social/mastodon, and submit. - Copy the client key and client secret; set
MASTODON_URLto your instance (for examplehttps://mastodon.social).
No review, no company page, no tier limits. If every platform worked like this, this series would be a paragraph.
Close the loop
Append the block to your .env, recreate, and connect each channel from the Postiz UI:
X_API_KEY=...
X_API_SECRET=...
LINKEDIN_CLIENT_ID=...
LINKEDIN_CLIENT_SECRET=...
REDDIT_CLIENT_ID=...
REDDIT_CLIENT_SECRET=...
MASTODON_URL=https://mastodon.social
MASTODON_CLIENT_ID=...
MASTODON_CLIENT_SECRET=...
docker compose up -d
Each Add channel click should now bounce you through the platform's consent screen and back to a connected account. Four networks, one afternoon, zero review queues.
We run this exact setup to schedule posts for Remotype (your phone as keyboard, trackpad, and remote for every computer you own), Remotext (a native code editor for iOS and Android with real SFTP and SSH), and Foldyni — one calendar instead of seven tabs.
Part 2 covers the three platforms that don't hand out credentials this easily: Facebook, Instagram, and TikTok — and the development-mode shortcut that makes their review queues mostly optional when you're posting to your own accounts.