Menu
AkurAI-Build
publicLatest change 5ecb45c5915e3bb122d43dbaf90b4eba39484c7d - organize native templates and reserve runtime routes by Olafur Bui
{% extends "layouts/docs.html" %}
{% block title %}Deployment and recovery ยท Bunfork docs{% endblock %}
{% block description %}Create digest-owned Bunfork deployment bundles, run hardened systemd units, and perform encrypted backup and verified restore procedures.{% endblock %}
{% block breadcrumb %}Deploy & recover{% endblock %}
{% block docs_title %}Deploy & recover{% endblock %}
{% block docs_summary %}A release should be identifiable, replaceable, and recoverable. Bunfork builds a local owned bundle and keeps runtime state outside it.{% endblock %}
{% block docs_content %}
<section class="doc-section" aria-labelledby="native-deploy">
<h2 id="native-deploy">Create a native release</h2>
<pre><code>./target/release/bunfork deploy
./bunfork-dist/bunfork \
--database "$HOME/.local/share/bunfork/bunfork.db" \
--key-file "$HOME/.config/bunfork/db.key" \
serve --token-file "$HOME/.config/bunfork/api.token"</code></pre>
<p><code>deploy</code> takes a project lock, runs tests, release-builds, stages, hashes, fsyncs, and atomically installs <code>bunfork-dist</code>. Its <code>bunfork.json</code> inventory owns every bundled file except the manifest itself.</p>
<p>Runtime database, key, and token paths are intentionally not bundled. Keep immutable release files under <code>$HOME/.local/lib/bunfork</code>, mutable data under <code>$HOME/.local/share/bunfork</code>, and secrets under <code>$HOME/.config/bunfork</code>.</p>
</section>
<section class="doc-section" aria-labelledby="static-deploy">
<h2 id="static-deploy">Bundle an admitted static site</h2>
<pre><code>./target/release/bunfork deploy \
--artifact frontend/out \
--static-manifest bunfork-static.json</code></pre>
<p>The static bundle contains the Bunfork binary, admitted site, strict artifact manifest, deployment inventory, and service units. It runs from any working directory and needs no data secrets.</p>
<pre><code>./bunfork-dist/bunfork serve \
--static ./bunfork-dist/site \
--manifest ./bunfork-dist/bunfork-static.json</code></pre>
</section>
<section class="doc-section" aria-labelledby="replace-release">
<h2 id="replace-release">Replace only what Bunfork owns</h2>
<p>If the output already exists, <code>--force</code> first validates its complete inventory and binary. Modified or unowned directories are refused. A verified previous release is preserved as a sibling and is never automatically deleted.</p>
<aside class="doc-note"><strong>Protected output names:</strong> Bunfork refuses hidden paths and project roots such as <code>app</code>, <code>src</code>, <code>data</code>, <code>backups</code>, <code>deploy</code>, <code>migrations</code>, <code>public</code>, and <code>target</code>.</aside>
</section>
<section class="doc-section" aria-labelledby="service-units">
<h2 id="service-units">Hardened user services</h2>
<p>The bundle includes native and static systemd user units configured for <code>0.0.0.0:3100</code>. They set a restrictive umask and enable filesystem/process controls including <code>NoNewPrivileges</code>, <code>ProtectSystem=strict</code>, an empty capability set, and restricted address families.</p>
<p>Bunfork copies the units; the operator still installs/enables them and configures the host firewall and TLS proxy.</p>
</section>
<section class="doc-section" aria-labelledby="backup-restore">
<h2 id="backup-restore">Backup and restore</h2>
<ol class="steps compact-steps">
<li>
<h3>Create an explicit backup</h3>
<pre><code>./target/release/bunfork backup \
--out backups/pre-release.db</code></pre>
<p>The destination must not already exist. Publication is synced and the encrypted schema is reopened and verified.</p>
</li>
<li>
<h3>Stop the server before restore</h3>
<pre><code>systemctl --user stop bunfork.service</code></pre>
<p>Bunfork has no distributed or online-restore lock. Quiesce every writer first.</p>
</li>
<li>
<h3>Restore with acknowledgement</h3>
<pre><code>./target/release/bunfork restore \
backups/pre-release.db --yes</code></pre>
<p>The backup is verified, installed atomically, and the prior live database is retained with a timestamped name.</p>
</li>
</ol>
<aside class="doc-callout warning" aria-labelledby="key-warning">
<h2 id="key-warning">A backup is not key rotation</h2>
<p>Backups use the same database key as the live file. Protect and recover that key separately; losing it makes both live and backup data unreadable.</p>
</aside>
</section>
<section class="doc-section" aria-labelledby="deploy-boundary">
<h2 id="deploy-boundary">Deployment boundary</h2>
<p>Bunfork creates and validates local release directories. It does not provision machines, transfer releases, configure DNS or TLS, manage remote backup storage, or remove retained releases. Those stay explicit operator responsibilities.</p>
</section>
<nav class="docs-pagination" aria-label="Documentation pagination">
<a href="/docs/data"><small>Previous</small><span aria-hidden="true">โ</span> SQLite & vectors</a>
<a href="/docs/security"><small>Next</small>Security <span aria-hidden="true">โ</span></a>
</nav>
{% endblock %}