<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux on Lessons learned</title><link>https://eghuro.cz/tags/linux/</link><description>Recent content in Linux on Lessons learned</description><generator>Hugo</generator><language>en-us</language><copyright>© Alexandr Mansurov · Licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)</copyright><lastBuildDate>Sat, 31 Oct 2026 22:29:00 +0100</lastBuildDate><atom:link href="https://eghuro.cz/tags/linux/index.xml" rel="self" type="application/rss+xml"/><item><title>Backing up ~/.claude and ~/.codex without archiving your AI logins</title><link>https://eghuro.cz/posts/ai-client-local-state-backup/</link><pubDate>Sat, 31 Oct 2026 22:29:00 +0100</pubDate><guid>https://eghuro.cz/posts/ai-client-local-state-backup/</guid><description>&lt;p&gt;If you back up the whole &lt;code&gt;~/.claude&lt;/code&gt; or &lt;code&gt;~/.codex&lt;/code&gt; folder, the restore works, and the backup now holds everything an infostealer wants. The same folder holds your settings, every session transcript in plaintext, and, on Linux, the login itself:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.claude/.credentials.json # Claude Code login, mode 0600&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.codex/auth.json # Codex login when file storage is in use&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.claude/projects/*/*.jsonl # transcripts: prompts, tool output, file contents&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Split the folder into two lists. Back up what you wrote: settings, instructions, skills, hooks, and memory. Keep transcripts as optional encrypted data. Leave login files out of routine backups and log in again after a restore.&lt;/p&gt;&#10;&#10;&lt;h2 id="where-ai-client-state-lives-on-macos-and-linux"&gt;Where AI client state lives on macOS and Linux &lt;/h2&gt;&#10;&lt;p&gt;I checked these paths against Claude Code 2.1.316, Claude Desktop for Linux 4.4212.0, ChatGPT for macOS 1.2026.183, the Codex desktop app for macOS 26.1027.30824, and Codex source at commit &lt;code&gt;67f0994&lt;/code&gt;. &amp;ldquo;Documented&amp;rdquo; means the vendor docs name the path. &amp;ldquo;Observed&amp;rdquo; means I found it by inspecting the official build so that it can change in any release.&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Client&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;State root&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Login material&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Evidence&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Claude Code&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/.claude/&lt;/code&gt; and &lt;code&gt;~/.claude.json&lt;/code&gt;, both under &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; if set&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Keychain on macOS, or &lt;code&gt;~/.claude/.credentials.json&lt;/code&gt; when the Keychain rejects the write (locked in an SSH session, for example). On Linux, always that file&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Documented&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Claude Desktop&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;macOS: &lt;code&gt;~/Library/Application Support/Claude/&lt;/code&gt;. Linux (beta): &lt;code&gt;${XDG_CONFIG_HOME:-~/.config}/Claude/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Electron cookies and Local Storage, extension secrets encrypted with &lt;code&gt;safeStorage&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;MCP config documented, rest observed&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ChatGPT desktop, macOS only&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/Library/Application Support/com.openai.chat/&lt;/code&gt;, &lt;code&gt;~/Library/Group Containers/2DC432GLL2.group.com.openai.chat/&lt;/code&gt;, &lt;code&gt;~/Library/Preferences/com.openai.chat.plist&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Keychain items in OpenAI&amp;rsquo;s access group&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Observed&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Codex desktop, macOS only&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/Library/Application Support/Codex/&lt;/code&gt;, plus &lt;code&gt;~/.codex&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Shared with Codex CLI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Observed&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Codex CLI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;${CODEX_HOME:-~/.codex}&lt;/code&gt;. &lt;code&gt;CODEX_SQLITE_HOME&lt;/code&gt;, &lt;code&gt;sqlite_home&lt;/code&gt; and &lt;code&gt;log_dir&lt;/code&gt; can move parts of it&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;auth.json&lt;/code&gt; in &lt;code&gt;file&lt;/code&gt; mode or as the &lt;code&gt;auto&lt;/code&gt; fallback; &lt;code&gt;.credentials.json&lt;/code&gt; for MCP OAuth without a keyring&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Documented and source&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Desktop sessions that run Claude Code write to &lt;code&gt;~/.claude/&lt;/code&gt;, not to the Electron folder, so include both.&lt;/p&gt;&#10;&#10;&lt;h2 id="what-to-back-up-and-what-to-leave-out"&gt;What to back up and what to leave out &lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Treatment&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Claude Code&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Codex&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Back up, versioned&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;settings.json&lt;/code&gt;, &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;rules/&lt;/code&gt;, &lt;code&gt;skills/&lt;/code&gt;, &lt;code&gt;commands/&lt;/code&gt;, &lt;code&gt;agents/&lt;/code&gt;, &lt;code&gt;workflows/&lt;/code&gt;, &lt;code&gt;output-styles/&lt;/code&gt;, &lt;code&gt;keybindings.json&lt;/code&gt;, &lt;code&gt;projects/*/memory/&lt;/code&gt;, &lt;code&gt;agent-memory/&lt;/code&gt;, &lt;code&gt;plugins/installed_plugins.json&lt;/code&gt; as a manifest&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;config.toml&lt;/code&gt;, &lt;code&gt;*.config.toml&lt;/code&gt;, &lt;code&gt;hooks.json&lt;/code&gt;, &lt;code&gt;rules/&lt;/code&gt;, &lt;code&gt;skills/&lt;/code&gt;, agent-role files&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Back up after a secret check&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;~/.claude.json&lt;/code&gt; (personal MCP servers, trust decisions)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;MCP &lt;code&gt;env&lt;/code&gt; blocks in &lt;code&gt;config.toml&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Optional, encrypted, short retention&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;projects/*/*.jsonl&lt;/code&gt;, &lt;code&gt;subagents/&lt;/code&gt;, &lt;code&gt;tool-results/&lt;/code&gt;, &lt;code&gt;history.jsonl&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;sessions/YYYY/MM/DD/rollout-*.jsonl&lt;/code&gt;, &lt;code&gt;archived_sessions/&lt;/code&gt;, &lt;code&gt;history.jsonl&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Exclude&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;.credentials.json&lt;/code&gt;, &lt;code&gt;file-history/&lt;/code&gt;, &lt;code&gt;paste-cache/&lt;/code&gt;, &lt;code&gt;debug/&lt;/code&gt;, &lt;code&gt;shell-snapshots/&lt;/code&gt;, &lt;code&gt;session-env/&lt;/code&gt;, &lt;code&gt;backups/&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;auth.json&lt;/code&gt;, &lt;code&gt;.credentials.json&lt;/code&gt;, &lt;code&gt;log/&lt;/code&gt;, &lt;code&gt;logs_2.sqlite&lt;/code&gt;, &lt;code&gt;shell_snapshots/&lt;/code&gt;, &lt;code&gt;packages/&lt;/code&gt;, caches&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;For Claude Desktop, keep &lt;code&gt;claude_desktop_config.json&lt;/code&gt; after checking its MCP &lt;code&gt;env&lt;/code&gt; blocks, plus a list of installed extensions and where each came from. Reinstall extensions instead of restoring their executable caches. The ChatGPT app&amp;rsquo;s local databases are caches of a server-side account; use the account&amp;rsquo;s data export for conversations you want to keep.&lt;/p&gt;&#10;&#10;&lt;h2 id="why-copying-the-whole-folder-is-the-wrong-default"&gt;Why copying the whole folder is the wrong default &lt;/h2&gt;&#10;&lt;p&gt;Transcripts are plaintext. &lt;a&#10; href="https://code.claude.com/docs/en/claude-directory.md"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;Anthropic&amp;rsquo;s docs&lt;/a&gt;&#10; say that anything passing through a tool is written to the session &lt;code&gt;.jsonl&lt;/code&gt;, so a &lt;code&gt;.env&lt;/code&gt; file a tool reads or a token a command prints is in there. Codex rollouts record tool activity the same way.&lt;/p&gt;&#10;&lt;p&gt;Your backup also keeps transcripts after the client has deleted them. Claude Code deletes transcripts after &lt;code&gt;cleanupPeriodDays&lt;/code&gt; (default 30), but keeps sessions started, or last continued in Claude Desktop or Cowork at any age unless you set &lt;code&gt;desktopSessionCleanupPeriodDays&lt;/code&gt;. A backup with a year of history still holds a transcript eleven months after the client deleted it.&lt;/p&gt;&#10;&lt;p&gt;A restore can also run code. Hooks, MCP server commands, skills, plugins, desktop extensions, and shell snapshots all execute something. If malware edited them, a full restore puts it back on the clean machine.&lt;/p&gt;&#10;&lt;p&gt;The Keychain protects less than it seems to. It stops someone who copies the disk offline, but malware running as your user can still request the item. The Linux desktop build can also fall back to Chromium&amp;rsquo;s basic password store when no wallet is running.&lt;/p&gt;&#10;&#10;&lt;h2 id="dead-ends-worth-skipping"&gt;Dead ends worth skipping &lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Guessing Linux paths from macOS ones.&lt;/strong&gt; Replacing &lt;code&gt;Library/Application Support&lt;/code&gt; with &lt;code&gt;.config&lt;/code&gt; works for Claude Desktop, which has a Linux beta. OpenAI ships no Linux desktop app for ChatGPT or Codex. The Codex source has Linux branches, but there is no supported Linux build. On Linux, your ChatGPT state lives in the browser profile.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Copying only the &lt;code&gt;.sqlite&lt;/code&gt; files.&lt;/strong&gt; Codex keeps state in &lt;code&gt;state_5.sqlite&lt;/code&gt;, &lt;code&gt;thread_history_1.sqlite&lt;/code&gt;, &lt;code&gt;memories_1.sqlite&lt;/code&gt; and &lt;a&#10; href="https://github.com/openai/codex/blob/67f0994b532b8740f14b5b738af7b7b2a915b1d6/codex-rs/state/src/sqlite.rs#L48-L53"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;others&lt;/a&gt;&#10;. A live copy without the &lt;code&gt;-wal&lt;/code&gt; and &lt;code&gt;-shm&lt;/code&gt; sidecars can be incomplete or corrupt. Stop the client and copy all three.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Treating the desktop database as the archive.&lt;/strong&gt; The Codex desktop app can rebuild its index from the rollout JSONL files, but metadata that lives only in the database is lost, back up the JSONL files.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Assuming &lt;code&gt;claude purge&lt;/code&gt; cleaned everything.&lt;/strong&gt; It doesn&amp;rsquo;t touch &lt;code&gt;shell-snapshots/&lt;/code&gt;, &lt;code&gt;backups/&lt;/code&gt; (older copies of &lt;code&gt;~/.claude.json&lt;/code&gt;) or files written by &lt;code&gt;/heapdump&lt;/code&gt;. According to Anthropic, a heap snapshot contains the full conversation and any credentials the process held.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2 id="restore-into-a-staging-profile"&gt;Restore into a staging profile &lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Reinstall the signed apps, plugins, and extensions from their sources.&lt;/li&gt;&#10;&lt;li&gt;Restore your config, then read every hook, MCP command, and executable path before the first launch.&lt;/li&gt;&#10;&lt;li&gt;Restore transcripts or memory only if you need them.&lt;/li&gt;&#10;&lt;li&gt;Log in again. Don&amp;rsquo;t restore &lt;code&gt;auth.json&lt;/code&gt;, &lt;code&gt;.credentials.json&lt;/code&gt;, cookies, or Keychain exports.&lt;/li&gt;&#10;&lt;li&gt;Resume one session and confirm that it uses the right account and repository.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&#10;&lt;h2 id="verify-the-backup-set"&gt;Verify the backup set &lt;/h2&gt;&#10;&lt;p&gt;To list what exists and how large it is, without printing any contents, run this on the machine you back up:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; p in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.claude&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.claude.json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.codex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;XDG_CONFIG_HOME&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.config&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/Claude&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Claude&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Codex&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/com.openai.chat&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Group Containers/2DC432GLL2.group.com.openai.chat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; du -sh &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then check that no login file ended up in the backup:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find /path/to/mounted/backup &lt;span class="se"&gt;\(&lt;/span&gt; -name .credentials.json -o -name auth.json &lt;span class="se"&gt;\)&lt;/span&gt; -print&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should print nothing. If it prints anything, that backup is a credential store: encrypt it, shorten its retention, or rotate the logins.&lt;/p&gt;&#10;&#10;&lt;h2 id="if-malware-may-already-have-run"&gt;If malware may already have run &lt;/h2&gt;&#10;&lt;p&gt;Don&amp;rsquo;t treat a restore as the cleanup. From a clean device, revoke your Claude and ChatGPT sessions, then rotate API keys, MCP and connector credentials, and any secret that appeared in a transcript or in tool output. Any backup the malware could reach counts as exposed. Rebuild the user profile, restore only config you have reviewed, and log in again.&lt;/p&gt;&#10;&#10;&lt;h2 id="caveats"&gt;Caveats &lt;/h2&gt;&#10;&lt;p&gt;Paths and retention rules change between releases. The ChatGPT and desktop paths come from build inspection, not from a published schema, so check them against your installed versions before you write a backup job. Sources: the &lt;a&#10; href="https://code.claude.com/docs/en/claude-directory.md"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;&lt;code&gt;.claude&lt;/code&gt; directory reference&lt;/a&gt;&#10;, &lt;a&#10; href="https://code.claude.com/docs/en/authentication.md#credential-management"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;Claude Code credential management&lt;/a&gt;&#10;, &lt;a&#10; href="https://learn.chatgpt.com/docs/config-file/config-advanced.md#config-and-state-locations"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;Codex config and state locations&lt;/a&gt;&#10;, &lt;a&#10; href="https://learn.chatgpt.com/docs/auth.md#credential-storage"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;Codex credential storage&lt;/a&gt;&#10;, &lt;a&#10; href="https://modelcontextprotocol.io/quickstart/user"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;Claude Desktop MCP config paths&lt;/a&gt;&#10;, and &lt;a&#10; href="https://www.electronjs.org/docs/latest/api/app#appgetpathname"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;Electron&amp;rsquo;s &lt;code&gt;app.getPath()&lt;/code&gt;&lt;/a&gt;&#10;.&lt;/p&gt;&#10;&lt;p&gt;Back up the config you wrote, and leave out the files the app uses for login. Run the &lt;code&gt;find&lt;/code&gt; check above against your latest backup tonight.&lt;/p&gt;&#10;</description></item><item><title>Unprivileged LXC containers share the host's per-user kernel limits: 'Too many open files' and 'disk quota exceeded'</title><link>https://eghuro.cz/posts/lxc-containers-share-host-kernel-limits/</link><pubDate>Wed, 21 Oct 2026 13:13:00 +0200</pubDate><guid>https://eghuro.cz/posts/lxc-containers-share-host-kernel-limits/</guid><description>&lt;p&gt;One day, two containers on the same host failed with errors that seemed unrelated. systemd in one of them:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemd[4573]: Failed to create control group inotify object: Too many open files&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemd[4573]: Failed to allocate manager object: Too many open files&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;systemd[1]: Failed to start user@1000.service - User Manager for UID 1000.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker in another, where every container sat at &lt;code&gt;Exited (128)&lt;/code&gt;:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OCI runtime create failed: runc create failed: unable to start container process: error during container init: unable to join session keyring: unable to create session key: disk quota exceeded: unknown&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No file descriptors had run out, and no disk was full. Both errors come from per-user kernel quotas counted on the host, and every unprivileged container there was drawing from the same two.&lt;/p&gt;&#10;&#10;&lt;h2 id="the-setup"&gt;The setup &lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Debian 13, kernel 6.12, LXC 6.0.4&lt;/li&gt;&#10;&lt;li&gt;More unprivileged containers than the hardware comfortably runs, all with the same idmap: container root is host UID 1000000&lt;/li&gt;&#10;&lt;li&gt;systemd in every container, Docker nested in some&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2 id="too-many-open-files-inotify-instances"&gt;Too many open files: inotify instances &lt;/h2&gt;&#10;&lt;p&gt;systemd opens inotify instances to watch cgroups and units, and &lt;code&gt;inotify_init1()&lt;/code&gt; fails with &lt;code&gt;EMFILE&lt;/code&gt; when the user&amp;rsquo;s instance limit is reached. strerror turns that into &amp;ldquo;Too many open files&amp;rdquo;. The limit is &lt;code&gt;fs.inotify.max_user_instances&lt;/code&gt;, 128 by default.&lt;/p&gt;&#10;&lt;p&gt;Count the instances per user on the host:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo find /proc/&lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;*/fd -lname &lt;span class="s1"&gt;&amp;#39;anon_inode:inotify&amp;#39;&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d/ -f3 &lt;span class="p"&gt;|&lt;/span&gt; xargs -I&lt;span class="o"&gt;{}&lt;/span&gt; ps -o &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; -p &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort &lt;span class="p"&gt;|&lt;/span&gt; uniq -c &lt;span class="p"&gt;|&lt;/span&gt; sort -rn&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat /proc/sys/fs/inotify/max_user_instances&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Host root held 23 instances, and uids in the container range (1000000 and up) held 104 between them: 127 of 128. On the first sighting, my coding agent got that far, then dropped it as a side effect of having started too many containers at once. That was half right, since each container&amp;rsquo;s systemd adds about five instances. A day later it came back.&lt;/p&gt;&#10;&lt;p&gt;The &lt;code&gt;lxc&lt;/code&gt; package already ships a higher limit, and it wasn&amp;rsquo;t in effect:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /etc/sysctl.d/30-lxc-inotify.conf | grep -v &amp;#39;^#&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fs.inotify.max_user_instances = 1024&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /proc/sys/fs/inotify/max_user_instances&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;128&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The file was dated three days after the last boot. &lt;code&gt;/etc/sysctl.d&lt;/code&gt; is applied by &lt;code&gt;systemd-sysctl&lt;/code&gt; at boot, and the package&amp;rsquo;s install hadn&amp;rsquo;t applied it, so the setting sat on disk doing nothing.&lt;/p&gt;&#10;&#10;&lt;h2 id="disk-quota-exceeded-kernel-keys"&gt;Disk quota exceeded: kernel keys &lt;/h2&gt;&#10;&lt;p&gt;runc gives each container it starts a new session keyring. &lt;code&gt;add_key()&lt;/code&gt; fails with &lt;code&gt;EDQUOT&lt;/code&gt; when the user&amp;rsquo;s key quota is full, and strerror calls that &amp;ldquo;Disk quota exceeded&amp;rdquo;. The quota is &lt;code&gt;kernel.keys.maxkeys&lt;/code&gt;, 200 keys for any uid other than root. The host shows usage per UID:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /proc/key-users&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0: 127 126/126 107/1000000 2283/25000000&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1000: 12 12/12 12/200 86/20000&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1000000: 198 198/198 198/200 4189/20000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;198/200&lt;/code&gt; are keys used against the quota. UID 1000000 is root in every container, so all the containers shared those 200 keys, and Docker&amp;rsquo;s restart attempts had nothing left.&lt;/p&gt;&#10;&#10;&lt;h2 id="the-fix"&gt;The fix &lt;/h2&gt;&#10;&lt;p&gt;Raise the limits and apply them right away, not at the next boot. Incus recommends 2000 keys and 2 MB in its &lt;a&#10; href="https://linuxcontainers.org/incus/docs/main/reference/server_settings"&#10; &#10; target="_blank" rel="noopener"&#10; &#10; &#10;&gt;server settings&lt;/a&gt;&#10;; 1024 inotify instances matches the &lt;code&gt;lxc&lt;/code&gt; package.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo tee /etc/sysctl.d/60-lxc-limits.conf &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;fs.inotify.max_user_instances = 1024&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kernel.keys.maxkeys = 2000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;kernel.keys.maxbytes = 2000000&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo sysctl -p /etc/sysctl.d/60-lxc-limits.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With Ansible, &lt;code&gt;ansible.posix.sysctl&lt;/code&gt; with &lt;code&gt;sysctl_set: true&lt;/code&gt; writes the file and sets the live value in one task.&lt;/p&gt;&#10;&lt;p&gt;Then run &lt;code&gt;systemctl reset-failed&lt;/code&gt; in the affected container, and &lt;code&gt;docker start&lt;/code&gt; for the dead Docker containers. Right after, uid 1000000 held 226 keys, already over the old limit.&lt;/p&gt;&#10;&#10;&lt;h2 id="why-the-two-quotas-are-counted-differently"&gt;Why the two quotas are counted differently &lt;/h2&gt;&#10;&lt;p&gt;The two quotas look similar, but separate idmaps would fix only one.&lt;/p&gt;&#10;&lt;p&gt;Keys are counted per host UID, against global sysctls. Containers that share an idmap share one quota. A separate idmap per container (&lt;code&gt;security.idmap.isolated&lt;/code&gt; in LXD and Incus) would give each its own.&lt;/p&gt;&#10;&lt;p&gt;inotify instances are counted per user namespace and charged up the chain of parent namespaces, at each level against the uid that created the child namespace. A new namespace&amp;rsquo;s own limit is &lt;code&gt;INT_MAX&lt;/code&gt;, so the limit that bites is the host&amp;rsquo;s, charged to whoever started the containers. LXC started as root charges host root, which is why the 23 instances of host root&amp;rsquo;s own daemons counted toward the same 128. Separate idmaps don&amp;rsquo;t change that.&lt;/p&gt;&#10;&#10;&lt;h2 id="takeaway"&gt;Takeaway &lt;/h2&gt;&#10;&lt;p&gt;On a container host, &amp;ldquo;Too many open files&amp;rdquo; and &amp;ldquo;disk quota exceeded&amp;rdquo; can mean that every container together hit a per-user kernel quota on the host. Check the host&amp;rsquo;s counters before you debug the container that complained.&lt;/p&gt;&#10;&lt;p&gt;Run the &lt;code&gt;find&lt;/code&gt; count and &lt;code&gt;cat /proc/key-users&lt;/code&gt; on your own container host and compare them with the limits before a container restart finds out for you.&lt;/p&gt;&#10;</description></item><item><title>Decode a MikroTik autosupout.rif yourself: 20 lines of Python found the out-of-memory kernel panic</title><link>https://eghuro.cz/posts/mikrotik-decode-autosupout-rif/</link><pubDate>Wed, 14 Oct 2026 18:17:00 +0200</pubDate><guid>https://eghuro.cz/posts/mikrotik-decode-autosupout-rif/</guid><description>&lt;p&gt;A MikroTik router kept rebooting every 10 minutes to 2.6 hours, with almost no traffic. After each boot, the log said:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;system,error,critical router was rebooted without proper shutdown, probably kernel failure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;system,error,critical kernel failure in previous boot&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;system,error,critical out of memory condition was detected&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;system,error,critical Automatic supout.rif file generated due to service malfunction, please contact MikroTik support and supply the generated file&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You don&amp;rsquo;t have to wait for support. &lt;code&gt;autosupout.rif&lt;/code&gt; is base64 with the bits in the other order, wrapped around zlib, and about 20 lines of Python turn it into plain text: the kernel&amp;rsquo;s last crash dumps, the log, &lt;code&gt;/proc&lt;/code&gt; and the full config. That&amp;rsquo;s where the cause was:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Out of memory and no killable processes...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kernel panic - not syncing: System is deadlocked on memory&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;h2 id="the-setup"&gt;The setup &lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;MikroTik hAP ac² (IPQ4019, 128 MiB RAM, 16 MiB flash)&lt;/li&gt;&#10;&lt;li&gt;RouterOS 6.49.5, then 7.23.8 (long-term) with the legacy &lt;code&gt;wireless&lt;/code&gt; package; both crashed the same way&lt;/li&gt;&#10;&lt;li&gt;Python 3 on a Mac to decode the file&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2 id="the-file-format"&gt;The file format &lt;/h2&gt;&#10;&lt;p&gt;Copy the file off the router and look at it:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scp admin@192.168.0.1:/autosupout.rif .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file autosupout.rif&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;head -2 autosupout.rif&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autosupout.rif: ASCII text, with CRLF line terminators&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--BEGIN ROUTEROS SUPOUT SECTION&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uQWZiV3ZAgHnt3X72tNOSb+7xXFYO5HTy0WSEgfKeG3rdsd643J2xjtT37s5kVHKSIbOWiUNJVs9&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It looks like base64, and &lt;code&gt;base64 -d&lt;/code&gt; turns it into noise. The alphabet is standard, but each group of four characters is read as a 24-bit little-endian number: the first character holds the lowest 6 bits, and the first output byte is the lowest 8 bits. Decoded, each section is its name, a NUL byte, and a zlib stream.&lt;/p&gt;&#10;&#10;&lt;h2 id="the-decoder"&gt;The decoder &lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;zlib&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ALPHABET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[^A-Za-z0-9+/=]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bytearray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rstrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ALPHABET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;little&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outdir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;sections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;--BEGIN ROUTEROS SUPOUT SECTION\r?\n(.*?)--END ROUTEROS SUPOUT SECTION&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ascii&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;section&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sections&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;section&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decompressobj&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decompress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[^\w.-]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;replace&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;02d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;safe&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;02d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;safe&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python3 supout.py autosupout.rif supout/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The 6.49.5 file had 76 sections and the 7.23.8 one 87. The useful ones:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Section&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;What&amp;rsquo;s in it&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;oops&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;the kernel log of the last few crashes, each with its timestamp&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;log&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;the RouterOS log since boot&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;resource&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;/system resource&lt;/code&gt; plus &lt;code&gt;/proc/meminfo&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;.proc&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;binary-ish dump of &lt;code&gt;/proc&lt;/code&gt;, including &lt;code&gt;slabinfo&lt;/code&gt;, &lt;code&gt;vmallocinfo&lt;/code&gt;, &lt;code&gt;buddyinfo&lt;/code&gt; (use &lt;code&gt;LC_ALL=C grep -a&lt;/code&gt;)&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;export&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;the full configuration&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;.debug&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;per-service debug output&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&#10;&lt;h2 id="what-it-showed"&gt;What it showed &lt;/h2&gt;&#10;&lt;p&gt;On 7.23.8, every crash in &lt;code&gt;oops&lt;/code&gt; ended the same way, after a process table in which every process had the same score:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ 691.378048][ T142] [ 150] 0 150 1667 153 28672 0 -1000 parser&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ 691.378492][ T142] Out of memory and no killable processes...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ 691.378509][ T142] Kernel panic - not syncing: System is deadlocked on memory&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;RouterOS runs every process with &lt;code&gt;oom_score_adj -1000&lt;/code&gt;, so the OOM killer has nothing to kill and the kernel panics. Any out-of-memory, however brief, is a reboot. 6.49.5 got there by another route, with the kernel set to panic on any OOM: &lt;code&gt;Kernel panic - not syncing: Out of memory: compulsory panic_on_oom is enabled&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;The processes weren&amp;rsquo;t the problem, at about 0.5 MiB each. &lt;code&gt;resource&lt;/code&gt;, written a minute after boot, was:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MemTotal: 118248 kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;MemFree: 7368 kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SUnreclaim: 52756 kB&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One minute into the boot, the kernel already held 52 MiB of unreclaimable memory. The caches in &lt;code&gt;slabinfo&lt;/code&gt; add up to only about 10 MiB, so the rest is allocated outside them. In two of the panics, other CPUs were inside the Wi-Fi driver (&lt;code&gt;ath_poll&lt;/code&gt;, &lt;code&gt;__w_qos_decrypt_mpdu&lt;/code&gt; in the &lt;code&gt;wlan&lt;/code&gt; and &lt;code&gt;ath&lt;/code&gt; modules), which makes it the main suspect, but turning one radio off didn&amp;rsquo;t settle it.&lt;/p&gt;&#10;&lt;p&gt;The same reading works on any embedded Linux box: check &lt;code&gt;oom_score_adj&lt;/code&gt; in the OOM dump, then &lt;code&gt;SUnreclaim&lt;/code&gt; against what the process table and &lt;code&gt;slabinfo&lt;/code&gt; explain.&lt;/p&gt;&#10;&#10;&lt;h2 id="read-the-timestamps-with-care"&gt;Read the timestamps with care &lt;/h2&gt;&#10;&lt;p&gt;The router has no battery-backed clock. After a crash, it restores an old time, and NTP takes minutes to catch up, so log and supout timestamps right after a reboot were about 7 minutes early. Five &amp;ldquo;crashes&amp;rdquo; stamped within two seconds of each other were most likely one boot loop.&lt;/p&gt;&#10;&lt;p&gt;The supout itself was written a minute &lt;em&gt;after&lt;/em&gt; the crash. The e-mail service tried to send the crash notice before PPPoE and DNS were up, died, and that service failure is what produced the file (&lt;code&gt;.debug&lt;/code&gt; shows &lt;code&gt;error: DNS resolve failed [code: 21]&lt;/code&gt; and then &lt;code&gt;died&lt;/code&gt;).&lt;/p&gt;&#10;&#10;&lt;h2 id="before-you-send-it-to-anyone"&gt;Before you send it to anyone &lt;/h2&gt;&#10;&lt;p&gt;The decoded sections held, in plain text, the PPPoE password, the WireGuard private key, a TSIG key, and a bearer token from a dynamic DNS script. Rotate those before you hand the file to MikroTik support or attach it to a forum post.&lt;/p&gt;&#10;&lt;p&gt;On a router this tight, delete the file after you copy it. The root of the file system is in RAM, and a 480 KiB supout is RAM the kernel needed:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/file remove [find name~&amp;#34;autosupout&amp;#34;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;h2 id="takeaway"&gt;Takeaway &lt;/h2&gt;&#10;&lt;p&gt;A &lt;code&gt;supout.rif&lt;/code&gt; holds the kernel log, &lt;code&gt;/proc&lt;/code&gt; and your config, and you can read it in a minute. Next time your MikroTik writes one, decode it and read &lt;code&gt;oops&lt;/code&gt; before you open a support ticket.&lt;/p&gt;&#10;</description></item></channel></rss>