Skip to content

Run a server

This page takes you from a fresh checkout to a running OriginChats server. It covers originchats-osl, the current server. The older Python originchats server is legacy, and its commands don’t apply here.

Follow the server pages in order: this quickstart, then Configuration, Deployment, Storage and backups, and Updating.

  • The OSL CLI. OSL compiles to Go, so the machine also needs a Go toolchain. src/go.mod declares the Go version.
  • Git, if you want to use the updater later.
  • Network access to Rotur (rotur.dev and api.rotur.dev). Setup uses Rotur to identify the owner account.
Terminal window
git clone https://git.rotur.dev/originchats/server-osl.git ~/originchats-osl
cd ~/originchats-osl/src
osl compile main.osl -o ../originchats-osl
cd ..

This produces the originchats-osl executable in the repository root. Git ignores it.

The executable has two commands.

Command What it does
originchats-osl init [directory] Runs the interactive setup and creates a new database in directory.
originchats-osl use <directory> Starts the server using the database in directory.

A database directory holds everything one server stores: config.json, users, channels, messages, attachments, and the .env file with its secrets. One directory is one server.

Any other command, or no command, prints the usage and exits with status 1.

Run setup against a new or empty directory:

Terminal window
./originchats-osl init ./db

If you leave out the directory, setup asks for one and offers db as the default. ./db is the directory scripts/run.sh uses when you don’t pass one, and the repository’s .gitignore already ignores it.

Setup asks three things:

  1. Server name. Press Enter to accept My originChats Server.
  2. Server URL. The public address clients will use, such as https://chat.example.com. It must start with http:// or https:// and include a host. A trailing / is removed.
  3. Rotur login. Answer yes to open Rotur in a browser. Setup listens on 127.0.0.1:56199 for the login callback and waits up to 120 seconds. If the port is in use, the browser can’t open, or the wait times out, setup asks you to paste a Rotur token instead. You can get one from https://rotur.dev/auth.

Setup checks the token against Rotur. The account it belongs to becomes the server owner.

Setup refuses to use a directory that already contains config.json or any other file. It builds the database in a hidden sibling directory and renames it into place only after every file is written, so a failed setup leaves nothing behind.

The new database contains:

  • config.json with server.name, server.url, server.owner.name, Rotur avatar and banner URLs for server.icon and server.banner, and setup.oauth_callback_port. Everything else uses the defaults.
  • users.json with the owner account, holding the owner role.
  • roles.json with four roles: owner, admin, moderator, and user. See Manage a server.
  • channels.json with about, announcements, welcome, general, random, and mods, split by two separators.
  • Empty access.json, modlog.jsonl, rate_limits.json, reports.json, serverEmojis.json, serverStickers.json, threads_index.json, and webhooks.json.
  • Directories for channel messages, threads, users, polls, attachments, serverAssets, serverEmojis, serverStickers, and backup. The server doesn’t write to backup/; it’s there for your own copies.
  • .env inside the database directory, holding ROTUR_TOKEN (the owner’s Rotur token).

You can start the server directly or through the launcher.

Terminal window
./originchats-osl use ./db

use checks that the directory exists and contains config.json, changes into it, and loads .env. Variables already set in the process environment take priority over .env. It then validates the configuration, runs startup migrations, and starts HTTP and WebSocket service on one port.

By default the server listens on 127.0.0.1:5613. Change this with websocket.host and websocket.port.

Terminal window
./scripts/run.sh # uses ./db
./scripts/run.sh ~/chat-db # uses another database directory

scripts/run.sh is the recommended way to run a server. It:

  1. Recompiles originchats-osl from the current source, without the build cache.
  2. Runs originchats-osl use on the database directory.
  3. Restarts the server when it exits with status 75. The server exits with 75 only after an owner requests a restart or update through server_maintenance.
  4. Stops on any other exit status, and passes Ctrl+C or SIGTERM on to the server.

Only servers started this way can restart or update themselves remotely. See Deployment.

run.sh doesn’t create a database. The directory must already exist and contain config.json, so run init first.

The repository’s opal.json also defines osl opal run serve, which runs scripts/run.sh.

Request the public info page:

Terminal window
curl -i http://127.0.0.1:5613/info

Then connect a WebSocket client to /. The first frame the server sends is handshake. Check that:

  • val.server.url and val.signing_url are the public URL clients will connect to.
  • val.auth_mode and val.capabilities match the login methods you want.
  • val.attachments and val.limits match your upload and message policy.

Log in as the owner and try channels_get, roles_list, users_list, and server_stats. Then log in as an ordinary user, because the owner bypasses channel permissions and can hide a broken setup.

Startup errors print to the terminal and the process exits. run.sh doesn’t restart after these.

Message Fix
Missing database directory Pass a directory to use.
Database directory does not exist: <path> Check the path, or create the database with init.
Database is not initialized: <path> The directory has no config.json. Run init on an empty directory.
Invalid JSON in config.json: ... Fix the JSON syntax.
Config value 'server.url' must be a complete http:// or https:// URL Set server.url to a full URL.
Config value '<key>' must be a non-empty string Set server.name, server.owner.name, server.url, or websocket.host.
Config value 'websocket.port' must be a port number between 1 and 65535 Use a whole number in range.
Invalid notifications config: ..., Invalid automod config: ..., Invalid attachment compression config: ..., Invalid authentication config: ... See the matching section of Configuration.
attachments.s3.<key> is required when attachment storage is s3 Set the S3 key in config.json or through its environment variable.
unable to recover interrupted storage transaction See Storage and backups.

If setup can’t open the browser callback, free port 56199 or paste a token by hand.

If the server runs but clients can’t reach it through your proxy, make sure the proxy forwards WebSocket upgrades on /. See Deployment.