Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

Mobius

Mobius is a cross-platform command line Hotline server implemented in Golang.

  • Project Goal: Make it simple to run a Hotline server on macOS, Linux, and Windows, with full compatibility for all popular Hotline clients.

Installation

Mobius is distributed through a single binary.

Depending on your platform and preferences, you can acquire the binary in the following ways:

Build from source

  1. Install Go if needed
  2. Run make server

Download pre-built release

See Releases page.

Docker

To run a Hotline server with a default, sample configuration with ports forwarded from the host OS to the container:

docker run --rm -p 5500:5500 -p 5501:5501 ghcr.io/jhalter/mobius-hotline-server:latest

You can now connect to localhost:5500 with your favorite Hotline client and play around, but all changes will be lost on container restart.

To serve files from the host OS and persist configuration changes, you'll want to set up a bind mount that maps a directory from the host into the container.

To do this, create a directory in a location of your choice on the host OS. For clarity, we'll assign the path to the HLFILES environment variable and re-use it.

Then run the docker command with -v and -init like so:

export HLFILES=/home/myuser/hotline-files
mdkir $HLFILES

sudo docker run \
    --pull=always \
    --rm \
    -p 5500:5500 \
    -p 5501:5501 \
    -v $HLFILES:/usr/local/var/mobius/config \
    ghcr.io/jhalter/mobius-hotline-server:latest \
    -init

It's a good security practice to run your server as a non-root user, which also happens to make editing the configuration files easier from the host OS.

To do this, add the --user flag to the docker run arguments with a user ID and group ID of a user on the host OS.

--user 1001:1001

Homebrew

For macOS the easiest path to installation is through Homebrew, as this works around Apple's notarization requirements for downloaded pre-compiled binaries by compiling the binary on your system during brew installation.

To install the server:

brew install jhalter/mobius-hotline-server/mobius-hotline-server

After installation mobius-hotline-server will be installed at $HOMEBREW_PREFIX/bin/mobius-hotline-server and should be in your $PATH.

The server config directory will be created under $HOMEBREW_PREFIX/var/mobius.

To start the service:

brew services start mobius-hotline-server

Server Configuration

After you have a server binary, the next step is to configure the server.

Configuration directory

Mobius stores its configuration and server state in a directory tree:

config
├── Agreement.txt
├── Files
│   └── hello.txt
├── MessageBoard.txt
├── ThreadedNews.yaml
├── Users
│   ├── admin.yaml
│   └── guest.yaml
├── banner.jpg
└── config.yaml

If you acquired the server binary by downloading it or compiling it, this directory doesn't exist yet! But you can generate it by running the the server with the -init flag:

./mobius-hotline-server -init -config example-config-dir

Brew users can find the config directory in $HOMEBREW_PREFIX/var/mobius.

Within this directory some files are intended to be edited to customize the server, while others are not.


  • 🛠️ Edit this file to customize your server.
  • ⚠️ Avoid manual edits outside of special circumstances (e.g. remove offending news content).

🛠️ Agreement.text - The server agreement sent to users after they join the server.

🛠️ Files - Home of your warez or any other files you'd like to share.

⚠️ MessageBoard.txt - Plain text file containing the server's message board. No need to edit this.

⚠️ ThreadedNews.yaml - YAML file containing the server's threaded news. No need to edit this.

⚠️ Users - Directory containing user account YAML files. No need to edit this.

🛠️ banner.jpg - Path to server banner image.

🛠️ config.yaml - Edit to set your server name, description, and enable tracker registration.

Server banners

Existing configurations using BannerFile continue to serve one banner. To choose a random banner for each client session, add BannerDirectory:

BannerFile: "banner.jpg"    # Single banner, and fallback for directory mode
BannerDirectory: "banners" # Optional; relative to the configuration directory

Create the directory and place JPEG or GIF banners inside it. Absolute directory paths are also accepted. Banners are always read from the local filesystem, independently of the file library's storage backend. The server loads readable, nonempty .jpg, .jpeg, and .gif files (case-insensitively) from that directory's immediate contents. Hidden files, subdirectories, and symlinks are skipped. Keep each image within the existing 262,140-byte client limit; the standard banner size is 468 × 60 pixels. Images are served as provided, without conversion or additional image-content validation. Banner display is only known to work in Hotline 1.8 clients.

When BannerDirectory is set, it takes precedence over BannerFile. Each session gets an equally likely choice and keeps that image for repeat downloads. Different sessions can receive the same image, and JPEG and GIF banners can be mixed. Images are cached in memory, so directory size determines the pool's memory use.

If the directory is missing, unreadable, or contains no usable images, the server logs a warning and uses BannerFile. BannerFile can be omitted in directory mode if no fallback is wanted. If neither source can be loaded, startup fails; a failed reload retains the previous working images.

After adding, removing, or replacing images, send SIGHUP or use POST /api/v1/reload. New sessions use the refreshed pool; existing directory-mode sessions retain their selected image, including a fallback image. Single-file mode continues to use the refreshed banner for subsequent download requests. Downloads already requested always finish with the bytes and size captured for that transfer. Restart after changing BannerDirectory or BannerFile in config.yaml. There is no automatic directory watching or timed rotation.

Feed-backed threaded news

An advanced NewsFeeds configuration can import RSS or Atom entries into an existing ordinary news category, including Sparkle appcasts and GitHub release feeds:

See Feed-backed threaded news for the complete administrator guide, including configuration rules, retention behavior, durable state, operational limits, and troubleshooting.

NewsFeeds:
  - CategoryPath: ["Software Updates", "Afterglow"]
    URL: "https://morphing.cloud/afterglow/appcast.xml"
  - CategoryPath: ["Software Updates", "Mobius"]
    URL: "https://github.com/jhalter/mobius/releases.atom"

The full target path must already exist as an ordinary category. Whenever a client opens it, Mobius conditionally checks the source and saves new entries as ordinary root articles in ThreadedNews.yaml. Existing entries are never rewritten, and deleted imports stay deleted. Feed failures are logged while the current local articles remain available. RSS and Atom are detected automatically; changes to NewsFeeds require restarting the server.

User accounts

The default installation includes two users:

  • guest (no password)
  • admin (default password admin).

User administration should be performed from a Hotline client. Avoid editing the files under the Users directory.

The FileRoot field in an account YAML file is the exception when assigning that account a separate file library. An empty value inherits the global FileRoot. With the default os file store, a relative value is resolved from the config directory and an absolute value is used as-is. With the memory or r2 file store, a relative value remains a path in the store's namespace. Restart the server after changing this field manually.

Run the server

By default running mobius-hotline-server will listen on ports 5500/5501 of all interfaces with info level logging to STDOUT.

Use the -h or -help flag for a list of options:

$ mobius-hotline-server -h
Usage of mobius-hotline-server:
  -bind int
    	Base Hotline server port.  File transfer port is base port + 1. (default 5500)
  -config string
    	Path to config root (default "/usr/local/var/mobius/config/")
  -init
    	Populate the config dir with default configuration
  -interface string
    	IP addr of interface to listen on.  Defaults to all interfaces.
  -log-file string
    	Path to log file
  -log-level string
    	Log level (default "info")
  -stats-port string
    	Enable stats HTTP endpoint on address and port
  -version
    	Print version and exit

To run as a systemd service, refer to this sample unit file: mobius-hotline-server.service

Connection logs

Hotline control connections include remote_addr on their connection, authentication, and request events. Use remote_addr (IP and source port) to correlate events for a connection. Each connection ends with a Connection closed summary containing its last stage, handshake_ok, authenticated, requests_received, requests_handled, duration_ms, and reason. For example, a client that completes the handshake and disconnects without sending a login produces an INFO summary like:

msg="Connection closed" remote_addr=192.0.2.1:52256 stage=login handshake_ok=true authenticated=false requests_received=0 requests_handled=0 duration_ms=12 reason=peer_closed

Truncated transactions are WARN events with buffered_bytes and expected_bytes. Oversized or malformed transactions have distinct reasons; resets and timeouts retain the underlying error. Payloads and passwords are not included in these diagnostics.

Authentication succeeded is emitted once when credentials verify. Agreement acceptance is logged separately as Agreement accepted; authentication alone does not mean a client has completed session setup or issued any requests.

After login, each request is logged with its operation as the message (for example, msg="Get user list"), plus transaction_id and transaction_type. This event records receipt before the handler runs. Panics and unsupported transactions are logged as Request failed and Request rejected. requests_received counts decoded post-login transactions, including keepalives and unsupported requests. requests_handled counts handlers that returned normally, including those generating error replies. Routine keepalive events are suppressed, but included in these counters.

Neither a request log nor the requests_handled count proves response delivery. The asynchronous writer logs Transaction write failed with the transaction ID if a socket write fails. Unexpected write failures are WARN events. Closed-connection errors caused by deliberate disconnects or server shutdown are DEBUG events.

File Storage

By default the file library is stored on the server's local disk. The -file-store flag selects an alternate backend:

  • os (default) — local filesystem
  • memory — in-memory, non-persistent (for testing)
  • r2 — Cloudflare R2 object storage

See docs/r2-file-store.md for R2 setup instructions.

HTTP API

The Mobius server includes an optional HTTP API for server administration and user management.

Configuration

To enable the API, use the --api-addr flag with an IP and port:

mobius-hotline-server --api-addr=127.0.0.1:5503

Authentication

The API supports optional authentication via API key. Set the --api-key flag:

mobius-hotline-server --api-addr=127.0.0.1:5503 --api-key=your-secret-key

Include the API key in the X-API-Key header:

curl -H "X-API-Key: your-secret-key" localhost:5503/api/v1/stats

API Documentation

Complete API documentation is available in the OpenAPI specification.

Endpoints

User Management

  • GET /api/v1/online - List currently online users
  • POST /api/v1/ban - Ban a user by username, nickname, or IP
  • POST /api/v1/unban - Remove a ban
  • GET /api/v1/banned/ips - List banned IP addresses
  • GET /api/v1/banned/usernames - List banned usernames
  • GET /api/v1/banned/nicknames - List banned nicknames

Server Administration

  • GET /api/v1/stats - Get server statistics
  • POST /api/v1/reload - Reload configuration
  • POST /api/v1/shutdown - Shutdown server

Examples

Get online users:

curl localhost:5503/api/v1/online

Ban a user:

curl -X POST -H "Content-Type: application/json" \
  -d '{"username":"baduser"}' \
  localhost:5503/api/v1/ban

Get server stats:

curl localhost:5503/api/v1/stats | jq .

Shutdown server:

curl -X POST -d 'Server maintenance' localhost:5503/api/v1/shutdown

关于 About

A Hotline server implemented in Golang for macOS, Linux, and Windows operating systems
hotlinehotline-server

语言 Languages

Go99.9%
Makefile0.1%
Dockerfile0.0%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
85
Total Commits
峰值: 13次/周
Less
More

核心贡献者 Contributors