ERNIE is a metadata curation system for research datasets at GFZ Helmholtz Centre for Geosciences. It supports DataCite Metadata Schema v4.7 for DOI registration, IGSN registration for physical samples, public landing pages for published records, and a search portal for curated datasets.
- DataCite metadata curation for DOI-ready dataset records
- Selective ISO 19115-3:2023 exports
- OAI-PMH harvesting
- IGSN workflows with CSV import and hierarchical sample relationships
- Public landing pages and DOI-oriented publication views
- Search and discovery workflows for published resources
- ORCID, ROR, RAiD, GCMD, SPDX, and MSL integration for enriched metadata
- Role-based access control for editorial and administrative workflows
- Container-first development and validation workflow for consistent local setup
This README documents the Docker-based development workflow only. For deeper setup notes, platform-specific troubleshooting, and the full command matrix, see docs/local-development.md.
- Docker Desktop
- Node.js 26 or newer and npm 10 or newer on the host
- OpenSSL support for generating local certificates
- On Windows, WSL2 is recommended, ideally with VS Code Remote - WSL
- On macOS, Docker Desktop runs on both Apple Silicon and Intel Macs. On Apple Silicon, enable Use Rosetta for x86_64/amd64 emulation under Docker Desktop → Settings → General so images without a native
arm64build still run reliably. - On macOS, the default shell (
zsh) and the bundledopenssl(LibreSSL) work out of the box. If Node.js is not installed yet, the easiest route is Homebrew (brew install node) or a version manager such asnvm.
The Docker-first workflow runs Composer and Laravel Artisan commands inside the app container, so PHP extensions such as bcmath are already available there:
npm run composer:app -- install
npm run artisan -- make:controller TestControllerIf you prefer to run composer install directly on the host, install PHP 8.5 with the required extensions, including bcmath, and verify that the PHP CLI used by Composer sees it.
Linux:
# Fedora
sudo dnf install php-bcmath
# Debian, Ubuntu, or WSL2 with Ubuntu
sudo apt install php-bcmath
php -m | grep -i '^bcmath$'
composer installmacOS with Homebrew PHP:
brew install php
php -m | grep -i '^bcmath$'
composer installIf bcmath is still missing on macOS, check php --ini and make sure your shell is using the Homebrew PHP binary rather than another PHP installation.
Windows:
- With WSL2, run the Debian/Ubuntu commands above inside your WSL shell.
- With native Windows PHP, enable
extension=bcmathin the loadedphp.ini, then verify it from PowerShell:
php --ini
php -m | findstr /I bcmath
composer install-
Clone the repository:
git clone https://github.com/McNamara84/ernie.git cd ernie -
Generate local TLS certificates:
Windows PowerShell:
.\docker\generate-certs.ps1macOS, Linux, WSL, Git Bash, or other POSIX shells:
./docker/generate-certs.sh
If ./docker/generate-certs.sh returns Permission denied, see Common Permission Errors.
On macOS the browser will flag the self-signed certificate on first launch. To trust it system-wide, add it to the system keychain:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain docker/traefik/certs/localhost.crt-
Create the Docker environment file:
Windows PowerShell:
Copy-Item .env.docker.example .env.docker
macOS, Linux, WSL, Git Bash, or other POSIX shells:
cp .env.docker.example .env.docker
The default values work for a standard local setup.
- Install host-side Node dependencies for frontend validation:
npm ci
This installs the local node_modules required by ESLint, TypeScript, Vitest, OpenAPI linting, and Playwright.
- Start the default development stack:
npm run docker:dev:up
The first startup can take a few minutes because Docker may need to build images, install dependencies, run migrations, and seed baseline data.
- Generate the application key:
npm run artisan -- key:generate
The development container normally writes APP_KEY to .env automatically on first boot. If the application reports No application encryption key has been specified (or APP_KEY= in .env is still empty), run this once while the stack is running, then reload the page.
-
Open the application:
- Main URL: https://ernie.localhost:3333
- Traefik dashboard: http://localhost:8080
If
ernie.localhostdoes not resolve on your machine, add127.0.0.1 ernie.localhostto your hosts file. On macOS and Linux this is/etc/hosts, for example:
echo "127.0.0.1 ernie.localhost" | sudo tee -a /etc/hosts
- Create the first administrator account:
npm run artisan -- add-user "Admin Name" admin@example.com SecurePassword
The first user created in a fresh environment becomes an administrator automatically.
- Initialize SPDX license data:
npm run artisan -- spdx:sync-licenses
- Initialize the local MSL Laboratories vocabulary:
npm run artisan -- get-msl-laboratories
This one-time download is required after the feature is first deployed. An administrator can alternatively run the first update from the Thesauri card under Editor Settings. Until it succeeds, MSL Laboratories remains unavailable to ERNIE and ELMO even if its consumer toggles are enabled.
The Docker entrypoints install missing Composer dependencies and container-local npm dependencies, run migrations, and seed baseline data when the database is empty. Host-side frontend commands still require the local npm ci step above.
For day-to-day Laravel commands, use the running app container instead of installing Composer dependencies on the host. For example:
npm run artisan -- make:controller TestControllerMost permission problems happen on the host side before the containers take over, or on Linux bind mounts. The development entrypoint already creates storage/ and bootstrap/cache and runs chown -R www-data:www-data plus chmod -R 775 on every start, so permissions inside the container are handled automatically. The cases below cover the host side.
The script lost its executable bit (common after downloading the repository as a ZIP, or when Git's core.fileMode is disabled). Restore it, or run it through the interpreter:
chmod +x docker/generate-certs.sh
./docker/generate-certs.sh
# alternative without changing the bit
bash docker/generate-certs.sh
PowerShell's execution policy blocks local scripts. Allow them for the current session only (no administrator rights required):
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\docker\generate-certs.ps1
# alternative without changing the policy
powershell -ExecutionPolicy Bypass -File .\docker\generate-certs.ps1
Your user is not in the docker group. This affects Docker Engine on Linux; Docker Desktop users normally do not see it.
sudo usermod -aG docker "$USER"
newgrp docker
Log out and back in (or use newgrp docker) so the membership applies, then start the stack again.
A fresh container start usually fixes this on its own, because the entrypoint re-applies ownership and permissions. If it persists, re-create the stack so the entrypoint runs cleanly:
npm run docker:dev:reset
npm run docker:dev:up
With bind mounts, the container's chown to www-data propagates to the host, so your host user may be unable to edit or delete those files. Reclaim ownership from the repository root:
sudo chown -R "$USER":"$USER" storage bootstrap/cache
This is a Linux bind-mount effect. Docker Desktop on macOS and Windows remaps ownership and generally does not need this step.
Tip: Run the host-side
npmcommands as your normal user, never withsudo. Installing Node.js viasudois a frequent cause of laterEACCESerrors during project dependency installation. If that already happened, reinstall Node.js with a version manager such asnvm(or Homebrew on macOS) so it lives in a user-writable location.
Use the npm wrapper commands whenever possible so Docker Compose and Laravel stay aligned with .env.docker.
Host-side frontend commands in this repository require local node_modules in your checkout.
| Command | Purpose |
|---|---|
npm run docker:dev:up |
Start the default development stack in the foreground |
npm run docker:dev:up:d |
Start the default development stack in the background |
npm run docker:dev:down |
Stop the development stack |
npm run docker:dev:reset |
Stop the stack and remove Docker volumes |
npm run docker:dev:assessment |
Start the stack with the assessment profile, which adds the F-UJI container |
npm run docker:dev:parity |
Start the stack with the parity profile, which currently adds the F-UJI container |
npm run artisan -- <command> |
Run a Laravel Artisan command inside the app container |
npm run composer:app -- <cmd> |
Run Composer inside the app container |
npm run check:backend |
Run optimized 2 GB Pest (parallel) and PHPStan against the Docker backend |
npm run check:frontend |
Run ESLint, OpenAPI linting, TypeScript checks, and one-shot Vitest on the host |
npm run check:parity |
Run the parity validation flow, including the MySQL-sensitive backend slice and Playwright |
For example, create a controller with:
npm run artisan -- make:controller TestControllerERNIE uses a split local validation workflow:
- PHP, Composer, Artisan, Pest, and PHPStan run against the Docker development stack
- ESLint, TypeScript, Vitest, and Playwright run from the host shell
Host-side frontend validation requires local node_modules in the repository checkout. Run npm ci after cloning and whenever package-lock.json changes. Use npm install only when intentionally adding or updating dependencies so npm can update the lockfile.
Recommended validation entry points:
npm run check:backendnpm run check:frontendnpm run check:parity
For the full local testing strategy, focused commands, and MySQL-sensitive test guidance, see docs/testing.md.
- docs/local-development.md for Docker setup details, platform guidance, and troubleshooting
- docs/testing.md for local validation strategy and command recommendations
- resources/data/openapi.json for the OpenAPI specification used by the public API
- Create a branch from
main. - Make your changes using the Docker development workflow described above.
- Run the relevant quality checks before opening a pull request.
- Open a pull request with a clear description of the change.
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later).