Files
leagues-tools/spring-backend/DEPLOYMENT.md

15 KiB

Deployment Guide - Debian/Proxmox VE

Overview

This guide covers deploying the Group Ironmen backend to a Debian container on Proxmox VE.


Architecture

┌─────────────────────────────────────────────┐
│  Proxmox VE Host                            │
│                                             │
│  ┌───────────────────────────────────────┐ │
│  │  Debian Container 1                   │ │
│  │  - Java 17                            │ │
│  │  - Spring Boot Backend (Port 8080)    │ │
│  │  - systemd service                    │ │
│  └───────────────┬───────────────────────┘ │
│                  │                          │
│  ┌───────────────┴───────────────────────┐ │
│  │  Debian Container 2 (or same)         │ │
│  │  - MariaDB (Port 3306)                │ │
│  │  - Database: groupironman             │ │
│  └───────────────────────────────────────┘ │
│                                             │
│  Network Bridge (vmbr0)                     │
│  - Backend: 192.168.1.100:8080             │
│  - Database: 192.168.1.101:3306            │
└─────────────────────────────────────────────┘

Prerequisites

1. Proxmox VE Setup

  • Proxmox VE 7.x or 8.x installed
  • Two Debian LXC containers (or one for both services)
  • Network bridge configured

2. Debian Container Requirements

  • Debian 11 (Bullseye) or Debian 12 (Bookworm)
  • At least 1GB RAM for backend
  • At least 2GB RAM for MariaDB
  • 10GB disk space minimum

Step 1: Create LXC Containers in Proxmox

Backend Container

# From Proxmox host
pct create 100 \
  local:vztmpl/debian-12-standard_12.0-1_amd64.tar.zst \
  --hostname group-ironmen-backend \
  --memory 2048 \
  --cores 2 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.1.100/24,gw=192.168.1.1 \
  --rootfs local-lvm:10 \
  --unprivileged 1 \
  --features nesting=1

# Start container
pct start 100

Database Container (Optional - can be same container)

pct create 101 \
  local:vztmpl/debian-12-standard_12.0-1_amd64.tar.zst \
  --hostname mariadb-server \
  --memory 4096 \
  --cores 2 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.1.101/24,gw=192.168.1.1 \
  --rootfs local-lvm:20 \
  --unprivileged 1

pct start 101

Step 2: Setup MariaDB Container

Enter Database Container

pct enter 101

Install MariaDB

apt update
apt install -y mariadb-server mariadb-client

# Secure installation
mysql_secure_installation

Create Database and User

mysql -u root -p
-- Create database
CREATE DATABASE groupironman CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Create user for backend
CREATE USER 'groupironmen'@'%' IDENTIFIED BY 'your_secure_password_here';

-- Grant privileges
GRANT ALL PRIVILEGES ON groupironman.* TO 'groupironmen'@'%';
FLUSH PRIVILEGES;

-- Verify
SHOW DATABASES;
SELECT User, Host FROM mysql.user WHERE User = 'groupironmen';

EXIT;

Configure MariaDB for Remote Access

# Edit MariaDB config
nano /etc/mysql/mariadb.conf.d/50-server.cnf

# Change bind-address to allow connections from backend container
# Find: bind-address = 127.0.0.1
# Change to: bind-address = 0.0.0.0

# Restart MariaDB
systemctl restart mariadb
systemctl enable mariadb

# Check status
systemctl status mariadb

# Test remote connection
mysql -h 192.168.1.101 -u groupironmen -p groupironman

Step 3: Setup Backend Container

Enter Backend Container

pct enter 100

Install Java 17

apt update
apt install -y openjdk-17-jdk-headless wget curl vim

# Verify Java version
java -version
# Should show: openjdk version "17.x.x"

Create Application Directory

# Create app directory
mkdir -p /opt/group-ironmen-backend
cd /opt/group-ironmen-backend

# Create logs directory
mkdir -p /var/log/group-ironmen-backend

Step 4: Build and Deploy Application

On your Windows development machine:

cd C:\Users\Sonder\Gitea\leagues-tools\spring-backend

# Build JAR file
./gradlew.bat clean build -x test

# JAR location: build/libs/group-ironmen-backend-1.0.0.jar

Transfer to Proxmox container:

# From Windows (using scp or WinSCP)
scp build/libs/group-ironmen-backend-1.0.0.jar root@192.168.1.100:/opt/group-ironmen-backend/

# Or use FileZilla/WinSCP GUI

Option B: Build on Container (Alternative)

# Install Git
apt install -y git

# Clone repository
cd /opt
git clone https://your-git-repo/leagues-tools.git
cd leagues-tools/spring-backend

# Build
./gradlew clean build -x test

# Copy JAR
cp build/libs/group-ironmen-backend-1.0.0.jar /opt/group-ironmen-backend/

Step 5: Configure Application

Create Environment Configuration

nano /opt/group-ironmen-backend/application.env
# Database Configuration
DB_HOST=192.168.1.101
DB_PORT=3306
DB_NAME=groupironman
DB_USER=groupironmen
DB_PASSWORD=your_secure_password_here

# Server Configuration
SERVER_PORT=8080

# Security
BACKEND_SECRET=change_this_to_a_random_64_character_string_for_production

# CORS (allow frontend origins)
CORS_ORIGINS=http://your-frontend-domain.com,http://localhost:4000

# Captcha (optional)
CAPTCHA_ENABLED=false
CAPTCHA_SITEKEY=
CAPTCHA_SECRET=

# Logging
LOGGING_LEVEL_ROOT=INFO
LOGGING_LEVEL_COM_OSLEAGUE=DEBUG

Set Secure Permissions

chmod 600 /opt/group-ironmen-backend/application.env
chown root:root /opt/group-ironmen-backend/application.env

Step 6: Create systemd Service

Create Service File

nano /etc/systemd/system/group-ironmen-backend.service
[Unit]
Description=Group Ironmen Backend - Spring Boot Application
After=network.target mariadb.service
Wants=mariadb.service

[Service]
Type=simple
User=root
WorkingDirectory=/opt/group-ironmen-backend
EnvironmentFile=/opt/group-ironmen-backend/application.env

ExecStart=/usr/bin/java \
    -Xms512m \
    -Xmx1024m \
    -Dserver.port=${SERVER_PORT} \
    -Dspring.datasource.url=jdbc:mariadb://${DB_HOST}:${DB_PORT}/${DB_NAME} \
    -Dspring.datasource.username=${DB_USER} \
    -Dspring.datasource.password=${DB_PASSWORD} \
    -Dapp.security.secret=${BACKEND_SECRET} \
    -Dapp.cors.allowed-origins=${CORS_ORIGINS} \
    -jar /opt/group-ironmen-backend/group-ironmen-backend-1.0.0.jar

Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=group-ironmen-backend

# Logging
StandardOutput=append:/var/log/group-ironmen-backend/application.log
StandardError=append:/var/log/group-ironmen-backend/error.log

[Install]
WantedBy=multi-user.target

Enable and Start Service

# Reload systemd
systemctl daemon-reload

# Enable service (start on boot)
systemctl enable group-ironmen-backend

# Start service
systemctl start group-ironmen-backend

# Check status
systemctl status group-ironmen-backend

# View logs
journalctl -u group-ironmen-backend -f
tail -f /var/log/group-ironmen-backend/application.log

Step 7: Test Deployment

Test from Container

# Health check (if Spring Actuator enabled)
curl http://localhost:8080/actuator/health

# Test GE prices endpoint
curl http://localhost:8080/api/ge-prices

# Test captcha config
curl http://localhost:8080/api/captcha-enabled

# Create test group
curl -X POST http://localhost:8080/api/create-group \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test Group",
    "member_names": ["Player1", "Player2"],
    "captcha_response": ""
  }'

Test from External Machine

# From your Windows machine or another host
curl http://192.168.1.100:8080/api/ge-prices

# Create group
curl -X POST http://192.168.1.100:8080/api/create-group \
  -H "Content-Type: application/json" \
  -d '{"name": "My Group", "member_names": ["Player1"]}'

Step 8: Firewall Configuration (Optional)

Configure iptables

# Allow port 8080 from specific networks
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 8080 -j ACCEPT

# Or allow from specific IP (frontend container)
iptables -A INPUT -p tcp -s 192.168.1.200 --dport 8080 -j ACCEPT

# Save rules
apt install -y iptables-persistent
netfilter-persistent save

Configure UFW (Alternative)

apt install -y ufw

# Allow SSH
ufw allow 22/tcp

# Allow backend port
ufw allow 8080/tcp

# Enable firewall
ufw enable
ufw status

Step 9: Reverse Proxy (Optional - for HTTPS)

Install Nginx

apt install -y nginx

Configure Nginx Reverse Proxy

nano /etc/nginx/sites-available/group-ironmen-backend
server {
    listen 80;
    server_name api.groupiron.men;  # Your domain

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # CORS headers (handled by Spring, but can add here too)
        add_header Access-Control-Allow-Origin *;
    }
}
# Enable site
ln -s /etc/nginx/sites-available/group-ironmen-backend /etc/nginx/sites-enabled/

# Test config
nginx -t

# Restart Nginx
systemctl restart nginx
systemctl enable nginx

Add SSL with Let's Encrypt

apt install -y certbot python3-certbot-nginx

# Get certificate
certbot --nginx -d api.groupiron.men

# Auto-renewal is configured automatically

Step 10: Monitoring and Maintenance

View Logs

# Application logs
tail -f /var/log/group-ironmen-backend/application.log

# System logs
journalctl -u group-ironmen-backend -f

# Last 100 lines
journalctl -u group-ironmen-backend -n 100

Restart Service

systemctl restart group-ironmen-backend

Update Application

# Stop service
systemctl stop group-ironmen-backend

# Backup current JAR
cp /opt/group-ironmen-backend/group-ironmen-backend-1.0.0.jar \
   /opt/group-ironmen-backend/backup/group-ironmen-backend-1.0.0.jar.$(date +%Y%m%d)

# Upload new JAR
# ... (use scp or WinSCP)

# Start service
systemctl start group-ironmen-backend

# Check status
systemctl status group-ironmen-backend

Database Backups

# Create backup script
nano /opt/scripts/backup-database.sh
#!/bin/bash
BACKUP_DIR="/opt/backups/mariadb"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

mysqldump -u groupironmen -p'your_password' groupironman \
  > $BACKUP_DIR/groupironman_$DATE.sql

# Keep last 7 days
find $BACKUP_DIR -name "groupironman_*.sql" -mtime +7 -delete
chmod +x /opt/scripts/backup-database.sh

# Add to crontab (daily at 2 AM)
crontab -e
0 2 * * * /opt/scripts/backup-database.sh

Troubleshooting

Service Won't Start

# Check logs
journalctl -u group-ironmen-backend -n 50 --no-pager

# Check if port is already in use
netstat -tulpn | grep 8080

# Check Java is installed
java -version

# Check file permissions
ls -la /opt/group-ironmen-backend/

Database Connection Issues

# Test connection from backend container
mysql -h 192.168.1.101 -u groupironmen -p groupironman

# Check MariaDB is listening on correct interface
netstat -tulpn | grep 3306

# Check firewall rules
iptables -L -n | grep 3306

Application Errors

# Enable debug logging
# Edit /opt/group-ironmen-backend/application.env
LOGGING_LEVEL_COM_OSLEAGUE=DEBUG

# Restart service
systemctl restart group-ironmen-backend

# Watch logs
tail -f /var/log/group-ironmen-backend/application.log

High Memory Usage

# Check Java heap
jps -lv

# Adjust JVM settings in systemd service
# Edit /etc/systemd/system/group-ironmen-backend.service
# Change: -Xms512m -Xmx1024m
# To: -Xms256m -Xmx768m

systemctl daemon-reload
systemctl restart group-ironmen-backend

Performance Tuning

JVM Tuning

# Edit systemd service file
nano /etc/systemd/system/group-ironmen-backend.service

# Add JVM options
ExecStart=/usr/bin/java \
    -Xms512m \
    -Xmx1024m \
    -XX:+UseG1GC \
    -XX:MaxGCPauseMillis=200 \
    -XX:+UseStringDeduplication \
    ...

MariaDB Tuning

# Edit MariaDB config
nano /etc/mysql/mariadb.conf.d/50-server.cnf

# Add under [mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
max_connections = 100

systemctl restart mariadb

Security Checklist

  • Changed default passwords for MariaDB root and groupironmen user
  • Set secure BACKEND_SECRET (64+ random characters)
  • Configured firewall (iptables/ufw) to restrict access
  • CORS origins set to specific domains (not *)
  • Regular database backups scheduled
  • Nginx reverse proxy with SSL (if public-facing)
  • Kept system updated (apt update && apt upgrade)
  • Monitored logs for suspicious activity
  • File permissions set correctly (600 for env file)

Quick Reference

Service Commands

systemctl start group-ironmen-backend
systemctl stop group-ironmen-backend
systemctl restart group-ironmen-backend
systemctl status group-ironmen-backend
systemctl enable group-ironmen-backend  # Start on boot
systemctl disable group-ironmen-backend # Don't start on boot

Log Commands

journalctl -u group-ironmen-backend -f              # Follow logs
journalctl -u group-ironmen-backend -n 100         # Last 100 lines
journalctl -u group-ironmen-backend --since today  # Today's logs
tail -f /var/log/group-ironmen-backend/application.log

Database Commands

mysql -u groupironmen -p groupironman              # Connect to DB
mysqldump -u groupironmen -p groupironman > backup.sql  # Backup
mysql -u groupironmen -p groupironman < backup.sql      # Restore

Network Diagram

Internet
    ↓
[Firewall/Router]
    ↓
Proxmox Bridge (vmbr0) - 192.168.1.0/24
    │
    ├── Backend Container (192.168.1.100:8080)
    │   └── group-ironmen-backend.service
    │       └── Spring Boot App
    │           ├── Port 8080 (HTTP API)
    │           └── Connects to → 192.168.1.101:3306
    │
    ├── Database Container (192.168.1.101:3306)
    │   └── MariaDB
    │       └── Database: groupironman
    │
    └── Frontend Container (192.168.1.200:4000) [Future]
        └── Next.js/React Frontend

Deployment Status: Ready for production deployment! Last Updated: 2025-10-27