Getting started
Configuration
Every setting the backend reads, what it defaults to, and what breaks when it is wrong. Most deployment problems are one of three addresses.
Where settings come from#
The API is a standard ASP.NET Core app, so any setting can come from appsettings.json, the
environment, or the command line. On top of that it reads a .env file: it looks in the
content root and up to two parent folders, and uses the first one it finds.
- Next to the binary in production, for example
C:\flicked\api\.envor/opt/flicked/api/.env. backend/.envin development, found by walking up from the project.- Environment variables win. A key already set in the environment is skipped when
.envis read. In the environment, write:as__, for exampleApi__PublicUrl.
The three addresses#
Nearly every deployment problem is one of these being wrong, and each fails quietly rather than
loudly. Each is read by a different program on a different machine, which is why none of them can be
localhost in production.
graph LR
browser["A friend's browser"] -->|"Steam:PublicUrl"| api["Flicked.Api :5165"]
launcher["Launcher"] -->|"FLICKED_API, compiled in"| api
cs2["CS2 server + MatchZy"] -->|"Api:PublicUrl"| api
api -->|"RCON"| cs2Who reads which address
| Setting | Read by | If it is wrong |
|---|---|---|
Steam:PublicUrl | A player's browser, signing in | Sign-in sends them back to their own PC |
Api:PublicUrl | The CS2 server, fetching a match config | The server fetches nothing and stays on its old map, with no error anywhere |
FLICKED_API | The launcher, compiled in at build time | The launcher looks for FLICKED on the player's own machine |
Backend reference#
Network and URLs#
| Key | Default | What it does |
|---|---|---|
Steam:PublicUrl | required | This API as a browser reaches it. Steam redirects back here after sign-in. Sign-in throws if it is missing; development sets it to http://localhost:5165 |
Api:PublicUrl | falls back to FLICKED_API_PUBLIC_URL, then Steam:PublicUrl | This API as a CS2 server reaches it. Sent to the server over RCON as the config URL and the event endpoint |
Dashboard:Url | http://localhost:3000 | Where the dashboard runs. Added to CORS by name, and used for the dashboard's sign-in redirect. Alias FLICKED_DASHBOARD_URL |
urls | localhost only | The interfaces Kestrel listens on. Use http://0.0.0.0:5165 to be reachable directly, or http://127.0.0.1:5165 behind a proxy |
Identity and secrets#
| Key | Default | What it does |
|---|---|---|
STEAM_API_KEY | none | Reads names and avatars from Steam. Free from steamcommunity.com/dev/apikey. Alias Steam:ApiKey |
FLICKED_ADMIN_STEAM_IDS | nobody | Comma-separated SteamID64s allowed into the dashboard. Checked on the server on every request. Alias Admin:SteamIds |
DataProtection:KeyPath | <content root>/keys | The folder holding the keys that encrypt stored RCON passwords. Alias FLICKED_KEY_PATH. Back it up |
Database#
| Key | Default | What it does |
|---|---|---|
ConnectionStrings:Flicked | required | The Npgsql connection string. Development points it at the Docker database |
Database:AutoMigrate | true | Apply EF Core migrations on startup, so a self-hoster upgrades by replacing a binary. Set to false to run migrations yourself |
Matchmaking#
| Key | Default | What it does |
|---|---|---|
Matchmaking:CompetitivePlayers | 10 | Players in a full Competitive match. Set to 2 to test with one other person |
Matchmaking:WingmanPlayers | 4 | Players in a full Wingman match |
Matchmaking:MinCompetitivePlayers | same as full | The smallest Competitive match worth starting when nobody else turns up. Equal to the full size means off |
Matchmaking:MinWingmanPlayers | same as full | The same, for Wingman |
Matchmaking:ShortHandedAfterSeconds | 20 | How long the longest-waiting party waits before a short match is tried |
Short-handed matches
For a small community that cannot reliably find ten people, set a minimum and the matchmaker will, after the wait, form a 4v4 or 3v3 out of whoever is queueing, largest first. A full match is always tried first, so a short match is never formed around players who could have had a real one.
Matchmaking:MinCompetitivePlayers=6
Matchmaking:MinWingmanPlayers=2
Matchmaking:ShortHandedAfterSeconds=20- Matches are always even. A minimum of 5 or 7 is read as 6 or 8, and nine people waiting become one 4v4 plus one player still in the queue. 5v4 is not a match worth starting.
- A party can still be too big. Party size is capped at half a full match. A five-stack on an instance with a minimum of 6 can only ever play a full 5v5, because six seats split 3-3 and a party is never split.
Build-time settings#
These are baked into a build. Changing them means rebuilding and redistributing.
| Variable | Used by | What it does |
|---|---|---|
FLICKED_API | Launcher | The API address, compiled into both the Rust side and the webview so they cannot disagree. Unset means http://localhost:5165 |
NEXT_PUBLIC_API_URL | Dashboard | The API address the dashboard calls |
Dashboard runtime#
| Variable | Typical value | Why |
|---|---|---|
PORT | 3000 | The port the standalone Next.js server listens on |
HOSTNAME | 0.0.0.0 or 127.0.0.1 | Next binds to localhost otherwise. Use loopback behind a proxy |
A complete example#
A production .env for a single VPS serving plain HTTP. For HTTPS behind Caddy, see
Deploy on Linux.
ConnectionStrings:Flicked=Host=localhost;Port=5432;Database=flicked;Username=flicked;Password=<db-password>
# This machine as the outside world sees it. Never localhost.
Steam:PublicUrl=http://<vps-address>:5165
Api:PublicUrl=http://<vps-address>:5165
Dashboard:Url=http://<vps-address>:3000
# Listen on every interface, not just localhost.
urls=http://0.0.0.0:5165
STEAM_API_KEY=<your-steam-web-api-key>
FLICKED_ADMIN_STEAM_IDS=<your-steamid64>
DataProtection:KeyPath=C:\flicked\keys