Docs / Configuration

Configuration reference

All Asobi config lives under the asobi OTP application. Set it via sys.config (releases), config.exs/sys.config.src (env-var templating), or application:set_env/3 at runtime.

Database

{asobi_repo, [
    {database, <<"asobi">>},
    {username, <<"postgres">>},
    {password, <<"postgres">>},
    {host,     <<"localhost">>},
    {port,     5432},
    {pool_size, 10}
]}

Environment variables: ASOBI_DB_HOST, ASOBI_DB_PORT, ASOBI_DB_NAME, ASOBI_DB_USER, ASOBI_DB_PASSWORD.

HTTP / WebSocket

{nova, [
    {cowboy_options, [{port, 8080}, {max_connections, 10000}]}
]}

Matches

{asobi, [
    {match_defaults, #{
        tick_rate_ms => 100,
        min_players  => 2,
        max_players  => 10,
        waiting_timeout_ms => 60000
    }},
    {match_modes, #{
        <<"arena">>  => #{callback_module => arena_game,  tick_rate_ms => 50},
        <<"ranked">> => #{callback_module => ranked_game, tick_rate_ms => 100}
    }}
]}

Matchmaker

{asobi, [
    {matchmaker, #{
        tick_interval    => 1000,
        max_wait_seconds => 60
    }},
    {matchmaker_strategy, asobi_matchmaker_fill}
]}

World server

{asobi, [
    {world, #{
        zone_size            => 256,      %% units per side
        tick_rate_ms         => 50,       %% 20 Hz
        lazy_zones           => true,
        zone_idle_ms         => 60000,
        terrain_provider     => my_terrain_module,
        snapshot_interval_ms => 30000
    }}
]}

Voting

{asobi, [
    {vote_templates, #{
        <<"default">>   => #{method => <<"plurality">>, window_ms => 15000,
                             visibility => <<"live">>},
        <<"boon_pick">> => #{method => <<"plurality">>, window_ms => 15000}
    }}
]}

Authentication

{asobi, [
    {oidc_providers, #{
        google    => #{issuer => <<"https://accounts.google.com">>,
                       client_id => <<"...">>, client_secret => <<"...">>},
        apple     => #{issuer => <<"https://appleid.apple.com">>,
                       client_id => <<"...">>, client_secret => <<"...">>}
    }},
    {steam_api_key, <<"...">>},
    {steam_app_id,  <<"...">>},
    {apple_bundle_id, <<"com.example.game">>},
    {session_token_ttl_seconds, 2592000}   %% 30 days
]}

Leaderboards

{asobi, [
    {leaderboards, #{
        <<"arena:weekly">> => #{mode => monotonic,
                                window => {weekly, monday, 0}},
        <<"xp:lifetime">>  => #{mode => cumulative}
    }}
]}

Lua runtime

{asobi_lua, [
    {bundle_dir,  <<"./game">>},
    {hot_reload,  true},
    {sandbox,     strict},             %% strict | permissive
    {instruction_limit, 1000000}       %% per-callback bytecode cap
]}

Clustering

{asobi, [
    {cluster, #{
        strategy => k8s_dns,
        service  => <<"asobi-headless">>,
        basename => <<"asobi">>
    }}
]}

Telemetry & logs

{kernel, [
    {logger, [
        {handler, default, logger_std_h, #{
            level => info,
            formatter => {nova_jsonlogger_formatter, #{}}
        }}
    ]}
]}

Common env vars

 ASOBI_DB_*           Postgres connection (HOST/PORT/NAME/USER/PASSWORD)
 ASOBI_CLUSTER_SEEDS  Comma-separated node names to ping on boot
 ERLANG_COOKIE        Distribution cookie (required for clustering)
 NODE_NAME            Full node name, e.g. asobi@10.0.0.1
 PORT                 HTTP listen port (default 8080)
 ASOBI_BUNDLE_DIR     Where asobi_lua looks for game/*.lua

Where next?