diff --git a/ROLLBACK.md b/ROLLBACK.md new file mode 100644 index 0000000..dbbcbf5 --- /dev/null +++ b/ROLLBACK.md @@ -0,0 +1,194 @@ +# Rollback — Retour vers la chart officielle GitHub + +Ce document couvre le retour de la source ArgoCD depuis ce fork Gitea +(`homegit.gyozamancave.fr/billisdead/postiz-helmchart`) vers la chart officielle +(`github.com/gitroomhq/postiz-helmchart`). + +--- + +## Structure des branches et référence upstream + +``` +Tag upstream-1.0.5 → commit 5d6a9de2 (upstream exact, immuable) + gitroomhq/postiz-helmchart, chart v1.0.5, jan 2025 + +main → contenu fonctionnellement identique à upstream + (source déployée par ArgoCD) + +feat/temporal-support → 5d6a9de2 → Temporal + env → ROLLBACK.md + (branche de travail pour l'upgrade v2.21.8) +``` + +### Inspecter le delta entre upstream et notre travail + +```bash +# Tout ce qui a changé par rapport à l'upstream dans la chart +git diff upstream-1.0.5 feat/temporal-support -- charts/ + +# Juste les fichiers modifiés (sans le contenu) +git diff --name-only upstream-1.0.5 feat/temporal-support + +# Comparer main avec upstream (doit être vide sur charts/) +git diff upstream-1.0.5 main -- charts/ +``` + +### Synchroniser le tag upstream si l'upstream GitHub évolue + +```bash +# Ajouter le remote GitHub si absent +git remote add upstream https://github.com/gitroomhq/postiz-helmchart + +# Récupérer le nouvel upstream +git fetch upstream + +# Créer un nouveau tag pour la nouvelle version upstream +git tag -a upstream- upstream/main -m "Upstream gitroomhq à " +git push origin upstream- +``` + +--- + +## Contexte de référence + +| Paramètre | Fork Gitea (actuel) | Chart officielle (cible rollback) | +|---|---|---| +| `repoURL` | `https://homegit.gyozamancave.fr/billisdead/postiz-helmchart` | `https://github.com/gitroomhq/postiz-helmchart` | +| `targetRevision` | `main` | `HEAD` | +| `path` | `charts/postiz` | `charts/postiz` | + +Les `values` inline dans l'Application ArgoCD ne changent pas. + +--- + +## Scénario 1 — Rollback normal (ArgoCD accessible) + +```bash +kubectl patch application postiz -n argocd --type='json' -p='[ + {"op": "replace", "path": "/spec/source/repoURL", "value": "https://github.com/gitroomhq/postiz-helmchart"}, + {"op": "replace", "path": "/spec/source/targetRevision", "value": "HEAD"} +]' + +kubectl annotate application postiz -n argocd \ + argocd.argoproj.io/refresh=hard --overwrite +``` + +Vérification : + +```bash +kubectl get application postiz -n argocd \ + -o jsonpath='{"sync: "}{.status.sync.status}{"\nhealth: "}{.status.health.status}{"\nrevision: "}{.status.sync.revision}{"\n"}' +``` + +Résultat attendu : `sync: Synced`, `health: Healthy`, revision = dernier commit GitHub. + +--- + +## Scénario 2 — Gitea inaccessible (rollback d'urgence) + +Si `homegit.gyozamancave.fr` est down et qu'ArgoCD est bloqué en erreur de fetch, +appliquer le patch de la même façon — ArgoCD re-tentera depuis GitHub immédiatement. + +```bash +# Même commande que le scénario 1 — ArgoCD abandonne le fetch Gitea dès que repoURL change +kubectl patch application postiz -n argocd --type='json' -p='[ + {"op": "replace", "path": "/spec/source/repoURL", "value": "https://github.com/gitroomhq/postiz-helmchart"}, + {"op": "replace", "path": "/spec/source/targetRevision", "value": "HEAD"} +]' +``` + +Si ArgoCD lui-même ne répond plus, patcher le CRD directement via le control plane : + +```bash +# Requiert un accès direct à k3s-master +KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl patch application postiz -n argocd \ + --type='json' -p='[ + {"op": "replace", "path": "/spec/source/repoURL", "value": "https://github.com/gitroomhq/postiz-helmchart"}, + {"op": "replace", "path": "/spec/source/targetRevision", "value": "HEAD"} + ]' +``` + +--- + +## Scénario 3 — Rollback après upgrade image (ex. v2.11.2 → v2.21.8 cassé) + +Le rollback de la source chart ne suffit pas si l'image Postiz a aussi été changée +**et que Prisma a migré le schéma DB**. Dans ce cas, la séquence est : + +### 3a. Rollback image seule (si DB non migrée) + +Éditer les values inline de l'Application ArgoCD et remettre le tag d'origine : + +```yaml +image: + tag: "v2.11.2" +``` + +```bash +# Puis forcer le sync +kubectl annotate application postiz -n argocd \ + argocd.argoproj.io/refresh=hard --overwrite +``` + +### 3b. Rollback image + restauration DB (si Prisma a migré) + +> **Toujours faire un `pg_dump` avant tout upgrade.** + +```bash +# 1. Scale down pour éviter les écritures pendant la restauration +kubectl scale deployment postiz-postiz-app --replicas=0 -n default + +# 2. Identifier le pod PostgreSQL +PGPOD=$(kubectl get pod -n default -l app.kubernetes.io/name=postgresql -o jsonpath='{.items[0].metadata.name}') + +# 3. Vider le schéma (le dump pg_dump sans --clean ne contient pas de DROP TABLE) +kubectl exec -n default "$PGPOD" -- bash -c \ + 'PGPASSWORD="" psql -U postiz postiz -c \ + "DROP SCHEMA public CASCADE; CREATE SCHEMA public; \ + GRANT ALL ON SCHEMA public TO postiz; \ + GRANT ALL ON SCHEMA public TO public;"' + +# 4. Restaurer depuis le backup local +kubectl exec -i -n default "$PGPOD" -- bash -c \ + 'PGPASSWORD="" psql -U postiz postiz' \ + < /path/to/postiz-backup-YYYYMMDD.sql + +# 5. Remettre le tag image v2.11.2 dans les values ArgoCD, puis scale up +kubectl scale deployment postiz-postiz-app --replicas=1 -n default +``` + +--- + +## Scénario 4 — Rollback vers un commit Gitea précis (pas GitHub) + +Si le problème vient d'un commit spécifique sur le fork mais que la branche `main` +reste valide, pointer sur le SHA du dernier commit stable : + +```bash +# Trouver le SHA stable (ex. avant le commit problématique) +git -C /home/billisdead/gitea-trucs/postiz-helm log --oneline main | head -10 + +# Patcher vers ce SHA +kubectl patch application postiz -n argocd --type='json' -p='[ + {"op": "replace", "path": "/spec/source/targetRevision", "value": ""} +]' +``` + +--- + +## Vérification post-rollback (tous scénarios) + +```bash +# Source effective +kubectl get application postiz -n argocd \ + -o jsonpath='{.spec.source.repoURL}{"\n"}{.spec.source.targetRevision}{"\n"}' + +# État de santé +kubectl get application postiz -n argocd \ + -o jsonpath='{"sync: "}{.status.sync.status}{"\nhealth: "}{.status.health.status}{"\n"}' + +# Pod toujours Running sans restart +kubectl get pods -n default -l "app.kubernetes.io/name=postiz-app" + +# Logs démarrage (vérifier absence d'erreur Temporal/DB/Redis) +kubectl logs -n default deployment/postiz-postiz-app --tail=30 +``` diff --git a/charts/postiz/Chart.yaml b/charts/postiz/Chart.yaml index e145255..56b960c 100644 --- a/charts/postiz/Chart.yaml +++ b/charts/postiz/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: postiz-app description: A Social Media Scheduling App type: application -version: 1.0.5 -appVersion: "1.3.0" +version: 1.1.0 +appVersion: "v2.21.8" maintainers: - name: jonathan-irvin email: offendingcommit@gmail.com diff --git a/charts/postiz/templates/NOTES.txt b/charts/postiz/templates/NOTES.txt new file mode 100644 index 0000000..b86cad7 --- /dev/null +++ b/charts/postiz/templates/NOTES.txt @@ -0,0 +1,46 @@ +Postiz has been deployed! + +Access URL: +{{- if .Values.ingress.enabled }} + https://{{ (first .Values.ingress.hosts).host }} +{{- else if eq .Values.service.type "NodePort" }} + http://:{{ .Values.service.nodePort }} +{{- else }} + kubectl port-forward svc/{{ include "postiz.fullname" . }} 5000:80 + http://localhost:5000 +{{- end }} + +{{- if .Values.temporal.enabled }} + +Temporal: + Internal address : {{ include "postiz.fullname" . }}-temporal:7233 + Status : kubectl get pods -l app.kubernetes.io/component=temporal + Init job logs : kubectl logs job/{{ include "postiz.fullname" . }}-temporal-init + + After first deploy, create Temporal search attributes: + kubectl exec deploy/{{ include "postiz.fullname" . }}-temporal -- \ + temporal operator search-attribute create \ + --namespace {{ .Values.temporal.namespace | default "default" }} \ + --name organizationId --type Keyword \ + --name postId --type Keyword +{{- else if .Values.temporal.address }} + +Temporal (external): {{ .Values.temporal.address }} +{{- else }} + +WARNING: Temporal is disabled and no address is configured. + Postiz v2.12.0+ requires Temporal for post scheduling. + Set temporal.enabled=true or provide temporal.address. +{{- end }} + +{{- if and (gt (.Values.replicaCount | int) 1) (eq (.Values.env.STORAGE_PROVIDER | default "local") "local") }} + +WARNING: replicaCount={{ .Values.replicaCount }} with STORAGE_PROVIDER=local is unsupported. + Local uploads are not shared across replicas. Use Cloudflare R2 or an RWX PVC. +{{- end }} + +Upgrade reminder: + Always back up the PostgreSQL database before upgrading Postiz: + kubectl exec -n -- \ + pg_dump -U {{ .Values.postgresql.auth.username }} {{ .Values.postgresql.auth.database }} \ + > postiz-backup-$(date +%Y%m%d).sql diff --git a/charts/postiz/templates/postiz-config.yaml b/charts/postiz/templates/postiz-config.yaml index 299706c..3a7599a 100644 --- a/charts/postiz/templates/postiz-config.yaml +++ b/charts/postiz/templates/postiz-config.yaml @@ -7,4 +7,11 @@ metadata: data: {{- range $key, $value := .Values.env }} {{ $key }}: {{ $value | quote }} - {{- end }} \ No newline at end of file + {{- end }} + {{- if .Values.temporal.enabled }} + TEMPORAL_ADDRESS: {{ default (printf "%s-temporal:7233" (include "postiz.fullname" .)) .Values.temporal.address | quote }} + TEMPORAL_NAMESPACE: {{ .Values.temporal.namespace | default "default" | quote }} + TEMPORAL_TLS: {{ .Values.temporal.tls | toString | quote }} + {{- else if .Values.temporal.address }} + TEMPORAL_ADDRESS: {{ .Values.temporal.address | quote }} + {{- end }} diff --git a/charts/postiz/templates/temporal-deployment.yaml b/charts/postiz/templates/temporal-deployment.yaml new file mode 100644 index 0000000..2e546e3 --- /dev/null +++ b/charts/postiz/templates/temporal-deployment.yaml @@ -0,0 +1,68 @@ +{{- if .Values.temporal.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "postiz.fullname" . }}-temporal + labels: + {{- include "postiz.labels" . | nindent 4 }} + app.kubernetes.io/component: temporal +spec: + replicas: 1 + selector: + matchLabels: + {{- include "postiz.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: temporal + template: + metadata: + labels: + {{- include "postiz.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: temporal + spec: + containers: + - name: temporal + image: "{{ .Values.temporal.image.repository }}:{{ .Values.temporal.image.tag }}" + imagePullPolicy: {{ .Values.temporal.image.pullPolicy }} + ports: + - name: grpc + containerPort: 7233 + protocol: TCP + env: + - name: DB + value: "postgres12" + - name: DB_PORT + value: "5432" + - name: POSTGRES_USER + value: {{ .Values.temporal.postgresql.user | quote }} + - name: POSTGRES_PWD + valueFrom: + secretKeyRef: + name: {{ include "postiz.fullname" . }}-temporal-secret + key: POSTGRES_PWD + - name: POSTGRES_SEEDS + value: {{ default (printf "%s-postgresql" .Release.Name) .Values.temporal.postgresql.seeds | quote }} + - name: DYNAMIC_CONFIG_FILE_PATH + value: "config/dynamicconfig/development-sql.yaml" + - name: ENABLE_ES + value: "false" + - name: TEMPORAL_NAMESPACE + value: {{ .Values.temporal.namespace | default "default" | quote }} + volumeMounts: + - name: dynamicconfig + mountPath: /etc/temporal/config/dynamicconfig + livenessProbe: + tcpSocket: + port: grpc + initialDelaySeconds: 30 + periodSeconds: 15 + failureThreshold: 5 + readinessProbe: + tcpSocket: + port: grpc + initialDelaySeconds: 15 + periodSeconds: 10 + failureThreshold: 5 + volumes: + - name: dynamicconfig + configMap: + name: {{ include "postiz.fullname" . }}-temporal-dynamicconfig +{{- end }} diff --git a/charts/postiz/templates/temporal-dynamicconfig.yaml b/charts/postiz/templates/temporal-dynamicconfig.yaml new file mode 100644 index 0000000..eef4864 --- /dev/null +++ b/charts/postiz/templates/temporal-dynamicconfig.yaml @@ -0,0 +1,16 @@ +{{- if .Values.temporal.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "postiz.fullname" . }}-temporal-dynamicconfig + labels: + {{- include "postiz.labels" . | nindent 4 }} +data: + development-sql.yaml: | + limit.maxIDLength: + - value: 255 + constraints: {} + system.forceSearchAttributesCacheRefreshOnRead: + - value: true + constraints: {} +{{- end }} diff --git a/charts/postiz/templates/temporal-init-job.yaml b/charts/postiz/templates/temporal-init-job.yaml new file mode 100644 index 0000000..20ad369 --- /dev/null +++ b/charts/postiz/templates/temporal-init-job.yaml @@ -0,0 +1,73 @@ +{{- if .Values.temporal.enabled }} +{{- if .Values.postgresql.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "postiz.fullname" . }}-temporal-init + labels: + {{- include "postiz.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + backoffLimit: 6 + template: + metadata: + labels: + app.kubernetes.io/component: temporal-init + {{- include "postiz.selectorLabels" . | nindent 8 }} + spec: + restartPolicy: OnFailure + initContainers: + - name: wait-for-postgres + image: postgres:16-alpine + command: + - sh + - -c + - | + until pg_isready -h $PGHOST -p 5432 -U postgres; do + echo "Waiting for PostgreSQL..."; sleep 3 + done + env: + - name: PGHOST + value: {{ printf "%s-postgresql" .Release.Name | quote }} + containers: + - name: create-temporal-user + image: postgres:16-alpine + command: + - sh + - -c + - | + export PGPASSWORD="$POSTGRES_PASSWORD" + psql -h "$PGHOST" -U postgres <<-SQL + DO \$\$ BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '$TEMPORAL_USER') THEN + EXECUTE format( + 'CREATE ROLE %I WITH LOGIN PASSWORD %L CREATEDB', + '$TEMPORAL_USER', + '$TEMPORAL_PWD' + ); + RAISE NOTICE 'Role $TEMPORAL_USER created.'; + ELSE + RAISE NOTICE 'Role $TEMPORAL_USER already exists, skipping.'; + END IF; + END \$\$; + SQL + env: + - name: PGHOST + value: {{ printf "%s-postgresql" .Release.Name | quote }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ printf "%s-postgresql" .Release.Name | quote }} + key: postgres-password + - name: TEMPORAL_USER + value: {{ .Values.temporal.postgresql.user | quote }} + - name: TEMPORAL_PWD + valueFrom: + secretKeyRef: + name: {{ include "postiz.fullname" . }}-temporal-secret + key: POSTGRES_PWD +{{- end }} +{{- end }} diff --git a/charts/postiz/templates/temporal-secret.yaml b/charts/postiz/templates/temporal-secret.yaml new file mode 100644 index 0000000..1e76e3a --- /dev/null +++ b/charts/postiz/templates/temporal-secret.yaml @@ -0,0 +1,14 @@ +{{- if .Values.temporal.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "postiz.fullname" . }}-temporal-secret + labels: + {{- include "postiz.labels" . | nindent 4 }} +type: Opaque +data: + POSTGRES_PWD: {{ .Values.temporal.postgresql.password | b64enc | quote }} + {{- if .Values.temporal.apiKey }} + TEMPORAL_API_KEY: {{ .Values.temporal.apiKey | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/charts/postiz/templates/temporal-service.yaml b/charts/postiz/templates/temporal-service.yaml new file mode 100644 index 0000000..3a4e5a9 --- /dev/null +++ b/charts/postiz/templates/temporal-service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.temporal.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "postiz.fullname" . }}-temporal + labels: + {{- include "postiz.labels" . | nindent 4 }} + app.kubernetes.io/component: temporal +spec: + type: ClusterIP + ports: + - port: 7233 + targetPort: grpc + protocol: TCP + name: grpc + selector: + {{- include "postiz.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: temporal +{{- end }} diff --git a/charts/postiz/values.yaml b/charts/postiz/values.yaml index 94e8120..ddcec6f 100644 --- a/charts/postiz/values.yaml +++ b/charts/postiz/values.yaml @@ -26,11 +26,9 @@ service: additionalPorts: [] ingress: - enabled: false # Disabled by default + enabled: false className: "" annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" hosts: - host: chart-example.local paths: @@ -38,9 +36,6 @@ ingress: pathType: Prefix port: 80 tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local extraRules: [] resources: {} @@ -62,18 +57,22 @@ tolerations: [] affinity: {} -# PostgreSQL configuration +# PostgreSQL configuration (Bitnami sub-chart) postgresql: enabled: true auth: username: postiz password: postiz-password database: postiz + # postgresPassword is used by the temporal init job to create the temporal user. + # Set this explicitly; if left empty, Bitnami generates a random password + # that the init job cannot retrieve. + postgresPassword: postgres-admin-password service: ports: postgresql: 5432 -# Redis configuration +# Redis configuration (Bitnami sub-chart) redis: enabled: true auth: @@ -83,21 +82,134 @@ redis: ports: redis: 6379 -# Environment variables +# Temporal workflow orchestration (required since Postiz v2.12.0) +# temporal.enabled=true → deploys Temporal alongside Postiz using the postgresql sub-chart +# temporal.enabled=false → Temporal must be deployed separately; set temporal.address +temporal: + enabled: true + # address: override auto-computed service address (-temporal:7233) + address: "" + namespace: "default" + tls: false + # apiKey: only required for Temporal Cloud; leave empty for self-hosted + apiKey: "" + image: + repository: temporalio/auto-setup + tag: "1.28.1" + pullPolicy: IfNotPresent + postgresql: + # Credentials for the temporal user created in the shared PostgreSQL instance. + # The init job creates this user via the postgres superuser before Temporal starts. + user: temporal + password: "temporal-password" + # seeds: PostgreSQL hostname. Defaults to the Bitnami postgresql sub-chart service. + seeds: "" + +# Non-sensitive environment variables (injected via ConfigMap) env: + # === Required === FRONTEND_URL: "http://localhost:4200" NEXT_PUBLIC_BACKEND_URL: "http://localhost:3000" - BACKEND_INTERNAL_URL: "http://backend:3000" + BACKEND_INTERNAL_URL: "http://localhost:3000" + + # === Application behaviour === + IS_GENERAL: "true" + NX_ADD_PLUGINS: "false" + MAIN_URL: "" + DISABLE_REGISTRATION: "false" + RUN_CRON: "" + API_LIMIT: "90" + RESTRICT_UPLOAD_DOMAINS: "" + DISALLOW_PLUS: "" + DISABLE_IMAGE_COMPRESSION: "false" + MOBILE_APP_SCHEME: "" + NOT_SECURED: "false" + + # === Storage === + STORAGE_PROVIDER: "local" UPLOAD_DIRECTORY: "" NEXT_PUBLIC_UPLOAD_STATIC_DIRECTORY: "" - NX_ADD_PLUGINS: "false" - IS_GENERAL: "true" + CLOUDFLARE_REGION: "auto" -# Sensitive environment variables (to be stored in Secrets) + # === Email === + EMAIL_PROVIDER: "resend" + EMAIL_HOST: "" + EMAIL_PORT: "" + EMAIL_SECURE: "false" + EMAIL_FROM_ADDRESS: "" + EMAIL_FROM_NAME: "" + + # === OAuth / OIDC sign-in === + POSTIZ_GENERIC_OAUTH: "false" + POSTIZ_OAUTH_URL: "" + POSTIZ_OAUTH_AUTH_URL: "" + POSTIZ_OAUTH_TOKEN_URL: "" + POSTIZ_OAUTH_USERINFO_URL: "" + POSTIZ_OAUTH_SCOPE: "openid profile email" + NEXT_PUBLIC_POSTIZ_OAUTH_DISPLAY_NAME: "" + NEXT_PUBLIC_POSTIZ_OAUTH_LOGO_URL: "" + + # === Social providers — non-sensitive settings === + X_URL: "" + DISABLE_X_ANALYTICS: "" + STRIP_LINKS_FROM_X_POSTS: "" + MASTODON_URL: "https://mastodon.social" + NEYNAR_LOGIN_URL: "" + MEWE_HOST: "" + + # === MCP / Agent === + MCP_URL: "" + BACKEND_URL: "" + + # === Payments === + FEE_AMOUNT: "0.05" + + # === Analytics & tracking (frontend) === + NEXT_PUBLIC_SENTRY_DSN: "" + NEXT_PUBLIC_GTM_ID: "" + NEXT_PUBLIC_FACEBOOK_PIXEL: "" + NEXT_PUBLIC_POSTHOG_HOST: "" + NEXT_PUBLIC_POSTHOG_KEY: "" + SENTRY_ORG: "" + SENTRY_PROJECT: "" + SENTRY_SPOTLIGHT: "false" + + # === Misc frontend === + NEXT_PUBLIC_DISCORD_SUPPORT: "" + NEXT_PUBLIC_POLOTNO: "" + NEXT_PUBLIC_VERSION: "" + NEXT_PUBLIC_APP_VERSION: "" + NEXT_PUBLIC_OVERRIDE_BACKEND_URL: "" + + # === Runtime === + PORT: "3000" + TZ: "UTC" + NODE_ENV: "production" + +# Sensitive environment variables (injected via Secret) secrets: + # === Required === DATABASE_URL: "" REDIS_URL: "" JWT_SECRET: "" + + # === Storage — Cloudflare R2 === + CLOUDFLARE_ACCOUNT_ID: "" + CLOUDFLARE_ACCESS_KEY: "" + CLOUDFLARE_SECRET_ACCESS_KEY: "" + CLOUDFLARE_BUCKETNAME: "" + CLOUDFLARE_BUCKET_URL: "" + + # === Email === + RESEND_API_KEY: "" + EMAIL_USER: "" + EMAIL_PASS: "" + + # === OAuth / OIDC sign-in === + POSTIZ_OAUTH_CLIENT_ID: "" + POSTIZ_OAUTH_CLIENT_SECRET: "" + + # === Social providers === X_API_KEY: "" X_API_SECRET: "" LINKEDIN_CLIENT_ID: "" @@ -106,9 +218,84 @@ secrets: REDDIT_CLIENT_SECRET: "" GITHUB_CLIENT_ID: "" GITHUB_CLIENT_SECRET: "" - RESEND_API_KEY: "" - CLOUDFLARE_ACCOUNT_ID: "" - CLOUDFLARE_ACCESS_KEY: "" - CLOUDFLARE_SECRET_ACCESS_KEY: "" - CLOUDFLARE_BUCKETNAME: "" - CLOUDFLARE_BUCKET_URL: "" + FACEBOOK_APP_ID: "" + FACEBOOK_APP_SECRET: "" + INSTAGRAM_APP_ID: "" + INSTAGRAM_APP_SECRET: "" + THREADS_APP_ID: "" + THREADS_APP_SECRET: "" + YOUTUBE_CLIENT_ID: "" + YOUTUBE_CLIENT_SECRET: "" + GOOGLE_GMB_CLIENT_ID: "" + GOOGLE_GMB_CLIENT_SECRET: "" + TIKTOK_CLIENT_ID: "" + TIKTOK_CLIENT_SECRET: "" + PINTEREST_CLIENT_ID: "" + PINTEREST_CLIENT_SECRET: "" + DRIBBBLE_CLIENT_ID: "" + DRIBBBLE_CLIENT_SECRET: "" + DISCORD_CLIENT_ID: "" + DISCORD_CLIENT_SECRET: "" + DISCORD_BOT_TOKEN_ID: "" + SLACK_ID: "" + SLACK_SECRET: "" + SLACK_SIGNING_SECRET: "" + TELEGRAM_TOKEN: "" + TELEGRAM_BOT_NAME: "" + MASTODON_CLIENT_ID: "" + MASTODON_CLIENT_SECRET: "" + NEYNAR_CLIENT_ID: "" + NEYNAR_SECRET_KEY: "" + MEWE_APP_ID: "" + MEWE_API_KEY: "" + TWITCH_CLIENT_ID: "" + TWITCH_CLIENT_SECRET: "" + KICK_CLIENT_ID: "" + KICK_SECRET: "" + VK_ID: "" + WHOP_CLIENT_ID: "" + BEEHIIVE_API_KEY: "" + BEEHIIVE_PUBLICATION_ID: "" + LISTMONK_DOMAIN: "" + LISTMONK_USER: "" + LISTMONK_API_KEY: "" + LISTMONK_LIST_ID: "" + LISTMONK_WELCOME_TEMPLATE_ID: "" + EXTENSION_ID: "" + + # === AI / Generation === + OPENAI_API_KEY: "" + OPENAI_APP_CHALLANGE: "" + ELEVENSLABS_API_KEY: "" + FAL_KEY: "" + TAVILY_API_KEY: "" + KIEAI_API_KEY: "" + TRANSLOADIT_AUTH: "" + TRANSLOADIT_SECRET: "" + TRANSLOADIT_TEMPLATE: "" + + # === Payments === + STRIPE_PUBLISHABLE_KEY: "" + STRIPE_SECRET_KEY: "" + STRIPE_SIGNING_KEY: "" + STRIPE_SIGNING_KEY_CONNECT: "" + STRIPE_DISCOUNT_ID: "" + NOWPAYMENTS_API_KEY: "" + NOWPAYMENTS_AMOUNT: "" + + # === Analytics secrets === + FACEBOOK_PIXEL_ACCESS_TOKEN: "" + NEXT_PUBLIC_TRACKING_TRIAL: "" + DATAFAST_API_KEY: "" + DATAFAST_WEBSITE_ID: "" + SENTRY_AUTH_TOKEN: "" + + # === MCP / Agent === + AGENT_API_KEY: "" + AGENT_MEDIA_SSO_KEY: "" + + # === Short-link providers === + DUB_TOKEN: "" + SHORT_IO_SECRET_KEY: "" + KUTT_API_KEY: "" + LINK_DRIP_API_KEY: ""