Configuration
TryPost is configured through environment variables in the .env file.
Basic Configuration
APP_NAME="TryPost"
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost
| Variable | Description |
|---|
APP_NAME | Your application name |
APP_ENV | Environment: local, staging, production |
APP_DEBUG | Enable debug mode (set to false in production) |
APP_URL | Your application URL |
Self-Hosted Mode
SELF_HOSTED=true is the default. It bypasses everything billing-related so you never have to touch Stripe or Cashier, and it locks down public sign-ups:
- Public registration is disabled —
/register is closed so random users can’t create accounts on your instance. Bootstrap the first admin via the UserSeeder (see Create the admin user); after that, every account comes from a workspace invite (Settings → Members).
- No Stripe, Cashier, or
CASHIER_TRIAL_DAYS configuration required
- The
LoadWorkspaceFromToken middleware skips the 402 Payment Required gate
- Plan limits are not enforced — unlimited workspaces, social accounts, members, and AI credits per account
- AI calls go straight to your configured provider; you pay the provider directly (no credit accounting)
There’s no reason to flip this to false on a self-hosted install. The Cloud SaaS deployment is the only place that runs with billing enabled.
Database
TryPost supports PostgreSQL and MySQL.
PostgreSQL (recommended)
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=trypost
DB_USERNAME=postgres
DB_PASSWORD=your_password
MySQL
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=trypost
DB_USERNAME=root
DB_PASSWORD=your_password
Redis
Redis is required for queues and caching.
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MEDIA_IMAGE_MAX_SIZE_MB=10
MEDIA_VIDEO_MAX_SIZE_MB=1024
MCP_UPLOAD_MAX_SIZE_MB=50
MCP_UPLOAD_URL_TTL_MINUTES=15
| Variable | Default | Description |
|---|
MEDIA_IMAGE_MAX_SIZE_MB | 10 | Max image upload size, in MB. Applied to direct uploads and URL fetches. |
MEDIA_VIDEO_MAX_SIZE_MB | 1024 | Max video upload size, in MB. Applied to direct uploads and URL fetches. |
MCP_UPLOAD_MAX_SIZE_MB | 50 | Hard cap (in MB) for files uploaded through the MCP request-media-upload-tool signed-URL flow. Intentionally smaller than the per-type caps because uploads stream through the app server. Raise it if your operators / nginx are sized for larger payloads. |
MCP_UPLOAD_URL_TTL_MINUTES | 15 | Lifetime of the signed upload URL returned by request-media-upload-tool. |
If you raise the video limit, also bump PHP’s upload_max_filesize and post_max_size and any reverse-proxy body-size cap to match. The MCP upload endpoint is additionally rate-limited at 10 requests / minute / IP — this is a hard-coded defense; tune the surrounding nginx/Cloudflare limits if you need a different floor.
File Storage
TryPost supports local public storage and S3-compatible cloud storage.
The default disk is Cloudflare R2 (FILESYSTEM_DISK=r2). For self-hosted installs without object storage configured, switch to public.
Public Disk
Stores files in storage/app/public and serves them directly from ${APP_URL}/storage.
After switching, create the symlink from public/storage to storage/app/public:
See Laravel’s public disk documentation for more details.
AWS S3
FILESYSTEM_DISK=s3
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=your_bucket
AWS_URL=https://your-bucket.s3.amazonaws.com
Cloudflare R2
FILESYSTEM_DISK=r2
R2_ACCESS_KEY_ID=your_key
R2_SECRET_ACCESS_KEY=your_secret
R2_ENDPOINT=https://your-account.r2.cloudflarestorage.com
R2_REGION=auto
R2_BUCKET=your_bucket
R2_URL=https://your-custom-domain.com
DigitalOcean Spaces
FILESYSTEM_DISK=spaces
SPACES_ACCESS_KEY_ID=your_key
SPACES_SECRET_ACCESS_KEY=your_secret
SPACES_ENDPOINT=https://nyc3.digitaloceanspaces.com
SPACES_REGION=nyc3
SPACES_BUCKET=your_bucket
Other S3-Compatible Storage
Any other S3-compatible storage (MinIO, Backblaze B2, etc.) can be used with the s3 disk configuration.
Mail
TryPost sends transactional emails for post notifications, team invites, account alerts, and authentication (email verification, password reset). A working mail configuration is required.
SendKit (recommended)
SendKit is TryPost’s official mailer — built by the same team and wired in as the default. Every new SendKit account is free and includes 3,000 transactional emails per month, which is plenty for a self-hosted TryPost instance handling post notifications, team invites, and account alerts.
- Create a free account at sendkit.dev
- Copy your API key from the SendKit dashboard
- Drop it into your
.env:
MAIL_MAILER=sendkit
SENDKIT_API_KEY=sk_your_sendkit_api_key
MAIL_FROM_ADDRESS="notifications@yourdomain.com"
MAIL_FROM_NAME="${APP_NAME}"
That’s it — no DNS warm-up, no domain verification dance to get the first emails out, and the free tier doesn’t expire.
SMTP
If you’d rather use your own SMTP server:
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="notifications@yourdomain.com"
MAIL_FROM_NAME="${APP_NAME}"
Emails sent by TryPost
| Email | When it’s sent |
|---|
| Post published | A scheduled post was successfully published |
| Post failed | A post failed to publish on one or more platforms |
| Account disconnected | A social account lost its authorization and needs reconnection |
| Connections check | Multiple accounts in a workspace were found disconnected |
| Workspace invite | A team member is invited to join a workspace |
| Email verification | A new user needs to verify their email address |
| Password reset | A user requests a password reset |
WebSockets (Reverb)
TryPost uses Laravel Reverb for real-time updates (live post status, notifications).
REVERB_APP_ID=1001
REVERB_APP_KEY=your-reverb-key
REVERB_APP_SECRET=your-reverb-secret
# Public hostname / port the browser will connect to
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http
# Bind address the Reverb server listens on (defaults to 0.0.0.0:8080)
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
| Variable | Description |
|---|
REVERB_APP_ID | Unique application ID |
REVERB_APP_KEY | Application key for client connections |
REVERB_APP_SECRET | Secret key for server-side authentication |
REVERB_HOST | Public hostname the browser uses to connect (advertised to clients) |
REVERB_PORT | Public port the browser connects to |
REVERB_SCHEME | Protocol: http or https |
REVERB_SERVER_HOST | Bind address the Reverb server listens on. Defaults to 0.0.0.0. |
REVERB_SERVER_PORT | Port the Reverb server listens on. Defaults to 8080. |
In production, set REVERB_SCHEME=https, set REVERB_HOST to your real public domain (e.g. app.example.com), and use a reverse proxy to handle SSL termination for WebSocket connections. REVERB_SERVER_HOST stays 0.0.0.0 so the daemon listens on all interfaces inside the box.
Each social platform requires API credentials from its developer portal. See each platform’s documentation for step-by-step setup.
Bluesky and Mastodon don’t require API credentials — they work out of the box.
# LinkedIn (https://developer.linkedin.com)
LINKEDIN_CLIENT_ID=
LINKEDIN_CLIENT_SECRET=
LINKEDIN_CLIENT_REDIRECT="${APP_URL}/accounts/linkedin/callback"
LINKEDIN_PAGE_CLIENT_REDIRECT="${APP_URL}/accounts/linkedin-page/callback"
# X / Twitter (https://developer.twitter.com)
X_CLIENT_ID=
X_CLIENT_SECRET=
X_CLIENT_REDIRECT="${APP_URL}/accounts/x/callback"
# Facebook (https://developers.facebook.com)
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
FACEBOOK_CLIENT_REDIRECT="${APP_URL}/accounts/facebook/callback"
# Instagram (https://developers.facebook.com)
INSTAGRAM_CLIENT_ID=
INSTAGRAM_CLIENT_SECRET=
INSTAGRAM_CLIENT_REDIRECT="${APP_URL}/accounts/instagram/callback"
# Threads (https://developers.facebook.com)
THREADS_CLIENT_ID=
THREADS_CLIENT_SECRET=
THREADS_CLIENT_REDIRECT="${APP_URL}/accounts/threads/callback"
# TikTok (https://developers.tiktok.com)
TIKTOK_CLIENT_ID=
TIKTOK_CLIENT_SECRET=
TIKTOK_CLIENT_REDIRECT="${APP_URL}/accounts/tiktok/callback"
# Google / YouTube (https://console.cloud.google.com)
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_CLIENT_REDIRECT="${APP_URL}/accounts/youtube/callback"
# Pinterest (https://developers.pinterest.com)
PINTEREST_CLIENT_ID=
PINTEREST_CLIENT_SECRET=
PINTEREST_CLIENT_REDIRECT="${APP_URL}/accounts/pinterest/callback"
You can selectively enable or disable platforms without removing their credentials. This is useful when API credentials are pending approval or temporarily revoked.
LINKEDIN_ENABLED=true
LINKEDIN_PAGE_ENABLED=true
X_ENABLED=true
TIKTOK_ENABLED=true
YOUTUBE_ENABLED=true
FACEBOOK_ENABLED=true
INSTAGRAM_ENABLED=true
INSTAGRAM_FACEBOOK_ENABLED=true
THREADS_ENABLED=true
PINTEREST_ENABLED=true
BLUESKY_ENABLED=true
MASTODON_ENABLED=true
Set any platform to false to hide it from the UI. All platforms are enabled by default.
Social login
TryPost supports sign in with Google and GitHub. Both providers are off by default — set the corresponding *_AUTH_ENABLED flag and provide credentials to surface the buttons on the login/register pages.
Google
Google login reuses the OAuth credentials from the YouTube integration, with a separate callback URL.
GOOGLE_AUTH_ENABLED=true
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_AUTH_CALLBACK="${APP_URL}/auth/google/callback"
In the Google Cloud Console, add both callback URLs to your OAuth 2.0 client:
https://your-domain.com/accounts/youtube/callback (YouTube connection)
https://your-domain.com/auth/google/callback (Google login)
GitHub
GITHUB_AUTH_ENABLED=true
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
GITHUB_AUTH_CALLBACK="${APP_URL}/auth/github/callback"
Register a new OAuth App at github.com/settings/developers and set the Authorization callback URL to ${APP_URL}/auth/github/callback.
AI features (optional)
The Generate / Review / Create AI flows in the post editor need a configured text-generation provider. Without one, the AI buttons stay disabled.
AI_TEXT_PROVIDER=openai
AI_TEXT_MODEL=gpt-5.4
OPENAI_API_KEY=sk-...
# Optional — image generation for the AI Create wizard
AI_IMAGE_PROVIDER=openai
# Optional — voiceover / TTS (used by future video flows)
AI_AUDIO_PROVIDER=eleven
ELEVENLABS_API_KEY=
| Variable | Description |
|---|
AI_TEXT_PROVIDER | openai (default), anthropic, gemini, azure, groq, xai, deepseek, mistral, ollama, openrouter, cohere, jina, or voyageai. |
AI_TEXT_MODEL | Model identifier for the text provider. Defaults to gpt-5.4. |
AI_IMAGE_PROVIDER | Provider used for AI image generation in the Create wizard. Defaults to openai. The active OpenAI image model is hardcoded to gpt-image-2. |
AI_AUDIO_PROVIDER | TTS provider. openai (default) or eleven. Note the key is eleven, not elevenlabs — setting elevenlabs will not resolve. |
| Provider API keys | Each provider reads its own env: OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY, GROQ_API_KEY, MISTRAL_API_KEY, OPENROUTER_API_KEY, COHERE_API_KEY, JINA_API_KEY, VOYAGEAI_API_KEY, ELEVENLABS_API_KEY. Ollama uses OLLAMA_BASE_URL (no key by default). |
Self-hosted instances skip the credit/quota check entirely (SELF_HOSTED=true), so AI calls go straight to the configured provider — you pay the provider directly.
Asset library (Unsplash & Giphy)
The Assets page exposes optional Unsplash and Giphy tabs. Configure these to enable them:
UNSPLASH_ACCESS_KEY=
UNSPLASH_SECRET_KEY=
GIPHY_API_KEY=
Without these keys, the Library tab still works — only the stock-photo and GIF tabs are hidden.
Analytics (optional)
PostHog
POSTHOG_ENABLED=true
POSTHOG_API_KEY=phc_your_key
POSTHOG_HOST=https://us.i.posthog.com
VITE_POSTHOG_API_KEY="${POSTHOG_API_KEY}"
VITE_POSTHOG_HOST="${POSTHOG_HOST}"
POSTHOG_ENABLED gates the entire integration — without it set to true, the keys are ignored.
Google Tag Manager
Both are optional and only needed if you want to track usage analytics.
Horizon (Queue Dashboard)
Laravel Horizon provides a dashboard to monitor your queues. Access it at /horizon.
HORIZON_ALLOWED_EMAILS=admin@example.com,dev@example.com
| Variable | Description |
|---|
HORIZON_ALLOWED_EMAILS | Comma-separated list of emails allowed to access Horizon in production |
If not set, Horizon dashboard will be inaccessible in non-local environments.
Next Steps