Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic discord integration #281

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
aeb0f28
Create skeleton runtime config
geekingfrog Apr 21, 2024
4856e6f
Move setup key to runtime config
geekingfrog Apr 21, 2024
fae24a8
Move Server TLS endpoint params to runtime config
geekingfrog Apr 21, 2024
ee59741
Move to runtime config the remaining endpoints config
geekingfrog Apr 21, 2024
c91d760
General config to runtime config
geekingfrog Apr 21, 2024
c4eb48d
Ecto repo config to runtime configuration
geekingfrog Apr 21, 2024
2a1daa0
Guardian config to runtime config
geekingfrog Apr 21, 2024
9a00456
Mailer configuration to runtime config
geekingfrog Apr 21, 2024
1bfc793
Logger configuration to runtime config
geekingfrog Apr 21, 2024
0a705e8
Remove prod_secret file completely
geekingfrog Apr 21, 2024
4dbe19e
Tidy some general config
geekingfrog Apr 21, 2024
3851789
Add config helpers for simple parsing
geekingfrog Apr 21, 2024
aaaff24
Add an example of environment file for sensitive values
geekingfrog Apr 21, 2024
c547c2b
Endpoint config to match prod
geekingfrog Apr 22, 2024
e74eaea
General config to match prod
geekingfrog Apr 22, 2024
1cc98fa
Mailer configuration to match prod
geekingfrog Apr 22, 2024
0362cf0
Allow email to be deactivated at startup
geekingfrog Apr 22, 2024
c57f173
Allow ports config to be set at runtime through env
geekingfrog Apr 28, 2024
3d79f34
Prefix all env var with TEI
geekingfrog May 8, 2024
6ec903a
Make example file usable locally
geekingfrog May 11, 2024
5cd1cd7
add hostname for DB in env var
geekingfrog May 11, 2024
5cf4003
Key to setup root user from environment
geekingfrog May 12, 2024
2bff16d
Fix mailer config
geekingfrog May 14, 2024
4576085
Start discord app nostrum dynamically
geekingfrog Apr 22, 2024
7ad0ab6
Discord bridge config through env variables
geekingfrog Apr 22, 2024
10a8cd8
Add discord bridge bot configuration
geekingfrog May 9, 2024
696e4d0
Disable discord locally
geekingfrog May 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ config :teiserver, TeiserverWeb.Endpoint,
formats: [html: TeiserverWeb.ErrorHTML, json: TeiserverWeb.ErrorJSON],
layout: false
],
pubsub_server: Teiserver.PubSub
pubsub_server: Teiserver.PubSub,
debug_errors: Config.config_env() == :dev,
code_reloader: Config.config_env() == :dev,
check_origin: Config.config_env() == :prod

config :esbuild,
version: "0.14.41",
Expand Down
3 changes: 0 additions & 3 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ config :teiserver, Teiserver.Repo,
# with webpack to recompile .js and .css sources.
config :teiserver, TeiserverWeb.Endpoint,
http: [ip: {127, 0, 0, 1}, port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [
# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
Expand Down
60 changes: 0 additions & 60 deletions config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ config :teiserver, TeiserverWeb.Endpoint,
https: [
port: 8888,
otp_app: :teiserver,
keyfile: "/var/www/tls/privkey.pem",
certfile: "/var/www/tls/cert.pem",
cacertfile: "/var/www/tls/fullchain.pem",
versions: [:"tlsv1.2"],
dhfile: '/var/www/tls/dh-params.pem',
ciphers: [
'ECDHE-ECDSA-AES256-GCM-SHA384',
'ECDHE-RSA-AES256-GCM-SHA384',
Expand Down Expand Up @@ -66,59 +61,4 @@ config :teiserver, TeiserverWeb.Endpoint,
root: ".",
cache_static_manifest: "priv/static/cache_manifest.json",
server: true,
check_origin: ["//yourdomain.com", "//*.yourdomain.com"],
version: Mix.Project.config()[:version]

config :teiserver, Teiserver,
certs: [
keyfile: "/var/www/tls/privkey.pem",
certfile: "/var/www/tls/cert.pem",
cacertfile: "/var/www/tls/fullchain.pem"
],
enable_benchmark: false,
node_name: "node-name",
enable_managed_lobbies: true,
tachyon_schema_path: "/apps/teiserver/lib/teiserver-0.1.0/priv/tachyon/schema_v1/*/*/*.json"

config :teiserver, Teiserver.Repo,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "40"),
timeout: 120_000,
queue_interval: 2000

# Do not print debug messages in production
config :logger,
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :info

config :logger,
backends: [
{LoggerFileBackend, :error_log},
{LoggerFileBackend, :notice_log},
{LoggerFileBackend, :info_log},
:console
]

config :logger, :error_log,
path: "/var/log/teiserver/error.log",
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :error

config :logger, :notice_log,
path: "/var/log/teiserver/notice.log",
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :notice

config :logger, :info_log,
path: "/var/log/teiserver/info.log",
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :info

# Overwritten in secret
config :teiserver, Teiserver.Account.Guardian,
secret_key: "yix2DcXsA9MzAI8WldmYiJ38j2GyyXf5beWGAOJHl0FKNH04n1VACYbepqutma27"

import_config "prod.secret.exs"
191 changes: 191 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import Config

# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.

# ## Sensitive values should be passed through the environment. An example
# EnvironmentFile that can be used with systemd is under
# documents/prod_files/example-environment-file

# ## Using releases
#
# If you use `mix release`, you need to explicitly enable the server
# by passing the PHX_SERVER=true when you start it:
#
# PHX_SERVER=true bin/teiserver start
#
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
# script that automatically sets the env var above.
if Teiserver.ConfigHelpers.get_env("PHX_SERVER", nil) do
config :teiserver, TeiserverWeb.Endpoint, server: true
end

# Only do some runtime configuration in production since in dev and tests the
# files are automatically recompiled on the fly and thus, config/{dev,test}.exs
# are just fine
if config_env() == :prod do
# used for mailing, checking origins, finding tls certs…
domain_name = Teiserver.ConfigHelpers.get_env("TEI_DOMAIN_NAME", "beyondallreason.info")

certificates = [
keyfile: Teiserver.ConfigHelpers.get_env("TEI_TLS_PRIVATE_KEY_PATH"),
certfile: Teiserver.ConfigHelpers.get_env("TEI_TLS_CERT_PATH"),
cacertfile: Teiserver.ConfigHelpers.get_env("TEI_TLS_CA_CERT_PATH")
]

# this is used in lib/teiserver_web/controllers/account/setup_controller.ex
# as a special endpoint to create the root user. Setting it to empty or nil
# will disable the functionality completely.
config :teiserver, Teiserver.Setup,
key: Teiserver.ConfigHelpers.get_env("TEI_SETUP_ROOT_KEY", nil)

enable_discord_bridge = Teiserver.ConfigHelpers.get_env("TEI_ENABLE_DISCORD_BRIDGE", true, :bool)

config :teiserver, Teiserver,
game_name: "Beyond All Reason",
game_name_short: "BAR",
main_website: "https://www.beyondallreason.info/",
privacy_email: "[email protected]",
discord: "https://discord.gg/beyond-all-reason",
enable_discord_bridge: enable_discord_bridge,
ports: [
tcp: Teiserver.ConfigHelpers.get_env("TEI_SPRING_TCP_PORT", 8200, :int),
tls: Teiserver.ConfigHelpers.get_env("TEI_SPRING_TLS_PORT", 8201, :int),
# this can likely be deprecated and removed. It's for an old version
# of tachyon running on another TLS socket
tachyon: Teiserver.ConfigHelpers.get_env("TEI_TACHYON_TLS_PORT", 8202, :int)
],
certs: certificates,
website: [
url: "beyondallreason.info"
],
server_flag: "GB-WLS",
enable_benchmark: false,
node_name: Teiserver.ConfigHelpers.get_env("TEI_NODE_NAME"),
extra_logging: false,
enable_managed_lobbies: true,
user_agreement:
"A verification code has been sent to your email address. Please read our terms of service at https://#{domain_name}/privacy_policy and the code of conduct at https://www.beyondallreason.info/code-of-conduct. Then enter your six digit code below if you agree to the terms."

config :teiserver, Teiserver.Repo,
hostname: Teiserver.ConfigHelpers.get_env("TEI_DB_HOSTNAME"),
username: Teiserver.ConfigHelpers.get_env("TEI_DB_USERNAME"),
password: Teiserver.ConfigHelpers.get_env("TEI_DB_PASSWORD"),
database: Teiserver.ConfigHelpers.get_env("TEI_DB_NAME"),
pool_size: 40,
timeout: 120_000,
queue_interval: 2000

check_origin =
if Teiserver.ConfigHelpers.get_env("TEI_SHOULD_CHECK_ORIGIN", false, :bool) do
["//#{domain_name}", "//*.#{domain_name}"]
else
false
end

config :teiserver, TeiserverWeb.Endpoint,
url: [host: domain_name],
check_origin: check_origin,
https:
certificates ++
[
versions: [:"tlsv1.2"],
# dhfile is not supported for tls 1.3
# https://www.erlang.org/doc/man/ssl.html#type-dh_file
dhfile: Teiserver.ConfigHelpers.get_env("TEI_TLS_DH_FILE_PATH", "/etc/ssl/dhparam.pem")
],
http: [:inet6, port: Teiserver.ConfigHelpers.get_env("TEI_PORT", "4000", :int)],
secret_key_base: Teiserver.ConfigHelpers.get_env("TEI_HTTP_SECRET_KEY_BASE")

config :teiserver, Teiserver.Account.Guardian,
issuer: Teiserver.ConfigHelpers.get_env("TEI_GUARDIAN_ISSUER", "teiserver"),
secret_key: Teiserver.ConfigHelpers.get_env("TEI_GUARDIAN_SECRET_KEY")

if Teiserver.ConfigHelpers.get_env("TEI_ENABLE_EMAIL_INTEGRATION", :bool) do
config :teiserver, Teiserver.Mailer,
adapter: Bamboo.SMTPAdapter,
contact_address:
Teiserver.ConfigHelpers.get_env("TEI_CONTACT_EMAIL_ADDRESS", "info@#{domain_name}"),
noreply_name: "Beyond All Reason",
noreply_address:
Teiserver.ConfigHelpers.get_env("TEI_NOREPLY_EMAIL_ADDRESS", "noreply@#{domain_name}"),
server: Teiserver.ConfigHelpers.get_env("TEI_SMTP_SERVER"),
hostname: Teiserver.ConfigHelpers.get_env("TEI_SMTP_HOSTNAME"),
# port: 1025,
port: Teiserver.ConfigHelpers.get_env("TEI_SMTP_PORT", "587", :int),
username: Teiserver.ConfigHelpers.get_env("TEI_SMTP_USERNAME"),
password: Teiserver.ConfigHelpers.get_env("TEI_SMTP_PASSWORD"),
# tls: :if_available, # can be `:always` or `:never`
# can be `:always` or `:never`
tls: :always,
tls_verify:
if(Teiserver.ConfigHelpers.get_env("TEI_SMTP_TLS_VERIFY", true, :bool),
do: :verify_peer,
else: :verify_none
),
# or {":system", ALLOWED_TLS_VERSIONS"} w/ comma seprated values (e.g. "tlsv1.1,tlsv1.2")
allowed_tls_versions: [:"tlsv1.2"],
# can be `true`
no_mx_lookups: false,
# auth: :if_available # can be `always`. If your smtp relay requires authentication set it to `always`.
auth: :always
end

log_root_path = Teiserver.ConfigHelpers.get_env("TEI_LOG_ROOT_PATH", "/var/log/teiserver/")

config :logger,
backends: [
{LoggerFileBackend, :error_log},
{LoggerFileBackend, :notice_log},
{LoggerFileBackend, :info_log},
:console
]

# Do not print debug messages in production
config :logger,
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :info

config :logger, :error_log,
path: "#{log_root_path}error.log",
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :error

config :logger, :notice_log,
path: "#{log_root_path}notice.log",
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :notice

config :logger, :info_log,
path: "#{log_root_path}info.log",
format: "$date $time [$level] $metadata $message\n",
metadata: [:request_id, :user_id],
level: :info

if enable_discord_bridge do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to miss the config :teiserver, DiscordBridgeBot, part I have https://github.com/beyond-all-reason/ansible-teiserver/blob/main/roles/teiserver/templates/prod.secret.exs.j2#L73-L77

I'm not sure how without that it would know to what server to connect, how have you tested it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't really test the actual integration since I don't have access to any token. Are there some test credentials somewhere I could use?
The only test I've done is that, when the discord integration is disabled, I can start the server normally and it won't complain that it's missing stuff for discord.

I've added the configuration for the bridge in 3b72d87

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can follow https://github.com/beyond-all-reason/ansible-teiserver?tab=readme-ov-file#discord to create discord for testing, there are also instructions there for email testing etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've amended the commit for the bot config, followed your steps and now it seems to work.
2024-05-11-475x166-scrot

config :nostrum,
gateway_intents: [
:guilds,
:guild_messages,
:guild_message_reactions,
:direct_messages,
:message_content,
:direct_message_reactions
],
log_full_events: true,
log_dispatch_events: true,
token: Teiserver.ConfigHelpers.get_env("TEI_DISCORD_BOT_TOKEN")

config :teiserver, Teiserver.Bridge.DiscordBridgeBot,
token: Teiserver.ConfigHelpers.get_env("TEI_DISCORD_BOT_TOKEN"),
guild_id: Teiserver.ConfigHelpers.get_env("TEI_DISCORD_GUILD_ID"),
bot_name: Teiserver.ConfigHelpers.get_env("TEI_DISCORD_BOT_NAME")
end
end
5 changes: 1 addition & 4 deletions documents/guides/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ If you've not already setup your server you might want to check out [documents/g
- Locally running Elixir
- Docker installed on your computer

### prod.secret.exs
`config/prod.secret.exs` is ignored in the gitignore for obvious reasons. This means you will need to create your own one. Luckily I [made a template for you](/documents/prod_files/example_prod_secret.exs).

#### Dockerfile
A docker file is included in the repo but within [documents/prod_files](documents/prod_files) are other docker images providing more control over the building of your image and might be of interest.

Expand Down Expand Up @@ -38,4 +35,4 @@ docker build --build-arg env=prod \
```
#!/usr/bin/env bash
docker run -v $(pwd):/opt/build --rm -it teiserver:latest /opt/build/bin/build
```
```
2 changes: 1 addition & 1 deletion documents/guides/production_setup_linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ tsapp eval "Teiserver.Release.migrate"
[Deployment itself is located in a different file.](/documents/guides/deployment.md), you will need to execute a deployment as part of the setup. There will be additional steps to take after your first deployment.

#### Creating the first user
To create your first root user make a note of `config :teiserver, Teiserver.Setup, key:` within `config/prod.secret.exs` as you will need that value here. Go to `https://domain.com/initial_setup/$KEY` where `$KEY` is replaced with the value in this config. This link will only work while a user with an email "root@localhost" has not been created. It is advised that once the user is created you set the initial_setup key to be an empty string which will disable the function entirely.
To create your first root user make a note of `config :teiserver, Teiserver.Setup, key:` within `config/runtime.exs` as you will need that value here. Go to `https://domain.com/initial_setup/$KEY` where `$KEY` is replaced with the value in this config. This link will only work while a user with an email "root@localhost" has not been created. It is advised that once the user is created you set the initial_setup key to be an empty string which will disable the function entirely.

A new user with developer level access will be created with the email `root@localhost` and a password identical to the setup key you just used. You can now login as that user, it is advised your first action should be to change/update the password and set the user details (name/email) to the ones you intend to use as admin.

Expand Down
53 changes: 53 additions & 0 deletions documents/prod_files/example-environment-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# This file is an example of a systemd environment file to configure a running service
# In the systemd unit file, it should be setup with a line:
# EnvironmentFile=/etc/sysconfig/teiserver
# Be careful, if this line is in the systemd unit definition but the file doesn't exist
# the service will be silently disabled

# For more info, see:
# https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#EnvironmentFile=
# and also:
# https://fedoraproject.org/wiki/Packaging:Systemd#EnvironmentFiles_and_support_for_/etc/sysconfig_files

# To easily load all these in your shell's environment:
# ```
# set -o allexport; source documents/prod_files/example-environment-file; set +o allexport
# ```

# General secrets
PHX_SERVER=true
TEI_NODE_NAME=staging-node-1

# DB configuration
TEI_DB_HOSTNAME=localhost
TEI_DB_USERNAME=teiserver_dev
TEI_DB_PASSWORD=123456789
TEI_DB_NAME=teiserver_dev

# TLS config
TEI_TLS_PRIVATE_KEY_PATH=priv/certs/localhost.key
TEI_TLS_CERT_PATH=priv/certs/localhost.crt
TEI_TLS_CA_CERT_PATH=priv/certs/localhost.crt
TEI_TLS_DH_FILE_PATH=priv/certs/dh-params.pem

# For cookie encryption, must be at least 64 bytes
TEI_HTTP_SECRET_KEY_BASE=2f894df108701d787156761fe6c122050a8f0f78426de0ea62593e766b9ffcf0f321ce66aef5e8948bb89dc9cc2f687797e2c30100eb001ff87bab23a005091e

# For Guardian (authentication)
TEI_GUARDIAN_SECRET_KEY=yet-another-random-key-to-keep-secret

# Email
TEI_ENABLE_EMAIL_INTEGRATION=true
# this assume you're running the container smtp4dev as explained in:
# https://github.com/beyond-all-reason/ansible-teiserver?tab=readme-ov-file#email
TEI_SMTP_SERVER=127.0.0.1
TEI_SMTP_PORT=2525
# the domain of the email
TEI_SMTP_HOSTNAME=beyondallreason.info
[email protected]
TEI_SMTP_PASSWORD=correct-battery-staple-horse-xkcd-936
TEI_SMTP_TLS_VERIFY=false

TEI_ENABLE_DISCORD_BRIDGE=false

# vim: ft=systemd
Loading
Loading