Free series. All open-source. No DevOps background required. Estimated hands-on time: 60–90 minutes.
You have a hardened VPS, two open ports, and a Cloudflare tunnel that makes your server invisible to the public internet. The walls are up. Now let's put something worth protecting inside them.
This part installs Docker, PostgreSQL, Nextcloud, Collabora Online, a unified 4-model AI proxy, and OpenClaw — your agentic butler — plus CalDAV calendar sync, custom domain email, and nightly backups to Supabase. By the end, the system is operational for daily use.
Every step follows the same pattern as Part 2: paste the command, observe the result, verify before proceeding. If something breaks, you know exactly where and how to fix it.
What You Will Complete in This Part
Read time: ~20 min. Hands-on: ~60–90 min. Prerequisites: Parts 1–2 completed. Four API keys gathered. Password manager open.
When this part is complete, eleven things will be true:
- Docker installed and running
- PostgreSQL containerized, holding Nextcloud data
- Nextcloud live at cloud.yourdomain.com, behind Cloudflare Access
- Collabora integrated — .docx/.xlsx open in-browser for real-time co-editing
- LLM proxy at ai.yourdomain.com, routing to 4 AI providers, keys in isolated .env
- OpenClaw installed, systemd-sandboxed, connected to your messaging app
- CalDAV sync active on all devices
- Custom domain email configured with DKIM/SPF/DMARC
- Supabase backup running nightly at 2 AM
- All 8 security layers active
- Monthly cost fully understood — no line surprises
Before You Build: Four API Keys
Collect all keys before touching the terminal:
OPENAI_API_KEY=sk-[your key]
ANTHROPIC_API_KEY=sk-ant-[your key]
GOOGLE_API_KEY=AIza-[your key]
PERPLEXITY_API_KEY=pplx-[your key]
Spending rule: set a hard $20/month cap per provider before your first API request. Total exposure: $80. Realistic spend for a 3-person team: $15–$35/month.
OpenAI — platform.openai.com. Broad reasoning, coding, general analysis. Anthropic — console.anthropic.com. Nuanced prose, contracts, editorial. Google — aistudio.google.com. Structured data, Workspace integration. Perplexity — perplexity.ai. Source-cited real-time research.
Step 1: Docker and PostgreSQL
Log in as myadmin.
sudo apt install -y docker.io docker-compose
sudo systemctl enable --now docker
sudo usermod -aG docker myadmin
Restart session: exit, log back in. Not optional — Docker commands fail without the group reload.
docker --version
docker ps
docker --version: 24.x.x+. docker ps: empty table (correct — no containers yet).
Step 2: The Compose Blueprint
Docker Compose manages the entire stack from one YAML file.
mkdir -p ~/nextcloud && cd ~/nextcloud
nano docker-compose.yml
Paste exactly. Three substitutions required:
version: '3'
services:
db:
image: postgres:15
restart: always
environment:
- POSTGRES_DB=nextcloud_db
- POSTGRES_USER=nextcloud_user
- POSTGRES_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
volumes:
- nextcloud_db_data:/var/lib/postgresql/data
app:
image: nextcloud:latest
restart: always
depends_on:
- db
ports:
- "127.0.0.1:8080:80"
environment:
- POSTGRES_HOST=db
- POSTGRES_DB=nextcloud_db
- POSTGRES_USER=nextcloud_user
- POSTGRES_PASSWORD=REPLACE_WITH_SAME_PASSWORD
volumes:
- nextcloud_data:/var/www/html
collabora:
image: collabora/code:latest
restart: always
environment:
- aliasgroup1=https://cloud.REPLACE_WITH_YOUR_DOMAIN:443
- extra_params=--o:ssl.enable=false --o:ssl.termination=true
ports:
- "127.0.0.1:9980:9980"
volumes:
nextcloud_db_data:
nextcloud_data:
Substitutions: (1) REPLACE_WITH_STRONG_PASSWORD — same 20+ char password in both locations. (2) REPLACE_WITH_YOUR_DOMAIN — your actual domain.
Save: Ctrl+O → Enter → Ctrl+X.
docker-compose up -d
First run pulls all images (~5–10 min). Verify:
docker ps
Three containers with Up status: PostgreSQL, Nextcloud, Collabora.
Browse to https://cloud.yourdomain.com. Cloudflare OTP → Nextcloud setup screen. Create admin account. Store credentials.
When the dashboard loads, your private cloud is operational.
Step 3: Collabora Online
Nextcloud → user icon → Apps → search "Nextcloud Office" → Install.
User icon → Administration Settings → Nextcloud Office → Use your own server → URL: https://office.yourdomain.com → Save.
Verify: + button → New Document → editor opens in browser. Open from second device → both cursors visible, edits sync in real time.
Step 4: The 4-Model AI Proxy
Runs at localhost:8000, routed to ai.yourdomain.com via Cloudflare Tunnel. Keys never reach the browser.
mkdir -p ~/llm-proxy && cd ~/llm-proxy
python3 -m venv venv
source venv/bin/activate
pip install fastapi uvicorn httpx python-dotenv
nano ~/llm-proxy/.env
Paste with your actual keys:
OPENAI_API_KEY=sk-your-openai-key
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
GOOGLE_API_KEY=AIza-your-google-key
PERPLEXITY_API_KEY=pplx-your-perplexity-key
PROXY_AUTH_TOKEN=REPLACE_WITH_RANDOM_TOKEN
Generate auth token:
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
Paste output as PROXY_AUTH_TOKEN value. Save.
chmod 600 ~/llm-proxy/.env
Full proxy application code is in the Part 5 operations file. Verify:
curl -s http://localhost:8000/health
Expected: {"status":"ok"}. Confirm at https://ai.yourdomain.com/health.
Model allocation: Claude for contracts/editorial. Perplexity for cited research. ChatGPT for general reasoning. Gemini for structured data. One portal, right model per task.
Step 5: OpenClaw — Full Install
A chatbot answers and waits. An agent acts and completes.
CVE-2026-25253 (CVSS 8.8, High) and the ClawJacked class were addressed in Part 1. The security posture from Part 2 — localhost binding, Cloudflare tunnel auth, UFW port restriction — neutralizes both structurally. This install specifies OpenClaw 2026.1.29 or later (patched).
npm install -g openclaw@latest
openclaw onboard --install-daemon
Interactive flow: select AI model (Claude/ChatGPT), configure working dirs, connect messaging app (Slack/Discord/Telegram).
Three mandatory configs before production:
- Set OpenClaw's internal spending cap (separate from provider caps).
- Restrict filesystem access — exclude dirs containing passwords, keys, financial records.
- No third-party skills without review — community extensions are unaudited.
openclaw status
Expected: "Gateway: running." Test via messaging app.
Step 6: CalDAV Calendar Sync
iPhone: Settings → Calendar → Accounts → Add → Other → CalDAV. Server: https://cloud.yourdomain.com/remote.php/dav.
Android: DAVx⁵ (free, Play Store). Same server + credentials.
Mac/PC: Apple Calendar or Thunderbird — CalDAV natively supported.
Test: create event in Nextcloud → appears on phone within minutes.
Step 7: Custom Domain Email
Cloudflare Email Routing: Email → Email Routing → Enable. Forward yourname@yourdomain.com to your existing inbox.
Send-as config: Gmail → Settings → Accounts and Import → Add another address. Apple Mail → Preferences → Accounts → alias.
DMARC: Cloudflare DNS → TXT record:
Name: _dmarc
Content: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
Verify at mail-tester.com. Score ≥8 = reliable inbox delivery.
Step 8: Supabase Nightly Backup
Create project at supabase.com. Region: US East. Copy connection string.
nano ~/.supabase-backup.conf
SUPABASE_URI="postgresql://postgres.[project-id]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgres"
LOCAL_DB_NAME="nextcloud_db"
LOCAL_DB_USER="nextcloud_user"
LOCAL_DB_CONTAINER="nextcloud_db_1"
chmod 600 ~/.supabase-backup.conf
nano ~/db-backup-to-supabase.sh
Paste (change myadmin if your username differs):
#!/bin/bash
set -euo pipefail
source /home/myadmin/.supabase-backup.conf
DATE=$(date +%Y%m%d_%H%M%S)
DUMP_DIR="/home/myadmin/db-backups"
DUMP_FILE="${DUMP_DIR}/nextcloud_db_${DATE}.sql"
mkdir -p "$DUMP_DIR"
echo "[$(date)] Backup started"
docker exec "$LOCAL_DB_CONTAINER" pg_dump -U "$LOCAL_DB_USER" "$LOCAL_DB_NAME" > "$DUMP_FILE"
echo "[$(date)] Local dump complete: $DUMP_FILE"
PGPASSWORD=$(echo "$SUPABASE_URI" | grep -oP '(?<=:)[^@]+(?=@)')
psql "$SUPABASE_URI" -c "DROP SCHEMA IF EXISTS nextcloud_backup CASCADE; CREATE SCHEMA nextcloud_backup;"
psql "$SUPABASE_URI" --set search_path=nextcloud_backup < "$DUMP_FILE" 2>/dev/null || true
echo "[$(date)] Transfer to Supabase complete"
find "$DUMP_DIR" -name "*.sql" -mtime +14 -delete
echo "[$(date)] Backup complete"
chmod 700 ~/db-backup-to-supabase.sh
~/db-backup-to-supabase.sh
Confirm in Supabase: Table Editor → nextcloud_backup schema exists.
crontab -e
Add:
0 2 * * * /home/myadmin/db-backup-to-supabase.sh >> /home/myadmin/db-backup.log 2>&1
Recovery (total server loss):
pg_dump "your-supabase-uri" --schema=nextcloud_backup > /tmp/restore.sql
docker exec -i nextcloud_db_1 psql -U nextcloud_user nextcloud_db < /tmp/restore.sql
Three Rules of AI Use
1. No PII in prompts. Names, SSNs, financial accounts, medical data — none of it belongs in an AI prompt. Use initials or pseudonyms. CCPA and HIPAA don't distinguish accidental from intentional disclosure.
2. No credentials in chat. Keys are in .env. Passwords are in Bitwarden. They never need to appear in a message.
3. Review every output before it acts. Claude writes excellent email. Read it first. OpenClaw organizes files as instructed. Check the result. The irreversible consequences of automated action belong to the human who gave the instruction.
Verification Checklist
docker ps
Expected: 3 containers Up.
Browser: https://cloud.yourdomain.com → Nextcloud loads. Open .docx → Collabora editor.
curl -s http://localhost:8000/health
{"status":"ok"} — also at https://ai.yourdomain.com/health.
openclaw status
"Gateway: running." Message via app → response arrives.
Calendar event in Nextcloud → phone. Email to custom domain → forwarding inbox. Reply → sender shows custom address.
sudo ufw status verbose
Active, 80+443 only.
sudo systemctl status fail2ban cloudflared
Both active.
~/db-backup-to-supabase.sh
Completes. Supabase shows data.
All twelve checked: system is fully operational for daily use.
Monthly Cost
VPS: $12–$48. Domain: ~$1. Cloudflare: $0. Supabase: $0. Software: $0. AI: $15–$35 (moderate, 3 users).
Total (3–8 person team): ~$35–$50/month. Equivalent SaaS for 3 users: $240/month AI alone, plus storage, monitoring, remote desktop — $400+ total.
What Part 4 Builds
Apache Guacamole — browser-based remote desktop. Prometheus + Grafana + Alertmanager — real-time monitoring with email alerts. AES-256 encrypted weekly backups — the third layer of defense.
When Part 4 is complete, the build is finished.
Series: Building Your Private AI Infrastructure
| Part | What It Covers |
|---|---|
| Part 1 — Architecture Overview | Stack, costs, security model |
| Part 2 — Zero-Trust Server | Vultr, Cloudflare, UFW, fail2ban |
| Part 3 — The Intelligence Layer (you are here) | Docker, Nextcloud, Collabora, AI proxy, OpenClaw |
| Part 4 — Operations & Monitoring | Guacamole, Prometheus, Grafana, encrypted backups |
| Part 5 — The Operations Manual | Maintenance, audits, cost optimization, runbook |
All five parts are published and free.
Legal Disclaimer
The information provided in this series is for educational and informational purposes only. It does not constitute legal, financial, tax, accounting, cybersecurity, or professional advice. All use is at the sole risk of the user. To the maximum extent permitted by applicable law, including the laws of the State of California (Cal. Civ. Code §§1668, 3513) and the State of New York (N.Y. GOL §5-323), the author disclaims all liability for any damages arising from use of this content. References to all third-party products are for informational purposes only. The author has no commercial relationship with any provider mentioned.
Part 4 is next. Questions, errors, environment-specific issues: comments. Every one gets read. Technical ones get detailed answers.
— Kusunoki
International Tax Specialist & Systems Builder
Sapporo, Japan | @kusunoki
Top comments (0)