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

Move config to runtime #278

Merged
Merged
Changes from all commits
Commits
Show all changes
23 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
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
@@ -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",
3 changes: 0 additions & 3 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -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)]},
60 changes: 0 additions & 60 deletions config/prod.exs
Original file line number Diff line number Diff line change
@@ -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',
@@ -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"
168 changes: 168 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
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
geekingfrog marked this conversation as resolved.
Show resolved Hide resolved
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)

config :teiserver, Teiserver,
game_name: "Beyond All Reason",
game_name_short: "BAR",
main_website: "https://www.beyondallreason.info/",
privacy_email: "privacy@beyondallreason.info",
discord: "https://discord.gg/beyond-all-reason",
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,
geekingfrog marked this conversation as resolved.
Show resolved Hide resolved
# 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
end
5 changes: 1 addition & 4 deletions documents/guides/deployment.md
Original file line number Diff line number Diff line change
@@ -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.

@@ -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
@@ -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.

51 changes: 51 additions & 0 deletions documents/prod_files/example-environment-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 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
TEI_SMTP_USERNAME=noreply@beyondallreason.info
TEI_SMTP_PASSWORD=correct-battery-staple-horse-xkcd-936
TEI_SMTP_TLS_VERIFY=false

# vim: ft=systemd
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this example is incomplete, it misses some required parameters like TEI_ENABLE_EMAIL_INTEGRATION that as far as I look at implementation, will crash the server. I think the sample should be something that has all variables required as minimum.

Loading
Loading