Self-hosted service
ushahidi/platform avatar
ushahidi/platform

ushahidi-platform: the PHP and REST backend behind a citizen reporting map

Ushahidi Platform API version 3+

730 stars510 forksPHPNOASSERTION

At a glance

What is it?
Ushahidi Platform is a PHP web application for collecting reports by SMS, Twitter, RSS and email, then categorising, geolocating and publishing them on a map, and this repository holds the backend with the REST API implementation. It suits activists and civic technology deployments that need to gather reports in the field, and the honest caveat is that the browser app lives in a separate repository and the automatic test suite is marked work in progress.
Who is it for?
Adopt ushahidi-platform if you are running a citizen reporting deployment that needs a documented REST API for submissions and a map view, and you can supply the browser client from the separate platform-client-mzima repository.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 74 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A collection pipeline, not just a map

Ushahidi Platform is an open source web application for information collection, visualisation and interactive mapping. The description in the README gives the specific job: it helps you to collect info from SMS, Twitter, RSS feeds and email, and it helps you to process that information, categorise it, geo-locate it and publish it on a map.

That sequence is the design. Reports arrive through channels that are cheap for someone in the field to use, a text message or a tweet, without needing a form or a network connection, and the platform's job is to turn those into structured, located, categorised items on a map.

The project is worth understanding in its context, because the name refers to a specific kind of deployment. Ushahidi was started in Kenya as a way for citizens to report violence by text message during a period of unrest, and the platform's shape follows from that: it is designed for organisations with no budget for bespoke software and no stable connectivity, run by volunteers or by a small team, with the data ending up somewhere that can be read without any special software.

The repository contains the backend code with the REST API implementation, and the browser app code lives in the Platform Client repository. That split is worth holding on to, because a large part of the product is not here. The README also points at the platform-client-mzima repository for the in-browser Platform experience, and there is a link to Ushahidi Platform v2, the previous generation of the product.

The project is written in PHP, the default branch is develop, the licence is a custom one that GitHub cannot classify, and the last push was on 2026-08-10. The releases are dated versions like v2025.04.0 from 2025-02-14 and v2025.02.0 from 2025-01-16, a calendar versioning scheme rather than a sequence.

Three commands to a running backend

The setup section gives the shortest path, and it is genuinely short.

Install Docker Engine, install the Make command, which parses the Makefile, and run `make start`. The backend will then be listening on localhost:8080.

The Makefile shows what that target expands to. `start` depends on `build`, `up` and `apply`, in that order. `build` copies `.env.dockerinit` to `.env` if the file does not exist, and then runs the compose build. `up` runs the compose up in the background. `apply` in turn depends on `composer-install` and `migrate`.

The Makefile picks its compose command at the top, checking whether `docker compose version` succeeds and falling back to `docker-compose` if it does not, so the same Makefile works with both the plugin and the standalone binary.

The rest of the targets are the everyday operations. `make apply` applies dependency and migration changes to containers without a full container build, and the README notes that this requires the containers to be up. `make start` will restart the containers, doing a full container build in the process. `make stop` stops the Docker containers, and `make down` takes everything down including deleting the database.

For development there is a `debug` target that exports `XDEBUG_MODE=debug,develop` before building and starting, which lines up with the Xdebug installation in the image. There is `logs` to tail the container logs, `enter` to get a shell inside the platform container, and `test` and `test-ci` targets that run the suite inside the container, with the test target exporting `XDEBUG_MODE=coverage`.

One line in the README is worth repeating because it tells you what state the project is in. The automated test running is marked WIP, with a note that it is to run the automated tests.

MariaDB, Redis and a separate worker container

The docker-compose file shows a three-service topology, and the third service is the one that is unusual.

The database is MariaDB 10.11, with a root password, a database and user both named ushahidi, and the server configured for utf8mb4 with the unicode 520 ci collation. It publishes port 33061 to the host, mapped to 3306, which keeps it off the conventional host port.

The cache and queue are Redis 7.2 on the alpine image, with no port published at all, so it is reachable only from inside the compose network.

The `platform` service is the web application, built from the repository's own Dockerfile, publishing 8080 to the host. Its environment is where the interesting configuration sits: `ENABLE_NGINX` and `ENABLE_PHPFPM` are both true, `ENABLE_PLATFORM_TASKS` is false, and `RUN_PLATFORM_MIGRATIONS` is true, so this container runs the migrations at startup. There is also a `DOCKERIZE_WAIT_FOR_mysql` pointing at `tcp://mysql:3306` and a `DOCKERIZE_WAIT_FOR_redis` pointing at `tcp://redis:6379`, which is the mechanism that stops the application starting before its dependencies are up. `CACHE_DRIVER` and `QUEUE_DRIVER` are both `redis`.

The third service, `platform_tasks`, is the same image with the flags inverted. `ENABLE_NGINX` and `ENABLE_PHPFPM` are false, `ENABLE_PLATFORM_TASKS` is true and `ENABLE_QUEUE_LISTEN` is true, and `TASK_RUN_PERIOD_SECS` is 30. `RUN_PLATFORM_MIGRATIONS` is false there, so migrations run once in the web container and not repeatedly from the worker.

That split is the pattern for a Laravel application with queued work: the web container serves requests and the worker container consumes the Redis queue on a schedule. The `extra_hosts` entry mapping `host.docker.internal` to the host gateway is there so a containerised service can reach something on the developer machine.

A PHP 7.4 image with a vendored package and a path repository

The Dockerfile is built on a prebuilt base image, `ushahidi/php-fpm-nginx:php-7.4`, and then layers a fair amount onto it.

Composer is set up with `COMPOSER_ALLOW_SUPERUSER=1` and the image runs `composer self-update --2`, pinning Composer 2. The install is done in two stages, first `composer install --no-autoloader --no-scripts`, then the rest of the source is copied in.

One step in that sequence has a comment that tells a story. Before the install, the Dockerfile copies a `packages` directory into the build context, and the comment says symm/gisconverter is a path-repository package whose upstream was deleted, so its source must be in the build context before composer install can resolve it. That is a path repository pinned to a directory in the tree, and the workaround is that the vendored source is committed alongside the application.

The image also installs PHP development headers and PECL tooling, updates the pecl channel twice, and installs xdebug 3.1.6, then enables it for both the fpm and the cli PHP INI directories with a custom `docker-php-ext-xdebug.ini`. The deb.sury.org keyring is fetched to get the PHP packages for the distribution, and the old key is deleted first with the command allowed to fail.

The runtime configuration at the end of the Dockerfile sets `ENABLE_PLATFORM_TASKS=true`, `DB_MIGRATIONS_HANDLED=true`, `RUN_PLATFORM_MIGRATIONS=true`, a virtual host root of `/var/www/httpdocs` with `index.php` as the index, and a `PHP_EXEC_TIME_LIMIT` of 3600, which is a long execution limit for a job that processes incoming reports. There are also two build arguments, `GIT_COMMIT_ID` and `GIT_BUILD_REF`, baked into the image as environment variables.

Two things in the repository confirm the Laravel structure underneath. There is an `artisan` file at the root and a `server.php`, and the `bootstrap/`, `app/`, `config/`, `database/`, `public/`, `resources/`, `routes/`, `storage/`, `src/` and `tests/` directories are the standard Laravel application skeleton. The `src/` directory alongside `app/` is not standard, and the `.env.example` sets `DEFAULT_CLIENT_URL`, which points at the separate client application.

Configuration that assumes a specific deployment shape

The .env.example file is short and it reveals what the defaults assume.

The Laravel block sets `APP_ENV=local`, `APP_DEBUG=true`, a placeholder application key, and `APP_TIMEZONE=UTC`. The database block sets `DB_CONNECTION=mysql`, a `DB_HOST` of 192.168.33.110, a matching `DB_HOST_REPLICA`, port 3306, database `ushahidi`, user `homestead` and password `secret`, with an empty `DB_SOCKET`. Those are Homestead defaults, the virtual machine addresses that Laravel's own tooling uses, so the example file is written for a local development environment rather than for a real deployment.

The cache and queue are set to memcached and sync respectively, with `REDIS_HOST` and `REDIS_PORT` present but unused by those two settings. The compose file overrides both to redis, so the effective configuration in the Docker path is Redis for both.

Two of the settings point outside the application. `HDX_URL` is set to the Humanitarian Data Exchange test data URL, which is a hint that the platform can pull in reference datasets, and there is a block of Gmail settings with an empty client id, client secret and redirect URI, which is for a mail source.

`MAINTENANCE_MODE=0` is the last line, and it is the only operational toggle in the example file.

The repository carries a Homestead.yml and a Vagrantfile as well, so the older, non-Docker development path is still present alongside the compose setup, and there are separate environment files for deploy, dockerinit and testing. The docker-compose file is version 2 in its declaration, and there is a `packages/` directory at the top level, which is where the vendored path-repository package lives.

A civic technology project with a mixed licensing and funding story

Two things about the project sit outside the code and are worth understanding before you build on it.

The first is the licence. The repository metadata classifies it as Other, a custom licence that GitHub cannot categorise, and the top level carries both a `LICENSE-AGPL` file and a `LICENSE.md`. The presence of an AGPL file alongside another licence file is a common arrangement where the core is AGPL and something else is different, and since the custom notice points at the LICENSE file, that is where the actual terms are.

The second is the funding and support model, which the README is unusually open about. The setup documentation mentions a note for grassroots organizations: if you are starting a deployment for a grassroots organisation, you can apply for a free social-impact responder account after verifying that you meet the criteria. That is a commercial support arrangement from the organisation that runs the project, offered on a means-tested basis.

The technical support path is similarly split. The README says to feel free to file an issue or submit a PR for general cases, and for official support to contact the organisation's own support desk. In other words, community support for general problems, vendor support for a deployment that needs guarantees.

The Makefile itself is worth reading as a summary of the workflow:

bash
start: build up apply

build:
	[ ! -f ./.env ] && cp -p -v ./.env.dockerinit ./.env || true
	$(DOCKER_COMPOSE) build

up:
	$(DOCKER_COMPOSE) up -d

The rest of the repository shows the standards the project works to. There is a CODE_OF_CONDUCT, a PULL_REQUEST_TEMPLATE, a SECURITY.md, a `captainhook.json` for git hooks, a `behat.yml.dist` and `phpspec.yml.dist` and `phpunit.xml.dist` for the three test layers, a `phinx.php` for migrations, an `.all-contributorsrc` and a `docs/contributors-to-ushahidi.md`, and a `.gitbook.yaml` with a `.gitbook/` directory for the documentation site. The `httpdocs/` directory is the document root, the `packages/` directory holds the local Composer packages, and the `docker/` directory has the `utils.sh` and `run.tasks.conf` files the image installs for the worker container.

The project follows the all-contributors specification, and the README asks for contributions of any kind.

Editorial conclusion

Adopt ushahidi-platform if you are running a citizen reporting deployment that needs a documented REST API for submissions and a map view, and you can supply the browser client from the separate platform-client-mzima repository. Do not adopt it as a turnkey product, since the frontend is not in this repository and the automated test suite is still work in progress, and check first that your PHP and MySQL expectations match the images, because the Dockerfile is built on PHP 7.4 with MariaDB 10.11 and Redis 7.2.

Frequently asked questions

What is Ushahidi Platform?

It is an open source web application for information collection, visualisation and interactive mapping. It collects reports from SMS, Twitter, RSS feeds and email, then processes, categorises, geo-locates and publishes them on a map. This repository holds the backend with the REST API implementation.

How do I run the Ushahidi Platform backend?

Install Docker Engine, install the Make command, and run `make start`. The backend will be listening on localhost:8080. The browser client is not in this repository, so you get the platform-client-mzima repository separately for the in-browser experience.

What does make down do to my data?

`make stop` stops the Docker containers, while `make down` takes everything down including deleting the database. `make apply` applies dependency and migration changes to running containers without a full rebuild, and requires the containers to be up.

What services does the Ushahidi docker-compose setup run?

Three: MariaDB 10.11 for the database with a root password and an ushahidi user and database, Redis 7.2 on alpine for the cache and queue, and the platform application itself, which is built from the repository Dockerfile and publishes port 8080 to the host.

What are the platform and platform_tasks containers for?

They are the same image with different flags. The platform container has ENABLE_NGINX and ENABLE_PHPFPM true, ENABLE_PLATFORM_TASKS false and RUN_PLATFORM_MIGRATIONS true, and serves web traffic. The platform_tasks container inverts those, enables ENABLE_QUEUE_LISTEN with TASK_RUN_PERIOD_SECS set to 30, and consumes the Redis queue.

Is Ushahidi Platform still being developed?

The repository is not archived and the last push was on 2026-08-10, with releases v2025.04.0 from 2025-02-14 and v2025.02.0 from 2025-01-16 on a calendar versioning scheme. The licence is a custom one GitHub cannot classify, with both a LICENSE-AGPL and a LICENSE.md in the repository root.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. ushahidi/platform on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ushahidi-platform.svg)](https://hysenlabs.com/projects/ushahidi-platform)

Was this useful?