2026-03-04 21:42:35 +02:00
# Lottery Backend
2026-01-03 15:34:33 +02:00
2026-03-04 21:42:35 +02:00
Spring Boot backend application for Lottery project.
2026-01-03 15:34:33 +02:00
## Technology Stack
- **Java 17**
- **Spring Boot 3.2.0**
- **MySQL 8.0** (using INT/BIGINT only, no floating point numbers)
- **Flyway** (database migrations)
- **Docker** (containerization)
- **Maven** (build tool)
## Local Development
### Prerequisites
- Java 17 JDK
- Maven 3.9+
- Docker and Docker Compose (for local MySQL)
### Setup
1. **Clone the repository **
2. **Start MySQL using Docker Compose ** :
```bash
docker-compose up -d db
```
3. **Create `.env` file ** (for local development):
```env
2026-03-04 21:42:35 +02:00
DB_NAME=lottery_db
2026-01-03 15:34:33 +02:00
DB_USERNAME=root
DB_PASSWORD=password
DB_ROOT_PASSWORD=password
TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
FRONTEND_URL=http://localhost:5173
```
4. **Run the application ** :
```bash
mvn spring-boot:run
```
Or build and run with Docker:
```bash
docker-compose up --build
```
### Database Migrations
Flyway automatically runs migrations on startup. Migrations are located in `src/main/resources/db/migration/` .
## Deployment Guides
### Railway Deployment (Staging Environment)
Railway is the primary deployment platform for staging. It provides built-in logging and easy environment variable management.
#### Step 1: Create Railway Project
1. Go to [Railway ](https://railway.app ) and sign in
2. Click * * "New Project"**
3. Select * * "Empty Project"**
#### Step 2: Create MySQL Database Service
1. In your Railway project, click * * "+ New"** → * * "Database"** → * * "Add MySQL"**
2. Railway will automatically create a MySQL database
3. Note the connection details (you'll need them for the backend service)
#### Step 3: Create Backend Service
1. In your Railway project, click * * "+ New"** → * * "GitHub Repo"** (or * * "Empty Service"**)
2. If using GitHub:
- Connect your GitHub account
2026-03-04 21:42:35 +02:00
- Select the `lottery-be` repository
2026-01-03 15:34:33 +02:00
- Railway will automatically detect it's a Java/Maven project
3. If using Empty Service:
- Click * * "Empty Service"**
- Connect to your repository or upload files
#### Step 4: Configure Environment Variables
In your backend service settings, go to * * "Variables"** and add:
```env
SPRING_DATASOURCE_URL=${MYSQL_URL}
SPRING_DATASOURCE_USERNAME=${MYSQLUSER}
SPRING_DATASOURCE_PASSWORD=${MYSQLPASSWORD}
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
FRONTEND_URL=https://your-frontend-url.railway.app
PORT=8080
```
**Note**: Railway automatically provides `MYSQL_URL` , `MYSQLUSER` , and `MYSQLPASSWORD` when you add a MySQL database. You can reference them using `${MYSQL_URL}` syntax.
#### Step 5: Link Database to Backend
1. In your backend service, go to * * "Settings"** → * * "Connect"**
2. Find your MySQL database service
3. Click * * "Connect"** - Railway will automatically add the MySQL connection variables
#### Step 6: Configure Health Check
1. In your backend service, go to * * "Settings"** → * * "Healthcheck"**
2. Set **Healthcheck Path ** to:
```
/actuator/health/readiness
```
3. Railway will poll this endpoint and wait for HTTP 200 before marking deployment as active
#### Step 7: Deploy
1. Railway will automatically deploy when you push to the connected branch
2. Or manually trigger deployment from the Railway dashboard
3. Check the * * "Deployments"** tab to monitor the deployment
#### Step 8: Get Backend URL
1. In your backend service, go to * * "Settings"** → * * "Networking"**
2. Click * * "Generate Domain"** to get a public URL
3. Or use the default Railway domain
2026-03-04 21:42:35 +02:00
4. Copy the URL (e.g., `https://lottery-be-production.up.railway.app` )
2026-01-03 15:34:33 +02:00
#### Step 9: Create Frontend Service (Optional - if deploying frontend to Railway)
1. In your Railway project, click * * "+ New"** → * * "GitHub Repo"**
2026-03-04 21:42:35 +02:00
2. Select your `lottery-fe` repository
2026-01-03 15:34:33 +02:00
3. Railway will detect it's a Node.js project
4. Add environment variable:
```env
VITE_API_BASE_URL=https://your-backend-url.railway.app
```
5. Railway will automatically build and deploy
#### Step 10: Create Volume (Optional - for persistent data)
If you need persistent storage:
1. In your Railway project, click * * "+ New"** → * * "Volume"**
2026-03-04 21:42:35 +02:00
2. Name it (e.g., `lottery-data` )
2026-01-03 15:34:33 +02:00
3. Mount it to your service if needed
### Inferno Deployment (Production Environment)
Inferno Solution provides the production environment. It requires manual server setup and uses Docker Compose with nginx.
#### Prerequisites
- Access to Inferno Solution server (via SSH)
- Docker and Docker Compose installed on the server
- JDK 17 installed on the server (for building, though Docker handles runtime)
- Domain name configured (optional, for HTTPS)
#### Step 1: Prepare Server
1. **SSH into your Inferno server ** :
```bash
ssh user@your -server-ip
```
2. **Install Docker ** (if not installed):
```bash
# For Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
sudo usermod -aG docker $USER
```
3. **Install Docker Compose ** (if not installed):
```bash
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```
4. **Install JDK 17 ** (for building):
```bash
# For Ubuntu/Debian
sudo apt update
sudo apt install openjdk-17-jdk -y
```
5. **Create project directory ** :
```bash
2026-03-04 21:42:35 +02:00
mkdir -p /opt/lottery
cd /opt/lottery
2026-01-03 15:34:33 +02:00
```
#### Step 2: Clone Repository
```bash
2026-03-04 21:42:35 +02:00
cd /opt/lottery
git clone https://github.com/your-username/lottery-be.git
cd lottery-be
2026-01-03 15:34:33 +02:00
```
#### Step 3: Create Secret Configuration File
Create a tmpfs mount for secrets (more secure than .env files):
```bash
# Create tmpfs mount point
sudo mkdir -p /run/secrets
sudo chmod 700 /run/secrets
# Create secret file
2026-03-04 21:42:35 +02:00
sudo nano /run/secrets/lottery-config.properties
2026-01-03 15:34:33 +02:00
```
Add the following content (replace with your actual values):
```properties
2026-03-04 21:42:35 +02:00
SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/lottery_db
SPRING_DATASOURCE_USERNAME=lottery_user
2026-01-03 15:34:33 +02:00
SPRING_DATASOURCE_PASSWORD=your_secure_mysql_password
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
FRONTEND_URL=https://your-frontend-domain.com
MYSQL_PASSWORD=your_secure_mysql_password
MYSQL_ROOT_PASSWORD=your_secure_mysql_root_password
```
**Important**:
- Use strong, unique passwords
- Keep this file secure (it's in tmpfs, so it's in-memory only)
- The file will be lost on reboot - you'll need to recreate it or use a startup script
#### Step 4: Configure Docker Compose for Inferno
The `docker-compose.inferno.yml` file is already configured. Make sure it's present in your repository.
#### Step 5: Build and Start Services
```bash
2026-03-04 21:42:35 +02:00
cd /opt/lottery/lottery-be
2026-01-03 15:34:33 +02:00
# Build and start all services
docker-compose -f docker-compose.inferno.yml up -d --build
```
This will:
- Build the backend application
- Start MySQL database
- Start backend service
- Start nginx reverse proxy
#### Step 6: Configure Nginx (if using custom domain)
1. **Edit nginx configuration ** :
```bash
2026-03-04 21:42:35 +02:00
nano nginx/conf.d/lottery.conf
2026-01-03 15:34:33 +02:00
```
2. **Update server_name ** (if using HTTPS):
```nginx
server {
listen 80;
server_name your-domain.com;
# ... rest of config
}
```
3. **Reload nginx ** :
```bash
docker-compose -f docker-compose.inferno.yml restart nginx
```
#### Step 7: Set Up SSL (Optional - Recommended for Production)
1. **Install Certbot ** (Let's Encrypt):
```bash
sudo apt install certbot python3-certbot-nginx -y
```
2. **Obtain SSL certificate ** :
```bash
sudo certbot --nginx -d your-domain.com
```
2026-03-04 21:42:35 +02:00
3. **Update nginx config ** to use HTTPS (uncomment HTTPS server block in `nginx/conf.d/lottery.conf` )
2026-01-03 15:34:33 +02:00
4. **Reload nginx ** :
```bash
docker-compose -f docker-compose.inferno.yml restart nginx
```
#### Step 8: Configure Firewall
```bash
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Allow SSH (if not already allowed)
sudo ufw allow 22/tcp
# Enable firewall
sudo ufw enable
```
#### Step 9: Set Up Auto-Start on Boot
Create a systemd service to ensure services start on boot:
```bash
2026-03-04 21:42:35 +02:00
sudo nano /etc/systemd/system/lottery.service
2026-01-03 15:34:33 +02:00
```
Add:
```ini
[Unit]
2026-03-04 21:42:35 +02:00
Description=Lottery Application
2026-01-03 15:34:33 +02:00
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
2026-03-04 21:42:35 +02:00
WorkingDirectory=/opt/lottery/lottery-be
2026-01-03 15:34:33 +02:00
ExecStart=/usr/local/bin/docker-compose -f docker-compose.inferno.yml up -d
ExecStop=/usr/local/bin/docker-compose -f docker-compose.inferno.yml down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
```
Enable the service:
```bash
sudo systemctl daemon-reload
2026-03-04 21:42:35 +02:00
sudo systemctl enable lottery.service
sudo systemctl start lottery.service
2026-01-03 15:34:33 +02:00
```
#### Step 10: Set Up Grafana Integration (Production Logging)
1. **Install Grafana and Loki ** (on a separate server or same server):
```bash
# Follow Grafana/Loki installation guide
# https://grafana.com/docs/loki/latest/installation/
```
2. **Configure Promtail ** to collect logs from Docker containers:
```yaml
# promtail-config.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
2026-03-04 21:42:35 +02:00
- job_name: lottery-backend
2026-01-03 15:34:33 +02:00
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: [__meta_docker_container_name]
2026-03-04 21:42:35 +02:00
regex: lottery-backend
2026-01-03 15:34:33 +02:00
action: keep
```
3. **Update docker-compose.inferno.yml ** to add logging driver:
```yaml
app:
# ... existing config
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
```
4. **Configure Grafana datasource ** to connect to Loki
#### Step 11: Monitor and Maintain
**Check service status**:
```bash
docker-compose -f docker-compose.inferno.yml ps
```
**View logs**:
```bash
# All services
docker-compose -f docker-compose.inferno.yml logs -f
# Specific service
docker-compose -f docker-compose.inferno.yml logs -f app
```
**Update application**:
```bash
2026-03-04 21:42:35 +02:00
cd /opt/lottery/lottery-be
2026-01-03 15:34:33 +02:00
git pull
docker-compose -f docker-compose.inferno.yml up -d --build
```
**Backup database**:
```bash
2026-03-04 21:42:35 +02:00
docker-compose -f docker-compose.inferno.yml exec db mysqldump -u lottery_user -p lottery_db > backup_$(date +%Y%m%d).sql
2026-01-03 15:34:33 +02:00
```
## Configuration
### Environment Variables
The application supports two configuration strategies:
1. **Environment Variables ** (Railway): Set variables in Railway dashboard
2026-03-04 21:42:35 +02:00
2. **Secret File ** (Inferno): Mount file at `/run/secrets/lottery-config.properties`
2026-01-03 15:34:33 +02:00
Priority: Secret file → Environment variables
### Required Variables
- `SPRING_DATASOURCE_URL` - MySQL connection URL
- `SPRING_DATASOURCE_USERNAME` - MySQL username
- `SPRING_DATASOURCE_PASSWORD` - MySQL password
- `TELEGRAM_BOT_TOKEN` - Telegram bot token for authentication
- `FRONTEND_URL` - Frontend URL for CORS configuration
### Database Schema
The database uses **INT ** and **BIGINT ** only - no floating point numbers.
Current tables:
- `users` - User information (id, telegram_id, username, created_at)
## API Endpoints
### Public Endpoints
- `GET /ping` - Health check (no auth required)
- `GET /actuator/health` - Application health
- `GET /actuator/health/readiness` - Readiness probe (checks database)
- `GET /actuator/health/liveness` - Liveness probe
### Protected Endpoints (require Telegram auth)
- `GET /api/users/current` - Get current user information
## Authorization
The application uses Telegram Mini App authentication:
1. Frontend sends `Authorization: tma <initData>` header
2. Backend validates Telegram signature
3. Backend creates/updates user in database
4. User is stored in thread-local context for the request
## Health Checks
- **Readiness**: `/actuator/health/readiness` - Checks database connectivity
- **Liveness**: `/actuator/health/liveness` - Checks if application is running
Configure Railway to use `/actuator/health/readiness` as the health check path.
## Logging
- **Railway**: Built-in logging available in Railway dashboard
- **Inferno**: Configure Grafana/Loki for log aggregation (see Grafana setup above)
## Troubleshooting
### Database Connection Issues
- Verify MySQL is running: `docker-compose ps`
- Check connection credentials in environment variables
- Review application logs for connection errors
### Authorization Failures
- Verify `TELEGRAM_BOT_TOKEN` is correct
- Check that frontend is sending `Authorization: tma <initData>` header
- Review backend logs for validation errors
### Deployment Issues
- Check health check endpoint: `curl http://your-url/actuator/health/readiness`
- Review Railway deployment logs
- Verify all environment variables are set correctly
## Development
### Running Tests
```bash
mvn test
```
### Building JAR
```bash
mvn clean package
```
### Running Locally with Docker
```bash
docker-compose up --build
```
## Project Structure
```
2026-03-04 21:42:35 +02:00
lottery-be/
2026-01-03 15:34:33 +02:00
├── src/
│ ├── main/
2026-03-04 21:42:35 +02:00
│ │ ├── java/com/lottery/lottery/
2026-01-03 15:34:33 +02:00
│ │ │ ├── config/ # Configuration classes
│ │ │ ├── controller/ # REST controllers
│ │ │ ├── dto/ # Data transfer objects
│ │ │ ├── exception/ # Exception handlers
│ │ │ ├── health/ # Health indicators
│ │ │ ├── logging/ # Grafana logging config
│ │ │ ├── model/ # JPA entities
│ │ │ ├── repository/ # JPA repositories
│ │ │ ├── security/ # Auth interceptor, UserContext
│ │ │ └── service/ # Business logic
│ │ └── resources/
│ │ ├── db/migration/ # Flyway migrations
│ │ └── application.yml # Application config
├── nginx/ # Nginx config (for Inferno)
├── Dockerfile # Dockerfile for Railway
├── Dockerfile.inferno # Dockerfile for Inferno
├── docker-compose.yml # Docker Compose for local/Railway
├── docker-compose.inferno.yml # Docker Compose for Inferno
└── pom.xml # Maven configuration
```
## License
[Your License Here]
2026-03-04 21:42:35 +02:00