218 lines
4.4 KiB
Markdown
218 lines
4.4 KiB
Markdown
|
|
# Quick Reference - VPS Deployment
|
||
|
|
|
||
|
|
## Common Commands
|
||
|
|
|
||
|
|
### Docker Compose (Backend)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd /opt/app/backend
|
||
|
|
|
||
|
|
# Start services
|
||
|
|
docker compose -f docker-compose.prod.yml up -d
|
||
|
|
|
||
|
|
# Stop services
|
||
|
|
docker compose -f docker-compose.prod.yml down
|
||
|
|
|
||
|
|
# Restart services
|
||
|
|
docker compose -f docker-compose.prod.yml restart
|
||
|
|
|
||
|
|
# View logs
|
||
|
|
docker compose -f docker-compose.prod.yml logs -f
|
||
|
|
|
||
|
|
# Rebuild and restart
|
||
|
|
docker compose -f docker-compose.prod.yml up -d --build
|
||
|
|
|
||
|
|
# Check status
|
||
|
|
docker compose -f docker-compose.prod.yml ps
|
||
|
|
```
|
||
|
|
|
||
|
|
### Nginx
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Test configuration
|
||
|
|
sudo nginx -t
|
||
|
|
|
||
|
|
# Reload configuration
|
||
|
|
sudo systemctl reload nginx
|
||
|
|
|
||
|
|
# Restart Nginx
|
||
|
|
sudo systemctl restart nginx
|
||
|
|
|
||
|
|
# Check status
|
||
|
|
sudo systemctl status nginx
|
||
|
|
|
||
|
|
# View logs
|
||
|
|
sudo tail -f /var/log/nginx/error.log
|
||
|
|
sudo tail -f /var/log/nginx/access.log
|
||
|
|
```
|
||
|
|
|
||
|
|
### SSL Certificate
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Renew certificate
|
||
|
|
sudo certbot renew
|
||
|
|
|
||
|
|
# Test renewal
|
||
|
|
sudo certbot renew --dry-run
|
||
|
|
|
||
|
|
# Check certificates
|
||
|
|
sudo certbot certificates
|
||
|
|
```
|
||
|
|
|
||
|
|
### Database
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Load database password from secret file (if not already loaded)
|
||
|
|
cd /opt/app/backend
|
||
|
|
source scripts/load-db-password.sh
|
||
|
|
|
||
|
|
# Backup
|
||
|
|
docker exec lottery-mysql mysqldump -u root -p${DB_PASSWORD} lottery_db > backup_$(date +%Y%m%d).sql
|
||
|
|
|
||
|
|
# Restore
|
||
|
|
docker exec -i lottery-mysql mysql -u root -p${DB_PASSWORD} lottery_db < backup.sql
|
||
|
|
|
||
|
|
# Access MySQL shell
|
||
|
|
docker exec -it lottery-mysql mysql -u root -p
|
||
|
|
```
|
||
|
|
|
||
|
|
### Health Checks
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Backend health
|
||
|
|
curl http://localhost:8080/actuator/health
|
||
|
|
|
||
|
|
# Frontend
|
||
|
|
curl https://yourdomain.com/
|
||
|
|
|
||
|
|
# API endpoint
|
||
|
|
curl https://yourdomain.com/api/health
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logs
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Backend logs
|
||
|
|
cd /opt/app/backend
|
||
|
|
docker compose -f docker-compose.prod.yml logs -f backend
|
||
|
|
|
||
|
|
# Database logs
|
||
|
|
docker compose -f docker-compose.prod.yml logs -f db
|
||
|
|
|
||
|
|
# All logs
|
||
|
|
docker compose -f docker-compose.prod.yml logs -f
|
||
|
|
|
||
|
|
# Nginx error log
|
||
|
|
sudo tail -f /var/log/nginx/error.log
|
||
|
|
```
|
||
|
|
|
||
|
|
### File Permissions
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Fix avatar directory permissions
|
||
|
|
sudo chown -R $USER:$USER /opt/app/data/avatars
|
||
|
|
sudo chmod -R 755 /opt/app/data/avatars
|
||
|
|
|
||
|
|
# Secure secret file
|
||
|
|
sudo chmod 640 /run/secrets/lottery-config.properties
|
||
|
|
sudo chown root:docker /run/secrets/lottery-config.properties
|
||
|
|
```
|
||
|
|
|
||
|
|
### Update Application
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Backend update
|
||
|
|
cd /opt/app/backend
|
||
|
|
git pull # or copy new files
|
||
|
|
docker compose -f docker-compose.prod.yml up -d --build
|
||
|
|
|
||
|
|
# Frontend update
|
||
|
|
# 1. Build locally: npm run build
|
||
|
|
# 2. Copy dist/ to /opt/app/frontend/dist/
|
||
|
|
scp -r dist/* user@vps:/opt/app/frontend/dist/
|
||
|
|
```
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Backend won't start
|
||
|
|
```bash
|
||
|
|
# Check logs
|
||
|
|
docker compose -f docker-compose.prod.yml logs backend
|
||
|
|
|
||
|
|
# Check secret file exists and is readable
|
||
|
|
sudo ls -la /run/secrets/lottery-config.properties
|
||
|
|
|
||
|
|
# Verify secret file is loaded (check logs for "Loading configuration from mounted secret file")
|
||
|
|
docker compose -f docker-compose.prod.yml logs backend | grep "Loading configuration"
|
||
|
|
|
||
|
|
# Verify database is ready
|
||
|
|
docker compose -f docker-compose.prod.yml ps db
|
||
|
|
```
|
||
|
|
|
||
|
|
### Frontend not loading
|
||
|
|
```bash
|
||
|
|
# Check Nginx config
|
||
|
|
sudo nginx -t
|
||
|
|
|
||
|
|
# Verify files exist
|
||
|
|
ls -la /opt/app/frontend/dist/
|
||
|
|
|
||
|
|
# Check Nginx error log
|
||
|
|
sudo tail -f /var/log/nginx/error.log
|
||
|
|
```
|
||
|
|
|
||
|
|
### WebSocket issues
|
||
|
|
```bash
|
||
|
|
# Check backend logs
|
||
|
|
docker compose -f docker-compose.prod.yml logs backend | grep -i websocket
|
||
|
|
|
||
|
|
# Verify Nginx WebSocket config
|
||
|
|
grep -A 10 "/ws" /opt/app/nginx/nginx.conf
|
||
|
|
```
|
||
|
|
|
||
|
|
### Database connection failed
|
||
|
|
```bash
|
||
|
|
# Check database container
|
||
|
|
docker ps | grep mysql
|
||
|
|
|
||
|
|
# Check database logs
|
||
|
|
docker compose -f docker-compose.prod.yml logs db
|
||
|
|
|
||
|
|
# Test connection
|
||
|
|
docker exec -it lottery-mysql mysql -u root -p
|
||
|
|
```
|
||
|
|
|
||
|
|
## File Locations
|
||
|
|
|
||
|
|
```
|
||
|
|
Backend source: /opt/app/backend/
|
||
|
|
Frontend build: /opt/app/frontend/dist/
|
||
|
|
Nginx config: /opt/app/nginx/nginx.conf
|
||
|
|
Avatar storage: /opt/app/data/avatars/
|
||
|
|
Database data: /opt/app/mysql/data/ (via Docker volume)
|
||
|
|
Secret file: /run/secrets/lottery-config.properties
|
||
|
|
```
|
||
|
|
|
||
|
|
## Configuration Variables
|
||
|
|
|
||
|
|
Required in `/run/secrets/lottery-config.properties`:
|
||
|
|
|
||
|
|
- `SPRING_DATASOURCE_URL`
|
||
|
|
- `SPRING_DATASOURCE_USERNAME`
|
||
|
|
- `SPRING_DATASOURCE_PASSWORD`
|
||
|
|
- `TELEGRAM_BOT_TOKEN`
|
||
|
|
- `TELEGRAM_CHANNEL_CHECKER_BOT_TOKEN`
|
||
|
|
- `TELEGRAM_FOLLOW_TASK_CHANNEL_ID`
|
||
|
|
- `FRONTEND_URL`
|
||
|
|
|
||
|
|
Optional:
|
||
|
|
- `APP_AVATAR_STORAGE_PATH`
|
||
|
|
- `APP_AVATAR_PUBLIC_BASE_URL`
|
||
|
|
- `APP_SESSION_MAX_ACTIVE_PER_USER`
|
||
|
|
- `APP_SESSION_CLEANUP_BATCH_SIZE`
|
||
|
|
- `APP_SESSION_CLEANUP_MAX_BATCHES`
|
||
|
|
- `GEOIP_DB_PATH`
|
||
|
|
|
||
|
|
**Note:** The MySQL container also needs `DB_PASSWORD` and `DB_ROOT_PASSWORD` as environment variables (should match `SPRING_DATASOURCE_PASSWORD`).
|
||
|
|
|