# TryPost — self-hosted production stack. # # 1. Generate an app key: docker compose -f compose.prod.yaml run --rm app php artisan key:generate --show # Paste the value into APP_KEY below. # 2. Edit APP_URL and the passwords marked "change me". # 3. Start: docker compose -f compose.prod.yaml up -d # # This pulls the published image — no local build. Postgres, Redis, the queue # workers, the scheduler and the WebSocket server all run for you. services: app: image: ghcr.io/trypostit/trypost:latest container_name: trypost restart: unless-stopped environment: # ===== Required ===== APP_NAME: TryPost APP_ENV: production APP_DEBUG: "false" APP_KEY: "" # <- run key:generate (see header) and paste here APP_URL: http://localhost:8000 # <- your public URL, e.g. https://post.yourdomain.com SELF_HOSTED: "true" ALLOW_MULTIPLE_SOCIAL_ACCOUNTS: "true" TRYPOST_TARGET: production # ===== Database (bundled postgres service below) ===== DB_CONNECTION: pgsql DB_HOST: pgsql DB_PORT: "5432" DB_DATABASE: trypost DB_USERNAME: trypost DB_PASSWORD: trypost-password # <- change me (must match POSTGRES_PASSWORD below) # ===== Redis / queue / cache / broadcasting ===== REDIS_HOST: redis REDIS_PORT: "6379" QUEUE_CONNECTION: redis CACHE_STORE: redis SESSION_DRIVER: database BROADCAST_CONNECTION: reverb # ===== WebSockets (Reverb) ===== # The published image bakes the client at localhost:8080. For a custom # domain, rebuild the image with --build-arg VITE_REVERB_HOST= # VITE_REVERB_PORT=443 VITE_REVERB_SCHEME=https. REVERB_APP_ID: "1001" REVERB_APP_KEY: trypost-reverb-key # must match the key baked into the published image REVERB_APP_SECRET: change-me-reverb-secret # <- change me REVERB_HOST: localhost REVERB_PORT: "8080" REVERB_SCHEME: http # ===== Passport (OAuth / API keys / MCP) ===== # REQUIRED for any durable deploy (and always for multi-node / load # balancers). File keys under storage/ are NOT persisted by the volumes # below — without these env vars a container recreate issues new keys and # invalidates every API/MCP token. Generate once: # docker compose -f compose.prod.yaml run --rm app php artisan passport:keys --show # then paste the PEM contents here (use \n for newlines). PASSPORT_PRIVATE_KEY: "" PASSPORT_PUBLIC_KEY: "" # ===== Storage ===== # Default: local disk, persisted in the "storage" volume below. FILESYSTEM_DISK: public # # --- Cloudflare R2: set FILESYSTEM_DISK=r2 and fill these --- # R2_ACCESS_KEY_ID: "" # R2_SECRET_ACCESS_KEY: "" # R2_ENDPOINT: "" # R2_BUCKET: "" # R2_URL: "" # public bucket URL (needed for media to display) # # --- AWS S3: set FILESYSTEM_DISK=s3 and fill these --- # AWS_ACCESS_KEY_ID: "" # AWS_SECRET_ACCESS_KEY: "" # AWS_DEFAULT_REGION: us-east-1 # AWS_BUCKET: "" # AWS_URL: "" # ===== Mail ===== # Defaults to "log" (emails written to the container log). Configure SMTP # for real password-reset / team-invite emails. MAIL_MAILER: log MAIL_FROM_ADDRESS: hello@example.com MAIL_FROM_NAME: TryPost # MAIL_MAILER: smtp # MAIL_HOST: "" # MAIL_PORT: "587" # MAIL_USERNAME: "" # MAIL_PASSWORD: "" # MAIL_SCHEME: tls # ===== Social platforms (fill in when you connect each network) ===== # Redirect URI in each portal: ${APP_URL}/accounts//callback # LINKEDIN_CLIENT_ID: "" # LINKEDIN_CLIENT_SECRET: "" # X_CLIENT_ID: "" # X_CLIENT_SECRET: "" # FACEBOOK_CLIENT_ID: "" # FACEBOOK_CLIENT_SECRET: "" # INSTAGRAM_CLIENT_ID: "" # INSTAGRAM_CLIENT_SECRET: "" # THREADS_CLIENT_ID: "" # THREADS_CLIENT_SECRET: "" # TIKTOK_CLIENT_ID: "" # TIKTOK_CLIENT_SECRET: "" # PINTEREST_CLIENT_ID: "" # PINTEREST_CLIENT_SECRET: "" # GOOGLE_CLIENT_ID: "" # YouTube + Google login # GOOGLE_CLIENT_SECRET: "" # ===== AI (optional — leave blank to disable AI features) ===== # OPENAI_API_KEY: "" # ANTHROPIC_API_KEY: "" # GEMINI_API_KEY: "" # OPENROUTER_API_KEY: "" # ELEVENLABS_API_KEY: "" ports: - "8000:80" # app (nginx) - "8080:8080" # Reverb WebSocket volumes: - storage:/var/www/html/storage/app depends_on: pgsql: condition: service_healthy redis: condition: service_healthy pgsql: image: postgres:16-alpine container_name: trypost-pgsql restart: unless-stopped environment: POSTGRES_DB: trypost POSTGRES_USER: trypost POSTGRES_PASSWORD: trypost-password # <- must match DB_PASSWORD above volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U trypost -d trypost'] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine container_name: trypost-redis restart: unless-stopped command: redis-server --appendonly yes volumes: - redisdata:/data healthcheck: test: ['CMD', 'redis-cli', 'ping'] interval: 10s timeout: 3s retries: 5 # Optional reverse proxy with automatic HTTPS (Let's Encrypt). # To serve on a domain: # 1. Point the domain's DNS at this host. # 2. Set APP_DOMAIN below and APP_URL above to https://. # 3. Start with the proxy profile: # docker compose -f compose.prod.yaml --profile proxy up -d # Without the profile, the app is served directly on http://localhost:8000. caddy: image: caddy:2-alpine container_name: trypost-caddy restart: unless-stopped profiles: [proxy] environment: APP_DOMAIN: post.example.com # <- your domain ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy-data:/data - caddy-config:/config depends_on: - app volumes: pgdata: redisdata: storage: caddy-data: caddy-config: