A web application to centralize the related tools of your projects, a dynamic connection management with security and data collection.
More technical details can be found in the subdirectories ligoj-api and ligoj-ui.
Cross-browser Testing Platform and Open Source <3 Provided by Sauce Labs
:8080 :8081
Navigateur ──────> ligoj-ui ──────────> ligoj-api ──────> ligoj-db
(Vue 3 SPA) Spring Boot Spring Boot MySQL 8
+ fichiers Vue REST API
+ proxy REST + plugins Java
| Service | Image | Port | Description |
|---|---|---|---|
| ligoj-db | mysql:8.0 |
— | Base de donnees |
| ligoj-api | ligoj/ligoj-api:4.0.1 |
8081 | API REST backend + plugins |
| ligoj-ui | Build local (Dockerfile) | 8080 | Frontend Vue 3 + proxy Spring |
| Couche | Technologie | Version | |
|---|---|---|---|
| Framework UI | Vue.js | 3.5 | Composition API, <script setup> |
| Build | Vite | 6.0 | HMR < 100ms, build < 2s |
| UI Library | Vuetify | 3.7 | Material Design 3 |
| State | Pinia | 2.2 | Stores reactifs |
| Router | Vue Router | 4.5 | Hash mode, guards auth |
| Icons | MDI | 7.4 | 7 000+ icones Material |
| Tests unitaires | Vitest | 4.0 | 141 tests |
| Tests e2e | Playwright | 1.58 | 53 tests |
| Runtime | Java 21 Temurin | 21 | Spring Boot |
| Build Docker | Node 22 + Maven 3.9 | — | Multi-stage |
| Suite | Framework | Tests | Temps |
|---|---|---|---|
| Stores & composables | Vitest | 50 | ~0.1s |
| Plugin system | Vitest | 16 | ~0.1s |
| Plugin formatters | Vitest | 37 | ~0.1s |
| Plugin API & contracts | Vitest | 40 | ~0.1s |
| Views | Vitest | 3 | ~0.1s |
| Unitaires (total) | Vitest | 141 | ~2s |
| End-to-end | Playwright | 53 | ~18s |
| Total | 194 |
| Page | Route | Donnees |
|---|---|---|
| Login | /login.html |
API auth |
| Home page | /#/ |
Cartes de navigation |
| Projects list | /#/home/project |
4 projets (MySQL) |
| Project details | /#/home/project/:id |
Souscriptions |
| Users list | /#/id/user |
API live |
| Groups list | /#/id/group |
API live |
| Companies list | /#/id/company |
API live |
| Delegates | /#/id/delegate |
5 delegations (MySQL) |
| Container Scopes | /#/id/container-scope |
Onglets group/company |
| System info | /#/system/information |
System information |
| Profile | /#/profile |
User profile |
Sans plugin IAM (LDAP/AD), le systeme utilise
feature:iam:empty. Les pages Identity affichent les donnees retournees par l'API (qui peuvent etre vides). Les pages Projects et Delegates utilisent les vraies donnees MySQL.
| Fonctionnalite | Fonctionnalite | ||
|---|---|---|---|
| ✓ | Authentification / Logout | ✓ | Dark mode |
| ✓ | Session persistante | ✓ | Responsive mobile |
| ✓ | Sidebar navigation | ✓ | Breadcrumbs |
| ✓ | Recherche dans les tables | ✓ | Tri des colonnes |
| ✓ | Pagination serveur | ✓ | Import/Export CSV |
| ✓ | Bulk select/delete | ✓ | Form guards (dirty state) |
| ✓ | Gestion d'erreurs (snackbar) | ✓ | Loading skeletons |
| ✓ | i18n FR/EN | ✓ | RBAC (autorisations UI) |
The build is driven by podman compose, a thin wrapper that delegates to an
external provider. By default it prefers docker-compose over podman-compose
when both are installed — which means installing podman-compose alone is not
enough on a machine that already has Docker Compose. Two steps:
# Linux (Fedora/RHEL/Amazon Linux 2023)
sudo dnf install -y podman podman-compose git
# Linux (Debian/Ubuntu)
sudo apt install -y podman python3-pip git && pip install --user podman-compose
# macOS
brew install podman podman-compose git && podman machine init && podman machine startUse a drop-in file rather than editing containers.conf directly — Podman
merges every *.conf it finds under containers.conf.d/, and a drop-in file
can declare its own [engine] section without colliding with one already
present in your main config (TOML rejects duplicate sections per file):
mkdir -p ~/.config/containers/containers.conf.d
cat > ~/.config/containers/containers.conf.d/ligoj-compose.conf <<'EOF'
[engine]
compose_providers = ["podman-compose"]
compose_warning_logs = false
EOFcompose_warning_logs = false silences the >>>> Executing external compose provider <<<< banner.
If you previously appended
[engine]directly to~/.config/containers/containers.confand gotKey 'engine' has already been defined, remove that appended block (and delete any duplicate[engine]section) before creating the drop-in file above.
which podman-compose # → /usr/bin/podman-compose (or similar)
podman compose version | head -n1 # → podman-compose version 1.x.xIf step 3 instead prints Docker Compose version vX.Y.Z (preceded by the
delegation banner), step 2 hasn't taken effect — check containers.conf and
that podman-compose is on PATH.
Why this matters: delegating to docker-compose triggers the warning
"Docker Compose is configured to build using Bake, but buildkit isn't enabled",
makes BUILDAH_FORMAT a no-op, and falls back to the legacy Docker builder
(Sending build context to Docker daemon ...) instead of buildah.
git clone https://github.com/ligoj/ligoj.git && cd ligoj
podman compose -p ligoj -f compose.yml -f compose-override.yml up -d --buildThen open Ligoj Home in your browser.
| Role | Login | Password |
|---|---|---|
| Administrator | ligoj-admin |
ligoj-admin |
| Regular user | ligoj-user |
ligoj-user |
For RBAC security, install: plugin-id, plugin-id-ldap, plugin-id-ldap-embedded.
See Wiki page
See each container ligoj-api and ligoj-ui.
Assumes Prerequisites are installed. Clones the repo, sets up a persistent home, then builds and starts the stack:
sudo systemctl enable --now podman.socket # Linux only, idempotent
git clone https://github.com/ligoj/ligoj.git
cd ligoj
mkdir -p "$(pwd)/.ligoj"
cat > .env <<EOF
LIGOJ_HOME=$(pwd)/.ligoj
PODMAN_USERNS=keep-id
EOF
podman compose -p ligoj -f compose.yml -f compose-override.yml up -d --build
xdg-open http://localhost:8080/ligoj 2>/dev/null || trueAWS_ACCOUNT="$(aws sts get-caller-identity --query "Account" --output text)"
AWS_REGION="$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/\(.*\)[a-z]/\1/')"
ECR_REGISTRY=$AWS_ACCOUNT.dkr.ecr.$AWS_REGION.amazonaws.com
docker image tag ligoj/ligoj-api:4.0.0 $ECR_REGISTRY/ligoj/ligoj-api:4.0.0
docker image tag ligoj/ligoj-ui:4.0.0 $ECR_REGISTRY/ligoj/ligoj-ui:4.0.0
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY
docker push $ECR_REGISTRY/ligoj/ligoj-api:4.0.0
docker push $ECR_REGISTRY/ligoj/ligoj-ui:4.0.0| Variable | Service | Phase | Default | Note |
|---|---|---|---|---|
| LIGOJ_HOME | api | RUN | /home/ligoj |
To map a persistent home |
| LIGOJ_REGISTRY | * | BUILD | To push to your registry. When provided, must ends with /. |
|
| LIGOJ_VERSION | app-* | BUILD | (version of application) | |
| LIGOJ_WEB_PORT | web | RUN | 8080 |
Internal WEB port |
| LIGOJ_PORT | web | RUN | 8080 |
Exposed port |
| LIGOJ_API_JAVA_OPTIONS | api | RUN | -Duser.timezone=UTC |
|
| LIGOJ_WEB_JAVA_OPTIONS | web | RUN | -Duser.timezone=UTC -Dsecurity=Rest |
|
| LIGOJ_API_CRYPTO | api | RUN | -Dapp.crypto.password=public |
Double encryption feature, see core-context-common.xml |
| LIGOJ_WEB_CRYPTO | web | RUN | -Dapp.crypto.password=public |
Double encryption feature, see core-context-common.xml |
| LIGOJ_API_CUSTOM_OPTS | api | RUN | `` | Additional Java properties LIGOJ_API_JAVA_OPTIONS |
| LIGOJ_WEB_CUSTOM_OPTS | web | RUN | `` | Additional Java properties, merged with LIGOJ_WEB_JAVA_OPTIONS |
| LIGOJ_BUILD_PLATFORM | app-* | BUILD | linux/amd64 |
Docker build platform. |
| LIGOJ_TARGET_PLATFORM | app-* | BUILD | linux/amd64 |
Docker run platform. |
| MAVEN_INSECURE_TLS | app-* | BUILD | false |
When true, disables Maven HTTPS cert + hostname validation. See app-api/README. |
| GIT_COMMIT | app-* | BUILD | 0 |
Captured from host git, embedded as ${buildNumber} in the WAR manifest and the git.commit OCI label. See Embedding git provenance. |
| GIT_BRANCH | app-* | BUILD | UNKNOWN_BRANCH |
Captured from host git, embedded as ${scmBranch}. |
| GIT_COMMIT_TIME | app-* | BUILD | 1970-01-01T00:00:00Z |
Captured from host git (ISO-8601), embedded as ${timestamp}. |
Sample .env file:
LIGOJ_HOME=/var/data/ligoj
PODMAN_USERNS=keep-id
LIGOJ_BUILD_PLATFORM=linux/arm64
LIGOJ_TARGET_PLATFORM=linux/arm64
LIGOJ_REGISTRY=nexus.sample.local/
LIGOJ_API_PREPARE_BUILD='export HTTP_PROXY=192.168.0.254:8000 && export HTTPS_PROXY=192.168.0.254:8000'| Source | Service | Destination | Phase | Note |
|---|---|---|---|---|
prepare-build.sh |
app-* | WORKDIR |
BUILD | Additional Bash commands executed inside the builder , before mvn but after MAVEN_OPTS is set. |
prepare-run.sh |
app-* | WORKDIR |
RUN | Additional Bash commands executed inside the final image, before java |
.m2/ |
app-* | /root/.m2/ |
BUILD | Custom Maven configuration: proxy, mirror, dependencies,... |
Minimal prepare-build.sh (HTTP proxy):
export http_proxy=192.168.0.254:8000
export https_proxy=192.168.0.254:8000A more complete sample — importing private/self-signed CA certificates so Maven
trusts an internal mirror — ships as
app-api/prepare-build-sample.sh and
app-ui/prepare-build-sample.sh. Copy the file
to prepare-build.sh to activate it.
The build context sent to the Docker builder is app-api/ / app-ui/ — the
repo's .git/ directory lives at the parent and is therefore invisible to the
builder. Without help, buildnumber-maven-plugin warns and falls back to
buildNumber=0 / scmBranch=UNKNOWN_BRANCH.
Capture the values on the host and pass them through as build args:
export GIT_COMMIT=$(git rev-parse HEAD)
export GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
export GIT_COMMIT_TIME=$(git log -1 --format=%cI)
podman compose -p ligoj -f compose.yml -f compose-override.yml buildcompose.yml interpolates these into build.args, both
Dockerfiles forward them to Maven as
-DbuildNumber=… -DscmBranch=… -Dtimestamp=…, and a profile in each module's
pom.xml activates on the presence of -DbuildNumber=, suppressing the SCM
lookup the plugin would otherwise attempt (this is what silences the
Cannot get the revision information from the scm repository warning).
Local Maven builds (mvn package without -DbuildNumber=…) are unaffected —
the plugin still reads the real .git on disk.
With Docker compose, the Ligoj home directory is persistent and contains:
- plugin installations
- container logs
- database data
mkdir -p "$(pwd)/.ligoj"
cat > .env <<EOF
LIGOJ_HOME=$(pwd)/.ligoj
PODMAN_USERNS=keep-id
EOFcompose.yml defines only the api and ui services. The database is picked
by layering exactly one of these override files on top:
| Database | Override file | Image (default) | Data directory |
|---|---|---|---|
| PostgreSQL (default) | compose-override.yml |
postgres:17 |
$LIGOJ_HOME/postgres |
| MySQL | compose-mysql.yml |
mysql:8.0.36 |
$LIGOJ_HOME/mysql |
Running
podman compose -p ligoj up -dwithout an override file fails on purpose — the DB choice is always explicit. To auto-load the PG override instead, renamecompose-override.ymltocompose.override.yml(the dot form is picked up automatically by Compose).
To avoid repeating the long flag list, define a small alias for your session:
# Tell buildah to emit Docker-format images (OCI is the buildah default and not
# accepted by every downstream registry). No-op if podman delegates to docker.
export BUILDAH_FORMAT=docker
# Pick ONE of these:
alias lc='podman compose -p ligoj -f compose.yml -f compose-override.yml' # PostgreSQL
alias lc='podman compose -p ligoj -f compose.yml -f compose-mysql.yml' # MySQL
lc build # build the images
lc up -d # start the stack
lc logs -f # tail the logs
lc down # stop the stackEach override file uses its own bind-mount directory (see the table above), so
the two databases coexist on disk and swapping back and forth is non-destructive.
The schema is created automatically by Hibernate (-Djpa.hbm2ddl=update) on first
start, so expect a longer first boot.
To start from a clean slate, wipe the matching directory:
rm -rf "${LIGOJ_HOME:-./.ligoj}/postgres" # or .../mysqlAPI is only available from a valid session.
- Swagger UI page
- WADL
Ligoj is massively based on plugin management.
All plugins are deployed in Maven central
To build and deploy a plugin, more information is available in the plugin-api repository.
Ligoj comes with a modular approach. For custom UI, the solutions are:
- Rebuild plugin-ui, with specific assets, and deploy this plugin in a custom Maven repository, or upload it with
/system/plugin/{artifact}/{version}API - Create your own plugin
plugin-ui-company, with your specific assets: overrides and additions. Then install this plugin as the above solution - Copy you specific assets in the Ligoj home directory such as
/home/ligoj/META-INF/resources/webjars,$(pwd)/.ligoj/META-INF/resources/webjars, depending on your runtime. For a sample:# With Ligoj CLI ligoj configuration set --id "ligoj.file.path" --value "^/home/ligoj/META-INF/resources/webjars/.*,^/home/ligoj/statics/themes/.*" ligoj file put --from /path/to/icon.png --path "/home/ligoj/META-INF/resources/webjars/home/img/logo.png" # With local access of Ligoj home folder mkdir -p "${LIGOJ_HOME}/META-INF/resources/webjars/home/img" && cp /path/to/icon.png "$_/logo.png"
SBOM content is exposed thanks to Spring Actuator at this endpoint http://localhost:8080/ligoj/manage/sbom