Hetzner Cloud โ€” Docker Compose โ€” Ubuntu 24.04

Business Automation Platform

Self-hosted infrastructure for URL shortening, dynamic QR codes, workflow automation, knowledge management, and privacy-friendly analytics.

System Architecture

All services behind Caddy for automatic HTTPS via Let's Encrypt

๐ŸŒ
Internet
Ports 80/443
โ†“
:80 / :443 ๐Ÿ”’
Caddy
Reverse Proxy + Auto HTTPS
โ†“ โ†“ โ†“ โ†“ โ†“
:8080 ๐Ÿ”—
Shlink
URLs + QR
:8080 ๐Ÿ“Š
Shlink Web
Dashboard
:5678 โšก
n8n
Automation
:80 ๐Ÿ“š
BookStack
Wiki / KB
:3000 ๐Ÿ“ˆ
Umami
Analytics
โ†“ โ†“ โ†“
๐Ÿ˜
PostgreSQL 16
Shlink + Umami
๐Ÿฌ
MariaDB 11
BookStack

Domain Map

Each service gets its own subdomain with automatic HTTPS

Subdomain Service Purpose
s.YOURDOMAIN.comShlinkShort URLs & QR Codes
links.YOURDOMAIN.comShlink Web ClientManagement Dashboard
n8n.YOURDOMAIN.comn8nWorkflow Automation
wiki.YOURDOMAIN.comBookStackKnowledge Base / Wiki
analytics.YOURDOMAIN.comUmamiPrivacy-Friendly Analytics

Services

Everything your team needs in one self-hosted stack

Shlink

s.YOURDOMAIN.com

URL shortener with built-in dynamic QR code generation. Change link destinations without changing the QR code.

  • REST API for programmatic URL management
  • Dynamic QR codes (SVG/PNG, customizable)
  • Visit tracking with GeoIP, device, referrer data
  • Custom slugs + campaign tagging
โšก

n8n

n8n.YOURDOMAIN.com

Visual workflow automation. Connect services, schedule tasks, and build data pipelines with 400+ integrations.

  • Webhook triggers for real-time automation
  • Cron scheduling for reports & backups
  • JavaScript/Python code execution nodes
  • Connects to Shlink, BookStack, Umami APIs
๐Ÿ“š

BookStack

wiki.YOURDOMAIN.com

Team knowledge base organized as Shelves, Books, Chapters, and Pages. Export to PDF, HTML, or Markdown.

  • Shelves > Books > Chapters > Pages hierarchy
  • Export for NotebookLM and Claude Projects
  • Full REST API for automation
  • WYSIWYG + Markdown editor
๐Ÿ“ˆ

Umami

analytics.YOURDOMAIN.com

Privacy-friendly web analytics. No cookies, GDPR compliant. Track landing pages from your short links.

  • Cookie-free, GDPR/CCPA compliant
  • Real-time visitor dashboard
  • Data export API for Claude Projects
  • Lightweight tracking script (~2KB)
๐Ÿ”’

Caddy

All subdomains

Automatic HTTPS reverse proxy. Zero-config TLS certificates from Let's Encrypt. HTTP/3 support.

  • Auto-renewing TLS certificates
  • HTTP/2 and HTTP/3 out of the box
  • Simple Caddyfile configuration
  • Routes each subdomain to internal containers

Command Reference

Essential commands for day-to-day operations. Click to copy.

Lifecycle
Start all services docker compose up -d
Stop all services docker compose down
Update all images docker compose pull && docker compose up -d
Restart a service docker compose restart [service]
Debugging
View logs (follow) docker compose logs -f [service]
Container status docker compose ps
Resource usage docker stats --no-stream
Validate compose docker compose config
Shlink
Generate API key docker exec -it shlink shlink api-key:generate
List short URLs docker exec -it shlink shlink short-url:list
Maintenance
Run backup ./scripts/backup.sh
Pre-deploy check ./scripts/validate-deploy.sh
SSH into VPS ssh root@YOUR_VPS_IP

Dynamic QR Codes

Generate customizable QR codes that let you change the destination URL anytime โ€” the QR image never changes.

๐Ÿ–จ๏ธ Print Materials

size500
formatpng
errorCorrectionH
margin20

๐Ÿ’ป Digital / Email

size300
formatsvg
errorCorrectionM
margin10

๐Ÿ“‡ Business Cards

size200
formatsvg
errorCorrectionQ
margin10

How Dynamic QR Works

Create a short URL โ†’ Print the QR code โ†’ Update the destination anytime via the API or web client. The QR code always points to the same short URL (e.g., s.YOURDOMAIN.com/my-campaign), so you can change where it goes without reprinting anything. Perfect for menus, packaging, business cards, and event materials.

Claude Code Skills & Agents

Custom commands and AI subagents for managing the platform through natural language

Skill

Deploy

Deploy or update services on the Hetzner VPS with pre-deploy validation and rollback support.

/deploy [service]
Skill

Shlink Manage

Create, update, and manage short URLs and QR codes via the Shlink REST API.

/shlink-manage
Skill

VPS Health

Run comprehensive health checks โ€” system resources, container status, error logs, and endpoint tests.

/vps-health
Skill

n8n Workflow

Build automation workflows connecting Shlink, BookStack, Umami, and external services.

/n8n-workflow [desc]
Skill

Research

Deep research on any topic using web search, docs, and codebase analysis.

/research [topic]
Skill

Morning Briefing

Daily status report with VPS health, link analytics, and suggested action items.

/morning-briefing
Agent

DevOps Engineer

Senior DevOps subagent for Docker operations, server maintenance, backups, and security hardening.

@devops-engineer
Agent

Marketing Analyst

Campaign planning, visit data analysis, QR specifications, and performance reporting.

@marketing-analyst
Agent

Knowledge Curator

Maintains BookStack wiki, prepares content for NotebookLM and Claude Projects, documents everything.

@knowledge-curator

Getting Started

Follow these steps to deploy the full stack on your Hetzner VPS

1

Clone the Repository

SSH into your VPS and clone the project to /opt/mvp-infra.

git clone git@github.com:erniemorales/mvp-infra.git /opt/mvp-infra
2

Configure Environment

Copy the example env file and fill in your actual values โ€” domains, passwords, API keys.

cp .env.example .env && nano .env
3

Point DNS

Create A records for all 5 subdomains pointing to your VPS IP: s., links., n8n., wiki., analytics.

4

Validate & Deploy

Run validation, then start all services. Caddy will automatically obtain SSL certificates.

./scripts/validate-deploy.sh && docker compose up -d
5

Change Default Passwords

Immediately change the Umami default login (admin / umami) and generate a proper Shlink API key.

6

Verify Everything

Check that all containers are healthy and all endpoints respond.

docker compose ps && curl -sf https://s.YOURDOMAIN.com/rest/health

Troubleshooting

Common issues and their solutions

Check the logs with docker compose logs -f [service]. Look for error messages on startup. Common causes: missing environment variables, database not ready yet (check depends_on + healthcheck), or port conflicts.
Make sure the DNS A record points to your VPS IP and has propagated (use dig subdomain.yourdomain.com). Caddy obtains certs automatically โ€” check Caddy logs with docker compose logs caddy. Ensure ports 80 and 443 are open in your firewall.
Pull the new image and recreate just that service: docker compose pull shlink && docker compose up -d shlink. The other services stay running. Always back up databases before updating.
Check that the database container is healthy: docker compose ps. If it shows "unhealthy", check its logs. Verify the password in .env matches what the DB was initialized with. If you changed the password after first run, you may need to recreate the volume.
Stop services with docker compose down, revert with git checkout HEAD~1, then start again with docker compose up -d. If a database migration went wrong, restore from the latest backup in /opt/backups/.
Verify WEBHOOK_URL in .env matches your public domain (https://n8n.YOURDOMAIN.com/). Make sure the workflow is active (not just saved). Test with curl -X POST https://n8n.YOURDOMAIN.com/webhook/test.

Resources & Documentation

Team guides, QR assets, and reference docs on Google Drive

🔗

Shlink Team Guide (EN)

Complete guide to URL shortening and dynamic QR codes

🔗

Guรญa Shlink (ES)

Guรญa completa de URLs cortas y QR dinรกmicos

🏫

Moon Spot Academy Info (EN)

Complete academy reference guide

🏫

Guรญa Moon Spot (ES)

Guรญa de referencia completa de la academia

📱

QR Code SVGs (17)

Pre-generated QR codes for all Moon Spot links

📁

SOPs & Guides Folder

All team documentation on Google Drive

🔌

IoT Setup Guide

Hardware onboarding for Carlos

💡

LEDs Setup Guide

Addressable COB LED installation for Carlos and Angel

Copied to clipboard!