Stop paying $15/mo for Linktree. LinkBreeze gives you links, analytics,
QR codes, themes, and a real admin panel — free, forever, in one Docker command.
🔗 Live Demo — see the public page in action.
🔐 Demo Dashboard — see the dashboard with all features (read-only).
✨ Features
- 🔗 Link Management — Add, reorder, and customize unlimited links with drag-and-drop
- 🌐 Multi-Page Support — Create unlimited pages, each with its own slug, theme, links, analytics, SEO, and QR code
- 🎨 Auto-Favicon Links — Links automatically show the target site's favicon — no manual icon uploads needed
- 📥 Migration Wizard — Import existing links and social profiles from Linktree, Bento, Hopp.bio, LittleLink, or any HTML/JSON export
- 🖼️ Link Thumbnails — Add images to your links for visual preview cards
- 🎵 Embed Widgets — Embed YouTube, Spotify, SoundCloud, Vimeo, or Bandcamp directly on your page
- ⏰ Link Scheduling — Schedule links to appear/disappear automatically with date/time controls
- 🏷️ Custom Redirect Slugs — Give any link a stable, shareable
/go/your-nameURL that survives delete-and-recreate. Reserved names and pure numbers are blocked so app routes can never be shadowed; a deactivated link with a slug redirects visitors to your public page instead of a 404 - 📊 Privacy-Respecting Analytics — Views, clicks, referrers, device type. Cookieless by design. Visitor IPs are hashed with a daily-rotating salt, never stored. Data older than 90 days is pruned automatically by default (Settings → Data; set 0 to keep everything).
- 📈 External Analytics — Inject Plausible, Umami, Matomo, or Google Analytics with one paste
- 🔔 Update Notifications — Dashboard banner notifies you when a new version is available (no phone-home, no auto-update)
- 🎨 Themes — 11 built-in presets (Aurora, Glassmorphism, Neon Cyberpunk, Editorial Paper, Terminal Mono, Pastel Soft, Brutalist, Retro Sunset, Minimal Light, 8-Bit Retro, Frutiger Aero) + full customizer with CSS token system (colors, 15 fonts + custom font upload, 8 background types, 8 card styles, layout controls, effects) + theme duplicate/import/export
- ✏️ Custom CSS — Fine-tune your page with raw CSS injection
- 📧 Email Capture — Collect subscriber emails on your public page, export to CSV
- 📱 Mobile-First — Gorgeous on every screen. Loads in under 300ms. Zero client-side JS bundles.
- 🎯 QR Codes — Auto-generated for your page. Download as SVG or PNG. Customize colors, embed your avatar or favicon in the center, export up to 1024 px for print.
- 🔒 Self-Hosted — Your data, your server. No third-party trackers. No ads. No subscription.
- 🐳 One-Command Deploy — Docker compose and you're live
🚀 Quick Start
One command — zero config — live in 30 seconds:
curl -fsSL https://linkbreeze.omnirise.dev/install.sh | bash
or pull the multi-arch image directly:
docker run -d --name linkbreeze --restart unless-stopped -p 3000:3000 -v linkbreeze-data:/app/data docker.io/omnirise/linkbreeze:latest
The script detects Docker or Podman, pulls the image, starts the container, and optionally sets up a systemd service for auto-start on boot. Want auto-start on boot? Run it with sudo bash instead and answer y when prompted.
Don't like piping to bash?
curl -fsSL https://linkbreeze.omnirise.dev/install.sh -o install.sh
less install.sh
bash install.sh
Then open http://localhost:3000 — the setup wizard takes under 30 seconds.
Prefer a different method? Expand one below:
🐳 Docker
No Node.js, no npm, no config files needed. Multi-arch images: linux/amd64 and linux/arm64 (Raspberry Pi 3/4/5, Apple Silicon, ARM VPS).
Linux / macOS / Windows CMD:
docker run -d --name linkbreeze --restart unless-stopped -p 3000:3000 -v linkbreeze-data:/app/data docker.io/omnirise/linkbreeze:latest
Windows PowerShell — use backticks for line breaks:
docker run -d
--name linkbreeze
--restart unless-stopped
-p 3000:3000
-v linkbreeze-data:/app/data
docker.io/omnirise/linkbreeze:latest
Database migrations run automatically on container startup — no manual
drizzle-kit migrate needed for Docker deployments.
🧩 Docker Compose
Best if you want to customize ports, add a reverse proxy, or manage updates easily.
Option A — Pull the pre-built image:
Create a docker-compose.yml:
services:
linkbreeze:
image: docker.io/omnirise/linkbreeze:latest
ports:
- "3000:3000"
volumes:
- linkbreeze-data:/app/data
restart: unless-stopped
volumes:
linkbreeze-data:
docker compose up -d
Option B — Build from source:
git clone https://github.com/Manak-hash/LinkBreeze.git
cd LinkBreeze
docker compose up -d --build
Upgrade anytime: docker compose pull && docker compose up -d
Logs: docker compose logs -f linkbreeze
☁️ Coolify
Running Coolify on your VPS?
- + New Resource → Docker Compose Empty
- Paste:
services:
linkbreeze:
image: docker.io/omnirise/linkbreeze:latest
ports:
- "3000:3000"
volumes:
- linkbreeze-data:/app/data
restart: unless-stopped
volumes:
linkbreeze-data:
- Set a domain (e.g., links.yourdomain.com
) for automatic SSL - Click Deploy — Coolify handles Let's Encrypt automatically
📦 Synology NAS
Running Synology DiskStation with Container Manager (DSM 7.2+)?
- Open Container Manager → Container → Create
- Image: docker.io/omnirise/linkbreeze:latest
(pull it first via Image → Add if not found) - Container settings:
- Port: Local 3000 → Container 3000
- Volume: Create /docker/linkbreeze/data and map to /app/data
- Restart policy: Unless stopped
- Click Done — live at
http://
Update later: pull the latest image, stop and recreate the container. Data persists in the volume.
🔧 Podman
Using Podman instead of Docker (RHEL, Fedora, CentOS)? Replace
docker with podman:
podman run -d --name linkbreeze --restart unless-stopped -p 3000:3000 -v linkbreeze-data:/app/data docker.io/omnirise/linkbreeze:latest
If you get permission errors on the volume, create it first:
podman volume create linkbreeze-data
For systemd integration with rootless Podman:
podman generate systemd after starting the container.
The one-line install script at the top of this section detects Podman automatically.
🖥️ Portainer
Using Portainer to manage containers? Deploy as a Stack.
- Go to your environment → Stacks → Add stack
- Name it
linkbreeze and paste:
services:
linkbreeze:
image: docker.io/omnirise/linkbreeze:latest
ports:
- "3000:3000"
volumes:
- linkbreeze-data:/app/data
restart: unless-stopped
volumes:
linkbreeze-data:
- Click Deploy the stack
Update: Stacks →
linkbreeze → Editor → click Pull and redeploy.
🔨 Manual (without Docker)
Requires Node.js 18+.
git clone https://github.com/Manak-hash/LinkBreeze.git
cd LinkBreeze
npm install
cp .env.example .env
Edit .env to set your SECRET_KEY and DATABASE_PATH if needed
npm run db:migrate
npm run dev
For production:
npm run build && npm start
🌐 Making Your Page Public
LinkBreeze runs on your server. Once deployed, your page is accessible to anyone
at
https://your-domain.com/your-slug. Here's how to get it online:
Quick start: Point your domain
- Point your domain's A record to your server IP
- Expose port 3000 or add a reverse proxy
- Done — your page is live at
https://your-domain.com/your-slug
Advanced deployment scenarios
For production setups — reverse proxies with automatic TLS, zero-trust tunnels,
Kubernetes, scheduled backups — see the
examples/ directory.
Each example is a single, self-contained file with a header comment explaining
when to use it.
Quick reference: which example for which scenario?
| What you want | Use this file |
|---------------|---------------|
| Automatic TLS without manual config |
docker-compose.caddy.yml or docker-compose.https-portal.yml |
| Automatic TLS with a dashboard (Traefik) | docker-compose.traefik.yml |
| Expose without opening ports (zero-trust) | docker-compose.cloudflare-tunnel.yml |
| You already use Nginx + Certbot | docker-compose.nginx.yml |
| Scheduled SQLite backups | docker-compose.with-backup.yml |
| Running on Kubernetes cluster | kubernetes.yaml |
Option 1: Reverse Proxy with Your Domain
Point your domain's A record to your server IP, then use a reverse proxy with
automatic HTTPS:
Caddy (recommended — auto HTTPS)
links.example.com {
reverse_proxy localhost:3000
}
examples/docker-compose.caddy.yml.
nginx
server {
server_name links.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
examples/docker-compose.nginx.yml.
Option 2: Cloudflare Tunnel (no open ports)
No domain purchase or port forwarding needed:
cloudflared tunnel --url http://localhost:3000
For a complete Docker Compose setup with Cloudflare Tunnel, see
examples/docker-compose.cloudflare-tunnel.yml.
📸 Screenshots
Click to expand
Public Page
Admin Dashboard
![Public Page [Aurora Theme]](public/screenshots/Public-Page(Aurora).jpeg)

Links
Profile


Theme
Live Preview Pane


Settings [General]
Settings [Appearance]
![Settings Page [General Tab]](public/screenshots/Settings(General).jpeg)
![Settings Page [Appearance Tab]](public/screenshots/Settings(Appearance).jpeg)
Settings [Security]
Settings [Data]
![Settings Page [Security Tab]](public/screenshots/Settings(Security).jpeg)
![Settings Page [Data Tab]](public/screenshots/Settings(Data).jpeg)
🆚 Comparison
| Feature | Linktree | LinkStack | LittleLink | Shako | LinkBreeze |
|---------|----------|-----------|------------|-------|----------------|
| Price | $15/mo | Free | Free | Free | Free |
| Admin Panel | ✅ | Slow | ❌ | ❌ | ✅ Fast |
| Multi-Page | ✅ (paid) | ❌ | ❌ | ❌ | ✅ |
| Auto-Favicon Links | ❌ | ❌ | ❌ | ❌ | ✅ |
| Migration Wizard | ❌ | ❌ | ❌ | ❌ | ✅ |
| Database | Theirs | MySQL | None | None | SQLite |
| Built-in Analytics | Paid | Basic | ❌ | ❌ | ✅ Full |
| External Analytics | ✅ | ✅ | ❌ | ❌ | ✅ |
| Email Capture | Paid | ❌ | ❌ | ❌ | ✅ |
| Embed Widgets | Paid | ❌ | ❌ | ❌ | ✅ |
| Link Thumbnails | ✅ | ❌ | ❌ | ❌ | ✅ |
| QR Codes | ✅ | ✅ | ❌ | ❌ | ✅ |
| Link Scheduling | Paid | ❌ | ❌ | ❌ | ✅ |
| Themes | Paid | Limited | CSS only | Config | ✅ Full Token System + Import/Export |
| Custom CSS | ❌ | ❌ | ✅ | ❌ | ✅ |
| Self-Hosted | ❌ | ✅ | ✅ | ✅ | ✅ |
| Language | Closed | PHP | HTML | Astro | TypeScript |
| Docker Deploy | N/A | Complex | Simple | Simple | One command |
| Page Load | ~2-3s | ~1-2s | Fast | Fast | <300ms |
| License | Closed | AGPL | MIT | GPL | MIT |
🛠️ Tech Stack
| Layer | Technology |
|-------|-----------|
| Framework | Next.js 16 (App Router, Server Components, ISR) |
| Database | SQLite via better-sqlite3 (WAL mode) |
| ORM | Drizzle ORM (type-safe, zero overhead) |
| Auth | Cookie-based HMAC sessions, Argon2id (legacy bcrypt hashes upgrade on login) |
| UI | shadcn/ui + Tailwind CSS 4 |
| Drag & Drop | dnd-kit |
| Charts | Recharts |
| QR Codes | qrcode (server-side SVG/PNG) |
| Validation | Zod |
| Icons | Lucide + custom social SVGs |
📖 Documentation
- Contributing Guide
- Security Policy
- Changelog
- Troubleshooting
- Architecture Decisions
- Configuration Reference
🛳️ Repositories & Registry
| Where | URL |
|---|---|
| Source (GitLab, canonical public mirror) | gitlab.com/omnirise00/linkbreeze |
| Source (GitHub) | github.com/Manak-hash/LinkBreeze |
| Container image |
docker.io/omnirise/linkbreeze (Docker Hub) |
All mirrors sync automatically — open issues/PRs on either forge.
⚙️ Configuration
All configuration is via environment variables (
.env). .env.example is the canonical reference — copy it (cp .env.example .env) and it documents every variable, including the wallet-credential blocks with their caveats inline:
| Variable | Default | Description |
|----------|---------|-------------|
|
PORT | 3000 | Server port |
| DATABASE_PATH | ./data/linkbreeze.db | SQLite database file path |
| SECRET_KEY | Auto-generated | HMAC signing key for sessions |
| EXTRA_SCRIPT_SRC | _(empty)_ | Space-separated analytics domains for CSP (e.g. plausible.io umami.is) |
| GOOGLE_WALLET_ISSUER_ID | _(empty)_ | Enables "Add to Google Wallet" buttons on public pages. Numeric issuer ID from the Google Pay & Wallet Console. |
| GOOGLE_WALLET_SERVICE_ACCOUNT_JSON | _(empty)_ | Full service-account JSON (client_email + private_key) authorized for the Wallet API. |
| APPLE_WALLET_CERT_PEM | _(empty)_ | Enables "Add to Apple Wallet" buttons. Pass Type ID signing certificate (PEM). |
| APPLE_WALLET_KEY_PEM | _(empty)_ | Private key matching the signing certificate (PEM). |
| APPLE_WALLET_KEY_PASSPHRASE | _(empty)_ | Passphrase for the signing key, if encrypted. |
| APPLE_WALLET_WWDR_PEM | _(empty)_ | Apple WWDR intermediate certificate (PEM). |
| APPLE_WALLET_TEAM_ID | _(empty)_ | Your 10-character Apple Team ID. |
| APPLE_WALLET_PASS_TYPE_ID | _(empty)_ | Your Pass Type ID (must start with pass.). |
Wallet passes & contact export: every public page renders a share block with a "Save contact" button (universal vCard, always on). When the matching credentials above are configured, "Add to Google Wallet" (free issuer account; passes only save for whitelisted test users until Google grants production access) and "Add to Apple Wallet" (requires a paid Apple Developer account; passes install from Safari only) light up automatically. Passes are static snapshots — the QR on the pass always opens the live page. The Settings → Integration tab shows per-wallet credential status and warns when the Apple signing certificate is about to expire.
Using external analytics (Plausible, Umami, Matomo, Google Analytics):
The built-in analytics covers views, clicks, referrers, and device type with no setup needed. If you want to add a third-party analytics provider, paste your
Chat with me