Configuration
MiniMost is designed to work out-of-the-box with zero configuration. All settings have sensible defaults and only need to be changed to customize the application for your environment.
settings.json
Location: src/minimost/settings.json — the file is bundled inside the
package so it ships in the wheel.
The main configuration file for MiniMost. It is a JSON object. All keys are optional — missing keys fall back to built-in defaults.
Example (showing all available keys with their defaults):
{
"channels": ["general", "software", "firmware", "systems", "off-topic"],
"image_retention_days": 30,
"file_retention_days": 30,
"message_retention_days": 770,
"max_upload_size_mb": 25,
"max_avatar_size_mb": 5,
"stun_port": 3478,
"max_login_attempts": 5,
"lockout_duration_minutes": 15
}
channelsList of public channel names visible to all users. Channels are displayed in the sidebar in the order listed. Changes take effect on the next server restart. If this key is absent or the file cannot be read, MiniMost falls back to a single
"general"channel. Channel names should be short, lowercase, and contain no spaces.image_retention_daysHow many days to keep image attachments in
uploads/before the background cleanup thread removes them. Defaults to30. Changes take effect at the next scheduled cleanup run — no restart required. See Administration for details.file_retention_daysHow many days to keep non-image file attachments in
uploads/before the background cleanup thread removes them. Defaults to30. Kept separate fromimage_retention_daysso administrators can apply different retention policies to images versus documents, archives, etc. Changes take effect at the next scheduled cleanup run — no restart required.message_retention_daysHow many days to keep messages in the per-user SQLite databases before they are permanently deleted. Unlike the soft-delete used when a user deletes a message, this removes the database rows entirely so the
users/*.dbfiles do not grow without bound over time. Defaults to770(approximately two years). Changes take effect at the next scheduled cleanup run — no restart required.Note
Messages deleted by this process are gone permanently — they cannot be recovered. Set this value to a period that comfortably covers how far back your users ever need to scroll.
max_upload_size_mbMaximum size in megabytes allowed for a single file attachment uploaded via the message input. Applies to all file types. Defaults to
25. The server enforces this limit per file and returns413if it is exceeded; the browser also warns the user before attempting the upload. Changes require a server restart to take effect.max_avatar_size_mbMaximum size in megabytes allowed for a profile avatar upload. The browser resizes the chosen image to 128×128 pixels before sending, so the upload is always small in practice — this limit guards against oversized source files being loaded into browser memory. Defaults to
5. Changes require a server restart to take effect.stun_portUDP port the bundled STUN server listens on, used by WebRTC calls and screen sharing so LAN peers can gather a server-reflexive ICE candidate. Must be an integer in the range
1–65535. Defaults to3478(the IANA-assigned STUN port). Avoid the OS ephemeral range (typically32768–60999on Linux) to prevent bind collisions. Changes require a server restart to take effect.max_login_attemptsNumber of consecutive failed login attempts allowed against an existing account before it is temporarily locked. Defaults to
5. Set to0(or any non-positive value) to disable account lockout entirely. The counter resets to zero on the next successful login. Read fresh on every login attempt, so changes take effect without a restart.lockout_duration_minutesHow long, in minutes, an account remains locked once
max_login_attemptsis reached. During the lockout window every login is rejected without checking the password, and the user is shown how many minutes remain. Defaults to15. Read fresh on every login attempt, so changes take effect without a restart.Note
Lockout is tracked per account (in the
users.failed_attemptsandusers.lockout_untilcolumns ofauth.db), not per IP address. A lockout message confirms that the account exists, which is a deliberate trade-off for clear user feedback; the rest of the login flow keeps invalid-username and invalid-password failures indistinguishable.
Warning
Removing a channel from settings.json does not delete its message
history. The messages remain in each user’s database but the channel will
no longer appear in the sidebar. If you re-add the channel name later,
the history reappears.
secret.key
Location: <project_root>/secret.key
A 64-character hexadecimal string used as Flask’s SECRET_KEY for signing
session cookies. MiniMost generates this file automatically on first startup
using secrets.token_hex().
Important
Keep this file secret and do not commit it to version control. If the secret key changes, all existing browser sessions are invalidated and users must log in again.
Back it up alongside your databases when migrating to a new server.
auth.db
Location: <project_root>/auth.db
The shared SQLite database that stores user credentials. Created automatically on first startup. Contains a single table:
CREATE TABLE users (
username TEXT PRIMARY KEY,
password_hash TEXT NOT NULL
);
password_hashstores a Werkzeug PBKDF2 hash, never plaintext.To reset a forgotten password, update this column directly with a new hash.
Generating a replacement hash:
from werkzeug.security import generate_password_hash
print(generate_password_hash("NewPassword123!"))
Then update the database:
sqlite3 auth.db
UPDATE users SET password_hash = '<output_from_above>' WHERE username = 'alice';
.quit
presence.db
Location: <project_root>/presence.db
The shared SQLite database for real-time state: presence status, typing indicators, read receipts, and message reactions. Created automatically on first startup.
This database can be safely deleted if it becomes corrupted — it will be recreated on next startup. The only data lost is:
Presence states (users will appear offline until they next reload).
Typing indicators (transient — no user-visible impact).
Read receipts (
✓checkmarks will disappear for existing messages).Reactions (emoji reactions will disappear from all messages).
users/ directory
Location: <project_root>/users/
Contains one SQLite .db file per registered user, named
<username>.db. Each file holds the user’s complete message history.
These files are the primary data store of MiniMost. Back them up regularly.
uploads/ directory
Location: <project_root>/uploads/
Stores all message file attachments. Two naming schemes are used:
Images (
jpg,jpeg,png,gif,webp) are stored as<uuid32hex><ext>(e.g.a3f1b2c4d5e6f7a8b9c0d1e2f3a4b5c6.jpg).All other files are stored as
<uuid32hex>_<original_filename>(e.g.a3f1b2c4d5e6f7a8b9c0d1e2f3a4b5c6_report.pdf), preserving the original name while still preventing collisions and path-traversal attacks.
Files are automatically purged by a background thread that runs every 24 hours,
using type-specific retention periods from settings.json:
"image_retention_days"controls how long image files are kept (default: 30)."file_retention_days"controls how long non-image files are kept (default: 30).
See Administration for details on manual cleanup.
avatars/ directory
Location: <project_root>/avatars/
Stores user profile avatar images. Each file is named <uuid32hex>.jpg and
is linked to a user via the avatar_file column in the user_settings
table in auth.db.
Avatars are uploaded at a maximum resolution of 128×128 pixels (the browser
crops and resizes the source image before sending). The maximum permitted source
file size is controlled by "max_avatar_size_mb" in settings.json
(default: 5 MB).
When a user uploads a new avatar, the previous file is automatically deleted. Avatar files are not subject to the automatic retention cleanup — they persist until the user replaces or removes them, or the user account is deleted.
gunicorn.conf.py
Location: <project_root>/gunicorn.conf.py
Configuration file for the Gunicorn WSGI server, used when running in production. The defaults are:
Setting |
Default |
Description |
|---|---|---|
|
|
Address and port to listen on. Change to a Unix socket when using Nginx as a reverse proxy. |
|
|
Number of worker processes. Each worker handles one request at a time (sync worker class). |
|
|
Synchronous workers. Suitable for MiniMost’s SQLite-based workload. |
|
|
Seconds before a worker is killed if it does not respond. Increase if link preview fetches are timing out. |
|
|
Load the application once in the master process before forking. Saves memory and startup time. |
|
|
Restart workers after this many requests to prevent memory leaks. |
|
|
Random jitter added to |
|
|
Log verbosity. |
|
|
Access log destination. Captured by systemd if running as a service. |
|
|
Added to |
Example: Unix socket bind (for use with Nginx)
# gunicorn.conf.py
bind = "unix:/run/gunicorn/minimost.sock"
Example: File-based logging
# gunicorn.conf.py
accesslog = "/var/log/minimost/access.log"
errorlog = "/var/log/minimost/error.log"
Environment Variables
MiniMost itself does not read any environment variables. Flask respects the following standard variables if set:
Variable |
Effect |
|---|---|
|
Set to |
|
Used by Gunicorn’s |