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.
137 lines
9.8 KiB
TypeScript
137 lines
9.8 KiB
TypeScript
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>{success, containerId, url, message, setupInstructions}</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 <jwt></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 '{
|
||
"appId": "minecraft",
|
||
"config": {
|
||
"subdomain": "mc",
|
||
"port": 25565
|
||
}
|
||
}'</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 (1–65535). 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>{memory, cpus}</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 '{ "message": "Deploy Minecraft Server on my home host and expose it at mc.sami" }'</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 <containerId></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/{appId}/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 <containerId></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>
|
||
);
|
||
}
|