Files
honey-be/README.md
Tihon 15498c8337
All checks were successful
Deploy to VPS / deploy (push) Successful in 52s
Initial setup, cleanup, VPS setup
2026-03-07 23:11:31 +02:00

14 KiB

Lottery Backend

Spring Boot backend application for Lottery project.

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:

    docker-compose up -d db
    
  3. Create .env file (for local development):

    DB_NAME=lottery_db
    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:

    mvn spring-boot:run
    

    Or build and run with Docker:

    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 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
    • Select the honey-be repository
    • 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:

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.

  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
  4. Copy the URL (e.g., https://lottery-be-production.up.railway.app)

Step 9: Create Frontend Service (Optional - if deploying frontend to Railway)

  1. In your Railway project, click "+ New""GitHub Repo"
  2. Select your lottery-fe repository
  3. Railway will detect it's a Node.js project
  4. Add environment variable:
    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"
  2. Name it (e.g., lottery-data)
  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:

    ssh user@your-server-ip
    
  2. Install Docker (if not installed):

    # 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):

    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):

    # For Ubuntu/Debian
    sudo apt update
    sudo apt install openjdk-17-jdk -y
    
  5. Create project directory:

    mkdir -p /opt/lottery
    cd /opt/lottery
    

Step 2: Clone Repository

cd /opt/lottery
git clone https://github.com/your-username/lottery-be.git
cd lottery-be

Step 3: Create Secret Configuration File

Create a tmpfs mount for secrets (more secure than .env files):

# Create tmpfs mount point
sudo mkdir -p /run/secrets
sudo chmod 700 /run/secrets

# Create secret file
sudo nano /run/secrets/lottery-config.properties

Add the following content (replace with your actual values):

SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/lottery_db
SPRING_DATASOURCE_USERNAME=lottery_user
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

cd /opt/lottery/lottery-be

# 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:

    nano nginx/conf.d/lottery.conf
    
  2. Update server_name (if using HTTPS):

    server {
        listen 80;
        server_name your-domain.com;
        # ... rest of config
    }
    
  3. Reload nginx:

    docker-compose -f docker-compose.inferno.yml restart nginx
    
  1. Install Certbot (Let's Encrypt):

    sudo apt install certbot python3-certbot-nginx -y
    
  2. Obtain SSL certificate:

    sudo certbot --nginx -d your-domain.com
    
  3. Update nginx config to use HTTPS (uncomment HTTPS server block in nginx/conf.d/lottery.conf)

  4. Reload nginx:

    docker-compose -f docker-compose.inferno.yml restart nginx
    

Step 8: Configure Firewall

# 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:

sudo nano /etc/systemd/system/lottery.service

Add:

[Unit]
Description=Lottery Application
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/lottery/lottery-be
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:

sudo systemctl daemon-reload
sudo systemctl enable lottery.service
sudo systemctl start lottery.service

Step 10: Set Up Grafana Integration (Production Logging)

  1. Install Grafana and Loki (on a separate server or same server):

    # Follow Grafana/Loki installation guide
    # https://grafana.com/docs/loki/latest/installation/
    
  2. Configure Promtail to collect logs from Docker containers:

    # 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:
      - job_name: lottery-backend
        docker_sd_configs:
          - host: unix:///var/run/docker.sock
            refresh_interval: 5s
        relabel_configs:
          - source_labels: [__meta_docker_container_name]
            regex: lottery-backend
            action: keep
    
  3. Update docker-compose.inferno.yml to add logging driver:

    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:

docker-compose -f docker-compose.inferno.yml ps

View logs:

# 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:

cd /opt/lottery/lottery-be
git pull
docker-compose -f docker-compose.inferno.yml up -d --build

Backup database:

docker-compose -f docker-compose.inferno.yml exec db mysqldump -u lottery_user -p lottery_db > backup_$(date +%Y%m%d).sql

Configuration

Environment Variables

The application supports two configuration strategies:

  1. Environment Variables (Railway): Set variables in Railway dashboard
  2. Secret File (Inferno): Mount file at /run/secrets/lottery-config.properties

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

mvn test

Building JAR

mvn clean package

Running Locally with Docker

docker-compose up --build

Project Structure

lottery-be/
├── src/
│   ├── main/
│   │   ├── java/com/lottery/lottery/
│   │   │   ├── 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]