Files
honey-be/VPS_SETUP_FROM_SCRATCH.md
Mykhailo Svishchov 82b9cfc8e3
Some checks failed
Deploy to Railway / deploy (push) Has been cancelled
Network Test / test_network (push) Has been cancelled
VPS setup
2026-03-07 17:33:08 +02:00

458 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Honey VPS Setup from Scratch (Inferno)
This guide walks through setting up a new VPS for the **Honey** app with the same layout as your existing lottery VPS: backend + MySQL + phpMyAdmin in Docker, frontend and admin panel served by Nginx, logging under `/opt/app/logs`, secrets in `/run/secrets`, and MySQL backups to a backup VPS.
**Target layout (mirrors your lottery setup):**
- **Containers:** backend (honey-be), MySQL (honey_db), phpMyAdmin
- **Served by Nginx:** frontend (honey-fe), admin panel (honey-admin)
- **Paths:** `/opt/app` for app files, `/run/secrets` for config, `/opt/app/logs` for logs
- **Nginx:** main config + site config (e.g. `nginx.conf` + `sites-enabled/your-domain`)
---
## 1. VPS basics
### 1.1 System update and installs
```bash
sudo apt update && sudo apt upgrade -y
```
```bash
# Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# Docker Compose (plugin)
sudo apt-get update
sudo apt-get install -y docker-compose-plugin
# Nginx + Certbot
sudo apt install -y nginx certbot python3-certbot-nginx
```
Log out and back in so `docker` group applies.
### 1.2 Directory structure under `/opt/app`
Create the same layout as lottery (backend, frontend, admin, nginx, data, logs, backups, mysql):
```bash
sudo mkdir -p /opt/app/backend
sudo mkdir -p /opt/app/frontend
sudo mkdir -p /opt/app/admin
sudo mkdir -p /opt/app/admin-panel
sudo mkdir -p /opt/app/nginx
sudo mkdir -p /opt/app/data/avatars
sudo mkdir -p /opt/app/logs
sudo mkdir -p /opt/app/backups
sudo mkdir -p /opt/app/mysql/data
sudo mkdir -p /opt/app/mysql/conf
sudo chown -R $USER:$USER /opt/app
sudo chmod -R 755 /opt/app
```
### 1.3 Git
```bash
sudo apt install git -y
git config --global alias.st status
ssh-keygen -t ed25519 -C "your_email@example.com" (replace email)
cat ~/.ssh/id_ed25519.pub (copy the key and add to origin)
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up (and login in local browser to tailscale)
```
Clone all repositories to respective folders.
---
## 2. Backend (honey-be) on VPS
### 2.1 Secret file (honey-config.properties)
Backend reads **`/run/secrets/honey-config.properties`** (see `ConfigLoader` and `docker-compose.prod.yml`). Create it from the template; **do not commit real values**.
On the VPS:
```bash
sudo mkdir -p /run/secrets
sudo cp /opt/app/backend/honey-be/honey-config.properties.template /run/secrets/honey-config.properties
sudo chmod 640 /run/secrets/honey-config.properties
sudo chown root:docker /run/secrets/honey-config.properties # if your user is in docker group, or root:$USER
```
Edit and set real values:
```bash
sudo nano /run/secrets/honey-config.properties
```
Notes:
- `SPRING_DATASOURCE_URL` - set to new DB URL
- `SPRING_DATASOURCE_PASSWORD` - just generate new secret
- `TELEGRAM_BOT_TOKEN` - token for Telegram bot
- `FRONTEND_URL` - put new domain here
- `APP_ADMIN_JWT_SECRET` - generate new secret using `openssl rand -base64 48` on VPS and put here
- `APP_TELEGRAM_WEBHOOK_TOKEN` - generate a new secret and set it using `POST https://api.telegram.org/bot<token>/setWebhook?url=https://<domain>/api/telegram/webhook/<secret>&max_connections=100`
- `PMA_ABSOLUTE_URI` - generate a new secret and set it. Don't forget to set the same to nginx
Create 2 files `admin_api_url` and `admin_base_path` with URL and secret path in `/run/secrets` folder.
### 2.3 Load DB password for Docker Compose
`docker-compose.prod.yml` expects `DB_ROOT_PASSWORD` (and MySQL healthcheck uses it). The repo has `scripts/load-db-password.sh` which reads the secret file; its currently wired to **lottery** path. For Honey, either:
- Edit `scripts/load-db-password.sh` and set:
- `SECRET_FILE="/run/secrets/honey-config.properties"`
- Or create a small wrapper that exports the same variables from `honey-config.properties`.
**When you need to source it:** Only for one-off manual `docker compose` runs (e.g. first-time start in §2.6, or starting phpMyAdmin in §4.1). You do **not** need to source it for deployment: `scripts/rolling-update.sh` loads the password from the secret file automatically when `DB_ROOT_PASSWORD` is not set.
**IMPORTANT**
`Change Java memory in docker-compose.prod.yml when you know the PROD VPS characteristics.`
### 2.4 Logging (logback) and config dir
Backend uses an external **logback** config so you can change log level without rebuilding. Create the config dir and put `logback-spring.xml` there:
```bash
mkdir -p /opt/app/backend/config
mkdir -p /opt/app/logs
```
Either copy from the JAR or from source:
```bash
# From backend dir
cp src/main/resources/logback-spring.xml /opt/app/backend/config/
# or extract from built JAR:
# unzip -p target/honey-be-*.jar BOOT-INF/classes/logback-spring.xml > /opt/app/backend/config/logback-spring.xml
```
Optional: run the existing setup script (it may still reference lottery paths; adjust or run the copy above):
```bash
cd /opt/app/backend/honey-be
./scripts/setup-logging.sh
```
Edit log level at any time:
```bash
nano /opt/app/backend/config/logback-spring.xml
# e.g. change <logger name="com.honey" level="INFO"/> to DEBUG
# Logback rescans periodically (e.g. 30s); no restart needed if scan is enabled
```
### 2.5 MySQL my.cnf (optional)
If you use a custom MySQL config in prod (e.g. for buffer pool):
```bash
# Create /opt/app/mysql/conf/my.cnf with your tuning; then in docker-compose.prod.yml
# the volume is already: /opt/app/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf:ro
```
Note: `on Staged VPS it has 4G RAM, so don't forget to change it for PROD accordingly.`
### 2.6 First start (backend + DB only)
```bash
cd /opt/app/backend/honey-be
source scripts/load-db-password.sh
docker compose -f docker-compose.prod.yml up -d db
# wait for DB healthy
docker compose -f docker-compose.prod.yml up -d backend
```
Note: `for Staged use a separate docker compose.`
Check:
```bash
docker ps
curl -s http://127.0.0.1:8080/actuator/health/readiness
```
Backend should listen only on `127.0.0.1:8080` (Nginx will proxy to it). Do **not** expose 8080 to the internet.
---
## 3. Nginx
### 3.1 Split config (like your lottery VPS)
- `Take 2 files from already working VPS: nginx.conf and sites-enabled/<domain.com> and put to new VPS.`
- `Remove or comment lines reg certificates and change 2 listen lines`:
```bash
# SSL Certificates
ssl_certificate /etc/letsencrypt/live/testforapp.website/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/testforapp.website/privkey.pem;
Change 'listen 443 ssl http2;' to 'listen 443;`
Change `listen [::]:443 ssl http2;` to `listen [::]:443;`
```
Enable and test:
```bash
sudo ln -s /etc/nginx/sites-available/testforapp.website /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
### 3.3 SSL (Lets Encrypt)
```bash
sudo certbot --nginx -d testforapp.website
```
Certbot will adjust the server block for certificates. Reload Nginx if needed.
And remove redundant ssl/listen lines from server block to not override certbot's configs.
---
## 4. phpMyAdmin
### 4.1 Start phpMyAdmin container
`docker-compose.prod.yml` already defines a **phpmyadmin** service (port 8081, same network as `db`). Start it:
```bash
cd /opt/app/backend/honey-be
source scripts/load-db-password.sh
docker compose -f docker-compose.prod.yml up -d phpmyadmin
```
### 4.2 Access via Nginx (recommended)
Do **not** expose 8081 publicly. Proxy it via Nginx under a secret path (e.g. `/your-secret-pma-path/`), as in the example above. Set `PMA_ABSOLUTE_URI` in the secret file so phpMyAdmin generates correct URLs:
In `/run/secrets/honey-config.properties` add (or use env when running compose):
```properties
PMA_ABSOLUTE_URI=https://your-domain.com/your-secret-pma-path/
```
Then reload Nginx and open `https://your-domain.com/your-secret-pma-path/`. Login: user `root`, password = `SPRING_DATASOURCE_PASSWORD` from the same secret file.
### 4.3 Optional: UFW for phpMyAdmin
If you ever expose 8081 temporarily, restrict it:
```bash
sudo ufw allow from YOUR_IP to any port 8081
sudo ufw reload
```
Prefer keeping 8081 bound to 127.0.0.1 and using only Nginx proxy.
---
## 5. Frontend (honey-fe)
### 5.1 Build locally and upload
On your machine (e.g. in `honey-test-fe` or your honey-fe repo):
```bash
cd honey-test-fe # or honey-fe
npm install
npm run build
scp -r dist/* root@YOUR_VPS_IP:/opt/app/frontend/dist/
```
Or with rsync:
```bash
rsync -avz dist/ root@YOUR_VPS_IP:/opt/app/frontend/dist/
```
Ensure the apps API base URL is correct for production (e.g. relative `""` or `VITE_API_BASE_URL` for your domain).
---
## 6. Admin panel (honey-admin)
### 6.1 Build with secret (on VPS or locally)
Admin often has a build that injects a public URL or env. From the repo:
```bash
cd honey-admin
npm install
npm run build:with-secret
```
Then copy the built output to the Nginx admin root:
**If you build on the VPS:**
```bash
cd /opt/app/admin/honey-admin
npm run build:with-secret
cp -r dist/* /opt/app/admin-panel/
```
**If you build locally:**
```bash
scp -r dist/* root@YOUR_VPS_IP:/opt/app/admin-panel/
```
The Nginx location for admin (e.g. `/your-secret-admin-path/`) must serve this directory and support SPA routing (`try_files` to `index.html`).
---
## 7. Rolling backend updates
Use the existing **rolling-update** script so Nginx switches to a new backend container with no downtime.
### 7.1 Script adaptation for Honey
The script in the repo may still reference **lottery** container names and Nginx paths. For Honey:
- **Containers:** `honey-backend` (primary), `honey-backend-new` (standby).
- **Nginx:** same idea as lottery: one upstream `backend` with `server 127.0.0.1:8080` and optionally `server 127.0.0.1:8082 backup;`. The script flips which port is primary.
Edit `scripts/rolling-update.sh` and replace:
- `lottery-backend``honey-backend`
- `lottery-backend-new``honey-backend-new`
The script auto-detects Nginx config from paths like `/etc/nginx/sites-enabled/win-spin.live`. For Honey, either:
- Symlink or name your site config so the script finds it (e.g. add a similar check for `honey.conf` in the script), or
- Set the path explicitly before running: `export NGINX_CONF=/etc/nginx/sites-enabled/your-domain && sudo ./scripts/rolling-update.sh`
### 7.2 Run rolling update
From the backend directory, run (no need to source `load-db-password.sh` — the script does it):
```bash
cd /opt/app/backend/honey-be
chmod +x scripts/rolling-update.sh
sudo ./scripts/rolling-update.sh
```
The script loads `DB_ROOT_PASSWORD` from the secret file if not set, then: builds the new image, starts `backend-new` on 8082, health-checks it, points Nginx to 8082, reloads Nginx, then stops the old backend.
---
## 8. Logging
- **App logs:** `/opt/app/logs/` (mounted into backend container; path can be set via `LOG_DIR` / logback).
- **Config:** `/opt/app/backend/config/logback-spring.xml` (edit to change level; no restart if scan is enabled).
- **Nginx:** `/var/log/nginx/access.log`, `/var/log/nginx/error.log`.
View backend logs:
```bash
docker logs -f honey-backend
# or
tail -f /opt/app/logs/honey-be.log
```
---
## 9. MySQL backups to backup VPS
### 9.1 Backup script for Honey
Copy and adapt the existing **`scripts/backup-database.sh`** (or create a Honey-specific one). Set:
- `MYSQL_CONTAINER="honey-mysql"`
- `MYSQL_DATABASE="honey_db"`
- `SECRET_FILE="/run/secrets/honey-config.properties"`
- `BACKUP_FILENAME="honey_db_backup_${TIMESTAMP}.sql"` (and `.gz` if compressing)
- Remote path and retention (e.g. `BACKUP_VPS_PATH`, keep last 30 days) to match your backup server.
Ensure the script runs as root (or with sudo) so it can read `/run/secrets/honey-config.properties`, and that it uses the same `DB_PASSWORD` / `SPRING_DATASOURCE_PASSWORD` as in the secret file.
### 9.2 SSH key to backup VPS
On the Honey VPS:
```bash
ssh-keygen -t ed25519 -C "backup@honey-vps" -f ~/.ssh/backup_key
ssh-copy-id -i ~/.ssh/backup_key.pub user@BACKUP_VPS_IP
```
Test:
```bash
ssh -i ~/.ssh/backup_key user@BACKUP_VPS_IP "echo OK"
```
### 9.3 Cron (daily at 2 AM)
```bash
sudo crontab -e
```
Add:
```cron
0 2 * * * /opt/app/backend/honey-be/scripts/backup-database.sh >> /opt/app/logs/backup.log 2>&1
```
Use the Honey-adapted backup script path and ensure `backup-database.sh` uses `honey_db` and `honey-mysql`.
---
## 10. Quick reference
| Item | Honey |
|------|-----------------------------------------------------------------|
| **App root** | `/opt/app` |
| **Backend code** | `/opt/app/backend/honey-be` (honey-be) |
| **Frontend static** | `/opt/app/frontend/dist` (honey-fe build) |
| **Admin static** | `/opt/app/admin-panel` (honey-admin build) |
| **Secret file** | `/run/secrets/honey-config.properties` |
| **Logs** | `/opt/app/logs` (+ logback config in `/opt/app/backend/config`) |
| **Avatars** | `/opt/app/data/avatars` |
| **Nginx** | `/etc/nginx/nginx.conf` + `/etc/nginx/sites-enabled/your-domain` |
| **DB container** | `honey-mysql` |
| **DB name** | `honey_db` |
| **Backend containers** | `honey-backend`, `honey-backend-new` (rolling) |
| **phpMyAdmin** | Container `honey-phpmyadmin`, port 8081 → proxy via Nginx secret path |
### Deploy commands (summary)
- **Backend (rolling):**
`cd /opt/app/backend/honey-be && chmod +x scripts/rolling-update.sh && sudo ./scripts/rolling-update.sh`
(Password is loaded from the secret file inside the script.)
- **Frontend:**
Local: `npm run build` then `scp -r dist/* root@VPS:/opt/app/frontend/dist/`
- **Admin:**
On VPS: `cd /opt/app/admin/honey-admin && npm run build:with-secret && cp -r dist/* /opt/app/admin-panel/`
Or build locally and `scp -r dist/* root@VPS:/opt/app/admin-panel/`
- **Log level:**
Edit `/opt/app/backend/config/logback-spring.xml` (no restart if scan enabled).
---
## 11. Checklist after setup
- [ ] `/opt/app` structure created; ownership and permissions correct.
- [ ] `/run/secrets/honey-config.properties` created and filled (no placeholders).
- [ ] `load-db-password.sh` (and backup/rolling scripts) use Honey secret path and container/db names.
- [ ] Backend + DB + phpMyAdmin start; health check returns 200.
- [ ] Nginx site config in place; `nginx -t` OK; HTTPS works.
- [ ] Frontend and admin builds deployed to `/opt/app/frontend/dist` and `/opt/app/admin-panel`.
- [ ] API and WebSocket work through Nginx; avatars and admin paths load.
- [ ] phpMyAdmin reachable only via Nginx secret path; 8081 not public.
- [ ] Rolling update script updated for `honey-backend` / `honey-backend-new` and tested.
- [ ] Backup script adapted for `honey_db` / `honey-mysql`; cron runs and backups appear on backup VPS.
- [ ] Logs under `/opt/app/logs` and logback config under `/opt/app/backend/config`; log level change works.
This gives you the same layout and workflow as your lottery VPS, but for Honey (honey-be, honey-fe, honey-admin) with Nginx, phpMyAdmin, logging, and backups.