15 KiB
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/appfor app files,/run/secretsfor config,/opt/app/logsfor logs - Nginx: main config + site config (e.g.
nginx.conf+sites-enabled/your-domain)
1. VPS basics
1.1 System update and installs
sudo apt update && sudo apt upgrade -y
# 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):
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
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:
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:
sudo nano /run/secrets/honey-config.properties
Notes:
SPRING_DATASOURCE_URL- set to new DB URLSPRING_DATASOURCE_PASSWORD- just generate new secretTELEGRAM_BOT_TOKEN- token for Telegram botFRONTEND_URL- put new domain hereAPP_ADMIN_JWT_SECRET- generate new secret usingopenssl rand -base64 48on VPS and put hereAPP_TELEGRAM_WEBHOOK_TOKEN- generate a new secret and set it usingPOST https://api.telegram.org/bot<token>/setWebhook?url=https://<domain>/api/telegram/webhook/<secret>&max_connections=100PMA_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; it’s currently wired to lottery path. For Honey, either:
- Edit
scripts/load-db-password.shand 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.Change the rolling-update.sh script to match sites-enabled nginx file name for PROD when you know the domain
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:
mkdir -p /opt/app/backend/config
mkdir -p /opt/app/logs
Either copy from the JAR or from source:
# 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):
cd /opt/app/backend/honey-be
./scripts/setup-logging.sh
Edit log level at any time:
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):
# 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)
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:
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:
# 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:
sudo ln -s /etc/nginx/sites-available/testforapp.website /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
3.3 SSL (Let’s Encrypt)
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:
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):
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:
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):
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:
rsync -avz dist/ root@YOUR_VPS_IP:/opt/app/frontend/dist/
Ensure the app’s 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:
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:
cd /opt/app/admin/honey-admin
npm run build:with-secret
cp -r dist/* /opt/app/admin-panel/
If you build locally:
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
backendwithserver 127.0.0.1:8080and optionallyserver 127.0.0.1:8082 backup;. The script flips which port is primary.
Edit scripts/rolling-update.sh and replace:
lottery-backend→honey-backendlottery-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.confin 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):
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 viaLOG_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:
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.gzif 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:
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:
ssh -i ~/.ssh/backup_key user@BACKUP_VPS_IP "echo OK"
9.3 Cron (daily at 2 AM)
sudo crontab -e
Add:
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 buildthenscp -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 andscp -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/appstructure created; ownership and permissions correct./run/secrets/honey-config.propertiescreated 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 -tOK; HTTPS works. - Frontend and admin builds deployed to
/opt/app/frontend/distand/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-newand tested. - Backup script adapted for
honey_db/honey-mysql; cron runs and backups appear on backup VPS. - Logs under
/opt/app/logsand 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.