Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Added

- **`docs/FAQ.md` and `docs/TROUBLESHOOTING.md`**, linked from the README and
the documentation index. These answers previously existed only as wiki source
in `docs/wiki/`, which meant nobody could read them until the GitHub wiki's
first page was created by hand — a step with no API. They are now part of the
documentation tree, and the wiki stays a convenience mirror.

### Changed

- **Progress bars are slid rather than stretched.** Around 28 of them — one per
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ redacted first.
[Website](https://gysosin.github.io/SysSentient/) ·
[Documentation](docs/README.md) ·
[Install](docs/INSTALL.md) ·
[FAQ](docs/FAQ.md) ·
[Troubleshooting](docs/TROUBLESHOOTING.md) ·
[Changelog](CHANGELOG.md)

> **Status:** pre-1.0. The daemon serves plain HTTP — terminate TLS in front of
Expand Down
53 changes: 53 additions & 0 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# FAQ

## Does it need a database server?

No. SQLite, in a single file at `database.path`. Nothing to install.

## How much history does it keep?

A year, in three tiers: raw samples for 24 hours, per-minute averages for 30
days, per-five-minute averages for a year. All three are configurable. Older
tiers are weighted averages, not samples thrown away — a minute's average is
weighted by how many samples it summarises, so a gap does not distort it.

## Does it send my data anywhere?

Only if you enable the AI analysis, and then only what that analysis needs.
Usernames, emails, IPs and paths are scrubbed before anything is sent. With
`ai.enabled: false` nothing leaves the machine at all. See
[PRIVACY.md](PRIVACY.md).

## What does it cost to run?

0.78% of one core at idle on a 2-second poll interval, and about 1.9 KB per
sample on disk before rollups. Both are measured, with the method written down,
in [PERFORMANCE.md](PERFORMANCE.md).

## Can I change the poll interval without restarting?

Yes. Poll interval, retention and log level are editable in **Settings →
Configuration** and apply immediately.

## Does it work on Windows and macOS?

Yes. Static binaries for linux, windows and darwin on amd64 and arm64, plus
`.deb`, `.rpm` and `.apk` packages and a multi-arch container image. There is
no C toolchain requirement — the SQLite driver is pure Go.

## Is there an API?

Yes, and the dashboard uses nothing else. `GET /api/metrics`, `/api/hosts`,
`/api/alerts`, `/api/export` (CSV or JSON), plus `/metrics` in Prometheus
exposition format. Authenticate with a session cookie or an `X-API-Key` header.

## How do I back it up?

```bash
sys-sentient --backup /var/backups/sys-sentient-$(date +%F).db
```

Do not copy the database file while the daemon is running. SQLite keeps the
database and its write-ahead log as two files that must agree, and a copy taken
between them is corrupt. The `--backup` flag uses SQLite's online backup, which
is safe on a live database.
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
| | |
|---|---|
| [INSTALL.md](INSTALL.md) | Packages, containers, building from source |
| [FAQ.md](FAQ.md) | The questions that come up in use |
| [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | When something is wrong, and what the logs mean |
| [CONFIGURATION.md](CONFIGURATION.md) | Every setting, and which apply without a restart |
| [ARCHITECTURE.md](ARCHITECTURE.md) | Shape, components, and the decisions behind them |
| [DEPLOYMENT.md](DEPLOYMENT.md) | Agents, servers, and fleets |
Expand Down
52 changes: 52 additions & 0 deletions docs/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Troubleshooting

## The dashboard is blank

The binary embeds the dashboard, so this is almost always a browser cache from
an older build. Hard-reload. If you are running from source, `web/dist` must
exist — run `npm run build` in `web/`.

## I lost the setup token

It is logged once, at startup, when no user account exists. If no account was
created yet, restart the daemon and it logs a fresh one. If an account does
exist, use the sign-in page instead.

## An agent is not appearing

Check its log first — it names the cause:

| Log line | Meaning |
|---|---|
| `revoked` | The credential was withdrawn. Generate a new token and re-run `agent join --force`. |
| `did not recognise this agent's credential` | Wrong or missing `agent.key`. Re-enrol. |
| `push failed, samples remain spooled` | Transient: the server is unreachable. Samples are buffered and retried. |

## `datetime()` returns NULL, or timestamps look wrong

Fixed in current builds. The pure-Go SQLite driver wrote `time.Time` in Go's
own `String()` format, which SQLite's date functions cannot parse. Every
binding site now uses an explicit layout. If you have a database written by an
affected build, the migration repairs it in place.

## The database file never shrinks

SQLite does not return freed pages to the filesystem on its own. Compaction
runs periodically; `sys-sentient --backup <path>` also writes a fully compacted
copy.

## High CPU

Raise `collector.poll_interval_seconds` — it is the dominant factor, and it is
editable in **Settings → Configuration** without a restart. Idle cost is 0.78%
of one core at a 2-second interval.

If you are measuring the daemon's own usage, match the process by exact name
(`pgrep -x sys-sentient`). A `pgrep -f` pattern also matches the shell you type
it in, which produces confident readings for the wrong process.

## Reporting a bug

Open an issue at
https://github.com/gysosin/SysSentient/issues with the output of
`sys-sentient --version` and the relevant log lines.
11 changes: 11 additions & 0 deletions docs/plans/19-repo-metadata-wiki.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,14 @@ than assuming it worked: it committed with no git identity (a wiki clone
inherits neither this repository's config nor necessarily a global one), and
its `[A-Z]*.md` glob published `README.md` as a wiki page despite a comment
claiming it excluded it.


## The content no longer depends on the wiki

FAQ and troubleshooting were only reachable as wiki source, so they were
invisible until someone created the wiki's first page by hand. They are now
`docs/FAQ.md` and `docs/TROUBLESHOOTING.md`, linked from the README and the docs
index, and rendered on GitHub like every other page in the tree.

`docs/wiki/` and `tool/publish_wiki.sh` remain for whoever wants the wiki tab
populated. Nothing is unreachable while that stays undone.
5 changes: 5 additions & 0 deletions docs/wiki/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Wiki source

> **The content here is also published in the docs tree**, which needs no manual
> step: [FAQ.md](../FAQ.md) and [TROUBLESHOOTING.md](../TROUBLESHOOTING.md).
> The wiki is a convenience mirror, not the only home — so nothing is
> unreachable while its first page is uncreated.

These pages are the GitHub wiki's content, kept here so they are reviewed and
versioned with the code rather than edited only in the wiki's own UI.

Expand Down
Loading