Deployment¶
The local deployment uses six services:
postgres: PostgreSQL 17 with a persistent named volume;api: Spring Boot application available on port8989locally. The base Compose file does not publish the API port;make docker-upadds the local override that publishes it;backend: static Vite build served by Nginx on port5173.docs: MkDocs site published on port8000.java-site: Maven Site with aggregated Javadocs published on port8083.presentation: Marp presentation published on port8082.
Start the Stack¶
Before starting the API, apply
java/api/src/main/resources/db/manual/task-domains.sql to the target database,
including for a new database. Follow the
migration instructions.
make docker-up
After startup:
- Documentation:
http://localhost:8000 - Java Maven Site:
http://localhost:8083 - Java API documentation:
http://localhost:8083/apidocs/ - Java client Maven Site:
http://localhost:8083/java-client/ - API health:
http://localhost:8989/actuator/health - Swagger UI:
http://localhost:8989/swagger-ui.html - Management console:
http://localhost:5173
The local Compose file supplies a development administrator account and JWT secret. The default console login is admin / admin.
Deployments on platforms such as Dokploy should use docker/compose.yml alone. The API remains available to other Compose services on port 8080, with no host port published. The local development override is docker/compose.local.yml.
Inspect service logs with:
make docker-logs
Stop containers while retaining PostgreSQL data:
make docker-down
Persistence Behavior¶
The API persists tasks, reusable tags, and hierarchical nomenclatures. The Compose volume is named from the project and the declared postgres-data volume; Docker Compose resolves the final volume name automatically.
The API also persists local authentication data in auth_roles, auth_users, and auth_user_roles. At startup it seeds the ANONYMOUS, ADMIN, and USER roles, then forces the administrator account from APP_ADMIN_USERNAME and APP_ADMIN_PASSWORD. If that username already exists, the account is enabled, its password hash is replaced from the environment value, and the ADMIN role is guaranteed.
Hibernate uses ddl-auto: update, but automatic schema updates do not replace
the task-domain migration, migrate legacy business data, or remove obsolete
schema objects. A volume created by an earlier version may retain
domain_templates or domain_records. The older
chat-auditing-soft-delete.sql migration remains legacy documentation
for the former schema; use task-domains.sql for this application version.
Reset the Demo Database¶
Reset the volume when you want to remove all demo data and obsolete tables. This operation is destructive.
docker compose -f docker/compose.yml -f docker/compose.local.yml down --volumes
docker compose -f docker/compose.yml -f docker/compose.local.yml up -d postgres
After PostgreSQL is ready, apply the task-domain migration using the database
connection settings, then run make docker-up to start the full stack. A reset
removes all task, taxonomy, authentication, and settings data; it is not an
upgrade procedure.
Build Documentation and Slides¶
The Java site image runs mvn site on the parent Maven project, which includes
both api and java-client. Keep both modules listed in java/pom.xml so their
site directories are generated before Docker copies them into the Nginx image.
To rebuild only the Java site:
docker compose -f docker/compose.yml build java-site
make docs-build
make presentation-build
The host commands make docs-build and make docs-serve use the lightweight
docs/mkdocs.yml configuration with MkDocs Material. Both read docs/src and
write generated output to site_output.
The Docker documentation service uses
ghcr.io/tiogars/mkdocs-docker-image:latest with the richer
docs/mkdocs/mkdocs.yml configuration, including PDF generation. The full docs
directory is mounted read-only at /server/docs so the configuration, hooks,
assets, overrides, templates, and Markdown sources are all available.
site_output is mounted separately at /server/site_output for generated files.
The server watches both the sources and the configuration directory.
Restart only the documentation service after changing its Compose configuration:
make docker-up-docs
To build HTML and PDF output with the image's bundled plugins:
docker compose -f docker/compose.yml run --rm --no-deps docs build --config-file docs/mkdocs/mkdocs.yml --strict
MKDOCS_CONFIG overrides the server configuration path inside the container.
Use a path under the mounted tree, such as docs/mkdocs/mkdocs.yml, rather than
a host path or ../docs/....
Publish the Flutter Applications¶
The backend image also serves the Flutter application builds and a public
download page at http://localhost:5173/downloads (linked from the login page
and the console menu). Files are served from /releases/, described by
/releases/manifest.json (version, size, SHA-256, default API URL).
The backend image copies whatever is present in docker/flutter-artifacts
(one sub-directory per platform). Populate it, then rebuild the backend:
# Android APK + Linux x64 archive, built in a Linux container
make flutter-docker-build API_BASE_URL=https://api.example.com
# Windows x64 archive: Flutter cannot cross-compile Windows from Linux, so either
make flutter-docker-build-windows API_BASE_URL=https://api.example.com # Docker in Windows containers mode
make flutter-package-windows API_BASE_URL=https://api.example.com # or on a Windows host with Flutter
make docker-up-backend
API_BASE_URL is compiled into the applications with
--dart-define=API_BASE_URL=... and becomes the default server shown in the
application settings; users can still change it. The flutter-deploy-*
targets accept the same variable. Missing platforms are shown as unavailable
on the download page.
Android release builds block clear-text HTTP traffic: use an HTTPS API URL for
the APK. The APK is signed with the debug key until a release signing
configuration is added to flutter/application/android/app/build.gradle.kts.
Production Considerations¶
Keep the API, database, console, and documentation as independently deployable units. Replace ddl-auto: update with versioned migrations, provide managed PostgreSQL credentials through secrets, terminate TLS at the platform edge, and set the console API base URL to the public API origin.
Provide these security variables through the deployment secret store:
| Variable | Required | Purpose |
|---|---|---|
APP_ADMIN_USERNAME |
Yes | Forced administrator username. |
APP_ADMIN_PASSWORD |
Yes | Forced administrator password, stored only as a BCrypt hash. |
APP_JWT_SECRET |
Yes | JWT HMAC signing secret, at least 32 characters. |
APP_JWT_EXPIRATION_SECONDS |
No | Access token lifetime; defaults to 3600 seconds. |