add APPLICATION_PROPERTIES env var for Spring Boot runtime tuning#762
add APPLICATION_PROPERTIES env var for Spring Boot runtime tuning#762WMP wants to merge 1 commit intombentley:masterfrom
Conversation
The Omada Controller (v5.x+) is built on Spring Boot. Its classpath includes /opt/tplink/EAPController/properties, so Spring Boot will automatically load an application.properties file placed there. inject_application_properties() writes the content of APPLICATION_PROPERTIES to that file before the JVM starts, enabling users to tune Spring Boot internals (Tomcat thread pool, async executors, logging) without rebuilding the image or overriding the CMD. - No-op when APPLICATION_PROPERTIES is unset - File is written as root before gosu switch; compatible with rootless mode - Does not affect omada.properties (separate file, separate purpose) - Adds docs/spring-boot-tuning.md with recommended settings and examples Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
I will take a look at this when I have time to properly review it, hopefully tomorrow. |
| The `APPLICATION_PROPERTIES` environment variable allows you to inject arbitrary Spring Boot properties | ||
| into the controller without rebuilding the image or overriding the `CMD`. | ||
|
|
||
| > **Disclaimer**: This is an unofficial tuning mechanism. TP-Link does not document or guarantee which |
There was a problem hiding this comment.
Could you use one of the Blockquote styles for this disclaimer to bring more attention to this statement?
|
|
||
| PROPS_FILE="/opt/tplink/EAPController/properties/application.properties" | ||
| echo "INFO: APPLICATION_PROPERTIES set; writing Spring Boot properties to ${PROPS_FILE}" | ||
| printf '%s\n' "${APPLICATION_PROPERTIES}" > "${PROPS_FILE}" |
There was a problem hiding this comment.
In non-rootless mode, the script runs as root at this point and gosu only executes at the very end. Double check my logic but the file is created owned by root:root with mode 640. The omada controller process (launched via exec gosu "${PUSERNAME}") is not in the root group, so it cannot read the file. Spring Boot will silently finds no application.properties and the feature does nothing.
So if I am right, the fix that would be easiest would probably be to add the same chown in inject_application_properties(), guarded for rootless.
| @@ -0,0 +1,190 @@ | |||
| # Spring Boot Tuning | |||
There was a problem hiding this comment.
Instead of putting this in a separate docs/ directory, could we just move this to the root of the project? I know it's starting to get a bit unorganized but that might be a future me problem to address properly.
Problem
The Omada Controller v5.x+ is built on Spring Boot with an embedded Tomcat server. Its default configuration allocates large thread pools (Tomcat max 200 threads, unbounded async executor) that are sized for general use — not for memory-constrained environments like Raspberry Pi, small VMs, or Kubernetes pods with tight resource limits. There was no way to tune these without rebuilding the image.
Key observation
The startup classpath is
-cp ".../lib/*:.../properties". Spring Boot automatically loadsapplication.propertiesfrom the classpath root. Theproperties/directory does not currently contain anapplication.propertiesfile, so adding one introduces no conflicts.Solution
A new
APPLICATION_PROPERTIESenvironment variable. Its content is written verbatim to/opt/tplink/EAPController/properties/application.propertiesat startup (before the JVM launches), picked up automatically by Spring Boot.What you can tune:
server.tomcat.threads.max/min-spare— HTTP worker thread poolspring.task.execution.pool.*— async@Asynctask executorspring.task.scheduling.pool.size—@Scheduledtask poollogging.level.*— log verbosityExample (Kubernetes):
Files changed
entrypoint-unified.sh— newinject_application_properties()function + env var init + call fromcommon_setup_and_validation()README.md— new table row + reference from the Low Resource Systems sectiondocs/spring-boot-tuning.md— new file with full reference: all tuneable properties, defaults, descriptions, and a complete memory-constrained exampleNotes
APPLICATION_PROPERTIESis unset — zero behaviour change for existing usersgosuswitch — works in rootless modeVerification
APPLICATION_PROPERTIES="server.tomcat.threads.max=50"INFO: APPLICATION_PROPERTIES set; writing Spring Boot properties to .../application.propertiesdocker exec <container> cat /opt/tplink/EAPController/properties/application.properties→ shows the content🤖 Generated with Claude Code