3.1 KiB
Message Log
This document defines the persisted chat-history format used by TNT 1.x.
Format: messages.log v1
Each record is one UTF-8 line:
RFC3339_UTC|username|content\n
Example:
2026-05-27T12:34:56Z|alice|hello
Rules:
- Timestamp is strict UTC RFC3339:
YYYY-MM-DDTHH:MM:SSZ. - The separator is literal
|. - A valid record has exactly three fields and exactly two separators.
usernameandcontentmust be non-empty valid UTF-8.usernamemust fitMAX_USERNAME_LEN;contentmust fitMAX_MESSAGE_LEN.- Every complete record ends with
\n.
The file has no header. The version is defined by this record contract so existing append-only logs remain readable.
Write Behavior
message_save() sanitizes fields before appending:
|,\n, and\rin usernames become_.|,\n, and\rin content become spaces.- Timestamps are written in UTC.
Private messages are not written to messages.log. :inbox stores incoming
and sent private-message copies only in each participant's live session memory,
so inbox state is lost on disconnect and never appears in tail, dump,
:last, or :search.
Replay And Search
Replay and search use the same strict parser. TNT skips records that are:
- malformed or missing fields
- invalid UTF-8
- too long
- outside the accepted timestamp window
- terminated without a trailing newline
- written with extra separators
Skipping a bad record is intentional recovery behavior. A truncated final line is treated as a partial append and ignored rather than replayed.
Export
dump [N] and dump -n N export valid persisted records through the SSH exec
interface and tntctl. The output format is exactly the v1 record format
above. Without N, dump exports all valid records; with N, it exports the
last N valid records.
Maintenance
scripts/logrotate.sh is the manual archive and compaction tool for
messages.log:
scripts/logrotate.sh [--dry-run] [--keep-archives N] LOG_FILE MAX_SIZE_MB KEEP_LINES
When the log exceeds MAX_SIZE_MB, the script archives the full file, compacts
the active file to the last KEEP_LINES records, compresses the archive when
gzip is available, and removes older archives beyond the retention limit.
Run it while TNT is stopped or during a quiet maintenance window if strict log
consistency matters.
Recovery
Installed tnt binaries provide offline log checking and recovery:
tnt --log-check LOG_FILE
tnt --log-recover LOG_FILE > recovered.messages.log
--log-check prints a summary:
path /var/lib/tnt/messages.log
records_seen 120
valid_records 119
invalid_records 1
first_invalid_line 120
It exits 0 when every record is valid and 1 when invalid records are found
or the log cannot be read. --log-recover writes only valid v1 records to
stdout, prints the same summary to stderr, and also exits 1 if records were
skipped. It never modifies the source log.
Compatibility
The v1 record format is stable for TNT 1.x. Future incompatible storage changes must document downgrade behavior in release notes and provide an operator-visible migration or export path.