Skip to content
FLICKED Docs

Self-hosting

Deploy on Windows

Build FLICKED and run it somewhere your friends can reach: one Windows VPS running the CS2 server, the backend and the dashboard together.

Everything works the same spread across several machines; the addresses just stop being the same one. On Linux? Deploy on Linux covers the same deployment with systemd and HTTPS in the main path.

What you need#

RequirementNotes
A Windows VPSThe one already running your CS2 server is fine
.NET 10 SDKOn your development machine only. The VPS needs nothing
Node.js LTSOn both, if you want the dashboard
A Steam Web API keyFree, from steamcommunity.com/dev/apikey
Your SteamID64So you can reach the dashboard as an admin

The three addresses#

Nearly every deployment problem is one of these being wrong, and each fails quietly.

what talks to what
a friend's PC                    your VPS                       Steam
─────────────                    ────────                       ─────
launcher  ──── http ────►  Flicked.Api :5165  ──── RCON ────►  CS2 + MatchZy
   │                              │  ▲                              │
   │                        Postgres  └────── match events ─────────┘
   │
   └──── steam://connect ──────────────────────────────────►  CS2 server
SettingWho reads itIf it is wrong
Steam:PublicUrlA friend's browser, signing inSign-in sends them back to their own PC
Api:PublicUrlThe CS2 server, fetching a match configThe server fetches nothing and stays on its old map, with no error anywhere
FLICKED_APIThe launcher, compiled inThe launcher looks for FLICKED on the player's own machine

All three must be your VPS address. Replace <vps-address> below with it.

Part 1: Build#

All three are built on your development machine. Nothing is compiled on the VPS.

The API#

Command Prompt
dotnet publish backend/Flicked.Api -c Release -r win-x64 --self-contained

Output lands in backend/Flicked.Api/bin/Release/net10.0/win-x64/publish/. --self-contained bundles the .NET runtime, so the VPS needs no SDK. It is about 115 MB the first time; later updates are two files.

The launcher#

The API address is compiled in, so a build made on your machine points at your machine unless you say otherwise:

Command Prompt
set FLICKED_API=http://<vps-address>:5165
cd launcher
npm install
npm run tauri build

Installers land in launcher/src-tauri/target/release/bundle/: an .exe (NSIS) and an .msi, the same app either way.

Friends will see "Windows protected your PC" when they run it. That is SmartScreen reacting to an unsigned installer, not to anything being wrong: More info, then Run anyway. Signing needs a paid certificate.

The dashboard#

Command Prompt
cd dashboard
npm install
set NEXT_PUBLIC_API_URL=http://<vps-address>:5165
npx next build

The build produces a standalone server. Assemble what the VPS needs:

deploy folder
.next/standalone/*   →  the server and its dependencies
.next/static/*       →  into <deploy>/.next/static
public/*             →  into <deploy>/public

That folder runs with Node alone, with no npm install on the VPS.

Part 2: Deploy#

  1. Install Postgres

    Docker Desktop on a Windows VPS usually cannot get the nested virtualization it needs, so install Postgres natively with the EnterpriseDB installer. It runs as a service and starts with the machine. Then, in SQL Shell (psql):

    psql
    CREATE USER flicked WITH PASSWORD 'pick-a-real-password';
    CREATE DATABASE flicked OWNER flicked;

    Create no tables. The API applies its own migrations on startup and seeds the map pool.

  2. Copy the API across

    Put the published folder anywhere on the VPS. These examples use C:\flicked\api.

  3. Configure it

    Create .env next to Flicked.Api.exe. It is read on startup and belongs in no repository. Every key is described in Configuration.

    C:\flicked\api\.env
    # The database you just created.
    ConnectionStrings:Flicked=Host=localhost;Port=5432;Database=flicked;Username=flicked;Password=<db-password>
    
    # This machine, as the outside world sees it. Never localhost: one of these is
    # read by a browser on someone else's PC, the other by the CS2 server.
    Steam:PublicUrl=http://<vps-address>:5165
    Api:PublicUrl=http://<vps-address>:5165
    
    # Where the dashboard runs. Needed for CORS and for the sign-in redirect.
    Dashboard:Url=http://<vps-address>:3000
    
    # Listen on every interface. The default is localhost only, which leaves the
    # API invisible from outside however the firewall is set.
    urls=http://0.0.0.0:5165
    
    STEAM_API_KEY=<your-steam-web-api-key>
    
    # Comma-separated SteamID64s allowed into the dashboard.
    FLICKED_ADMIN_STEAM_IDS=<your-steamid64>
    
    # Encryption keys for stored RCON passwords. Back this folder up.
    DataProtection:KeyPath=C:\flicked\keys
    
    # Optional, while testing: play with fewer people than a real match needs.
    # Matchmaking:CompetitivePlayers=2
    
    # Optional, for a small community: start short-handed rather than wait for a
    # tenth player who is not coming.
    # Matchmaking:MinCompetitivePlayers=6
  4. Open the ports

    In an administrator PowerShell on the VPS:

    PowerShell (admin)
    New-NetFirewallRule -DisplayName "FLICKED API" -Direction Inbound -Protocol TCP -LocalPort 5165 -Action Allow
    New-NetFirewallRule -DisplayName "FLICKED Dashboard" -Direction Inbound -Protocol TCP -LocalPort 3000 -Action Allow

    Many providers have a second firewall in their web panel. If a port still looks closed, check there.

  5. Start the API

    Run Flicked.Api.exe. The first start applies the migrations; watch that it gets through them without an exception. Then test it from your own PC, not from the VPS, because a service can answer itself while being unreachable from outside:

    Your PC
    curl http://<vps-address>:5165/api/news
  6. Start the dashboard

    PowerShell
    cd C:\flicked\dashboard
    $env:PORT=3000; $env:HOSTNAME="0.0.0.0"; node server.js

    HOSTNAME=0.0.0.0 matters for the same reason urls did: Next binds to localhost otherwise.

  7. Add your CS2 server

    Open http://<vps-address>:3000, sign in with Steam, and add the server with its host, port and RCON password. FLICKED handles the rest: it reloads MatchZy before each match, and sends the config URL and event settings over RCON, so server.cfg needs no FLICKED-specific lines.

    A server that answers the pool's RCON ping shows as Idle and can host matches. One that does not is Offline and is skipped until it answers. For the game side, see Running the CS2 server.

Keep it running#

A console window dies when you log out of the VPS. Install NSSM and register the API as a service:

Command Prompt (admin)
nssm install FlickedApi C:\flicked\api\Flicked.Api.exe
nssm set FlickedApi AppDirectory C:\flicked\api
nssm start FlickedApi

Upgrading#

After the first deployment you rarely need the whole 115 MB again. Unless the dependencies changed, a new backend build is two files:

  1. dotnet publish as above, on your machine
  2. stop the API on the VPS
  3. copy Flicked.Api.dll and Flicked.Api.pdb over the old ones
  4. start it; any new migrations apply on startup

Back up the database first when an upgrade migrates data. From PowerShell, not psql, since pg_dump is a program rather than a psql command:

PowerShell
$pg = Get-ChildItem "C:\Program Files\PostgreSQL\*\bin\pg_dump.exe" | Select-Object -First 1
& $pg.FullName -U postgres -d flicked -f C:\backup.sql

Troubleshooting#

Every one of these has happened during a real setup.

SymptomCause
API unreachable from outside, firewall looks openurls=http://0.0.0.0:5165 missing, so it bound to localhost
Server never loads the voted map, console shows nothingApi:PublicUrl is localhost or unreachable, so the server fetched its config from itself
Sign-in sends a friend back to their own PCSteam:PublicUrl is localhost
News and leaderboard empty in the launcher, everything else fineThe launcher was built without FLICKED_API
Dashboard signs in, then every request failsThe dashboard is not on the same host as the API (SameSite=Lax)
Server X has an unreadable RCON passwordThe database moved between machines without its DataProtection keys
Match timers start part-way through, or sit at zeroThe VPS clock or the player's is wrong; sync both
invalid command \...You are in psql and typed a program name; programs belong in PowerShell
The ampersand (&) character is not allowedTwo PowerShell commands on one line; separate them with ;
-U is not recognized after a quoted pathPowerShell needs & in front of a quoted path to run it
Esc
↑↓ navigate ↵ open