Files

179 lines
3.7 KiB
Markdown

# Strike Arena
Next.js 15 standalone application for Strike Arena. The app runs on Node.js 22, stores data in SQLite through `better-sqlite3`, and is served by Nginx in Docker Compose.
## Runtime Paths
- SQLite database: `/app/data/strike-arena.db`
- Uploaded files: `/app/uploads`
- Game images in the repository: `uploads/games`
SQLite WAL and foreign keys are enabled on startup in `src/lib/bd.ts`.
## Environment
Create `.env` from the example:
```bash
cp .env.local.example .env
```
Required variables:
```env
ADMIN_HASHED_PASSWORD=
JWT_SECRET=
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
```
Generate a production `JWT_SECRET`:
```bash
JWT_SECRET_NEW="$(openssl rand -base64 48 | tr -d '\n')"
sed -i "s#^JWT_SECRET=.*#JWT_SECRET=${JWT_SECRET_NEW}#" .env
grep '^JWT_SECRET=' .env
```
Do not deploy with `JWT_SECRET=replace-with-generated-secret`.
## Local Development
```bash
npm ci
npm run dev
```
Open `http://localhost:3000`.
## Production Docker
The production Compose file binds Nginx to `10.20.0.25:18083`.
`uploads` is mounted as `./uploads:/app/uploads` so repository images remain available and new admin uploads are persisted on the host. SQLite data is stored in the Docker volume `sqlite_data`.
Deploy on `docker-runtime-2`:
```bash
ssh -i /root/.ssh/docker2_vm_ed25519 crimson@10.20.0.25
sudo su
mkdir -p /opt/docker-apps/strike_arena
chown -R crimson:crimson /opt/docker-apps/strike_arena
cd /opt/docker-apps/strike_arena
git clone https://git.flamy.studio/sbb45/StikeArena_chrt.git .
cp .env.local.example .env
```
Set a real `JWT_SECRET`, fill Telegram variables if notifications are needed, then prepare uploads permissions:
```bash
mkdir -p uploads/games
chown -R 1001:1001 uploads
```
Check the port:
```bash
ss -lntup | grep ':18083' || true
```
Build and run:
```bash
docker compose config
docker compose build --no-cache
docker compose up -d
docker compose ps
docker compose logs -f --tail=120 app nginx
```
Runtime checks:
```bash
curl -I http://10.20.0.25:18083
curl -I http://10.20.0.25:18083/health
curl -I http://10.20.0.25:18083/api/faq
curl -I http://10.20.0.25:18083/api/games
```
SQLite checks:
```bash
docker compose exec app node - <<'NODE'
const Database = require('better-sqlite3');
const db = new Database('/app/data/strike-arena.db');
console.log(db.pragma('journal_mode', { simple: true }));
console.log(db.pragma('foreign_keys', { simple: true }));
db.close();
NODE
```
Expected output:
```text
wal
1
```
Check persisted paths:
```bash
docker compose exec app ls -lah /app/data
docker compose exec app ls -lah /app/uploads/games | head
```
## Caddy
Add this on `edge-proxy` after the app responds on `10.20.0.25:18083`:
```bash
ssh -i /root/.ssh/edge_vm_ed25519 crimson@192.168.0.80
curl -I --connect-timeout 5 http://10.20.0.25:18083
curl -I --connect-timeout 5 http://10.20.0.25:18083/health
sudo grep -R "belixa.ru\|10.20.0.25:18083" -n /etc/caddy || true
sudo cp -a /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%F-%H%M%S)
```
Append the Caddy block:
```caddyfile
# Strike Arena
http://www.belixa.ru, https://www.belixa.ru {
redir https://belixa.ru{uri} 308
}
belixa.ru {
encode zstd gzip
reverse_proxy 10.20.0.25:18083 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto https
header_up X-Forwarded-Port 443
}
}
```
Reload Caddy:
```bash
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager
```
Public checks:
```bash
curl -I https://belixa.ru
curl -I https://www.belixa.ru
curl -I http://belixa.ru
curl -I http://www.belixa.ru
```