Stop copy-pasting boilerplate. Clone this, rename the package, and ship.
A production-ready Spring Boot 3 REST API template with everything you need baked in โ JWT auth, rate limiting, Swagger docs, Docker, GitHub Actions CI/CD, and more.
| Feature | Details |
|---|---|
| ๐ JWT Authentication | Access token (15 min) + Refresh token (7 days) with rotation |
| ๐ฎ Role-Based Access Control | ROLE_USER and ROLE_ADMIN via @PreAuthorize |
| ๐ฆ Rate Limiting | Per-IP rate limiting using Bucket4j (configurable) |
| ๐ OpenAPI 3 / Swagger UI | Auto-generated docs at /swagger-ui.html |
| ๐ก๏ธ Global Exception Handling | Consistent ApiResponse<T> across all endpoints |
| ๐๏ธ Flyway Migrations | Version-controlled schema with rollback support |
| ๐ณ Docker + Docker Compose | Multi-stage build, nginx reverse proxy, MySQL |
| โ๏ธ CI/CD via GitHub Actions | Test โ Build โ Push Docker โ Deploy to EC2 |
| ๐ Actuator | /actuator/health, /actuator/metrics |
| ๐ Request ID Tracking | MDC-based request ID in every log line |
| ๐ CORS Configured | Configurable via environment variables |
| โ Bean Validation | Jakarta Validation on all request DTOs |
src/main/java/com/starterkit/
โโโ config/ # Security, Swagger, DataInitializer
โโโ controller/ # AuthController, UserController, HealthController
โโโ dto/
โ โโโ request/ # RegisterRequest, LoginRequest, RefreshTokenRequest
โ โโโ response/ # ApiResponse<T>, AuthResponse, UserResponse
โโโ entity/ # User, Role, RefreshToken
โโโ exception/ # GlobalExceptionHandler + custom exceptions
โโโ filter/ # JwtAuthFilter, RateLimitFilter, RequestIdFilter
โโโ repository/ # JPA repositories
โโโ security/ # JwtService, UserDetailsServiceImpl
โโโ service/ # AuthService, UserService
- Java 17+
- Maven 3.8+
- Docker & Docker Compose
git clone https://github.com/raahulllkushwaha/springboot-starter-kit.git
cd springboot-starter-kit
mvn spring-boot:runApp starts at http://localhost:8080
Swagger UI: http://localhost:8080/swagger-ui.html
H2 Console: http://localhost:8080/h2-console (JDBC URL: jdbc:h2:mem:starterkit)
cp .env.example .env
# Edit .env with your values
docker compose up -dPOST /api/v1/auth/register โ Register new user
POST /api/v1/auth/login โ Login, get tokens
POST /api/v1/auth/refresh โ Refresh access token
POST /api/v1/auth/logout โ Revoke refresh token
GET /api/v1/users/me โ Get current user (any authenticated)
GET /api/v1/users/{id} โ Get user by ID (admin or self)
GET /api/v1/users โ List all users (admin only)
DELETE /api/v1/users/{id} โ Delete user (admin only)
GET /api/v1/ping โ Health check
GET /actuator/health โ Spring Actuator health
1. Register โ POST /api/v1/auth/register
Body: { name, email, password }
2. Login โ POST /api/v1/auth/login
Body: { email, password }
Returns: { accessToken, refreshToken, ... }
3. Use API โ Add header: Authorization: Bearer <accessToken>
4. Refresh โ POST /api/v1/auth/refresh
Body: { refreshToken }
Returns: new accessToken + rotated refreshToken
5. Logout โ POST /api/v1/auth/logout
Body: { refreshToken }
Default admin credentials (seeded on startup):
- Email:
admin@example.com - Password:
Admin@1234
โ ๏ธ Change these via environment variablesADMIN_EMAILandADMIN_PASSWORDbefore deploying.
All key settings are environment-variable driven:
| Variable | Default | Description |
|---|---|---|
SPRING_PROFILES_ACTIVE |
dev |
dev (H2) or prod (MySQL) |
DB_HOST |
localhost |
MySQL host |
DB_NAME |
starterkit |
Database name |
DB_USERNAME |
โ | MySQL username |
DB_PASSWORD |
โ | MySQL password |
JWT_SECRET |
(dev default) | Must change in prod |
JWT_ACCESS_EXPIRY |
900000 |
Access token TTL (ms) |
JWT_REFRESH_EXPIRY |
604800000 |
Refresh token TTL (ms) |
CORS_ALLOWED_ORIGINS |
localhost:3000 |
Comma-separated origins |
docker build -t springboot-starter-kit .# Production (MySQL + Nginx + App)
docker compose up -d
# Development (only MySQL, run app locally)
docker compose -f docker-compose.dev.yml up -dThe pipeline runs on every push to main:
Push to main
โ
[Test] โ mvn test (with MySQL service container)
โ
[Docker] โ Build & push image to Docker Hub
โ
[Deploy] โ SSH into EC2, docker compose pull && up
| Secret | Description |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub username |
DOCKERHUB_TOKEN |
Docker Hub access token |
EC2_HOST |
EC2 public IP / domain |
EC2_USER |
EC2 SSH username (e.g. ubuntu) |
EC2_SSH_KEY |
EC2 private key (PEM contents) |
Configured in application.yml:
app:
rate-limit:
enabled: true
capacity: 20 # max tokens in bucket
refill-tokens: 20 # tokens added per window
refill-seconds: 60 # window sizeReturns 429 Too Many Requests when limit exceeded.
- Rename package: Find & replace
com.starterkitโcom.yourcompany.yourapp - Update
application.yml: Changespring.application.name - Update
SwaggerConfig.java: Set your name/contact/GitHub URL - Update
docker-compose.yml: Change container names and image names - Add your entities: Create entities โ migration SQL โ repository โ service โ controller
- Deploy: Push to
main, GitHub Actions handles the rest
# Unit + integration tests (uses H2)
mvn test
# Skip tests (for fast build)
mvn package -DskipTestsThis starter supports two authentication strategies.
POST /login โ accessToken + refreshToken returned
Client: Authorization: Bearer <token> OR HTTP-only cookie
Server: validates JWT signature โ zero DB calls
โ
Stateless, mobile-friendly, microservices-ready
POST /login โ SESSION cookie set automatically
Client: cookie on every request (browser handles it)
Server: reads SecurityContext from JDBC session store
โ
No custom JWT filter โ uses Spring Security built-in flow
โ
Instant revocation (delete session from DB)
โ
Survives server restarts (JDBC-backed)
git checkout feature/spring-session
# Set in .env: SPRING_PROFILES_ACTIVE=session
mvn spring-boot:run- Java 21 + Spring Boot 3.3.0
- Spring Security 6 (JWT, RBAC)
- jjwt 0.12 (JWT library)
- Bucket4j 8 (Rate limiting)
- SpringDoc OpenAPI 3 / Swagger UI
- Flyway (Database migrations)
- MySQL 8 / H2 (dev)
- Lombok
- Docker + Nginx
- GitHub Actions
PRs are welcome! If you find this useful, please โญ the repo.
- Fork the repo
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push (
git push origin feature/amazing-feature) - Open a Pull Request
MIT ยฉ Rahul Kushwaha
If this saved you hours of setup, consider giving it a โญ