towerops/config/config.exs
Graham McIntire 50324c61ce feat(metrics): expose Prometheus /metrics via PromEx on :9568
Add PromEx with Application/BEAM/Phoenix/LiveView/Ecto/Oban plugins plus
a custom plugin that bridges existing Towerops Oban/Redis telemetry events.
The metrics HTTP server runs isolated on port 9568 so scrape traffic never
traverses the public Traefik IngressRoute.

The pod template carries prometheus.io annotations (scrape, port, path, job)
so the external Prometheus on 10.0.15.31 discovers each pod through the
existing kubernetes-pods scrape job (apiserver-proxy).
2026-05-08 10:25:25 -05:00

182 lines
5.6 KiB
Elixir

# This file is responsible for configuring your application
# and its dependencies with the aid of the Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
# General application configuration
import Config
# Configure time zone database to use tzdata for IANA timezone support
config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase
config :error_tracker,
repo: Towerops.Repo,
otp_app: :towerops,
ignorer: Towerops.ErrorTrackerIgnorer
# Configure esbuild (the version is required)
config :esbuild,
version: "0.25.4",
towerops: [
args:
~w(js/app.ts --bundle --splitting --format=esm --target=es2022 --outdir=../priv/static/assets/js --external:/fonts/* --external:/images/* --alias:@=.),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
]
config :honeybadger,
api_key: "hbp_xe5xMnpLZ2XJsXQJujoEkgCmiqCfwa0uYA3Y",
environment_name: config_env(),
insights_enabled: true,
use_logger: true,
filter: Towerops.HoneybadgerFilter
# Configure Elixir's Logger
config :logger, :default_formatter,
format: "$time $metadata[$level] $message\n",
metadata: [
:request_id,
:remote_ip,
:status,
:duration_ms,
:kind,
:reason,
:stacktrace,
:agent_token_id,
:device_id,
:error
]
# Filter out noisy errors from port scanners and bots
config :logger, :default_handler,
filters: [
# Suppress HTTP/0.9 and other invalid protocol errors from Bandit
# These are typically from port scanners and automated bots
bandit_invalid_http: {&Towerops.LogFilter.filter_bandit_errors/2, []},
# Suppress benign port_died and write_failed errors during K8s pod shutdown
shutdown_errors: {&Towerops.LoggerFilters.drop_shutdown_errors/2, []}
]
# Register protobuf MIME type for agent API
config :mime, :types, %{
"application/x-protobuf" => ["protobuf"]
}
# Filter sensitive parameters from logs
# These parameters will be replaced with "[FILTERED]" in Phoenix logs and error reports
config :phoenix, :filter_parameters, [
"password",
"snmp_community",
"community",
"secret",
"token",
"api_key",
# SNMPv3 credentials (for future use)
"auth_password",
"priv_password",
"auth_pass",
"priv_pass"
]
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
# Configure Req HTTP client to use our Finch pool with CA certs
config :req, default_options: [finch: Towerops.Finch]
# Configure tailwind (the version is required)
config :tailwind,
version: "4.1.12",
towerops: [
args: ~w(
--input=assets/css/app.css
--output=priv/static/assets/css/app.css
),
cd: Path.expand("..", __DIR__)
]
# Configure the mailer
#
# By default it uses the "Local" adapter which stores the emails
# locally. You can see the emails in your browser, at "/dev/mailbox".
#
# For production it's recommended to configure a different adapter
# at the `config/runtime.exs`.
config :towerops, Towerops.Mailer, adapter: Swoosh.Adapters.Local
# PromEx — Prometheus metrics exporter.
# Runs an isolated HTTP server on port 9568 so scrape traffic never traverses
# the public Traefik IngressRoute. The Pod template in k8s/deployment.yaml
# carries `prometheus.io/scrape` annotations so the external Prometheus
# (10.0.15.31) discovers it via the apiserver-proxy `kubernetes-pods` job.
config :towerops, Towerops.PromEx,
manual_metrics_start_delay: :no_delay,
drop_metrics_groups: [],
grafana: :disabled,
metrics_server: [
port: 9568,
path: "/metrics",
protocol: :http,
pool_size: 5,
cowboy_opts: [],
auth_strategy: :none
]
# Configure Ecto to use SQL structure dumps for faster test setup
# This allows CI to load the schema instantly instead of running 172+ migrations
config :towerops, Towerops.Repo,
dump_path: "priv/repo/structure.sql",
migration_timestamps: [type: :naive_datetime_usec],
types: Towerops.PostgrexTypes
# Configure the endpoint
config :towerops, ToweropsWeb.Endpoint,
url: [host: "localhost"],
adapter: Bandit.PhoenixAdapter,
render_errors: [
formats: [html: ToweropsWeb.ErrorHTML, json: ToweropsWeb.ErrorJSON],
layout: false
],
pubsub_server: Towerops.PubSub,
live_view: [signing_salt: "Uh1ABfdI"]
# Default coverage raster directory for dev/test. Production overrides this
# to "/data/coverage" (the shared NFS mount) in config/prod.exs so all
# replicas can serve the rasters and pod restarts don't lose them.
config :towerops, :coverage_storage_dir, {:towerops, "priv/static/coverage"}
# SNMP MIB directories for production (in Docker image)
# MIB files are included in the release at /app/priv/mibs
# MibTranslator automatically expands these to include subdirectories
# Override in dev.exs for local development paths
config :towerops, :mib_dirs, [
"/app/priv/mibs",
"/usr/share/snmp/mibs"
]
config :towerops, :scopes,
user: [
default: true,
module: Towerops.Accounts.Scope,
assign_key: :current_scope,
access_path: [:user, :id],
schema_key: :user_id,
schema_type: :binary_id,
schema_table: :users,
test_data_fixture: Towerops.AccountsFixtures,
test_setup_helper: :register_and_log_in_user
]
# Agent Docker Image
# Override this in runtime.exs or environment-specific config
config :towerops,
agent_docker_image: "codeberg.org/towerops-agent/towerops-agent:latest"
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
config :towerops,
ecto_repos: [Towerops.Repo],
generators: [timestamp_type: :utc_datetime, binary_id: true]
import_config "#{config_env()}.exs"