fix: загрузка sac-api.env через pydantic, не EnvironmentFile systemd
This commit is contained in:
+23
-4
@@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -5,15 +6,33 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
|||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
SCHEMA_PATH = ROOT / "schemas" / "event-schema-v1.json"
|
SCHEMA_PATH = ROOT / "schemas" / "event-schema-v1.json"
|
||||||
|
DEFAULT_CONFIG_FILE = Path("/opt/security-alert-center/config/sac-api.env")
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
def _resolve_config_files() -> tuple[str, ...]:
|
||||||
model_config = SettingsConfigDict(
|
"""Файлы конфигурации для pydantic (корректный разбор кавычек и URL)."""
|
||||||
env_file=".env",
|
candidates: list[Path] = []
|
||||||
|
explicit = os.environ.get("SAC_CONFIG_FILE", "").strip()
|
||||||
|
if explicit:
|
||||||
|
candidates.append(Path(explicit))
|
||||||
|
else:
|
||||||
|
candidates.append(DEFAULT_CONFIG_FILE)
|
||||||
|
candidates.append(Path(".env"))
|
||||||
|
return tuple(str(p) for p in candidates if p.is_file())
|
||||||
|
|
||||||
|
|
||||||
|
def _settings_config() -> SettingsConfigDict:
|
||||||
|
files = _resolve_config_files()
|
||||||
|
return SettingsConfigDict(
|
||||||
|
env_file=files if files else None,
|
||||||
env_file_encoding="utf-8",
|
env_file_encoding="utf-8",
|
||||||
extra="ignore",
|
extra="ignore",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Settings(BaseSettings):
|
||||||
|
model_config = _settings_config()
|
||||||
|
|
||||||
database_url: str = "postgresql+psycopg2://sac:sac@localhost:5432/sac"
|
database_url: str = "postgresql+psycopg2://sac:sac@localhost:5432/sac"
|
||||||
sac_public_url: str = "http://localhost:8000"
|
sac_public_url: str = "http://localhost:8000"
|
||||||
jwt_secret: str = "change-me-in-production"
|
jwt_secret: str = "change-me-in-production"
|
||||||
@@ -24,7 +43,7 @@ class Settings(BaseSettings):
|
|||||||
sac_admin_username: str = "admin"
|
sac_admin_username: str = "admin"
|
||||||
sac_admin_password: str = ""
|
sac_admin_password: str = ""
|
||||||
|
|
||||||
event_schema_path: str = str(SCHEMA_PATH) # override: EVENT_SCHEMA_PATH
|
event_schema_path: str = str(SCHEMA_PATH)
|
||||||
cors_origins: str = "*"
|
cors_origins: str = "*"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# Native: /opt/security-alert-center/config/sac-api.env
|
# Native: /opt/security-alert-center/config/sac-api.env
|
||||||
# sudo chown sac:sac /opt/security-alert-center/config/sac-api.env
|
# sudo chown sac:sac ... && sudo chmod 600 ...
|
||||||
# sudo chmod 600 /opt/security-alert-center/config/sac-api.env
|
# Пароль в URL — в двойных кавычках. Символ # в пароле допустим только внутри кавычек.
|
||||||
|
# systemd НЕ парсит этот файл — читает приложение (SAC_CONFIG_FILE).
|
||||||
|
|
||||||
DATABASE_URL=postgresql+psycopg2://sac:CHANGE_ME_POSTGRES_PASSWORD@127.0.0.1:5432/sac
|
DATABASE_URL=postgresql+psycopg2://sac:CHANGE_ME_POSTGRES_PASSWORD@127.0.0.1:5432/sac
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ Type=simple
|
|||||||
User=sac
|
User=sac
|
||||||
Group=sac
|
Group=sac
|
||||||
WorkingDirectory=/opt/security-alert-center/backend
|
WorkingDirectory=/opt/security-alert-center/backend
|
||||||
EnvironmentFile=/opt/security-alert-center/config/sac-api.env
|
# Конфиг читает само приложение (pydantic), не systemd — иначе ломаются пароли с #, $ и т.д.
|
||||||
|
Environment=SAC_CONFIG_FILE=/opt/security-alert-center/config/sac-api.env
|
||||||
Environment=PYTHONPATH=/opt/security-alert-center/backend
|
Environment=PYTHONPATH=/opt/security-alert-center/backend
|
||||||
ExecStart=/opt/security-alert-center/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000
|
ExecStart=/opt/security-alert-center/backend/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8000
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|||||||
@@ -171,7 +171,10 @@ sudo -u sac bash -c 'set -a; source /opt/security-alert-center/config/sac-api.en
|
|||||||
|
|
||||||
## 8. systemd
|
## 8. systemd
|
||||||
|
|
||||||
|
Приложение загружает `config/sac-api.env` **само** (не через `EnvironmentFile` systemd) — так же, как при `alembic` с `source`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
cd /opt/security-alert-center && sudo git pull
|
||||||
sudo cp /opt/security-alert-center/deploy/systemd/sac-api.service /etc/systemd/system/
|
sudo cp /opt/security-alert-center/deploy/systemd/sac-api.service /etc/systemd/system/
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl enable sac-api
|
sudo systemctl enable sac-api
|
||||||
@@ -290,7 +293,8 @@ sudo systemctl restart sac-api
|
|||||||
| Симптом | Действие |
|
| Симптом | Действие |
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
| `sac-api.env: Permission denied` | Конфиг в `/opt/security-alert-center/config/`, `chown sac:sac`, `chmod 600`. Не используйте `/etc/...` с каталогом `root:root` |
|
| `sac-api.env: Permission denied` | Конфиг в `/opt/security-alert-center/config/`, `chown sac:sac`, `chmod 600`. Не используйте `/etc/...` с каталогом `root:root` |
|
||||||
| `password authentication failed for user sac` | Пароль в `DATABASE_URL` ≠ пароль в PostgreSQL; или `.env` не прочитан (тогда берётся дефолт `sac:sac`). Исправить пароль: `sudo -u postgres psql -c "ALTER USER sac PASSWORD '...';"` и обновить `DATABASE_URL` |
|
| `password authentication failed` в **sac-api**, но alembic OK | Старый unit с `EnvironmentFile=` — `git pull`, обновить `sac-api.service`, `daemon-reload`, `restart`. Либо пароль в `DATABASE_URL` ≠ PostgreSQL |
|
||||||
|
| `password authentication failed` везде | Пароль в `DATABASE_URL` в кавычках; `ALTER USER sac WITH PASSWORD`; тот же пароль в URL |
|
||||||
| `database: error` / SQLAlchemy connect | `systemctl status postgresql`; проверить `DATABASE_URL` после успешного `source` |
|
| `database: error` / SQLAlchemy connect | `systemctl status postgresql`; проверить `DATABASE_URL` после успешного `source` |
|
||||||
| 401 ingest | ключ в `Authorization: Bearer`; проверить `SAC_BOOTSTRAP_API_KEY` |
|
| 401 ingest | ключ в `Authorization: Bearer`; проверить `SAC_BOOTSTRAP_API_KEY` |
|
||||||
| 502 от nginx | API не слушает: `ss -lntp \| grep 8000`, `systemctl restart sac-api` |
|
| 502 от nginx | API не слушает: `ss -lntp \| grep 8000`, `systemctl restart sac-api` |
|
||||||
|
|||||||
Reference in New Issue
Block a user