From 75b5e578460d5f70807f21d04507b276d19a4a3c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:45:11 +0000 Subject: [PATCH] Add Bahmni Lite community container with caddy/fail2ban integration Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com> Agent-Logs-Url: https://github.com/nextcloud/all-in-one/sessions/729f8a52-a9df-49b9-b95f-20103c416d52 --- .../bahmni-lite/bahmni-lite.json | 451 ++++++++++++++++++ community-containers/bahmni-lite/readme.md | 39 ++ php/containers-schema.json | 2 +- 3 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 community-containers/bahmni-lite/bahmni-lite.json create mode 100644 community-containers/bahmni-lite/readme.md diff --git a/community-containers/bahmni-lite/bahmni-lite.json b/community-containers/bahmni-lite/bahmni-lite.json new file mode 100644 index 00000000..542b5c67 --- /dev/null +++ b/community-containers/bahmni-lite/bahmni-lite.json @@ -0,0 +1,451 @@ +{ + "aio_services_v1": [ + { + "container_name": "nextcloud-aio-bahmni-openmrs", + "display_name": "Bahmni Lite", + "documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/bahmni-lite", + "image": "bahmni/openmrs", + "image_tag": "latest", + "internal_port": "8080", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "OMRS_DB_NAME=openmrs", + "OMRS_DB_HOSTNAME=nextcloud-aio-bahmni-openmrsdb", + "OMRS_DB_USERNAME=openmrs-user", + "OMRS_DB_PASSWORD=%BAHMNI_OPENMRS_DB_PASSWORD%", + "OMRS_CREATE_TABLES=false", + "OMRS_AUTO_UPDATE_DATABASE=true", + "OMRS_MODULE_WEB_ADMIN=false", + "OMRS_JAVA_SERVER_OPTS=", + "OMRS_JAVA_MEMORY_OPTS=", + "SEND_MAIL=false", + "MAIL_TRANSPORT_PROTOCOL=smtps", + "MAIL_SMTP_AUTH=true", + "MAIL_SMTP_STARTTLS_ENABLE=true", + "MAIL_SMTP_SSL_ENABLE=true", + "MAIL_DEBUG=false", + "MAIL_FROM=", + "MAIL_USER=", + "MAIL_PASSWORD=", + "MAIL_SMTP_HOST=", + "MAIL_SMTP_PORT=", + "OMRS_DOCKER_ENV=true", + "OMRS_C3P0_MAX_SIZE=50", + "LUCENE_MATCH_TYPE=START", + "DOCUMENT_MAX_SIZE_MB=7", + "WEIGHT_CONCEPT_UUID=5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "HEIGHT_CONCEPT_UUID=5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + ], + "secrets": [ + "BAHMNI_OPENMRS_DB_PASSWORD" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_config", + "destination": "/etc/bahmni_config/", + "writeable": false + }, + { + "source": "nextcloud_aio_bahmni_lab_results", + "destination": "/home/bahmni/uploaded_results", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_uploaded_files", + "destination": "/home/bahmni/uploaded-files", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_patient_images", + "destination": "/home/bahmni/patient_images", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_document_images", + "destination": "/home/bahmni/document_images", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_clinical_forms", + "destination": "/home/bahmni/clinical_forms", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_configuration_checksums", + "destination": "/openmrs/data/configuration_checksums", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_patient_images", + "nextcloud_aio_bahmni_document_images", + "nextcloud_aio_bahmni_clinical_forms", + "nextcloud_aio_bahmni_lab_results", + "nextcloud_aio_bahmni_uploaded_files", + "nextcloud_aio_bahmni_configuration_checksums" + ], + "depends_on": [ + "nextcloud-aio-bahmni-openmrsdb", + "nextcloud-aio-bahmni-config" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-openmrsdb", + "image": "bahmni/openmrs-db", + "image_tag": "1.0.0-lite-mysql5.6", + "internal_port": "3306", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "MYSQL_ROOT_PASSWORD=%BAHMNI_MYSQL_ROOT_PASSWORD%", + "MYSQL_DATABASE=openmrs", + "MYSQL_USER=openmrs-user", + "MYSQL_PASSWORD=%BAHMNI_OPENMRS_DB_PASSWORD%" + ], + "secrets": [ + "BAHMNI_MYSQL_ROOT_PASSWORD", + "BAHMNI_OPENMRS_DB_PASSWORD" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_openmrsdb", + "destination": "/var/lib/mysql", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_configuration_checksums", + "destination": "/configuration_checksums", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_openmrsdb" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-config", + "image": "bahmni/clinic-config", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_config", + "destination": "/usr/local/bahmni_config", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_config" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-web", + "image": "bahmni/bahmni-web", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_config", + "destination": "/usr/local/apache2/htdocs/bahmni_config/", + "writeable": false + } + ], + "depends_on": [ + "nextcloud-aio-bahmni-openmrs" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-apps-frontend", + "image": "bahmni/bahmni-apps-frontend", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-lab", + "image": "bahmni/bahmni-lab", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-implementer-interface", + "image": "bahmni/implementer-interface", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ], + "depends_on": [ + "nextcloud-aio-bahmni-openmrs" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-reportsdb", + "image": "mysql", + "image_tag": "8.0", + "internal_port": "3306", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "MYSQL_ROOT_PASSWORD=%BAHMNI_MYSQL_ROOT_PASSWORD%", + "MYSQL_DATABASE=bahmni-reports", + "MYSQL_USER=reports-user", + "MYSQL_PASSWORD=%BAHMNI_REPORTS_DB_PASSWORD%" + ], + "secrets": [ + "BAHMNI_REPORTS_DB_PASSWORD" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_reportsdb", + "destination": "/var/lib/mysql", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_reportsdb" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-reports", + "image": "bahmni/reports", + "image_tag": "latest", + "internal_port": "8080", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "OPENMRS_DB_HOST=nextcloud-aio-bahmni-openmrsdb", + "OPENMRS_DB_NAME=openmrs", + "OPENMRS_DB_USERNAME=openmrs-user", + "OPENMRS_DB_PASSWORD=%BAHMNI_OPENMRS_DB_PASSWORD%", + "OPENMRS_HOST=nextcloud-aio-bahmni-openmrs", + "OPENMRS_PORT=8080", + "REPORTS_DB_SERVER=nextcloud-aio-bahmni-reportsdb", + "REPORTS_DB_NAME=bahmni-reports", + "REPORTS_DB_USERNAME=reports-user", + "REPORTS_DB_PASSWORD=%BAHMNI_REPORTS_DB_PASSWORD%" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_config", + "destination": "/etc/bahmni_config/", + "writeable": false + }, + { + "source": "nextcloud_aio_bahmni_queued_reports", + "destination": "/home/bahmni/reports", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_queued_reports" + ], + "depends_on": [ + "nextcloud-aio-bahmni-reportsdb", + "nextcloud-aio-bahmni-openmrs" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-patient-documents", + "image": "bahmni/patient-documents", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "OPENMRS_HOST=nextcloud-aio-bahmni-openmrs" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_document_images", + "destination": "/usr/share/nginx/html/document_images", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_lab_results", + "destination": "/usr/share/nginx/html/uploaded_results", + "writeable": true + }, + { + "source": "nextcloud_aio_bahmni_uploaded_files", + "destination": "/usr/share/nginx/html/uploaded-files", + "writeable": true + } + ], + "depends_on": [ + "nextcloud-aio-bahmni-openmrs" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-appointments", + "image": "bahmni/appointments", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-craterdb", + "image": "mysql", + "image_tag": "8.0", + "internal_port": "3306", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "MYSQL_ROOT_PASSWORD=%BAHMNI_MYSQL_ROOT_PASSWORD%", + "MYSQL_DATABASE=crater", + "MYSQL_USER=crater", + "MYSQL_PASSWORD=%BAHMNI_CRATER_DB_PASSWORD%" + ], + "secrets": [ + "BAHMNI_CRATER_DB_PASSWORD" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_craterdb", + "destination": "/var/lib/mysql", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_craterdb" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-crater-php", + "image": "bahmni/crater-php", + "image_tag": "latest", + "internal_port": "9000", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "APP_URL=http://nextcloud-aio-bahmni-crater-nginx", + "DB_HOST=nextcloud-aio-bahmni-craterdb", + "DB_PORT=3306", + "DB_DATABASE=crater", + "DB_USERNAME=crater", + "DB_PASSWORD=%BAHMNI_CRATER_DB_PASSWORD%", + "SANCTUM_STATEFUL_DOMAINS=nextcloud-aio-bahmni-crater-nginx", + "SESSION_DOMAIN=nextcloud-aio-bahmni-crater-nginx", + "AUTO_INSTALL=true", + "ADMIN_NAME=Super Admin", + "ADMIN_EMAIL=admin@bahmni.org", + "ADMIN_PASSWORD=%BAHMNI_CRATER_ADMIN_PASSWORD%", + "COMPANY_NAME=Bahmni", + "COMPANY_SLUG=bahmni", + "COUNTRY_ID=101", + "CRATER_DEFAULT_CURRENCY=USD", + "APP_DEBUG=false" + ], + "secrets": [ + "BAHMNI_CRATER_ADMIN_PASSWORD" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_crater_app", + "destination": "/var/www/storage/app/public", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_crater_app" + ], + "depends_on": [ + "nextcloud-aio-bahmni-craterdb" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-crater-nginx", + "image": "bahmni/crater-nginx", + "image_tag": "latest", + "internal_port": "80", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_crater_app", + "destination": "/var/www/public/storage", + "writeable": true + } + ], + "depends_on": [ + "nextcloud-aio-bahmni-crater-php" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-crater-atomfeed-db", + "image": "mysql", + "image_tag": "8.0", + "internal_port": "3306", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "MYSQL_ROOT_PASSWORD=%BAHMNI_MYSQL_ROOT_PASSWORD%", + "MYSQL_DATABASE=crater-atomfeed", + "MYSQL_USER=crater-atomfeed-user", + "MYSQL_PASSWORD=%BAHMNI_CRATER_ATOMFEED_DB_PASSWORD%" + ], + "secrets": [ + "BAHMNI_CRATER_ATOMFEED_DB_PASSWORD" + ], + "volumes": [ + { + "source": "nextcloud_aio_bahmni_crater_atomfeed_db", + "destination": "/var/lib/mysql", + "writeable": true + } + ], + "backup_volumes": [ + "nextcloud_aio_bahmni_crater_atomfeed_db" + ] + }, + { + "container_name": "nextcloud-aio-bahmni-crater-atomfeed", + "image": "bahmni/crater-atomfeed", + "image_tag": "latest", + "internal_port": "8080", + "restart": "unless-stopped", + "environment": [ + "TZ=%TIMEZONE%", + "OPENMRS_HOST=nextcloud-aio-bahmni-openmrs", + "OPENMRS_PORT=8080", + "OPENMRS_ATOMFEED_USER=admin", + "OPENMRS_ATOMFEED_PASSWORD=Admin123", + "CRATER_ATOMFEED_DB_HOST=nextcloud-aio-bahmni-crater-atomfeed-db", + "CRATER_ATOMFEED_DB_PORT=3306", + "CRATER_USERNAME=admin@bahmni.org", + "CRATER_PASSWORD=%BAHMNI_CRATER_ADMIN_PASSWORD%", + "CRATER_ATOMFEED_DB_USERNAME=crater-atomfeed-user", + "CRATER_ATOMFEED_DB_PASSWORD=%BAHMNI_CRATER_ATOMFEED_DB_PASSWORD%", + "CRATER_ATOMFEED_DB_NAME=crater-atomfeed", + "CRATER_URL=http://nextcloud-aio-bahmni-crater-nginx" + ], + "depends_on": [ + "nextcloud-aio-bahmni-openmrs", + "nextcloud-aio-bahmni-crater-nginx", + "nextcloud-aio-bahmni-crater-atomfeed-db" + ] + } + ] +} diff --git a/community-containers/bahmni-lite/readme.md b/community-containers/bahmni-lite/readme.md new file mode 100644 index 00000000..475d682f --- /dev/null +++ b/community-containers/bahmni-lite/readme.md @@ -0,0 +1,39 @@ +## Bahmni Lite +This container bundle sets up [Bahmni Lite](https://www.bahmni.org/), an open-source Electronic Medical Record (EMR) and hospital management system, and auto-configures it for you. + +Bahmni Lite includes the following services: +- **OpenMRS** – core EMR application +- **OpenMRS Database** – pre-seeded MySQL database (Bahmni Lite schema) +- **Bahmni Config** – clinic configuration (init container) +- **Bahmni Web** – classic Bahmni EMR frontend (AngularJS) +- **Bahmni Apps Frontend** – new React-based Bahmni frontend +- **Bahmni Lab** – lab results module +- **Implementer Interface** – form/concept builder +- **Reports** + **Reports DB** – reporting service and its database +- **Patient Documents** – document storage and serving +- **Appointments** – appointments module +- **Crater** (PHP + Nginx + DB) – billing/invoicing system +- **Crater Atomfeed** + **Crater Atomfeed DB** – OpenMRS ↔ Crater sync service + +### Notes +- You need to configure a reverse proxy in order to use this container bundle, since Bahmni needs a dedicated (sub)domain! For that, you might have a look at https://github.com/nextcloud/all-in-one/tree/main/community-containers/caddy or follow https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md. You need to point the reverse proxy at `nextcloud-aio-bahmni-openmrs:8080` for the core Bahmni/OpenMRS application. +- The core Bahmni EMR is accessible at `/openmrs/` on the OpenMRS container (`nextcloud-aio-bahmni-openmrs`, port `8080`). After starting, visit `http:///openmrs/` and log in with the default credentials: username `admin`, password `Admin123`. **⚠️ Change the default OpenMRS admin password immediately after first login.** The Bahmni database image ships with this well-known default — leaving it in place is a serious security risk. Note: after changing the OpenMRS admin password, you must also update `OPENMRS_ATOMFEED_PASSWORD` in the `nextcloud-aio-bahmni-crater-atomfeed` container to match the new password, otherwise the Crater billing sync will stop working. +- For the full Bahmni UI experience (Bahmni Web, Bahmni Apps Frontend etc.), a reverse proxy must be set up to route the following paths to the correct containers: + - `/openmrs/` → `nextcloud-aio-bahmni-openmrs:8080` + - `/bahmni/` → `nextcloud-aio-bahmni-web:80` + - `/bahmni-new/` → `nextcloud-aio-bahmni-apps-frontend:80` + - `/bahmni-lab/` → `nextcloud-aio-bahmni-lab:80` + - `/implementer-interface/` → `nextcloud-aio-bahmni-implementer-interface:80` + - `/document_images/`, `/uploaded_results/`, `/uploaded-files/` → `nextcloud-aio-bahmni-patient-documents:80` + - `/appointments/` → `nextcloud-aio-bahmni-appointments:80` + - `/reports/` → `nextcloud-aio-bahmni-reports:8080` +- The Crater billing system can be reached at `nextcloud-aio-bahmni-crater-nginx:80`. The Crater admin email is `admin@bahmni.org` and the password is shown next to the container in the AIO interface. +- All Bahmni data (patient images, documents, clinical forms, databases) will be automatically included in AIOs backup solution! +- This container bundle requires significant system resources. A minimum of **4 GB RAM** and **2 CPU cores** is recommended; **8 GB RAM** is preferred for production use. +- See https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers how to add it to the AIO stack. + +### Repository +https://github.com/Bahmni/bahmni-docker + +### Maintainer +https://github.com/Bahmni diff --git a/php/containers-schema.json b/php/containers-schema.json index fc0e03dc..b5efff4a 100644 --- a/php/containers-schema.json +++ b/php/containers-schema.json @@ -216,7 +216,7 @@ "properties": { "destination": { "type": "string", - "pattern": "^((/[a-z_/.-]+)|(%[A-Z_]+%))$" + "pattern": "^((/[a-z0-9_/.-]+)|(%[A-Z_]+%))$" }, "source": { "type": "string",