Building a JAR and running it on a server
Nobody copies sources to a server or runs ./mvnw spring-boot:run there. The application is built into a single executable JAR file: your code, all libraries and the embedded Tomcat inside. The server needs only Java 25 — and one command to start.
Building
./mvnw clean packageMaven compiles the code, runs the tests and builds the file in the target folder:
target/blog-0.0.1-SNAPSHOT.jar 64 MB — for running
target/blog-0.0.1-SNAPSHOT.jar.original 40 KB — only your classesThe big file was built by spring-boot-maven-plugin: it packed all dependencies inside. The .original file is a plain JAR without libraries; it is not used on the server. If tests fail, the JAR is not built; -DskipTests skips them, but fixing them is better.
Running
java -jar target/blog-0.0.1-SNAPSHOT.jarThe log shows the same lines as when starting through Maven. Ctrl+C stops the application; on a server it usually runs as a systemd service or in a container so that it comes back up by itself after a reboot.
Settings for the server
For the server we create a prod profile. It holds no passwords — only what differs from development:
# src/main/resources/application-prod.yaml
spring:
jpa:
show-sql: false
h2:
console:
enabled: false
logging:
file:
name: logs/blog.logThe database address and password are passed as environment variables at startup:
SPRING_PROFILES_ACTIVE=prod \
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/blog \
SPRING_DATASOURCE_USERNAME=blog \
SPRING_DATASOURCE_PASSWORD=changeme \
java -jar target/blog-0.0.1-SNAPSHOT.jarSpring Boot turns SPRING_DATASOURCE_URL into the spring.datasource.url setting itself — no files need rewriting on the server. For PostgreSQL, pom.xml must contain the org.postgresql:postgresql driver and the flyway-database-postgresql module.
What you see at startup
INFO ... The following 1 profile is active: "prod"
INFO ... Database: jdbc:postgresql://localhost:5432/blog (PostgreSQL 18.3)
INFO ... Migrating schema "public" to version "1 - create tables"
INFO ... Migrating schema "public" to version "2 - add password and role"
INFO ... Successfully applied 2 migrations to schema "public", now at version v2On an empty PostgreSQL database Flyway applied both migrations — the same files that worked with H2. After that curl http://localhost:8080/actuator/health answers with the UP status, and the log is copied to logs/blog.log.
A pre-deployment checklist
| What to check | How |
|---|---|
The prod profile is on | The line The following 1 profile is active: "prod" |
| No passwords in Git | Environment variables only |
| The H2 console is off | spring.h2.console.enabled: false |
| The schema is managed by migrations | ddl-auto: validate and Flyway |
| There is a health check | /actuator/health answers UP |
Common mistake
If you start the wrong file, Java answers:
no main manifest attribute, in target\blog-0.0.1-SNAPSHOT.jar.originalThis is the .original file without libraries and without an entry point. Run the JAR without that suffix. The same error appears when pom.xml lacks spring-boot-maven-plugin: then the big executable file is never built at all.