Files
VectorDNS/app/docs/self-hosting/page.tsx
2026-02-26 12:10:58 -05:00

344 lines
10 KiB
TypeScript

import type { Metadata } from "next";
import { Server, ArrowRight, Terminal, Package, Cloud } from "lucide-react";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
export const metadata: Metadata = {
title: "Self-Hosting",
};
function CodeBlock({ code }: { code: string }) {
return (
<pre className="overflow-x-auto rounded-md border bg-muted/50 p-4 font-mono text-sm leading-relaxed">
<code>{code.trim()}</code>
</pre>
);
}
function Step({
n,
title,
children,
}: {
n: number;
title: string;
children: React.ReactNode;
}) {
return (
<div className="flex gap-4">
<div className="flex size-7 shrink-0 items-center justify-center rounded-full border bg-muted text-sm font-semibold">
{n}
</div>
<div className="flex-1 space-y-3 pt-0.5">
<p className="font-medium">{title}</p>
{children}
</div>
</div>
);
}
export default function SelfHostingPage() {
return (
<div className="space-y-10">
{/* Header */}
<div>
<div className="mb-3 flex items-center gap-2 text-sm text-muted-foreground">
<Server className="size-4" />
<span>Deployment</span>
<ArrowRight className="size-3" />
<span>Self-Hosting</span>
</div>
<h1 className="text-3xl font-bold tracking-tight">Self-Hosting</h1>
<p className="mt-2 text-muted-foreground">
Run the VectorDNS Go server on your own VPS or infrastructure. The DNS
API is a single stateless binary no database required.
</p>
</div>
{/* Prerequisites */}
<Card>
<CardHeader>
<CardTitle className="text-base">Prerequisites</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-2 text-sm text-muted-foreground">
<li className="flex items-center gap-2">
<Badge variant="outline" className="font-mono text-xs">
Docker
</Badge>
Recommended no Go toolchain required on the host.
</li>
<li className="flex items-center gap-2">
<Badge variant="outline" className="font-mono text-xs">
Go 1.22+
</Badge>
Required only if building from source.
</li>
<li className="flex items-center gap-2">
<Badge variant="outline" className="font-mono text-xs">
Port 8080
</Badge>
Default port (configurable via{" "}
<span className="font-mono text-xs">PORT</span> env var).
</li>
</ul>
</CardContent>
</Card>
{/* Docker (recommended) */}
<div className="space-y-4">
<div className="flex items-center gap-2">
<Package className="size-5 text-primary" />
<h2 className="text-xl font-semibold tracking-tight">
Docker (Recommended)
</h2>
<Badge variant="secondary" className="text-xs">
Recommended
</Badge>
</div>
<div className="space-y-6">
<Step n={1} title="Clone the repository">
<CodeBlock code="git clone https://github.com/DevVoxel/vectordns-server.git && cd vectordns-server" />
</Step>
<Step n={2} title="Create your .env file">
<CodeBlock
code={`cp .env.example .env
# Edit .env with your values
nano .env`}
/>
<p className="text-sm text-muted-foreground">
At minimum, set{" "}
<span className="font-mono text-xs bg-muted px-1 rounded">
API_KEY
</span>{" "}
and{" "}
<span className="font-mono text-xs bg-muted px-1 rounded">
CORS_ORIGINS
</span>
. See{" "}
<a
href="/docs/configuration"
className="text-primary underline-offset-4 hover:underline"
>
Configuration
</a>{" "}
for all options.
</p>
</Step>
<Step n={3} title="Build the Docker image">
<CodeBlock code="docker build -t vectordns-server ." />
</Step>
<Step n={4} title="Run the container">
<CodeBlock code="docker run -d -p 8080:8080 --env-file .env --name vectordns-server vectordns-server" />
<p className="text-sm text-muted-foreground">
The server will be available at{" "}
<span className="font-mono text-xs bg-muted px-1 rounded">
http://localhost:8080
</span>
.
</p>
</Step>
<Step n={5} title="Verify it's running">
<CodeBlock code="curl http://localhost:8080/api/v1/health" />
<p className="text-sm text-muted-foreground">
Should return{" "}
<span className="font-mono text-xs bg-muted px-1 rounded">{`{"status":"ok","version":"0.1.0"}`}</span>
.
</p>
</Step>
</div>
</div>
<Separator />
{/* From source */}
<div className="space-y-4">
<div className="flex items-center gap-2">
<Terminal className="size-5 text-primary" />
<h2 className="text-xl font-semibold tracking-tight">From Source</h2>
</div>
<p className="text-sm text-muted-foreground">
If you prefer to build and run without Docker (requires Go 1.22+):
</p>
<div className="space-y-6">
<Step n={1} title="Install dependencies">
<CodeBlock code="go mod tidy" />
</Step>
<Step n={2} title="Configure environment">
<CodeBlock code="cp .env.example .env && nano .env" />
</Step>
<Step n={3} title="Run the server">
<CodeBlock code="go run ./cmd/server" />
</Step>
<Step n={4} title="Build a binary (optional)">
<CodeBlock
code={`go build -o vectordns-server ./cmd/server
./vectordns-server`}
/>
</Step>
</div>
</div>
<Separator />
{/* VPS Deployment */}
<div className="space-y-4">
<div className="flex items-center gap-2">
<Cloud className="size-5 text-primary" />
<h2 className="text-xl font-semibold tracking-tight">
VPS Deployment
</h2>
</div>
<p className="text-sm text-muted-foreground">
Deploying to a VPS (e.g. DigitalOcean, Hetzner, Linode)? Here is a
recommended setup.
</p>
<Card>
<CardHeader>
<CardTitle className="text-sm">Reverse proxy with nginx</CardTitle>
<CardDescription>
Serve the Go server behind nginx so you can add TLS and a clean
domain path.
</CardDescription>
</CardHeader>
<CardContent>
<CodeBlock
code={`# /etc/nginx/sites-available/vectordns
server {
listen 443 ssl;
server_name api.yourdomain.com;
location /api/ {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}`}
/>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-sm">
systemd service (non-Docker)
</CardTitle>
<CardDescription>
Keep the server running across reboots without Docker.
</CardDescription>
</CardHeader>
<CardContent>
<CodeBlock
code={`# /etc/systemd/system/vectordns-server.service
[Unit]
Description=VectorDNS Go Server
After=network.target
[Service]
ExecStart=/opt/vectordns/vectordns-server
EnvironmentFile=/opt/vectordns/.env
Restart=on-failure
User=www-data
[Install]
WantedBy=multi-user.target`}
/>
<div className="mt-3">
<CodeBlock
code={`sudo systemctl enable vectordns-server
sudo systemctl start vectordns-server`}
/>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-sm">
docker-compose (with Redis near-term)
</CardTitle>
<CardDescription>
Future: once Redis caching is added, a docker-compose setup will
be provided.
</CardDescription>
</CardHeader>
<CardContent>
<CodeBlock
code={`# docker-compose.yml (planned)
services:
server:
build: .
ports:
- "8080:8080"
env_file: .env
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"`}
/>
<p className="mt-3 text-sm text-muted-foreground">
Redis caching is on the roadmap. This configuration will be
provided when the caching layer ships.
</p>
</CardContent>
</Card>
</div>
{/* Security note */}
<Card className="border-yellow-500/20 bg-yellow-500/5">
<CardHeader>
<CardTitle className="text-sm text-yellow-500">
Security Checklist
</CardTitle>
</CardHeader>
<CardContent>
<ul className="space-y-1.5 text-sm text-muted-foreground">
<li>
Set a strong{" "}
<span className="font-mono text-xs bg-muted px-1 rounded">
API_KEY
</span>{" "}
do not leave auth disabled in production.
</li>
<li>
Set{" "}
<span className="font-mono text-xs bg-muted px-1 rounded">
CORS_ORIGINS
</span>{" "}
to your exact frontend domain, not{" "}
<span className="font-mono text-xs">*</span>.
</li>
<li>
Always run behind TLS (use Let`&apos;`s Encrypt via Certbot with
nginx).
</li>
<li> Rate limiting is enabled by default keep it on.</li>
</ul>
</CardContent>
</Card>
</div>
);
}