[{"data":1,"prerenderedAt":25},["ShallowReactive",2],{"$fdcrjnxapg03t":3},{"html":4,"toc":5,"minutes":9},"\u003Cp>The QxChat server, \u003Ccode>qxprotocol\u003C\u002Fcode>, is one Rust program configured by one TOML file. It stores accounts in SQLite out of the box or in PostgreSQL, and it serves the web client itself, so the people you invite only need your address.\u003C\u002Fp>\n\u003Ch2 id=\"what-you-need\">\u003Ca class=\"anchor\" href=\"#what-you-need\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>What you need\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>Rust 1.88 or newer, \u003Ccode>git\u003C\u002Fcode> and \u003Ccode>bun\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>A writable \u003Ccode>QXP_ROOT\u003C\u002Fcode> folder, with outbound access to GitHub and the Bun registry (the server builds the web client on startup).\u003C\u002Fli>\n\u003Cli>A domain and a TLS certificate if other people will connect. A TURN server if you want calls to work across strict networks.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"quick-start\">\u003Ca class=\"anchor\" href=\"#quick-start\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Quick start\u003C\u002Fh2>\n\u003Cdiv class=\"code\">\u003Cspan class=\"lang\">sh\u003C\u002Fspan>\u003Cpre>\u003Ccode>git clone https:\u002F\u002Fgithub.com\u002Flqxp\u002Flqxp\ncd lqxp\ncp files\u002Fconfig.example.toml files\u002Fconfig.custom.toml\n$EDITOR files\u002Fconfig.custom.toml\ncargo run --release\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>The server listens on port 4560. Open \u003Ccode>http:\u002F\u002Flocalhost:4560\u002Fapp\u002F\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>On the very first start with an empty database, the server refuses to start on purpose. Add \u003Ccode>createIfMissing = true\u003C\u002Fcode> under \u003Ccode>[database]\u003C\u002Fcode>, start once, then remove the line.\u003C\u002Fp>\n\u003Ch2 id=\"with-docker\">\u003Ca class=\"anchor\" href=\"#with-docker\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>With Docker\u003C\u002Fh2>\n\u003Cdiv class=\"code\">\u003Cspan class=\"lang\">sh\u003C\u002Fspan>\u003Cpre>\u003Ccode>docker compose up -d --build\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>The compose file mounts \u003Ccode>files\u002Fconfig.custom.toml\u003C\u002Fcode> read-only, plus the SQLite database and \u003Ccode>files\u002Fdatabase.json\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"the-config-file\">\u003Ca class=\"anchor\" href=\"#the-config-file\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>The config file\u003C\u002Fh2>\n\u003Cdiv class=\"table\" tabindex=\"0\">\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Section\u003C\u002Fth>\u003Cth>What it sets\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Ccode>[api]\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Public domain, ports, entry points\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Ccode>[web]\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Where the web client comes from: a signed release, or a build from the client repository\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Ccode>[network]\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Upload folder, public folder, the embedded web chat\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Ccode>[rtc]\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>TURN servers, relay-only mode, whether calls are on\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Ccode>[database]\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>SQLite path or PostgreSQL URL, \u003Ccode>createIfMissing\u003C\u002Fcode>\u003C\u002Ftd>\u003C\u002Ftr>\u003Ctr>\u003Ctd>\u003Ccode>[security]\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>CAPTCHA, proof-of-time difficulty, Privacy Pass, abuse thresholds\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Ch2 id=\"pointing-the-apps-at-your-server\">\u003Ca class=\"anchor\" href=\"#pointing-the-apps-at-your-server\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Pointing the apps at your server\u003C\u002Fh2>\n\u003Cp>Desktop and mobile builds read \u003Ccode>QXP_SERVER_ORIGIN\u003C\u002Fcode>, \u003Ccode>QXP_API_BASE_URL\u003C\u002Fcode> and \u003Ccode>QXP_WS_URL\u003C\u002Fcode>, plus \u003Ccode>QXP_TURN_URLS\u003C\u002Fcode>, \u003Ccode>QXP_TURN_USERNAME\u003C\u002Fcode>, \u003Ccode>QXP_TURN_CREDENTIAL\u003C\u002Fcode> and \u003Ccode>QXP_CALLS_ENABLED\u003C\u002Fcode> for calls. See the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Flqxp\u002Fapp\" target=\"_blank\" rel=\"noopener\">app repository\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2 id=\"updating\">\u003Ca class=\"anchor\" href=\"#updating\" aria-hidden=\"true\" tabindex=\"-1\">#\u003C\u002Fa>Updating\u003C\u002Fh2>\n\u003Cp>On bare metal, \u003Ccode>.\u002Fupdate.sh\u003C\u002Fcode> pulls, rebuilds and restarts through PM2. With Docker, pull and run \u003Ccode>docker compose up -d --build\u003C\u002Fcode> again.\u003C\u002Fp>\n\u003Cp>Room messages live in memory only, so a restart clears them from the server. Accounts, rooms and settings are kept in the database.\u003C\u002Fp>\n",[6,10,13,16,19,22],{"id":7,"text":8,"depth":9},"what-you-need","What you need",2,{"id":11,"text":12,"depth":9},"quick-start","Quick start",{"id":14,"text":15,"depth":9},"with-docker","With Docker",{"id":17,"text":18,"depth":9},"the-config-file","The config file",{"id":20,"text":21,"depth":9},"pointing-the-apps-at-your-server","Pointing the apps at your server",{"id":23,"text":24,"depth":9},"updating","Updating",1793535120530]