This commit is contained in:
2026-05-10 08:48:42 +02:00
parent cc9d3220c9
commit 79df1aa493
15 changed files with 3523 additions and 892 deletions

View File

@@ -285,6 +285,10 @@ class Settings(BaseSettings):
default="info",
description="Application log level: debug | info | warning | error | critical.",
)
log_file: str | None = Field(
default="/data/log/bangui.log",
description="Optional file path for writing application logs. Set to null to disable file logging.",
)
geoip_db_path: str | None = Field(
default=None,
description=(

View File

@@ -107,15 +107,20 @@ def _external_logging_processor(
return event_dict
def _configure_logging(log_level: str, settings: Settings | None = None) -> None:
def _configure_logging(log_level: str, log_file: str | None, settings: Settings | None = None) -> None:
"""Configure structlog for production JSON output.
Args:
log_level: One of ``debug``, ``info``, ``warning``, ``error``, ``critical``.
log_file: Optional file path to write logs to (in addition to stdout).
settings: Optional Settings object to configure external logging.
"""
level: int = logging.getLevelName(log_level.upper())
logging.basicConfig(level=level, stream=sys.stdout, format="%(message)s")
handlers: list[logging.Handler] = [logging.StreamHandler(sys.stdout)]
if log_file:
os.makedirs(os.path.dirname(log_file), exist_ok=True)
handlers.append(logging.FileHandler(log_file))
logging.basicConfig(level=level, handlers=handlers, format="%(message)s")
processors = [
structlog.contextvars.merge_contextvars,
@@ -225,7 +230,7 @@ async def _lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
raise RuntimeError(msg) from exc
# Now configure logging with the handler in place
_configure_logging(settings.log_level, settings)
_configure_logging(settings.log_level, settings.log_file, settings)
log.info("bangui_starting_up", database_path=settings.database_path)

View File

@@ -158,7 +158,8 @@ def _build_inactive_jail(
ban_time_seconds = _parse_time_to_seconds(settings.get("bantime"), 600)
find_time_seconds = _parse_time_to_seconds(settings.get("findtime"), 600)
log_encoding = settings.get("logencoding") or "auto"
backend = settings.get("backend") or "auto"
backend_raw = settings.get("backend") or "auto"
backend = backend_raw if not (backend_raw.startswith("%(") and backend_raw.endswith(")")) else "auto"
date_pattern = settings.get("datepattern") or None
use_dns = settings.get("usedns") or "warn"
prefregex = settings.get("prefregex") or ""

View File

@@ -112,49 +112,49 @@ HEALTH_CHECK_INTERVAL_SECONDS: Final[int] = 30
# Rate limits (per IP)
# ---------------------------------------------------------------------------
RATE_LIMIT_BANS_BAN_REQUESTS: Final[int] = 100
RATE_LIMIT_BANS_BAN_REQUESTS: Final[int] = 10000
"""Max ban requests per IP per minute."""
RATE_LIMIT_BANS_UNBAN_REQUESTS: Final[int] = 100
RATE_LIMIT_BANS_UNBAN_REQUESTS: Final[int] = 10000
"""Max unban requests per IP per minute."""
RATE_LIMIT_BLOCKLIST_IMPORT_REQUESTS: Final[int] = 100
RATE_LIMIT_BLOCKLIST_IMPORT_REQUESTS: Final[int] = 10000
"""Max blocklist import requests per IP per hour."""
RATE_LIMIT_CONFIG_UPDATE_REQUESTS: Final[int] = 50
RATE_LIMIT_CONFIG_UPDATE_REQUESTS: Final[int] = 5000
"""Max config update requests per IP per minute."""
RATE_LIMIT_FILTER_UPDATE_REQUESTS: Final[int] = 50
RATE_LIMIT_FILTER_UPDATE_REQUESTS: Final[int] = 5000
"""Max filter config update requests per IP per minute."""
RATE_LIMIT_FILTER_CREATE_REQUESTS: Final[int] = 50
RATE_LIMIT_FILTER_CREATE_REQUESTS: Final[int] = 5000
"""Max filter config create requests per IP per minute."""
RATE_LIMIT_FILTER_DELETE_REQUESTS: Final[int] = 50
RATE_LIMIT_FILTER_DELETE_REQUESTS: Final[int] = 5000
"""Max filter config delete requests per IP per minute."""
RATE_LIMIT_ACTION_UPDATE_REQUESTS: Final[int] = 50
RATE_LIMIT_ACTION_UPDATE_REQUESTS: Final[int] = 5000
"""Max action config update requests per IP per minute."""
RATE_LIMIT_ACTION_CREATE_REQUESTS: Final[int] = 50
RATE_LIMIT_ACTION_CREATE_REQUESTS: Final[int] = 5000
"""Max action config create requests per IP per minute."""
RATE_LIMIT_ACTION_DELETE_REQUESTS: Final[int] = 50
RATE_LIMIT_ACTION_DELETE_REQUESTS: Final[int] = 5000
"""Max action config delete requests per IP per minute."""
RATE_LIMIT_JAIL_UPDATE_REQUESTS: Final[int] = 100
RATE_LIMIT_JAIL_UPDATE_REQUESTS: Final[int] = 10000
"""Max jail config update requests per IP per minute."""
RATE_LIMIT_JAIL_CREATE_REQUESTS: Final[int] = 100
RATE_LIMIT_JAIL_CREATE_REQUESTS: Final[int] = 10000
"""Max jail config create requests per IP per minute."""
RATE_LIMIT_JAIL_DELETE_REQUESTS: Final[int] = 100
RATE_LIMIT_JAIL_DELETE_REQUESTS: Final[int] = 10000
"""Max jail config delete requests per IP per minute."""
RATE_LIMIT_JAIL_ACTIVATE_REQUESTS: Final[int] = 100
RATE_LIMIT_JAIL_ACTIVATE_REQUESTS: Final[int] = 10000
"""Max jail activation requests per IP per minute."""
RATE_LIMIT_JAIL_DEACTIVATE_REQUESTS: Final[int] = 100
RATE_LIMIT_JAIL_DEACTIVATE_REQUESTS: Final[int] = 10000
"""Max jail deactivation requests per IP per minute."""
# ---------------------------------------------------------------------------