Files
dashcaddy.net/src/app/docs/catalog/minecraft/page.tsx
T
Hermes 414c962d3c docs(catalog): audit and fix 10 hallucinations in install guides
Round-1 docs claimed things the code does not do. This commit rewrites
all 77 per-template pages + the catalog index to match reality:

CORRECTED:
- REST API payload shape: was {template, subdomain, port, environment}
  Real Joi schema (src/utilities/validate.js appDeploy) is
  {appId, config: {subdomain, port, mediaPath?, plexClaimToken?, ...}}
  All optional fields now documented per-schema.

- Auth methods: was just "Authorization: Bearer" — real middleware
  accepts three (TOTP session cookie, Authorization: Bearer JWT,
  X-API-Key header). All three now shown.

- Deploy is synchronous: was "poll GET /api/v1/apps/{id}/status" — there
  is no status endpoint. Response shape documented as
  {success, containerId, url, message, setupInstructions}.

- AI Intent Router: was "starts the deployment" — it returns a
  structured intent; the caller must POST /api/v1/apps/deploy to
  actually provision. Documented accurately.

- MCP dashcaddy_deploy_app: was treated as full deploy — it only writes
  the Caddy route + services.json entry, NOT the container. Documented
  as such with manual docker pull as next step.

- Watchtower: was claimed to auto-update every 24h — DashCaddy does NOT
  poll for new digests. Watchtower is a separate template with default
  schedule 0 0 4 * * * (cron 04:00). Documented.

- Update button: was "Apps → {Name} → Update" — no such endpoint exists.
  Manual docker pull + restart now documented.

- Restore-on-install: was "prompt to restore from snapshot during install"
  — no such prompt. POST /api/v1/apps/{appId}/restore documented.

- Backups: was "default daily snapshot" — backup schedule is
  configurable via backup-config.json, not "nightly" by default.
  Volumes ARE included; documented.

- Dashboard menu: was "Apps → Catalog" — actual entry is the
  "App Selector" button on the dashboard home. Documented.

- Dashboard URL: status.sami confirmed correct (configurable via
  dashboardHost).

Also fixes default port resolution: was using portList[0].split(":")[0]
which leaks "{{PORT}}" literal when the template uses the placeholder.
Now uses t.defaultPort (Joi-validated) first, falling back to portList.

Build: 78 routes prerender as static, TypeScript clean.
2026-08-15 03:28:15 -07:00

137 lines
9.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Navbar from '@/components/Navbar';
import Footer from '@/components/Footer';
import DocsLayout from '@/components/docs/DocsLayout';
export const metadata = {
title: 'Install Minecraft Server — DashCaddy Docs',
description: 'Install and configure Minecraft Server via DashCaddy. Minecraft Java Edition dedicated server',
};
export default function minecraftDocsPage() {
return (
<div className="flex min-h-screen flex-col bg-surface-950 text-surface-50">
<Navbar />
<DocsLayout
title="Install Minecraft Server"
intro="Minecraft Java Edition dedicated server"
>
<div className="mb-6 flex flex-wrap gap-3 text-xs font-semibold">
<span className="rounded-full bg-surface-800 px-3 py-1 text-surface-300">Category: Gaming</span>
<span className="rounded-full px-3 py-1" style={{ backgroundColor: '#7cf2c022', color: '#7cf2c0' }}>Difficulty: Easy</span>
<span className="rounded-full bg-surface-800 px-3 py-1 text-surface-300">Docker image: <code className="text-brand-400">itzg/minecraft-server:latest</code></span>
</div>
<h2>What is Minecraft Server?</h2>
<p>Minecraft Java Edition dedicated server</p>
<p>Minecraft Server ships as a self-contained Docker image that DashCaddy provisions with one click. DashCaddy handles the container lifecycle, DNS record, Caddy reverse-proxy entry, and HTTPS certificate so you can focus on using Minecraft Server, not installing it.</p>
<h2>Prerequisites</h2>
<ul>
<li>A running DashCaddy host with the dashboard accessible (default URL: <code>https://status.sami</code>; configurable via the <code>dashboardHost</code> setting in <code>config.json</code>).</li>
<li>You must be signed in to the dashboard with an admin session, or have an API key with admin scope (<code>POST /api/v1/auth/keys</code> to create one).</li>
<li>No special host paths required.</li>
<li>For HTTPS with a real certificate, Technitium DNS must be configured and the host must have port 80/443 reachable from the internet. Otherwise DashCaddy will fall back to direct-IP access or a self-signed certificate.</li>
</ul>
<h2>Install via the DashCaddy dashboard</h2>
<ol>
<li>Sign in at <code>https://status.sami</code> (or your host's dashboard URL).</li>
<li>Click the <strong>📱 App Selector</strong> button on the dashboard home page.</li>
<li>Pick <strong>Minecraft Server</strong> from the Gaming category.</li>
<li>Fill in the deployment form: subdomain (default suggestion: <code>mc</code>), host port (default: <code>25565</code>).</li>
<li>Click <strong>Deploy</strong>. DashCaddy will pull the image, create persistent volumes, write a Caddy route, create the DNS record, and wait up to 30 seconds for the container's health check (<code>tcp://localhost:25565</code>) to pass.</li>
<li>When the dashboard shows the service as <strong>Running</strong>, the URL (built from your subdomain and configured TLD) is clickable. The deploy API returns a synchronous response with <code>&#123;success, containerId, url, message, setupInstructions&#125;</code> — there is no separate status-poll endpoint; the dashboard updates live.</li>
</ol>
<h2>Install via the REST API</h2>
<p>Authenticate with an API key (or a JWT minted via <code>POST /api/v1/auth/jwt</code>). Send as <code>X-API-Key: dk_...</code> or <code>Authorization: Bearer &lt;jwt&gt;</code>.</p>
<pre className="overflow-x-auto rounded-lg bg-surface-900 p-4 text-sm"><code>curl -X POST https://status.sami/api/v1/apps/deploy \\
-H "X-API-Key: dk_your_api_key" \\
-H "Content-Type: application/json" \\
-d '&#123;
"appId": "minecraft",
"config": &#123;
"subdomain": "mc",
"port": 25565
&#125;
&#125;'</code></pre>
<p>The full body schema is in <code>src/utilities/validate.js</code> (Joi schema <code>appDeploy</code>). All <code>config.*</code> fields except <code>subdomain</code> are optional. Notable options:</p>
<ul>
<li><code>config.port</code> — host port (165535). Defaults to the template's <code>defaultPort</code>.</li>
<li><code>config.mediaPath</code> host directory to mount as the media library.</li>
<li><code>config.plexClaimToken</code> Plex claim token (when the upstream service needs one).</li>
<li><code>config.useExisting: true</code> + <code>existingContainerId</code> attach DashCaddy metadata to an already-running container instead of pulling a new image.</li>
<li><code>config.tailscaleOnly: true</code> restrict the reverse-proxy entry to your Tailscale network.</li>
<li><code>config.allowedIPs</code> array of CIDR ranges allowed past the reverse proxy.</li>
<li><code>config.createDns: false</code> skip DNS record creation (use when the subdomain already resolves).</li>
<li><code>config.resources</code> <code>&#123;memory, cpus&#125;</code> limits applied to the container.</li>
</ul>
<h2>Install via the AI Intent Router (returns a structured intent)</h2>
<p>The Intent Router returns a structured intent, not a deployed container. To deploy via AI, send natural language to:</p>
<pre className="overflow-x-auto rounded-lg bg-surface-900 p-4 text-sm"><code>curl -X POST https://status.sami/api/v1/ai/intent \\
-H "X-API-Key: dk_your_api_key" \\
-H "Content-Type: application/json" \\
-d '&#123; "message": "Deploy Minecraft Server on my home host and expose it at mc.sami" &#125;'</code></pre>
<p>The response includes <code>intent</code>, <code>action</code>, <code>parameters</code>, and <code>followup</code> your client (or the MCP server) must then call <code>POST /api/v1/apps/deploy</code> with those parameters to actually provision the container.</p>
<h2>Install via the MCP Server</h2>
<p>For AI agents (Claude Desktop, Hermes, etc.) configure the MCP server (<code>src/mcp/mcp-server.js</code>) with:</p>
<pre className="overflow-x-auto rounded-lg bg-surface-900 p-4 text-sm"><code>DASHCADDY_URL=https://status.sami:3001 # internal API URL, may differ from dashboard URL
DASHCADDY_API_KEY=dk_your_api_key</code></pre>
<p>The server exposes <code>dashcaddy_deploy_app</code>. Note: this tool writes the Caddy route and creates the <code>services.json</code> entry, but it does NOT pull the Docker image or start the container. You must run <code>docker pull itzg/minecraft-server:latest</code> and start the container yourself for the URL to actually serve traffic. For a fully-managed deployment, call <code>POST /api/v1/apps/deploy</code> directly from your agent.</p>
<h2>Post-install: first-run checklist</h2>
<ol>
<li>Server accepts the Minecraft EULA automatically</li>
<li>Connect with your Minecraft client to the server IP:port</li>
<li>Configure server.properties in the data volume for customization</li>
<li>Supports Vanilla, Paper, Forge, Fabric via TYPE environment variable</li>
</ol>
<h2>Volumes and persistent data</h2>
<p>DashCaddy creates these volume mounts in the container spec:</p>
<ul>
<li><code>/opt/minecraft/data:/data</code></li>
</ul>
<p>All paths are host paths (left side) mapped into the container (right side). Restarting the container preserves data; reinstalling the template preserves it unless you explicitly pass <code>config.useExisting: false</code> AND wipe the volume. Bind mounts use the host-path conventions above (e.g. <code>/opt/plex/config</code> becomes a bind mount to the host directory of the same path).</p>
<h2>Environment variables</h2>
<ul>
<li><code>EULA</code></li>
<li><code>TYPE</code></li>
<li><code>VERSION</code></li>
<li><code>MEMORY</code></li>
<li><code>MAX_PLAYERS</code></li>
<li><code>MOTD</code></li>
</ul><p>These are baked into the template at deploy time and shipped to the container. The deploy handler does NOT allow overriding them via the API payload to change them you must edit the template definition in <code>dashcaddy-api/src/docker/app-templates.js</code>.</p>
<h2>Updating the image</h2>
<p>There is no built-in auto-update DashCaddy does NOT poll for new image digests. To pull a new version:</p>
<ol>
<li>SSH into the DashCaddy host and run <code>docker pull itzg/minecraft-server:latest</code>.</li>
<li>Restart the container: <code>docker restart &lt;containerId&gt;</code> (find the ID via <code>GET /api/v1/services</code> or the dashboard).</li>
<li>Or deploy Watchtower from this catalog (separate template that polls Docker Hub and updates other containers automatically, default schedule <code>0 0 4 * * *</code> = 04:00 daily).</li>
</ol>
<h2>Backups</h2>
<p>The default backup policy includes the entire <code>/app/data/</code> directory (services, config, credentials, stats) AND all Docker volumes. Backups are scheduled via <code>backup-config.json</code> the default schedule is configurable, not "nightly" out of the box. To restore on a fresh host, redeploy the same template and then call <code>POST /api/v1/apps/&#123;appId&#125;/restore</code> with a backup ID from <code>GET /api/v1/backups/history</code>.</p>
<h2>Troubleshooting</h2>
<p>Common issues with Minecraft Server:</p>
<ul>
<li><strong>Container won't start:</strong> check the dashboard's Logs panel. Most startup failures are permission errors on the host-path volume.</li>
<li><strong>URL not reachable after deploy:</strong> the Caddy route was written but DNS hasn't propagated, or port 80/443 is firewalled. Check <code>GET /api/v1/dns/records</code> and <code>systemctl status caddy</code> on the host.</li>
<li><strong>Health check timeout (deploy returns 30s after start):</strong> the container is starting but <code>tcp://localhost:25565</code> is not returning 200. Inspect <code>docker logs &lt;containerId&gt;</code> directly.</li>
</ul>
<p>For layer-by-layer diagnostics, see the <a href="/docs/troubleshooting" className="text-brand-400 underline">Troubleshooting guide</a>.</p>
<hr className="my-8 border-surface-700" />
<p className="text-sm text-surface-400">
Template ID: <code>minecraft</code>. Source: <code>dashcaddy-api/src/docker/app-templates.js</code>.
</p>
</DocsLayout>
<Footer />
</div>
);
}