Add a release workflow that builds docker/Dockerfile (production target) for linux/amd64 and linux/arm64 on native runners and publishes a single multi-arch manifest to ghcr.io/trypostit/trypost on every v*.*.* tag, tagged with semver (1.2.3, 1.2, 1) and latest. Add compose.prod.yaml: a self-host stack that pulls the published image alongside Postgres and Redis with persistent volumes. Config is inline with sectioned comments, including a commented S3/R2 block (storage already uses the default disk, so switching is config-only). No application code is changed.
147 lines
4.6 KiB
YAML
147 lines
4.6 KiB
YAML
# 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"
|
|
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) =====
|
|
REVERB_APP_ID: "1001"
|
|
REVERB_APP_KEY: trypost-reverb-key
|
|
REVERB_APP_SECRET: change-me-reverb-secret # <- change me
|
|
REVERB_HOST: localhost # <- for a real domain, set to that host (and PORT 443 / SCHEME https)
|
|
REVERB_PORT: "8080"
|
|
REVERB_SCHEME: http
|
|
|
|
# ===== 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/<platform>/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: ""
|
|
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
|
|
|
|
volumes:
|
|
pgdata:
|
|
redisdata:
|
|
storage:
|