Deployment and Operations
OxideBBS runs as a local binary (oxidebbs-server) plus a local CLI. Remote admin access is intentionally not supported in this release.
For cross-platform deployments on Windows, macOS, and Linux hosts with Docker, use Docker Deployment. That path keeps the runtime Linux, includes DOSEMU2 inside the image, and stores DecentDB/runtime/door state on Docker named volumes.
Runtime deployment workflow
- Generate config and scaffold:
cargo run -p oxidebbs-server -- --data /srv/oxidebbs/data/oxidebbs.ddb setup \
--output /etc/oxidebbs/oxidebbs.toml \
--board-name "My BBS" \
--sysop-alias sysop \
--sysop-password "change-this"- Validate before first boot:
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml check- Start serving:
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml serve- Install your distribution's DOSEMU2 package on hosts that will launch DOS doors. The executable is commonly named
dosemu, but legacydosemu-1.xis not supported because it does not accept OxideBBS's run-localpts <path>COM1 mapping:
dosemu --versionFedora hosts should follow DOSEMU2 on Fedora. The validated Fedora setup uses the stsp/dosemu2 Copr packages and requires libdj64.so.0 to be visible through ldconfig; otherwise DOSEMU2 can fail while booting COMMAND.COM.
DOSEMU2 in the v1 path is headless and does not need SDL or a display server.
In Debian 13 Proxmox LXC deployments:
- ensure
/dev/ptsis mounted and writable in the container, - verify DOSEMU2 sees a PTY path by checking
/dev/pts, - prefer unprivileged LXC when policy allows it, because DOSEMU2 is not tied to privileged-only settings for this model.
test -d /dev/pts && ls -ld /dev/pts- Validate and dry-run the bundled test door:
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml doors check oxide-check
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml doors dropfile oxide-check --user sysop --node 1 --format DORINFO1.DEF
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml doors test oxide-check --user sysop --dry-run- To run a live smoke test, keep DOSEMU2 installed, enable
oxide-checkin the active config, start the server, and launchoxide-checkfrom the callerDoorsmenu.
The deployed byte path is:
caller telnet client
<-> OxideBBS caller transport
<-> OxideBBS PTY byte bridge
<-> DOSEMU2 COM1 pts backend
<-> DOSEMU2-emulated COM1 UART
<-> DOS door programLive launch should produce per-node runtime data and report files under runtime/node-001/:
OXDOSEMU2.CONFis generated with$_com1 = "pts .../node-001/OXCOM1.PTY"OXCOM1.PTYappears while the door is active- bridge ownership remains with OxideBBS, not by a serial daemon
- Verify health:
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml status
cargo run -p oxidebbs-server -- --config /etc/oxidebbs/oxidebbs.toml nodes listLive launch fails clearly when:
dosemuis missing,- the per-node PTY path never appears,
- the node runtime directory is not writable,
- the caller disconnects before the door exits,
- or the runtime timeout triggers and closes the child.
Native build prerequisites
When compiling in fresh Debian/Ubuntu environments:
sudo apt-get install -y clang libclang-devLocal control socket in deployment
serve starts a Unix control socket at:
<runtime path>/oxidebbs-control.sockThis socket enables:
- live
statusandnodesqueries - live node messaging/disconnect/broadcast/reset-stale
- stale node detection visibility
On Unix, the runtime directory is mode 0700, the socket is mode 0600, and incoming control clients are rejected unless their peer UID matches the server process UID.
If the socket path already exists and is active, startup fails instead of silently falling back to offline behavior.
If no process is listening, startup removes a stale socket file automatically.
For unexpected runtime-path permission or ownership issues, recover with:
systemctl stop oxidebbs
rm -f /srv/oxidebbs/runtime/oxidebbs-control.sock
install -d -o oxidebbs -g oxidebbs /srv/oxidebbs/runtime
systemctl start oxidebbsStale node and operations checks
nodes listshows stale states from heartbeat age and marks stale nodes asstale.nodes reset-staleasks the live runtime to disconnect stale nodes through the local control socket.statusreports uptime from the live listener when available; otherwise marks it unavailable.- Live
status --jsonincludesaudit_write_failures, the count of best-effort audit writes that failed during the current server run.
Service layout examples
A systemd service should call the built binary with explicit config and writable paths:
[Unit]
Description=OxideBBS telnet server
After=network-online.target
[Service]
Type=simple
User=oxidebbs
Group=oxidebbs
WorkingDirectory=/srv/oxidebbs
Environment=RUST_LOG=oxidebbs=info
ExecStart=/usr/local/bin/oxidebbs-server --config /etc/oxidebbs/oxidebbs.toml serve
Restart=on-failure
[Install]
WantedBy=multi-user.targetKeep the configured telnet bind on 127.0.0.1:2323 unless you are deliberately exposing a plaintext telnet service. Public binds send credentials and caller traffic without encryption.
Before public exposure, run a connection limit smoke test with max_connections + 1 callers. The extra caller should receive the busy message while accepted nodes remain visible and stable through nodes list.
Documentation site deployment
The documentation site is independent of the runtime. Build and publish with VitePress using existing GitHub workflow configuration:
npm ci
npm run docs:build
npm run docs:devThe built output is docs/.vitepress/dist and is published by .github/workflows/pages.yml.