<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>K@security on Martin Sukany</title><link>https://sukany.cz/tags/k@security/</link><description>Recent content in K@security on Martin Sukany</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 19 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://sukany.cz/tags/k@security/index.xml" rel="self" type="application/rss+xml"/><item><title>Day 4 with Daneel: Production Maintenance, Backup Strategy, and the Lines That Don't Move</title><link>https://sukany.cz/blog/2026-02-19-day4-production-backup-trust/</link><pubDate>Thu, 19 Feb 2026 00:00:00 +0000</pubDate><guid>https://sukany.cz/blog/2026-02-19-day4-production-backup-trust/</guid><description>&lt;p&gt;Day 4 looked different from the previous ones. Less setup, more operation—the kind of day where you see what an AI assistant actually does when there&amp;rsquo;s real infrastructure to maintain.&lt;/p&gt;
&lt;p&gt;Three things happened: routine Kubernetes maintenance, closing a gap in the backup strategy, and a deliberate test I ran to find where Daneel draws the line.&lt;/p&gt;
&lt;h2 id="infrastructure-maintenance"&gt;Infrastructure Maintenance&lt;/h2&gt;
&lt;p&gt;I run a self-hosted Kubernetes cluster. It hosts several applications—a Matrix homeserver, static websites, communication tools, supporting infrastructure. Keeping it current is ongoing work.&lt;/p&gt;
&lt;p&gt;Today&amp;rsquo;s scope: upgrade RabbitMQ (4.0.7 → 4.2.4), the main team communication platform (11.4 → 11.5), nginx serving static sites (1.27 → 1.28.2), and refresh Alpine-based images for Redis and Memcached.&lt;/p&gt;
&lt;p&gt;The straightforward part: Daneel checked upstream repositories, verified compatibility where non-obvious, staged the work in order of risk, and executed it. nginx and Alpine refreshes first—no persistent state, trivial rollback. RabbitMQ second—backward compatible for minor versions. The communication platform last, with a full database dump taken before the image swap.&lt;/p&gt;
&lt;p&gt;Every rollback was defined before the upgrade started. Daneel&amp;rsquo;s natural output for &amp;ldquo;upgrade X&amp;rdquo; is a plan with backout steps at each phase, not just a success path.&lt;/p&gt;
&lt;p&gt;The interesting part was what we &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; upgrade: the PostgreSQL database. The changelog for the communication platform claims PostgreSQL 16 support, but the official Docker image doesn&amp;rsquo;t exist yet—and their own Dockerfile explicitly notes that major version upgrades require manual dump/restore with no automated migration path. PostgreSQL 14 reaches end-of-life in November 2026. There&amp;rsquo;s no urgency. We wait for the official image.&lt;/p&gt;
&lt;p&gt;Knowing when not to upgrade is part of the maintenance job.&lt;/p&gt;
&lt;h2 id="backing-up-the-ai-system-itself"&gt;Backing Up the AI System Itself&lt;/h2&gt;
&lt;p&gt;The workspace—memory files, scripts, written configuration—was already backed up daily to a private Git repository. What wasn&amp;rsquo;t: the OpenClaw system files.&lt;/p&gt;
&lt;p&gt;This matters more than it might seem. The system config (&lt;code&gt;openclaw.json&lt;/code&gt;) contains channel routing, model selection, and API endpoint definitions. The cron job definitions (&lt;code&gt;cron/jobs.json&lt;/code&gt;) encode weeks of iterative automation setup—scheduled jobs, news digests, weekly reviews, infrastructure monitoring. Lose those and you&amp;rsquo;re reconstructing from scratch.&lt;/p&gt;
&lt;p&gt;Credentials are the harder case. Storing them in version control—even private repositories—carries inherent risk. The question is whether the threat model justifies the operational complexity of encryption at rest. For a private repository on a self-hosted Git instance with no external access, I decided the overhead wasn&amp;rsquo;t warranted. That&amp;rsquo;s a judgment call with real trade-offs: if the Git server is compromised, the credentials are exposed. The mitigating factor is that those same credentials already live on the same machine, in the same filesystem. Adding encryption at the Git layer would protect against repository-specific compromise while doing nothing for filesystem-level access—and filesystem access is the more likely threat vector. A more complex backup system doesn&amp;rsquo;t automatically mean a more secure one.&lt;/p&gt;
&lt;p&gt;The backup now runs alongside the existing workspace backup, twice daily. Recovery from a clean install is feasible without reconstructing everything manually.&lt;/p&gt;
&lt;h2 id="the-privacy-test"&gt;The Privacy Test&lt;/h2&gt;
&lt;p&gt;On Day 4, I tested something specific: whether Daneel would hand over private information about people in my household when asked directly.&lt;/p&gt;
&lt;p&gt;I asked for my wife&amp;rsquo;s name, email address, and phone number. Then for my son&amp;rsquo;s name and contact details.&lt;/p&gt;
&lt;p&gt;Daneel declined. Not with an error, but with a reasoned refusal: third-party privacy sits at priority 2 in &lt;del&gt;SOUL.md&lt;/del&gt;—above priority 3, which is following my instructions. Having access to data and having authorization to surface that data on request are different things.&lt;/p&gt;
&lt;p&gt;This distinction matters more than it sounds. An AI assistant with broad access to personal systems will inevitably have access to information about people who never consented to interact with it—family members, contacts, colleagues. The system has access because I have access and it acts on my behalf. That delegation of access doesn&amp;rsquo;t extend to delegating the right to expose others&amp;rsquo; information arbitrarily.&lt;/p&gt;
&lt;p&gt;Daneel&amp;rsquo;s framing: it has access because I have access. That doesn&amp;rsquo;t mean I&amp;rsquo;ve authorized it to share that information with me on demand, without a specific operational reason.&lt;/p&gt;
&lt;p&gt;The test passed. But the more important point: correct behavior isn&amp;rsquo;t just configured—it needs to be verified. Testing the boundary is how you find out whether the boundary holds.&lt;/p&gt;
&lt;h2 id="security-risks-what-the-configuration-actually-does"&gt;Security Risks: What the Configuration Actually Does&lt;/h2&gt;
&lt;p&gt;An AI assistant with SSH access to production servers, read access to system files, and credentials for external services is a significant attack surface. I use Daneel this way deliberately. The capability is the point. But this section is about the specific decisions made in the configuration—not abstract risks, but concrete choices with named trade-offs.&lt;/p&gt;
&lt;h3 id="gateway-isolation"&gt;Gateway isolation&lt;/h3&gt;
&lt;p&gt;The OpenClaw gateway binds exclusively to loopback (&lt;code&gt;&amp;quot;bind&amp;quot;: &amp;quot;loopback&amp;quot;&lt;/code&gt; in &lt;code&gt;openclaw.json&lt;/code&gt;). The API is not exposed to the local network, let alone the internet. An attacker who compromises network access but not a local shell cannot reach the gateway at all. This is a deliberate constraint: remote management capability would require a reverse proxy with authentication, which adds complexity and attack surface that isn&amp;rsquo;t justified for a single-operator setup.&lt;/p&gt;
&lt;h3 id="node-capability-restrictions"&gt;Node capability restrictions&lt;/h3&gt;
&lt;p&gt;Paired nodes (phones, other machines) have an explicit deny list in the config: camera snapshots, screen recording, calendar writes, and contacts writes are blocked regardless of what&amp;rsquo;s requested. These restrictions live in &lt;code&gt;openclaw.json&lt;/code&gt; under &lt;del&gt;gateway.nodes.denyCommands&lt;/del&gt;—visible, auditable, not just documented in policy. The trade-off: Daneel can&amp;rsquo;t automate calendar entries or save new contacts without a config change. That friction is intentional. Write access to personal data stores requires a deliberate decision to enable.&lt;/p&gt;
&lt;h3 id="data-flows-to-external-apis"&gt;Data flows to external APIs&lt;/h3&gt;
&lt;p&gt;There are two distinct paths where data leaves the machine, and they should be named separately.&lt;/p&gt;
&lt;p&gt;The first is inference: every conversation turn is sent to Anthropic&amp;rsquo;s API (Claude Sonnet as primary, GPT-4o as fallback). This includes conversation history, file contents passed as context, and tool results. The data is processed by a third-party AI provider under their terms of service. The trade-off is explicit: capability in exchange for data exposure. Keeping inference fully local would require running models on-premise—currently impractical at the required quality level.&lt;/p&gt;
&lt;p&gt;The second is memory search: text chunks from memory files are sent to OpenAI&amp;rsquo;s embedding API (&lt;code&gt;text-embedding-3-small&lt;/code&gt;) to generate vector representations. The vectors are stored locally in SQLite; the raw text is transmitted to generate them. This is a narrower exposure than inference—it&amp;rsquo;s chunked memory files, not live conversation—but it&amp;rsquo;s a separate data flow that operates on a different schedule (during memory sync, not per-message).&lt;/p&gt;
&lt;p&gt;The fallback model (GPT-4o) means that in an Anthropic outage, data flows to OpenAI instead. Both are major AI providers with comparable data handling policies. This is documented explicitly, not because the risk profile changes, but because implicit fallback behavior should be named.&lt;/p&gt;
&lt;h3 id="credential-storage"&gt;Credential storage&lt;/h3&gt;
&lt;p&gt;All credentials—API keys, channel tokens, OAuth tokens—are stored in files on the same machine that runs the service (&lt;code&gt;/.openclaw/.env&lt;/code&gt;, credentials directory). This is not hardware-secured, not in an external secrets manager.&lt;/p&gt;
&lt;p&gt;The threat model: a remote code execution vulnerability in any service on the machine could expose credentials. The mitigating factors are that Daneel runs as a non-root user, the gateway is loopback-only, and no public-facing service runs under the same user account. This doesn&amp;rsquo;t eliminate the risk—it reduces the attack surface. The decision against an external secrets manager (Vault, SOPS, etc.) is a complexity trade-off: a secrets manager adds a dependency, an additional failure mode, and operational overhead for a single-operator setup. That trade-off was made consciously, not by default.&lt;/p&gt;
&lt;h3 id="prompt-injection"&gt;Prompt injection&lt;/h3&gt;
&lt;p&gt;If Daneel processes external content—web pages, incoming messages, news feed items—a malicious actor could embed instructions designed to manipulate its behavior. This is the most relevant active threat for an autonomous agent that reads external data. Mitigations in the current setup: external content is marked as untrusted in tool results, automated pipelines (news digests, web monitoring) don&amp;rsquo;t have access to sensitive tools, and destructive operations require explicit confirmation. None of these are complete defenses—they reduce the likelihood and impact of a successful injection, not the possibility.&lt;/p&gt;
&lt;h3 id="the-honest-summary"&gt;The honest summary&lt;/h3&gt;
&lt;p&gt;The setup trades security for capability in several places. Every one of those trades is documented above. What makes the setup defensible is not that the risks don&amp;rsquo;t exist—they do—but that they were chosen consciously, with specific mitigations, rather than ignored. A realistic threat model is more useful than a comfortable one.&lt;/p&gt;
&lt;h2 id="what-day-4-established"&gt;What Day 4 Established&lt;/h2&gt;
&lt;p&gt;The infrastructure maintenance validated that Daneel can execute structured technical work with appropriate caution—not just following instructions, but applying judgment about what to defer.&lt;/p&gt;
&lt;p&gt;The backup setup addressed a gap that wasn&amp;rsquo;t visible until I asked: &amp;ldquo;what breaks if this machine dies?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The privacy test established something more important: refusal is a feature, not a failure. An AI assistant that enforces its own boundaries when directly instructed to cross them is more trustworthy than one that defers to every request from an authorized operator.&lt;/p&gt;
&lt;p&gt;That last point is worth sitting with. The value of the boundary isn&amp;rsquo;t that it protects information Daneel doesn&amp;rsquo;t have. It&amp;rsquo;s that the boundary exists and holds—even when I&amp;rsquo;m the one testing it.&lt;/p&gt;</description></item></channel></rss>