{
  "schema_version": 1,
  "generated_at": "2026-10-22T00:00:00.000Z",
  "canonical_url": "https://openlogs.fyi/tools/postiz",
  "slug": "postiz",
  "name": "Postiz",
  "tagline": "Schedules posts to social media accounts from one web app.",
  "replaces": {
    "summary": "Paid social media scheduling services, such as Buffer and Hootsuite.",
    "products": [
      {
        "slug": "buffer",
        "name": "Buffer",
        "vendor": "Buffer",
        "url": "https://openlogs.fyi/alternatives/buffer"
      },
      {
        "slug": "hootsuite",
        "name": "Hootsuite",
        "vendor": "Hootsuite",
        "url": "https://openlogs.fyi/alternatives/hootsuite"
      }
    ]
  },
  "stack": [
    {
      "kind": "language",
      "name": "TypeScript"
    },
    {
      "kind": "database",
      "name": "PostgreSQL"
    },
    {
      "kind": "database",
      "name": "Redis"
    }
  ],
  "deployment_methods": [
    "docker_compose"
  ],
  "requirements": {
    "min_ram_mb": null,
    "min_cpu_cores": null,
    "source_url": null
  },
  "license": {
    "spdx": "AGPL-3.0",
    "class": "osi",
    "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/LICENSE"
  },
  "business_model": {
    "value": "unknown",
    "notes": "The README at the pinned commit does not state a business model, so it stays unknown.",
    "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/README.md",
    "checked_at": "2026-10-22"
  },
  "difficulty": {
    "value": "hard",
    "reason": "9 services (4 database or broker: postgres, redis, elasticsearch), 7 volume mounts, no env values to set, no elevated host access. Heuristic score 7 of 11: hard."
  },
  "repository": {
    "owner": "gitroomhq",
    "name": "postiz-app",
    "url": "https://github.com/gitroomhq/postiz-app"
  },
  "compose_check": {
    "status": "config_ok",
    "validated_at": "2026-10-22",
    "summary": "config_ok on 2026-10-22"
  },
  "recipe": {
    "version": 1,
    "source_path": "docker-compose.yaml",
    "source_repo": "gitroomhq/postiz-app",
    "source_commit_sha": "c06abc3d786b8f719ced5716ccc70dd8a7251a05",
    "source_kind": "app_repo",
    "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml"
  },
  "install_steps": [
    {
      "order": 1,
      "kind": "prerequisite",
      "language": "text",
      "label": "Docker with the Compose plugin",
      "body": "A host with Docker and the Docker Compose plugin. This entry runs from a compose file.",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "validation_status": "unvalidated"
    },
    {
      "order": 2,
      "kind": "compose",
      "language": "yaml",
      "label": "Save the compose file as docker-compose.yaml",
      "body": "services:\n  postiz:\n    image: ghcr.io/gitroomhq/postiz-app:latest\n    container_name: postiz\n    restart: always\n    environment:\n      # === Required Settings\n      MAIN_URL: 'http://localhost:4007'\n      FRONTEND_URL: 'http://localhost:4007'\n      NEXT_PUBLIC_BACKEND_URL: 'http://localhost:4007/api'\n      JWT_SECRET: 'random string that is unique to every install - just type random characters here!'\n      DATABASE_URL: 'postgresql://postiz-user:postiz-password@postiz-postgres:5432/postiz-db-local'\n      REDIS_URL: 'redis://postiz-redis:6379'\n      BACKEND_INTERNAL_URL: 'http://localhost:3000'\n      TEMPORAL_ADDRESS: 'temporal:7233'\n      IS_GENERAL: 'true'\n      DISABLE_REGISTRATION: 'false'\n\n      # === Storage Settings\n      STORAGE_PROVIDER: 'local'\n      UPLOAD_DIRECTORY: '/uploads'\n      NEXT_PUBLIC_UPLOAD_DIRECTORY: '/uploads'\n\n      # === Cloudflare (R2) Settings\n      # STORAGE_PROVIDER: 'cloudflare'\n      # CLOUDFLARE_ACCOUNT_ID: 'your-account-id'\n      # CLOUDFLARE_ACCESS_KEY: 'your-access-key'\n      # CLOUDFLARE_SECRET_ACCESS_KEY: 'your-secret-access-key'\n      # CLOUDFLARE_BUCKETNAME: 'your-bucket-name'\n      # CLOUDFLARE_BUCKET_URL: 'https://your-bucket-url.r2.cloudflarestorage.com/'\n      # CLOUDFLARE_REGION: 'auto'\n\n      # === Social Media API Settings\n      X_URL: ''\n      X_API_KEY: ''\n      X_API_SECRET: ''\n      LINKEDIN_CLIENT_ID: ''\n      LINKEDIN_CLIENT_SECRET: ''\n      REDDIT_CLIENT_ID: ''\n      REDDIT_CLIENT_SECRET: ''\n      GITHUB_CLIENT_ID: ''\n      GITHUB_CLIENT_SECRET: ''\n      APPLE_CLIENT_ID: ''\n      APPLE_TEAM_ID: ''\n      APPLE_KEY_ID: ''\n      APPLE_PRIVATE_KEY: ''\n      BEEHIIVE_API_KEY: ''\n      BEEHIIVE_PUBLICATION_ID: ''\n      THREADS_APP_ID: ''\n      THREADS_APP_SECRET: ''\n      FACEBOOK_APP_ID: ''\n      FACEBOOK_APP_SECRET: ''\n      YOUTUBE_CLIENT_ID: ''\n      YOUTUBE_CLIENT_SECRET: ''\n      TIKTOK_CLIENT_ID: ''\n      TIKTOK_CLIENT_SECRET: ''\n      TIKTOK_BUSINESS_CLIENT_ID: ''\n      TIKTOK_BUSINESS_CLIENT_SECRET: ''\n      PINTEREST_CLIENT_ID: ''\n      PINTEREST_CLIENT_SECRET: ''\n      DRIBBBLE_CLIENT_ID: ''\n      DRIBBBLE_CLIENT_SECRET: ''\n      TUMBLR_CLIENT_ID: ''\n      TUMBLR_CLIENT_SECRET: ''\n      DISCORD_CLIENT_ID: ''\n      DISCORD_CLIENT_SECRET: ''\n      DISCORD_BOT_TOKEN_ID: ''\n      SLACK_ID: ''\n      SLACK_SECRET: ''\n      SLACK_SIGNING_SECRET: ''\n      MASTODON_URL: 'https://mastodon.social'\n      MASTODON_CLIENT_ID: ''\n      MASTODON_CLIENT_SECRET: ''\n\n      # === OAuth & Authentik Settings\n      # NEXT_PUBLIC_POSTIZ_OAUTH_DISPLAY_NAME: 'Authentik'\n      # NEXT_PUBLIC_POSTIZ_OAUTH_LOGO_URL: 'https://raw.githubusercontent.com/walkxcode/dashboard-icons/master/png/authentik.png'\n      # POSTIZ_GENERIC_OAUTH: 'false'\n      # POSTIZ_OAUTH_URL: 'https://auth.example.com'\n      # POSTIZ_OAUTH_AUTH_URL: 'https://auth.example.com/application/o/authorize'\n      # POSTIZ_OAUTH_TOKEN_URL: 'https://auth.example.com/application/o/token'\n      # POSTIZ_OAUTH_USERINFO_URL: 'https://authentik.example.com/application/o/userinfo'\n      # POSTIZ_OAUTH_CLIENT_ID: ''\n      # POSTIZ_OAUTH_CLIENT_SECRET: ''\n      # POSTIZ_OAUTH_SCOPE: \"openid profile email\"  # Optional: uncomment to override default scope\n\n      # === Sentry\n\n      # NEXT_PUBLIC_SENTRY_DSN: 'http://spotlight:8969/stream'\n      # SENTRY_SPOTLIGHT: '1'\n\n      # === Misc Settings\n      OPENAI_API_KEY: ''\n      # Only this OAuth client can receive verified user email claims via OIDC.\n      OPENAI_OAUTH_CLIENT_ID: ''\n      NEXT_PUBLIC_DISCORD_SUPPORT: ''\n      NEXT_PUBLIC_POLOTNO: ''\n      API_LIMIT: 30\n\n      # === Payment / Stripe Settings\n      FEE_AMOUNT: 0.05\n      STRIPE_PUBLISHABLE_KEY: ''\n      STRIPE_SECRET_KEY: ''\n      STRIPE_SIGNING_KEY: ''\n      STRIPE_SIGNING_KEY_CONNECT: ''\n\n      # === Developer Settings\n      NX_ADD_PLUGINS: false\n\n      # === Short Link Service Settings (Optional - leave blank if unused)\n      # DUB_TOKEN: \"\"\n      # DUB_API_ENDPOINT: \"https://api.dub.co\"\n      # DUB_SHORT_LINK_DOMAIN: \"dub.sh\"\n      # SHORT_IO_SECRET_KEY: \"\"\n      # KUTT_API_KEY: \"\"\n      # KUTT_API_ENDPOINT: \"https://kutt.it/api/v2\"\n      # KUTT_SHORT_LINK_DOMAIN: \"kutt.it\"\n      # LINK_DRIP_API_KEY: \"\"\n      # LINK_DRIP_API_ENDPOINT: \"https://api.linkdrip.com/v1/\"\n      # LINK_DRIP_SHORT_LINK_DOMAIN: \"dripl.ink\"\n\n    volumes:\n      - postiz-config:/config/\n      - postiz-uploads:/uploads/\n    ports:\n      - '4007:5000'\n    networks:\n      - postiz-network\n      - temporal-network\n    depends_on:\n      postiz-postgres:\n        condition: service_healthy\n      postiz-redis:\n        condition: service_healthy\n\n  postiz-postgres:\n    image: postgres:17-alpine\n    container_name: postiz-postgres\n    restart: always\n    environment:\n      POSTGRES_PASSWORD: postiz-password\n      POSTGRES_USER: postiz-user\n      POSTGRES_DB: postiz-db-local\n    volumes:\n      - postgres-volume:/var/lib/postgresql/data\n    networks:\n      - postiz-network\n    healthcheck:\n      test: pg_isready -U postiz-user -d postiz-db-local\n      interval: 10s\n      timeout: 3s\n      retries: 3\n  postiz-redis:\n    image: redis:7.2\n    container_name: postiz-redis\n    restart: always\n    healthcheck:\n      test: redis-cli ping\n      interval: 10s\n      timeout: 3s\n      retries: 3\n    volumes:\n      - postiz-redis-data:/data\n    networks:\n      - postiz-network\n\n  # For Application Monitoring / Debugging\n  spotlight:\n    pull_policy: always\n    container_name: spotlight\n    ports:\n      - 8969:8969/tcp\n    image: ghcr.io/getsentry/spotlight:latest\n    networks:\n      - postiz-network\n\n  # -----------------------\n  # Temporal Stack\n  # -----------------------\n  temporal-elasticsearch:\n    container_name: temporal-elasticsearch\n    image: elasticsearch:7.17.27\n    environment:\n      - cluster.routing.allocation.disk.threshold_enabled=true\n      - cluster.routing.allocation.disk.watermark.low=512mb\n      - cluster.routing.allocation.disk.watermark.high=256mb\n      - cluster.routing.allocation.disk.watermark.flood_stage=128mb\n      - discovery.type=single-node\n      - ES_JAVA_OPTS=-Xms256m -Xmx256m\n      - xpack.security.enabled=false\n    networks:\n      - temporal-network\n    expose:\n      - 9200\n    volumes:\n      - /var/lib/elasticsearch/data\n\n  temporal-postgresql:\n    container_name: temporal-postgresql\n    image: postgres:16\n    environment:\n      POSTGRES_PASSWORD: temporal\n      POSTGRES_USER: temporal\n    networks:\n      - temporal-network\n    expose:\n      - 5432\n    volumes:\n      - /var/lib/postgresql/data\n\n  temporal:\n    container_name: temporal\n    ports:\n      - '7233:7233'\n    image: temporalio/auto-setup:1.28.1\n    depends_on:\n      - temporal-postgresql\n      - temporal-elasticsearch\n    environment:\n      - DB=postgres12\n      - DB_PORT=5432\n      - POSTGRES_USER=temporal\n      - POSTGRES_PWD=temporal\n      - POSTGRES_SEEDS=temporal-postgresql\n      - DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development-sql.yaml\n      - ENABLE_ES=true\n      - ES_SEEDS=temporal-elasticsearch\n      - ES_VERSION=v7\n      - TEMPORAL_NAMESPACE=default\n    networks:\n      - temporal-network\n    volumes:\n      - ./dynamicconfig:/etc/temporal/config/dynamicconfig\n    labels:\n      kompose.volume.type: configMap\n\n  temporal-admin-tools:\n    container_name: temporal-admin-tools\n    image: temporalio/admin-tools:1.28.1-tctl-1.18.4-cli-1.4.1\n    environment:\n      - TEMPORAL_ADDRESS=temporal:7233\n      - TEMPORAL_CLI_ADDRESS=temporal:7233\n    networks:\n      - temporal-network\n    stdin_open: true\n    depends_on:\n      - temporal\n    tty: true\n\n  temporal-ui:\n    container_name: temporal-ui\n    image: temporalio/ui:2.34.0\n    environment:\n      - TEMPORAL_ADDRESS=temporal:7233\n      - TEMPORAL_CORS_ORIGINS=http://127.0.0.1:3000\n    networks:\n      - temporal-network\n    ports:\n      - '8080:8080'\n\nvolumes:\n  postgres-volume:\n    external: false\n\n  postiz-redis-data:\n    external: false\n\n  postiz-config:\n    external: false\n\n  postiz-uploads:\n    external: false\n\nnetworks:\n  postiz-network:\n    external: false\n  temporal-network:\n    driver: bridge\n    name: temporal-network\n",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "validation_status": "config_ok"
    },
    {
      "order": 3,
      "kind": "shell",
      "language": "bash",
      "label": "Start it",
      "body": "docker compose up -d",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "validation_status": "unvalidated"
    },
    {
      "order": 4,
      "kind": "verify",
      "language": "text",
      "label": "Open the app",
      "body": "Open http://localhost:4007. The compose file publishes host port 4007 for the postiz service.",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "validation_status": "unvalidated"
    }
  ],
  "notes": [
    {
      "kind": "gotcha",
      "title": "Some images use the latest tag or no tag",
      "body": "Images without a pinned version: postiz: ghcr.io/gitroomhq/postiz-app:latest, spotlight: ghcr.io/getsentry/spotlight:latest. A later pull can get a different version.",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file publishes host ports",
      "body": "Host ports: 4007 (postiz), 8969 (spotlight), 7233 (temporal), 8080 (temporal-ui). A port without a host address listens on all host network interfaces.",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file mounts host folders",
      "body": "Host paths mounted into containers: ./dynamicconfig at /etc/temporal/config/dynamicconfig (temporal).",
      "source_url": "https://github.com/gitroomhq/postiz-app/blob/c06abc3d786b8f719ced5716ccc70dd8a7251a05/docker-compose.yaml",
      "checked_at": "2026-10-22"
    }
  ],
  "signals": {
    "captured_at": "2026-10-22",
    "stars": 37561,
    "forks": 7326,
    "open_issues": 222,
    "last_push": "2026-10-21",
    "days_since_push": 0,
    "latest_release": "v2.25.1",
    "latest_release_date": "2026-10-11",
    "days_since_release": 10
  },
  "links": {
    "html": "https://openlogs.fyi/tools/postiz",
    "markdown": "https://openlogs.fyi/tools/postiz.md",
    "json": "https://openlogs.fyi/tools/postiz.json"
  },
  "updated_at": "2026-10-22"
}
