Systemd State 'stop-sigterm' timed out

First, please stop using your "server control script". That is systemd's job. The init system already keeps track of service PIDs and provides start/stop commands.

Also, don't use the - flag in ExecStart unless you really know that it's necessary. It tells systemd to ignore startup failures, and surely you would want to know when the service failed.

Finally, try to avoid myapp & in the startup scripts. (Init doesn't need that – services already run in background by definition.) If you must use it, then Type=forking would be more correct.

(Setting the correct Type= tells systemd what to expect, i.e. when to consider the server as "starting" vs "started" vs "finished". Type=simple means the initial process never 'backgrounds' itself; Type=forking is the opposite.)

With that, the following should work better:

app.service

[Unit]
Description=java server

[Service]
Type=simple
User=deploy
ExecStart=/home/deploy/server/start.sh
SyslogIdentifier=my-app
Restart=always
RestartSec=100

[Install]
WantedBy=multi-user.target

start.sh

#!/bin/sh
cd "$(dirname "$0")"
exec java -mx500m -cp lib/* mylcass -port 8080 -arg val

If your start.sh is really that simple, you could also just not use it at all.

IMHO, this is actually the prefered way:

[Unit]
Description=My Java App

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/server
ExecStart=/usr/bin/java -mx500m -cp lib/* mylcass -port 8080 -arg val
SyslogIdentifier=my-app
Restart=always
RestartSec=100

[Install]
WantedBy=multi-user.target

No need to replicate the functionality that Systemd gives to you for free.

Note, this does not replicate the > server.log functionality of your start.sh script. Instead, the output is handled by journald which is much better, imho.

If you need user configuration, either read the configuration files directly in your program or use environment variables with systemd. See Environment= and EnvironmentFile= service options.

You can even convert those environment variables into arguments passed to the command with ${FOO}.

Use override files in app.service.d/* to keep the ENV variables (or other configuration) separate.