refactor: deploy model — all files under /opt/pulse-lets-go

Single prefix deployment: /opt/pulse-lets-go/ contains
bin/, data/, web/, log/ — no more split across
/usr/local/bin, /etc, /usr/local/share, /var/log.

* Makefile: install → deploy target with PREFIX=/opt/pulse-lets-go
* deploy/pulse-lets-go.service: all paths under /opt/pulse-lets-go,
  removed stale nats.service dependency
* main.go: default dataDir = parent of exeDir (PREFIX/bin → PREFIX/data)
* README: updated all paths, step 1 uses make deploy
This commit is contained in:
Maksim Totmin 2026-06-25 19:35:54 +07:00
parent 0d8a56e73f
commit 273e316af9
4 changed files with 46 additions and 46 deletions

View File

@ -1,12 +1,12 @@
# pulse-lets-go — Telephone Load Balancer
# Сборка Go backend + SvelteKit фронта в единый бинарник.
APP := pulse-lets-go
BINDIR := bin
APP := pulse-lets-go
BINDIR := bin
WEB_DIR := web
DATA_DIR := data
PREFIX := /opt/pulse-lets-go
.PHONY: all build build-go build-web clean run test install \
.PHONY: all build build-go build-web clean run test deploy \
emulate emulate-normal emulate-overload emulate-cpu-low emulate-fail-high \
emulate-node-down emulate-stale emulate-chaos build-emulator \
build-siptest siptest-uas siptest-uac siptest-full
@ -50,21 +50,23 @@ build-prod:
rm -rf $(BINDIR)/web && cp -r $(WEB_DIR)/build $(BINDIR)/web
CGO_ENABLED=0 go build -ldflags="-s -w" -o $(BINDIR)/$(APP) ./cmd/$(APP)
# Установка: копирует бинарник и статику в /usr/local
install: build
@echo "→ Установка в /usr/local"
mkdir -p /usr/local/share/$(APP)/web
cp -r $(WEB_DIR)/build /usr/local/share/$(APP)/web/
cp $(BINDIR)/$(APP) /usr/local/bin/$(APP)
chmod +x /usr/local/bin/$(APP)
@echo "✓ Установлен в /usr/local/bin/$(APP)"
# Деплой в PREFIX: бинарник + статика + data + log
deploy: build-prod
@echo "→ Деплой в $(PREFIX)"
install -d $(PREFIX)/bin $(PREFIX)/data $(PREFIX)/web $(PREFIX)/log
install -m 755 $(BINDIR)/$(APP) $(PREFIX)/bin/
cp -r $(WEB_DIR)/build/. $(PREFIX)/web/
@echo "✓ Готово: $(PREFIX)"
@echo " $(PREFIX)/bin/$(APP)"
@echo " $(PREFIX)/web/ (SvelteKit статика)"
@echo " $(PREFIX)/data/ (config.json, trunks.json, users.json)"
@echo " $(PREFIX)/log/ (ASCII-лог метрик)"
# Установка systemd unit
install-systemd:
@echo "→ Установка systemd unit"
cp deploy/$(APP).service /etc/systemd/system/
install -m 644 deploy/$(APP).service /etc/systemd/system/
systemctl daemon-reload
@echo "✓ systemd unit установлен. Запуск: systemctl start $(APP)"
@echo "✓ systemd unit установлен. Запуск: sudo systemctl start $(APP)"
# ============================================================
# Эмулятор метрик

View File

@ -423,7 +423,7 @@ end
### systemd
```bash
make install # копирует бинарник + web-статику
make deploy # полный деплой в /opt/pulse-lets-go
make install-systemd # устанавливает systemd unit
```
@ -436,16 +436,15 @@ After=network.target
[Service]
User=pulse
Group=pulse
WorkingDirectory=/usr/local/share/pulse-lets-go
Environment=PULSE_DATA_DIR=/etc/pulse-lets-go
ExecStart=/usr/local/bin/pulse-lets-go
ExecStart=/opt/pulse-lets-go/bin/pulse-lets-go
WorkingDirectory=/opt/pulse-lets-go
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/etc/pulse-lets-go /var/log/pulse-lets-go
ReadWritePaths=/opt/pulse-lets-go/data /opt/pulse-lets-go/log
[Install]
WantedBy=multi-user.target
@ -454,14 +453,15 @@ WantedBy=multi-user.target
### Структура директорий
```
/usr/local/share/pulse-lets-go/
├── web/build/ # SvelteKit статика
/etc/pulse-lets-go/
├── config.json # Конфигурация
├── trunks.json # Транки
├── users.json # Пользователи
/var/log/pulse-lets-go/
└── metrics.YYYY-MM-DD.log # ASCII-лог метрик
/opt/pulse-lets-go/
├── bin/pulse-lets-go # Бинарник
├── data/
│ ├── config.json # Конфигурация
│ ├── trunks.json # Транки
│ └── users.json # Пользователи
├── web/ # SvelteKit статика
└── log/
└── metrics.YYYY-MM-DD.log # ASCII-лог метрик
```
### Security
@ -497,13 +497,13 @@ fs_cli -x "load mod_curl"
# <load module="mod_curl"/>
```
### Порядок деплоя (7 шагов)
### Порядок деплоя (8 шагов)
**Шаг 1 — Скопировать бинарник и конфиги**
**Шаг 1 — Деплой на сервер**
```bash
make build-prod
scp bin/pulse-lets-go devadmin@10.101.60.81:/usr/local/bin/
scp -r contrib/route.lua devadmin@10.101.60.81:/tmp/
make deploy
scp -r /opt/pulse-lets-go devadmin@10.101.60.81:/opt/
scp contrib/route.lua devadmin@10.101.60.81:/tmp/
```
**Шаг 2 — NATS сервер** (если не установлен)
@ -562,11 +562,10 @@ curl -X POST .../api/trunks
**Шаг 7 — Запуск pulse-lets-go**
```bash
sudo mkdir -p /etc/pulse-lets-go /var/log/pulse-lets-go
# config.json создастся автоматически при первом запуске
# config.json создастся автоматически при первом запуске в /opt/pulse-lets-go/data/
# Добавить esl блок в config.json:
# "esl": {"host": "127.0.0.1", "port": 8021, "password": "ClueCon"}
PULSE_DATA_DIR=/etc/pulse-lets-go ./pulse-lets-go
/opt/pulse-lets-go/bin/pulse-lets-go
```
**Шаг 8 — Проверка**

View File

@ -27,11 +27,12 @@ import (
func main() {
// Определяем рабочую директорию
// По умолчанию data/ — родительская папка от бинарника.
// Пример: /opt/pulse-lets-go/bin/pulse-lets-go → /opt/pulse-lets-go/data
exe, _ := os.Executable()
exeDir := filepath.Dir(exe)
dataDir := filepath.Join(exeDir, "data")
dataDir := filepath.Join(filepath.Dir(exeDir), "data")
// Разрешаем переопределение через переменную окружения
if envDir := os.Getenv("PULSE_DATA_DIR"); envDir != "" {
dataDir = envDir
}
@ -235,13 +236,13 @@ func main() {
}
// findWebDir ищет директорию со SvelteKit сборкой (web/build/).
// Пробует по порядку: переменная окружения, рядом с бинарником, в корне проекта, CWD.
// Пробует по порядку: PULSE_WEB_DIR, CWD, ../web/build, рядом с бинарником.
func findWebDir(exeDir string) string {
candidates := []string{
os.Getenv("PULSE_WEB_DIR"),
"web/build", // ./web/build (CWD — dev, systemd working dir)
filepath.Join(filepath.Dir(exeDir), "web", "build"), // ../web/build (корень проекта, dev с bin/)
filepath.Join(exeDir, "web", "build"), // рядом с бинарником (production install)
filepath.Join(exeDir, "web", "build"), // рядом с бинарником (production install, make deploy)
}
for _, d := range candidates {
if d == "" {

View File

@ -1,16 +1,14 @@
[Unit]
Description=pulse-lets-go — Telephone Load Balancer
Documentation=https://github.com/pulse-lets-go
After=network.target nats.service
Wants=nats.service
After=network.target
[Service]
Type=simple
User=pulse
Group=pulse
ExecStart=/usr/local/bin/pulse-lets-go
WorkingDirectory=/usr/local/share/pulse-lets-go
Environment=PULSE_DATA_DIR=/etc/pulse-lets-go
ExecStart=/opt/pulse-lets-go/bin/pulse-lets-go
WorkingDirectory=/opt/pulse-lets-go
Restart=always
RestartSec=5
@ -19,7 +17,7 @@ NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/etc/pulse-lets-go /var/log/pulse-lets-go
ReadWritePaths=/opt/pulse-lets-go/data /opt/pulse-lets-go/log
# Логирование
StandardOutput=journal