# 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 ```bash # 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) ```bash 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 ```bash pct enter 101 ``` ### Install MariaDB ```bash apt update apt install -y mariadb-server mariadb-client # Secure installation mysql_secure_installation ``` ### Create Database and User ```bash mysql -u root -p ``` ```sql -- 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 ```bash # 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 ```bash pct enter 100 ``` ### Install Java 17 ```bash 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 ```bash # 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 ### Option A: Build on Development Machine (Recommended) On your **Windows development machine**: ```bash 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: ```bash # 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) ```bash # 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 ```bash nano /opt/group-ironmen-backend/application.env ``` ```bash # 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 ```bash 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 ```bash nano /etc/systemd/system/group-ironmen-backend.service ``` ```ini [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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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) ```bash 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 ```bash apt install -y nginx ``` ### Configure Nginx Reverse Proxy ```bash nano /etc/nginx/sites-available/group-ironmen-backend ``` ```nginx 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 *; } } ``` ```bash # 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 ```bash 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 ```bash # 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 ```bash systemctl restart group-ironmen-backend ``` ### Update Application ```bash # 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 ```bash # Create backup script nano /opt/scripts/backup-database.sh ``` ```bash #!/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 ``` ```bash 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash 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 ```bash 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 ```bash 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