6.9 KiB · text History e3999f1
# 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

config :oh_my_ex_oh_ircd, :scopes,
  user: [
    default: true,
    module: OhMyExOhIrcd.Accounts.Scope,
    assign_key: :current_scope,
    access_path: [:user, :id],
    schema_key: :user_id,
    schema_type: :id,
    schema_table: :users,
    test_data_fixture: OhMyExOhIrcd.AccountsFixtures,
    test_setup_helper: :register_and_log_in_user
  ]

config :oh_my_ex_oh_ircd,
  ecto_repos: [OhMyExOhIrcd.Repo],
  generators: [timestamp_type: :utc_datetime]

# Pseudo-service nicks. These nicks are reserved (registered into the
# global Horde registry at boot) so real users can't take them, and
# PRIVMSGs to them route to the corresponding service process.
config :oh_my_ex_oh_ircd, :services,
  chanserv_nick: "ChanServ",
  service_host: "services."

# WebIRC LiveView toggle. When enabled, logged-in users can open
# /webirc to participate in the cluster from a browser tab.
config :oh_my_ex_oh_ircd, :webirc, enabled: false

# IRC operators (OPER command). Each entry's password is a bcrypt hash:
#
#   iex> Bcrypt.hash_pwd_salt("yourpassword")
#
# `host_mask` is an IRC glob applied to `user@host` of the connecting
# client; `"*@*"` allows opers from anywhere. Override per-env (likely
# in runtime.exs or env-specific config files).
config :oh_my_ex_oh_ircd, :opers, %{}

# IRCd listener defaults; overridden in runtime.exs from env.
# `allow_anonymous: false` means connections must authenticate via SASL or PASS
# before completing registration. Flip to `true` (or set IRC_ALLOW_ANONYMOUS=1)
# to let unauthenticated clients in.
# Deployment mode for TLS. This is a **compile-time** decision — change it
# in config.exs (not runtime.exs) and rebuild the release.
#
#   :standalone — site_encrypt is wired into the Phoenix endpoint. It
#                 serves HTTP-01 challenges, obtains and auto-renews the
#                 cert via ACME (Let's Encrypt in prod, the in-process
#                 internal CA in dev/test). The TLSListener reads cert
#                 files from site_encrypt's db_folder.
#
#   :kubernetes — site_encrypt is NOT compiled into the endpoint. Cert
#                 files are expected to be on disk (typically mounted
#                 from a cert-manager Secret). Set
#                 `OhMyExOhIrcd.IRC.TLSListener` `cert_path`/`key_path`
#                 (or `IRC_TLS_CERT_PATH`/`IRC_TLS_KEY_PATH` env vars in
#                 runtime.exs) to point at them.
#
# Can be overridden at build time via the `TLS_MODE` env var. CI uses this
# to produce both image variants from the same source tree (see the
# Dockerfile `TLS_MODE` build-arg and `.gitlab-ci.yml`).
config :oh_my_ex_oh_ircd,
       :tls_mode,
       String.to_atom(System.get_env("TLS_MODE", "standalone"))

# TLS IRC listener (port 6697). In :standalone mode, `cert_path`/`key_path`
# default to whatever site_encrypt writes. In :kubernetes mode they're
# required (the listener will refuse to start without them).
config :oh_my_ex_oh_ircd, OhMyExOhIrcd.IRC.TLSListener,
  enabled: false,
  port: 6697,
  cert_path: nil,
  key_path: nil

# ACME config used only in :standalone mode. Use the :internal directory_url
# in dev so we provision via the in-process CA; point at letsencrypt staging
# or production for real deployments.
config :oh_my_ex_oh_ircd, :acme,
  client: :native,
  domains: ["localhost"],
  emails: ["admin@localhost"],
  directory_url: {:internal, [port: 4002]}

config :oh_my_ex_oh_ircd, OhMyExOhIrcd.IRC.Listener,
  port: 6667,
  server_name: "oh-my-ex-oh.irc",
  network_name: "OhMyExOhIRC",
  allow_anonymous: false,
  # Idle PING after this much inactivity; client must reply within
  # ping_timeout_ms or we drop the connection with `Ping timeout`.
  ping_interval_ms: 120_000,
  ping_timeout_ms: 60_000,
  # Flood control: each parsed command adds a per-command penalty
  # (`flood_penalty_default` by default — see Connection for the
  # per-command overrides) to a counter that drains at 1 sec/sec.
  # When the counter exceeds `flood_threshold_seconds` the connection
  # is dropped with `ERROR :Excess Flood`.
  # 20s gives ~10 normal commands or ~13 mode changes in a tight burst
  # before the connection is killed. The bucket drains at 1 sec/sec.
  flood_threshold_seconds: 20,
  flood_penalty_default: 1.0,
  # When `true`, the listener expects each connection to start with a
  # PROXY v1 or v2 header (Traefik / HAProxy / AWS NLB-style). The real
  # client IP from the header replaces what `peername/0` reports — i.e.
  # `state.host` (used in WHOIS, ban masks, K-lines, flood IDs).
  # Default `false` so direct TCP keeps working. Flip via
  # `IRC_PROXY_PROTOCOL=true` at runtime.
  proxy_protocol: false,
  motd: [
    "Welcome to OhMyExOhIRC.",
    "",
    "This server is part of a libcluster + Horde Elixir cluster.",
    "Channel messages replay across netsplits via DeltaCrdt.",
    "",
    "Be kind. Have fun."
  ]

# libcluster topologies. The :gossip strategy works out of the box on a LAN.
# Swap to Cluster.Strategy.Kubernetes or .Gossip.DNSPoll in prod.
config :libcluster,
  topologies: [
    oh_my_ex_oh: [
      strategy: Cluster.Strategy.Gossip
    ]
  ]

# Configure the endpoint
config :oh_my_ex_oh_ircd, OhMyExOhIrcdWeb.Endpoint,
  url: [host: "localhost"],
  adapter: Bandit.PhoenixAdapter,
  render_errors: [
    formats: [html: OhMyExOhIrcdWeb.ErrorHTML, json: OhMyExOhIrcdWeb.ErrorJSON],
    layout: false
  ],
  pubsub_server: OhMyExOhIrcd.PubSub,
  live_view: [signing_salt: "0mFhWrcq"]

# 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 :oh_my_ex_oh_ircd, OhMyExOhIrcd.Mailer, adapter: Swoosh.Adapters.Local

# Configure esbuild (the version is required)
config :esbuild,
  version: "0.25.4",
  oh_my_ex_oh_ircd: [
    args:
      ~w(js/app.js --bundle --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()]}
  ]

# Configure tailwind (the version is required)
config :tailwind,
  version: "4.1.12",
  oh_my_ex_oh_ircd: [
    args: ~w(
      --input=assets/css/app.css
      --output=priv/static/assets/css/app.css
    ),
    cd: Path.expand("..", __DIR__)
  ]

# Configure Elixir's Logger
config :logger, :default_formatter,
  format: "$time $metadata[$level] $message\n",
  metadata: [:request_id]

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"