Spaces:
Running
Running
| title: HuggingPost | |
| emoji: π | |
| colorFrom: pink | |
| colorTo: indigo | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: true | |
| license: agpl-3.0 | |
| secrets: | |
| - name: HF_TOKEN | |
| description: HF token with WRITE access β enables DB+uploads backup persistence to a private HF Dataset. | |
| - name: CLOUDFLARE_WORKERS_TOKEN | |
| description: Cloudflare API token to auto-provision an outbound proxy and the Keep-Alive monitor. | |
| [](https://github.com/somratpro/huggingpost) | |
| [](https://opensource.org/licenses/MIT) | |
| [](https://huggingface.co/spaces/somratpro/HuggingPost) | |
| [](https://github.com/gitroomhq/postiz-app) | |
| **Self-host [Postiz](https://postiz.com) (open-source social-media scheduler β X, LinkedIn, Facebook, Threads, TikTok, YouTube, Pinterest, Reddit, Mastodon, Discord, Slack, and more) on the free Hugging Face Spaces tier.** Persistent across restarts via private HF Dataset backup. No external database, no paid storage required. | |
| ## Table of Contents | |
| - [β¨ Features](#-features) | |
| - [π Quick Start](#-quick-start) | |
| - [π Configuration](#-configuration) | |
| - [πΎ Backup & Persistence](#-backup--persistence) | |
| - [π Keep It Awake](#-keep-it-awake) | |
| - [π Cloudflare Proxy *(Optional)*](#-cloudflare-proxy-optional) | |
| - [π Connecting Social Accounts](#-connecting-social-accounts) | |
| - [ποΈ Architecture](#οΈ-architecture) | |
| - [π Troubleshooting](#-troubleshooting) | |
| - [π Links](#-links) | |
| ## β¨ Features | |
| - π **30+ Social Platforms** β schedule posts to X, LinkedIn, Facebook, Threads, TikTok, YouTube, Reddit, Mastodon, Discord, Slack, Pinterest, etc. | |
| - β‘ **One-click deploy** β duplicate the Space, add `HF_TOKEN`, you're done. | |
| - πΎ **Persistent across restarts** β PostgreSQL + uploaded media auto-backed up to a private HF Dataset every 5 min and restored on boot. | |
| - π **Keep-Alive** β add `CLOUDFLARE_WORKERS_TOKEN` as a Space secret and a cron monitor is created automatically via Cloudflare Workers. | |
| - π **Outbound firewall workaround** β optional Cloudflare Worker proxy auto-provisioned for blocked platform APIs. | |
| - π **Secrets generated** β `JWT_SECRET` auto-generated on first boot and persisted, no manual setup. | |
| - π **100% HF-Native** β no external Postgres/Redis/storage accounts needed for the default path. | |
| - π **Pinned to v2.11.3** β last release before Postiz mandated Temporal (which doesn't fit in a single HF container). | |
| ## π Quick Start | |
| ### Step 1: Duplicate this Space | |
| [](https://huggingface.co/spaces/somratpro/HuggingPost?duplicate=true) | |
| ### Step 2: Add `HF_TOKEN` | |
| In your new Space's **Settings β Variables and secrets β New secret**: | |
| | Secret | How to get it | | |
| | :--- | :--- | | |
| | `HF_TOKEN` | [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) β New token β **Write** access | | |
| > [!WARNING] | |
| > Without `HF_TOKEN`, your data (accounts, scheduled posts, uploaded media) is **lost on every Space restart**. Set this up first. | |
| ### Step 3: Wait for the build (~5β8 min first time) | |
| Watch progress in the **Logs** tab. The Postiz build is heavy because it compiles a Next.js frontend + NestJS backend. | |
| ### Step 4: Open the Space | |
| Land on the HuggingPost dashboard. Click **Open Postiz β** to reach the login page. **Sign up** to create the first admin account β registration is auto-activated unless you set `RESEND_API_KEY`. | |
| ### Step 5: Set Up Keep-Alive (1 min) | |
| Add your **Cloudflare Workers Token** as a Space secret named `CLOUDFLARE_WORKERS_TOKEN`. HuggingPost will automatically create a Worker cron that pings `/health` every 10 min. Without this, the Space will sleep and scheduled posts won't fire. | |
| ## π Configuration | |
| ### Required | |
| | Variable | Purpose | | |
| | :--- | :--- | | |
| | `HF_TOKEN` | Write-access HF token β enables backup persistence | | |
| ### Recommended | |
| | Variable | Default | Purpose | | |
| | :--- | :--- | :--- | | |
| | `SYNC_INTERVAL` | `3600` | Backup interval in seconds (1 hour) | | |
| | `BACKUP_DATASET_NAME` | `huggingpost-backup` | Private dataset name (`<user>/<name>`) | | |
| | `RESEND_API_KEY` | β | Required only if you want signup activation emails | | |
| ### Storage (Optional β for media offload) | |
| By default, uploaded media (post images/videos) is stored in `/postiz/uploads` inside the container and included in the HF Dataset backup. If your media exceeds ~80 MB total, switch to Cloudflare R2: | |
| | Variable | Purpose | | |
| | :--- | :--- | | |
| | `STORAGE_PROVIDER` | Set to `cloudflare` | | |
| | `CLOUDFLARE_ACCOUNT_ID` | R2 account ID | | |
| | `CLOUDFLARE_ACCESS_KEY` | R2 access key | | |
| | `CLOUDFLARE_SECRET_ACCESS_KEY` | R2 secret | | |
| | `CLOUDFLARE_BUCKETNAME` | R2 bucket name | | |
| | `CLOUDFLARE_BUCKET_URL` | Public R2 URL prefix | | |
| R2 free tier is 10 GB storage + 1M reads/month β plenty for typical use. | |
| ### Advanced | |
| | Variable | Default | Purpose | | |
| | :--- | :--- | :--- | | |
| | `JWT_SECRET` | auto-generated | If unset, generated and persisted on first boot | | |
| | `SYNC_MAX_FILE_BYTES` | `104857600` (100 MB) | Skip backup if tarball exceeds this size | | |
| | `DISABLE_REGISTRATION` | `false` | Set to `true` after creating your admin account | | |
| | `API_LIMIT` | `30` | Public API hourly rate limit | | |
| ## πΎ Backup & Persistence | |
| Every `SYNC_INTERVAL` seconds (default 5 min), HuggingPost: | |
| 1. Runs `pg_dump` on the Postiz database. | |
| 2. Tars the dump + `/postiz/uploads` + `/postiz/.secrets`. | |
| 3. Uploads `snapshots/latest.tar.gz` to your private dataset `<your-username>/huggingpost-backup`. | |
| On boot, the reverse happens β secrets restored first, then DB drop+recreate+replay, then uploads copied back. Your scheduled posts, accounts, and media survive restarts. | |
| **To inspect or download your backup:** | |
| ```bash | |
| huggingface-cli download --repo-type dataset <your-username>/huggingpost-backup | |
| ``` | |
| > [!NOTE] | |
| > The dataset is **private** by default. Don't share its URL publicly β the SQL dump contains your full Postiz state, including encrypted social-media tokens. | |
| ## π Keep It Awake | |
| Free HF Spaces sleep after ~48h of no traffic. A sleeping Space cannot fire scheduled posts. Add your `CLOUDFLARE_WORKERS_TOKEN` as a Space secret. HuggingPost will automatically create a Cloudflare Worker cron that pings the Space every 10 minutes to keep it active. The dashboard shows the current "Keep Awake" status. | |
| ## π Cloudflare Proxy *(Optional)* | |
| Hugging Face Spaces sometimes block outbound HTTP to specific social-platform APIs. HuggingPost ships the same transparent Cloudflare Worker proxy used in HuggingClip / HuggingClaw / Hugging8n. | |
| **Auto-setup:** | |
| 1. Create a Cloudflare API Token with `Workers Scripts: Edit` permission. | |
| 2. Add `CLOUDFLARE_WORKERS_TOKEN` as a Space secret. | |
| 3. Restart the Space. | |
| HuggingPost will create or update a Worker named `<your-space-host>-proxy` and route blocked outbound traffic through it transparently. You can add extra domains with `CLOUDFLARE_PROXY_DOMAINS` (comma-separated, merged with built-in defaults). Set to `*` to proxy all external traffic. | |
| ## π Connecting Social Accounts | |
| Each social platform requires you to register your Postiz instance as an OAuth app. The callback URL pattern is: | |
| ``` | |
| https://<your-space-host>/app/api/integrations/social/<platform>/callback | |
| ``` | |
| (Note the `/app` prefix β Postiz UI is mounted there so its API is too.) | |
| For each platform you want (X, LinkedIn, Facebook, etc.), follow the [Postiz provider docs](https://docs.postiz.com/providers) to obtain client ID + secret, then enter them inside Postiz **Settings β Channels** (NOT as Space secrets β Postiz stores them encrypted in its DB). | |
| > [!TIP] | |
| > Some platforms (like X) require a publicly verifiable domain. The HF Space subdomain (`*.hf.space`) works for most but not all platforms. Check each platform's app-creation requirements. | |
| ## ποΈ Architecture | |
| ``` | |
| HuggingPost/ | |
| βββ Dockerfile # Two-stage: build Postiz v2.11.3 β runtime | |
| βββ start.sh # Orchestrator (Postgres β Redis β restore β procs) | |
| βββ health-server.js # Port 7860: dashboard + reverse proxy split | |
| βββ postiz-sync.py # Backup/restore DB + uploads to HF Dataset | |
| βββ cloudflare-proxy.js # Transparent outbound proxy injected via NODE_OPTIONS | |
| βββ cloudflare-proxy-setup.py | |
| βββ cloudflare-keepalive-setup.py | |
| βββ docker-compose.yml # Local dev convenience | |
| βββ .env.example # Configuration reference | |
| βββ README.md | |
| ``` | |
| **Single-port routing** (port 7860, the only port HF Spaces exposes): | |
| | Path | Target | Notes | | |
| | :--- | :--- | :--- | | |
| | `/` | HuggingPost dashboard (local) | Status + Keep Awake tile | | |
| | `/health`, `/status` | local | JSON handlers | | |
| | `/app` or `/app/*` | Postiz nginx `:5000` | `/app` stripped β Next.js built with `basePath="/app"` | | |
| | `/_next/*`, `/static/*` | 301 β `/app/<path>` | Catches absolute-URL leaks | | |
| | anything else | 404 | β | | |
| **Internal processes:** | |
| | Process | Port | Notes | | |
| | :--- | :--- | :--- | | |
| | `health-server.js` | 7860 (public) | Dashboard + reverse proxy | | |
| | nginx | 5000 (internal) | Routes `/api`β3000, `/uploads`βfs, `/`β4200 | | |
| | Postiz backend (NestJS) | 3000 | Started by PM2 | | |
| | Postiz frontend (Next.js) | 4200 | Started by PM2, `basePath=/app` baked at build | | |
| | Postiz workers | β | BullMQ consumer | | |
| | Postiz cron | β | Schedule tick | | |
| | `postgres` | 5432 | β | | |
| | `redis-server` | 6379 | β | | |
| | `postiz-sync.py` (loop) | β | β | | |
| Total resident set ~3β6 GB under typical load β well within HF free tier's 16 GB. | |
| ## π Troubleshooting | |
| **First boot takes 5β8 minutes** | |
| The Next.js frontend is not compiled during the Docker build (the HF builder's ~4 GB memory limit is less than `next build` needs). Instead it compiles on first container startup where 16 GB is available. Watch `[frontend-build]` lines in the Logs tab. Postiz starts automatically when done. All subsequent restarts are fast β the compiled `.next` is stored in the HF Dataset backup and restored at boot. | |
| **"Postiz backend unavailable" on first load** | |
| On restarts after the first boot, wait 30β90 s for PM2 processes to come up. Check the dashboard status badges. | |
| **Data lost after restart** | |
| `HF_TOKEN` is not set, or it doesn't have write access. Add it and the next restart will restore from backup. The backup must have run at least once before the restart. | |
| **Backup too large (>100 MB)** | |
| Either move media to Cloudflare R2 (`STORAGE_PROVIDER=cloudflare`) or raise `SYNC_MAX_FILE_BYTES`. The HF Dataset itself supports much larger files, but huge backups slow restart. | |
| **Scheduled posts didn't fire while I was away** | |
| The Space slept. Add `CLOUDFLARE_WORKERS_TOKEN` as a Space secret to enable automatic keep-awake monitoring. | |
| **OAuth callback fails for X/Facebook/LinkedIn** | |
| Some platforms reject `*.hf.space` subdomains as redirect URIs. You may need to put a custom domain in front (Cloudflare β HF Space CNAME). | |
| **Out of memory during build (exit 137 / OOMKilled)** | |
| The Dockerfile patches `apps/frontend/next.config.js` to disable sourcemap generation (`productionBrowserSourceMaps: false` + Sentry `sourcemaps.disable: true`). Without these, peak build memory exceeds HF Space builder limits. If you forked and removed those sed patches, OOM returns. Builds also run apps sequentially (backend β workers β cron β frontend) at 3 GB heap each β parallel builds OOM. | |
| **`prisma-db-push` fails on first boot** | |
| Usually means Postgres didn't finish starting. Container will exit and HF will auto-restart β second boot usually succeeds. If it persists, check Logs for the actual Prisma error. | |
| ## π Links | |
| - [Postiz on GitHub](https://github.com/gitroomhq/postiz-app) | |
| - [Postiz docs](https://docs.postiz.com) | |
| - [HuggingFace Spaces docs](https://huggingface.co/docs/hub/spaces) | |
| ## π More Projects | |
| Similar projects by [@somratpro](https://github.com/somratpro) β all free, one-click deploy on HF Spaces: | |
| | Project | What it runs | HF Space | GitHub | | |
| | :--- | :--- | :--- | :--- | | |
| | **HuggingFlow** | DeerFlow β deep research agent | [Space](https://huggingface.co/spaces/somratpro/HuggingFlow) | [Repo](https://github.com/somratpro/HuggingFlow) | | |
| | **HuggingClip** | Paperclip β AI agent orchestration platform | [Space](https://huggingface.co/spaces/somratpro/HuggingClip) | [Repo](https://github.com/somratpro/huggingclip) | | |
| | **HuggingClaw** | OpenClaw β Claude Code in the browser | [Space](https://huggingface.co/spaces/somratpro/HuggingClaw) | [Repo](https://github.com/somratpro/huggingclaw) | | |
| | **HuggingMes** | Hermes β Self-hosted agent gateway | [Space](https://huggingface.co/spaces/somratpro/HuggingMes) | [Repo](https://github.com/somratpro/huggingmes) | | |
| | **Hugging8n** | n8n β workflow & automation platform | [Space](https://huggingface.co/spaces/somratpro/Hugging8n) | [Repo](https://github.com/somratpro/hugging8n) | | |
| ## π License | |
| Wrapper code: MIT. Postiz itself: AGPL-3.0 β see [github.com/gitroomhq/postiz-app](https://github.com/gitroomhq/postiz-app/blob/main/LICENSE) for terms. | |
| *Made with β€οΈ by [@somratpro](https://github.com/somratpro)* | |