Environment variables
All configuration can be supplied as environment variables. Spring Boot maps uppercase, underscore-separated env var names to the dot-notation keys in application.yml automatically.
| Environment Variable | Default Value | Description |
|---|---|---|
SPRING_DATASOURCE_URL |
jdbc:postgresql://localhost:5432/open_task_hub |
JDBC connection URL for the PostgreSQL database. |
SPRING_DATASOURCE_USERNAME |
forge |
PostgreSQL database username. |
SPRING_DATASOURCE_PASSWORD |
forge |
PostgreSQL database password. |
SERVER_PORT |
8080 |
HTTP port the application listens on. |
OPEN_TASK_HUB_BOOTSTRAP_ADMIN_PASSWORD |
admin123 |
Password for the built-in admin account created on first startup. |
OPEN_TASK_HUB_BOOTSTRAP_USER_PASSWORD |
robert123 |
Password for the built-in robert user account created on first startup. |
application.yml reference
The complete application.yml showing all configurable properties with their defaults:
spring:
datasource:
url: ${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/open_task_hub}
username: ${SPRING_DATASOURCE_USERNAME:forge}
password: ${SPRING_DATASOURCE_PASSWORD:forge}
driver-class-name: org.postgresql.Driver
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: false
jpa:
hibernate:
ddl-auto: validate
show-sql: false
open-in-view: false
thymeleaf:
cache: false # set to true in production
encoding: UTF-8
server:
port: ${SERVER_PORT:8080}
error:
include-message: never
include-stacktrace: never
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: when-authorized
open-task-hub:
bootstrap:
admin-password: ${OPEN_TASK_HUB_BOOTSTRAP_ADMIN_PASSWORD:admin123}
user-password: ${OPEN_TASK_HUB_BOOTSTRAP_USER_PASSWORD:robert123}
Database settings
Open Task Hub requires PostgreSQL 14 or later. The connection pool is managed by HikariCP (Spring Boot default). The schema is managed entirely by Flyway — migration scripts live in src/main/resources/db/migration/.
Flyway migrations
Flyway runs automatically on startup. Migrations are versioned SQL files (e.g. V1__init.sql, V2__add_labels.sql). Never edit a migration that has already been applied — add a new migration instead.
Connection pool tuning
For high-traffic deployments, tune the HikariCP pool size:
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000 # ms
idle-timeout: 600000 # ms
max-lifetime: 1800000 # ms
Bootstrap accounts
On first startup (when no users exist in the database), Open Task Hub creates two accounts automatically:
| Username | Role | Password env var | Default password |
|---|---|---|---|
admin |
ADMIN | OPEN_TASK_HUB_BOOTSTRAP_ADMIN_PASSWORD |
admin123 |
robert |
USER | OPEN_TASK_HUB_BOOTSTRAP_USER_PASSWORD |
robert123 |
Disabling bootstrap
If you manage users externally (LDAP, SSO, etc.), you can pre-populate the users table yourself before startup and the bootstrap step will be skipped automatically.
Server settings
Changing the port
export SERVER_PORT=9090 ./gradlew bootRun
Running behind a reverse proxy
When running behind Nginx or Apache, add the following to pass the correct remote address and protocol:
server: forward-headers-strategy: framework
HTTPS / TLS
For TLS termination, the recommended approach is to use a reverse proxy (Nginx, Caddy, Traefik) in front of Open Task Hub rather than configuring TLS in Spring Boot directly. Example Nginx configuration:
server {
listen 443 ssl;
server_name taskhub.example.com;
ssl_certificate /etc/ssl/certs/your-cert.pem;
ssl_certificate_key /etc/ssl/private/your-key.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Spring Actuator endpoints
Open Task Hub exposes Spring Boot Actuator endpoints under /actuator for operational monitoring. By default, only health, info, and metrics are exposed over HTTP.
| Endpoint | URL | Description |
|---|---|---|
health |
/actuator/health |
Application and database health status. Returns UP or DOWN with component details for authenticated users. |
info |
/actuator/info |
Application version and build information. |
metrics |
/actuator/metrics |
JVM and application metrics. Enumerate available metrics at /actuator/metrics, fetch individual metric at /actuator/metrics/{name}. |
Health check example
curl -u admin:admin123 \ http://localhost:8080/actuator/health # Response: { "status": "UP", "components": { "db": { "status": "UP", "details": { "database": "PostgreSQL" } }, "diskSpace": { "status": "UP" }, "ping": { "status": "UP" } } }
Exposing additional endpoints
To expose more actuator endpoints (e.g. for monitoring systems like Prometheus), edit application.yml:
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus,env,beans
env, beans, and threaddump can expose internal application state. Restrict them to localhost or behind a secure admin network.
Security
Open Task Hub uses Spring Security with two parallel authentication mechanisms, configured to coexist seamlessly.
Form Login
Used by the Thymeleaf web UI. Browsers POST to /login and receive a session cookie. A CSRF token is required for all state-changing requests from the browser.
- Login page:
GET /login - Process login:
POST /login - Logout:
POST /logout - Default redirect after login:
/dashboard
HTTP Basic (API)
Used by REST API clients. Send the Authorization: Basic <base64(user:pass)> header with every request. No session is created.
- No cookies or CSRF needed
- Stateless — each request is independently authenticated
- Works on all
/api/**paths - Also works on web UI paths (for automated testing)
Password storage
All passwords are hashed using BCrypt before storage. The raw password is never persisted. Spring Security's PasswordEncoder handles encoding and verification.
Session configuration
Browser sessions are stored server-side in memory by default. For clustered deployments, configure Spring Session with Redis or JDBC to share sessions across instances:
spring:
session:
store-type: redis # or 'jdbc'
redis:
host: localhost
port: 6379
Role-based access
| Role | Description | Access level |
|---|---|---|
| ADMIN | System administrator | Unrestricted access to all projects, members, settings, and actuator endpoints. |
| USER | Regular user | Access controlled by project membership and role (OWNER / MEMBER / VIEWER). |
Production checklist
Before deploying Open Task Hub to a production environment, work through this checklist:
Set strong values for OPEN_TASK_HUB_BOOTSTRAP_ADMIN_PASSWORD and OPEN_TASK_HUB_BOOTSTRAP_USER_PASSWORD before first startup.
Terminate TLS at a reverse proxy (Nginx, Caddy) and set server.forward-headers-strategy=framework.
Create a dedicated PostgreSQL user with CONNECT, SELECT, INSERT, UPDATE, DELETE on open_task_hub only — not a superuser.
Set spring.thymeleaf.cache=true to avoid re-parsing templates on every request.
Expose only health publicly. Restrict metrics and other endpoints to admin users or a private network.
Use pg_dump or a managed database service backup feature. Test restores periodically.
The default config already sets server.error.include-message=never and include-stacktrace=never. Do not change this.
SPRING_DATASOURCE_URL=jdbc:postgresql://db.internal:5432/open_task_hub \ SPRING_DATASOURCE_USERNAME=oth_prod \ SPRING_DATASOURCE_PASSWORD='<strong-db-password>' \ SERVER_PORT=8080 \ OPEN_TASK_HUB_BOOTSTRAP_ADMIN_PASSWORD='<strong-admin-password>' \ OPEN_TASK_HUB_BOOTSTRAP_USER_PASSWORD='<strong-user-password>' \ java -Dspring.thymeleaf.cache=true \ -jar open-task-hub.jar