在 Traefik 後方自託管 prompts.chat:打造以私隱為先的提示詞庫
Self-Hosting prompts.chat: A Privacy-First Prompt Library Behind Traefik
文章作者以 Traefik、Tailscale 和 Docker 自託管開源提示詞庫 prompts.chat,並以 Tailscale ACL 限制存取,避免向公網開放。啟用 SQLite WAL 後,持續執行 10+ 個並行寫入操作而未再出現鎖定。Traefik dashboard 另設基本認證;整套架構可在每月 $5、1GB RAM 的 VPS 上運行。
Why prompts.chat Belongs in Your Homelab
When testing f/prompts.chat — the open-source prompt library formerly known as Awesome ChatGPT Prompts — I needed a self-hosted instance that wouldn't leak internal prompts to third-party SaaS. The project ships as a static site, but real production deployments need:
- Reverse proxy with automatic HTTPS
- Zero-trust network access (no public exposure)
- Persistent storage for custom prompts
- Local authentication layer
Here's the battle-tested stack I landed on after two failed attempts with bare Nginx and accidental public exposure.
Architecture: Traefik + Tailscale + Docker
# docker-compose.yml
version: '3.8'
services:
prompts-chat:
image: ghcr.io/f/prompts.chat:latest
container_name: prompts-chat
restart: unless-stopped
volumes:
- ./data:/app/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.prompts.rule=Host(`prompts.homelab.local`)"
- "traefik.http.routers.prompts.entrypoints=websecure"
- "traefik.http.routers.prompts.tls=true"
- "traefik.http.services.prompts.loadbalancer.server.port=3000"
networks:
- homelab
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
command:
- "--api.insecure=false"
- "--providers.docker=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.tailscale.acme.tlschallenge=true"
ports:
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik-certs:/letsencrypt
networks:
- homelab
networks:
homelab:
driver: bridge
Zero-Trust Routing with Tailscale ACL
Instead of exposing port 443 to the internet, bind Traefik to your Tailscale interface:
// tailscale-acl.json
{
"acls": [
{
"action": "accept",
"src": ["group:engineering"],
"dst": ["tag:homelab:443"]
}
],
"tagOwners": {
"tag:homelab": ["admin@yourorg.com"]
}
}
Apply the policy:
tailscale up --advertise-tags=tag:homelab
sudo ufw allow in on tailscale0 to any port 443
sudo ufw deny 443 # block public interface
Deployment & Verification
# Start stack
docker-compose up -d
# Verify Traefik routes
docker logs traefik | grep prompts
# Test internal access
curl -k https://prompts.homelab.local
# Confirm external block
curl -I https://<public-ip>:443 # should timeout
War Story: SQLite Corruption Under Load
During initial testing with three concurrent users editing prompts, the app crashed with:
SQLite database is locked (5)
Root cause: prompts.chat uses a single SQLite file without WAL mode. Fix:
# Enable Write-Ahead Logging
sqlite3 data/prompts.db "PRAGMA journal_mode=WAL;"
# Verify
sqlite3 data/prompts.db "PRAGMA journal_mode;"
# Should return: wal
After enabling WAL, sustained 10+ concurrent write operations with zero locks.
Accidental Public Exposure (and the Fix)
First deployment mistake: I exposed Traefik dashboard on :8080 without authentication. Shodan indexed it within 4 hours.
The hard lesson: every listening port needs explicit access control.
Fixed config:
# Traefik dynamic config (traefik-config.yml)
http:
middlewares:
basic-auth:
basicAuth:
users:
- "admin:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" # htpasswd generated
routers:
traefik-dashboard:
rule: "Host(`traefik.homelab.local`)"
service: api@internal
middlewares:
- basic-auth
entryPoints:
- websecure
Mount this config:
volumes:
- ./traefik-config.yml:/etc/traefik/dynamic/config.yml:ro
Performance Notes
- Cold start: ~2.3s (Node.js SSR)
- Warm response: <80ms (cached static assets)
- Memory footprint: 140MB (prompts.chat) + 95MB (Traefik)
- Disk I/O: negligible after WAL mode
When NOT to Self-Host This
Skip this setup if:
- Your team is distributed without VPN — the Tailscale ACL model assumes a private network backbone
- You need multi-region replication — SQLite won't scale horizontally
- Compliance requires audit trails — you'll need to add event logging middleware
Next Steps
For production-grade deployments, add:
- Automated SQLite backups (
litestreamto S3) - Prometheus metrics export from Traefik
- Fail2ban rules for repeated auth failures
- Health check endpoint monitoring
The complete stack runs on a $5/month VPS with 1GB RAM. Total setup time: 18 minutes after sorting out the SQLite locking issue.
No affiliate links. No sponsored tools. Just a working reference architecture for keeping your prompt library private.
來源:DEV Community · dev.to