diff --git a/ushahidi/app.yaml b/ushahidi/app.yaml new file mode 100644 index 0000000..a7e5bff --- /dev/null +++ b/ushahidi/app.yaml @@ -0,0 +1,5 @@ +name: ushahidi +is: ushahidi +description: Ushahidi is a crisis mapping and data collection platform that enables communities to collect, visualize, and act on data from multiple sources. +icon: https://www.ushahidi.com/images/logo.svg +latest: "5" diff --git a/ushahidi/versions/5/README.md b/ushahidi/versions/5/README.md new file mode 100644 index 0000000..4a53f85 --- /dev/null +++ b/ushahidi/versions/5/README.md @@ -0,0 +1,35 @@ +# Ushahidi + +Ushahidi is a crisis mapping and crowdsourcing platform for collecting, visualising, and analysing reports from a community. + +## Dependencies + +- **MySQL** - Database for storing posts, surveys, and users +- **Redis** - Used for caching and background job queuing + +## Configuration + +Key settings in `config.yaml`: + +- **domain** - Where the Ushahidi web client will be accessible +- **apiDomain** - Where the Ushahidi API is accessible (default: `ushahidi-api.{your-cloud-domain}`) +- **storage** - Persistent volume size (default: `2Gi`) +- **db.name** - Database name (default: `ushahidi`) + +## First-Time Setup + +1. Add and deploy the app: + ```bash + wild app add ushahidi + wild app deploy ushahidi + ``` + +2. Visit the client URL and complete the setup wizard to create your admin account and configure your deployment. + +3. Start creating surveys and collecting reports from the public. + +## Notes + +- Ushahidi has two components: the **API** (Laravel) and the **Client** (Angular) — both are deployed together and served on separate domains +- The Laravel API has a slow startup (~2 minutes) due to framework initialization — the deployment uses extended liveness probe delays to prevent restart loops +- The `appKey` is auto-generated in `secrets.yaml` and used for Laravel encryption diff --git a/ushahidi/versions/5/db-init-job.yaml b/ushahidi/versions/5/db-init-job.yaml new file mode 100644 index 0000000..b92fe6b --- /dev/null +++ b/ushahidi/versions/5/db-init-job.yaml @@ -0,0 +1,64 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: ushahidi-db-init + labels: + component: db-init +spec: + template: + metadata: + labels: + component: db-init + spec: + restartPolicy: OnFailure + securityContext: + runAsNonRoot: true + runAsUser: 999 + runAsGroup: 999 + seccompProfile: + type: RuntimeDefault + containers: + - name: mysql-init + image: mysql:9.1.0 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: false + env: + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: ushahidi-secrets + key: mysql.rootPassword + - name: DB_HOSTNAME + value: {{ .db.host }} + - name: DB_PORT + value: "{{ .db.port }}" + - name: DB_DATABASE_NAME + value: {{ .db.name }} + - name: DB_USERNAME + value: {{ .db.user }} + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: ushahidi-secrets + key: dbPassword + command: + - /bin/bash + - -c + - | + set -e + until mysql -h ${DB_HOSTNAME} -P ${DB_PORT} -u root -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1" 2>/dev/null; do + echo "Waiting for MySQL..." + sleep 2 + done + mysql -h ${DB_HOSTNAME} -P ${DB_PORT} -u root -p${MYSQL_ROOT_PASSWORD} </dev/null; do + echo "Waiting for MySQL..." + sleep 2 + done + echo "MySQL is ready" + containers: + - name: ushahidi-api + image: ghcr.io/ushahidi/platform:v2025.04.1 + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: APP_ENV + value: production + - name: APP_DEBUG + value: "false" + - name: APP_KEY + valueFrom: + secretKeyRef: + name: ushahidi-secrets + key: appKey + - name: ENABLE_NGINX + value: "true" + - name: ENABLE_PHPFPM + value: "true" + - name: ENABLE_PLATFORM_TASKS + value: "false" + - name: RUN_PLATFORM_MIGRATIONS + value: "true" + - name: DB_MIGRATIONS_HANDLED + value: "true" + - name: DB_CONNECTION + value: mysql + - name: DB_HOST + value: {{ .db.host }} + - name: DB_PORT + value: "{{ .db.port }}" + - name: DB_DATABASE + value: {{ .db.name }} + - name: DB_USERNAME + value: {{ .db.user }} + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: ushahidi-secrets + key: dbPassword + - name: REDIS_HOST + value: {{ .redis.host }} + - name: REDIS_PORT + value: "{{ .redis.port }}" + - name: CACHE_DRIVER + value: redis + - name: QUEUE_DRIVER + value: redis + - name: CLIENT_URL + value: https://{{ .domain }} + - name: HTTP_PORT + value: "8080" + resources: + limits: + cpu: "1" + ephemeral-storage: 1Gi + memory: 512Mi + requests: + cpu: 50m + ephemeral-storage: 100Mi + memory: 256Mi + volumeMounts: + - name: ushahidi-storage + mountPath: /var/www/storage/app/public + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 120 + timeoutSeconds: 10 + periodSeconds: 30 + failureThreshold: 6 + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 60 + timeoutSeconds: 5 + periodSeconds: 15 + failureThreshold: 3 + securityContext: + allowPrivilegeEscalation: true + readOnlyRootFilesystem: false + volumes: + - name: ushahidi-storage + persistentVolumeClaim: + claimName: ushahidi-storage + restartPolicy: Always diff --git a/ushahidi/versions/5/deployment-client.yaml b/ushahidi/versions/5/deployment-client.yaml new file mode 100644 index 0000000..3784d92 --- /dev/null +++ b/ushahidi/versions/5/deployment-client.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ushahidi-client + namespace: ushahidi +spec: + replicas: 1 + selector: + matchLabels: + component: client + template: + metadata: + labels: + component: client + spec: + securityContext: + runAsNonRoot: false + runAsUser: 0 + seccompProfile: + type: RuntimeDefault + containers: + - name: ushahidi-client + image: ushahidi/platform-client:v5.1.0 + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: BACKEND_URL + value: https://{{ .apiDomain }} + resources: + limits: + cpu: 200m + ephemeral-storage: 256Mi + memory: 128Mi + requests: + cpu: 50m + ephemeral-storage: 50Mi + memory: 64Mi + livenessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 15 + timeoutSeconds: 5 + periodSeconds: 30 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 5 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 3 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + add: + - CHOWN + - SETUID + - SETGID + readOnlyRootFilesystem: false + restartPolicy: Always diff --git a/ushahidi/versions/5/deployment-worker.yaml b/ushahidi/versions/5/deployment-worker.yaml new file mode 100644 index 0000000..73ec8c2 --- /dev/null +++ b/ushahidi/versions/5/deployment-worker.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ushahidi-worker + namespace: ushahidi +spec: + replicas: 1 + selector: + matchLabels: + component: worker + template: + metadata: + labels: + component: worker + spec: + securityContext: + runAsUser: 0 + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault + containers: + - name: ushahidi-worker + image: ghcr.io/ushahidi/platform:v2025.04.1 + env: + - name: APP_ENV + value: production + - name: APP_DEBUG + value: "false" + - name: APP_KEY + valueFrom: + secretKeyRef: + name: ushahidi-secrets + key: appKey + - name: ENABLE_NGINX + value: "false" + - name: ENABLE_PHPFPM + value: "false" + - name: ENABLE_PLATFORM_TASKS + value: "true" + - name: ENABLE_QUEUE_LISTEN + value: "true" + - name: TASK_RUN_PERIOD_SECS + value: "30" + - name: RUN_PLATFORM_MIGRATIONS + value: "false" + - name: DB_MIGRATIONS_HANDLED + value: "true" + - name: DB_CONNECTION + value: mysql + - name: DB_HOST + value: {{ .db.host }} + - name: DB_PORT + value: "{{ .db.port }}" + - name: DB_DATABASE + value: {{ .db.name }} + - name: DB_USERNAME + value: {{ .db.user }} + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: ushahidi-secrets + key: dbPassword + - name: REDIS_HOST + value: {{ .redis.host }} + - name: REDIS_PORT + value: "{{ .redis.port }}" + - name: CACHE_DRIVER + value: redis + - name: QUEUE_DRIVER + value: redis + resources: + limits: + cpu: "1" + ephemeral-storage: 1Gi + memory: 512Mi + requests: + cpu: 50m + ephemeral-storage: 100Mi + memory: 128Mi + securityContext: + allowPrivilegeEscalation: true + readOnlyRootFilesystem: false + restartPolicy: Always diff --git a/ushahidi/versions/5/ingress.yaml b/ushahidi/versions/5/ingress.yaml new file mode 100644 index 0000000..f722eda --- /dev/null +++ b/ushahidi/versions/5/ingress.yaml @@ -0,0 +1,57 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ushahidi-client + namespace: ushahidi + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" + external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }} + external-dns.alpha.kubernetes.io/cloudflare-proxied: "false" + external-dns.alpha.kubernetes.io/ttl: "60" +spec: + ingressClassName: traefik + tls: + - hosts: + - {{ .domain }} + secretName: {{ .tlsSecretName }} + rules: + - host: {{ .domain }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ushahidi-client + port: + number: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ushahidi-api + namespace: ushahidi + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" + external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }} + external-dns.alpha.kubernetes.io/cloudflare-proxied: "false" + external-dns.alpha.kubernetes.io/ttl: "60" +spec: + ingressClassName: traefik + tls: + - hosts: + - {{ .apiDomain }} + secretName: {{ .tlsSecretName }} + rules: + - host: {{ .apiDomain }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ushahidi-api + port: + number: 80 diff --git a/ushahidi/versions/5/kustomization.yaml b/ushahidi/versions/5/kustomization.yaml new file mode 100644 index 0000000..1269cf1 --- /dev/null +++ b/ushahidi/versions/5/kustomization.yaml @@ -0,0 +1,18 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: ushahidi +labels: + - includeSelectors: true + pairs: + app: ushahidi + managedBy: kustomize + partOf: wild-cloud +resources: + - namespace.yaml + - db-init-job.yaml + - deployment-api.yaml + - deployment-worker.yaml + - deployment-client.yaml + - service.yaml + - ingress.yaml + - pvc.yaml diff --git a/ushahidi/versions/5/manifest.yaml b/ushahidi/versions/5/manifest.yaml new file mode 100644 index 0000000..491a5d5 --- /dev/null +++ b/ushahidi/versions/5/manifest.yaml @@ -0,0 +1,24 @@ +version: 5.1.0-2 +requires: + - name: mysql + - name: redis +defaultConfig: + namespace: ushahidi + externalDnsDomain: '{{ .cloud.domain }}' + domain: ushahidi.{{ .cloud.domain }} + apiDomain: ushahidi-api.{{ .cloud.domain }} + tlsSecretName: wildcard-wild-cloud-tls + storage: 2Gi + db: + host: '{{ .apps.mysql.host }}' + port: '3306' + name: ushahidi + user: ushahidi + redis: + host: '{{ .apps.redis.host }}' + port: '{{ .apps.redis.port }}' +defaultSecrets: + - key: appKey + - key: dbPassword +requiredSecrets: + - mysql.rootPassword diff --git a/ushahidi/versions/5/namespace.yaml b/ushahidi/versions/5/namespace.yaml new file mode 100644 index 0000000..b7816b8 --- /dev/null +++ b/ushahidi/versions/5/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: "{{ .namespace }}" diff --git a/ushahidi/versions/5/pvc.yaml b/ushahidi/versions/5/pvc.yaml new file mode 100644 index 0000000..4806f8e --- /dev/null +++ b/ushahidi/versions/5/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ushahidi-storage + namespace: ushahidi +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .storage }} diff --git a/ushahidi/versions/5/service.yaml b/ushahidi/versions/5/service.yaml new file mode 100644 index 0000000..ccf0d5b --- /dev/null +++ b/ushahidi/versions/5/service.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: Service +metadata: + name: ushahidi-api + namespace: ushahidi +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + component: api +--- +apiVersion: v1 +kind: Service +metadata: + name: ushahidi-client + namespace: ushahidi +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + component: client