Shlink is an open-source, API-first URL shortener. You get branded short links on your own domain (like go.example.com/promo), visit statistics (referrers, countries, devices), QR codes, tags, custom slugs, expiry dates and multiple domains. Everything is managed through a REST API, a CLI, or the separate Shlink web client. Self-hosting means your links don’t die if a shortener service shuts down, and visitor data stays with you.
Simpler PHP alternative: YOURLS.
Requirements
- A small VPS: 1 vCPU and 1 GB RAM handles a lot of redirects.
- A short domain (or subdomain) pointed at the server with an A record. See DNS records explained.
- A database: SQLite for small setups; MySQL/MariaDB or PostgreSQL for real use.
Install with Docker Compose
# /opt/shlink/compose.yaml
services:
shlink:
image: shlinkio/shlink:stable
restart: unless-stopped
environment:
DEFAULT_DOMAIN: go.example.com
IS_HTTPS_ENABLED: "true"
DB_DRIVER: postgres
DB_HOST: db
DB_NAME: shlink
DB_USER: shlink
DB_PASSWORD: change-me
GEOLITE_LICENSE_KEY: your-maxmind-key # optional: visit locations
TIMEZONE: UTC
ports:
- "127.0.0.1:8080:8080"
depends_on: [db]
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_DB: shlink
POSTGRES_USER: shlink
POSTGRES_PASSWORD: change-me
volumes:
- ./pgdata:/var/lib/postgresql/data
web-client: # optional admin UI
image: shlinkio/shlink-web-client:stable
restart: unless-stopped
ports:
- "127.0.0.1:8081:8080"
cd /opt/shlink && docker compose up -d
docker compose exec shlink shlink api-key:generate # save the key it prints
GeoLite2: for country and city stats, create a free MaxMind account, and set GEOLITE_LICENSE_KEY. Shlink downloads and updates the database itself.
Nginx with HTTPS
server {
server_name go.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# listen 443 ssl; certbot --nginx -d go.example.com
}
Serve the web client on a separate hostname (for example shlink-admin.example.com). It’s a static app that talks to the API from your browser using the API key. Restrict it with basic auth or an IP allowlist. See Nginx basic auth and Let’s Encrypt.
Visitor IPs come from X-Forwarded-For. If you also use Cloudflare, pass the real IP through. See real IP behind Cloudflare.
Create short URLs
CLI:
docker compose exec shlink shlink short-url:create https://example.com/landing/spring-sale --custom-slug=spring --tags=campaign
docker compose exec shlink shlink short-url:list
docker compose exec shlink shlink short-url:visits spring
REST API:
curl -X POST https://go.example.com/rest/v3/short-urls \
-H "X-Api-Key: $SHLINK_KEY" -H "Content-Type: application/json" \
-d '{"longUrl":"https://example.com/docs","customSlug":"docs","tags":["docs"],"validUntil":"2027-01-01T00:00:00Z"}'
The API makes it easy to create links from scripts, CI, or automation tools like n8n.
Web client: add your server (URL plus API key) and manage links, tags, QR codes and visit charts in the browser.
Useful features
- Multiple domains: one instance can serve several short domains.
- Device-specific redirects: send Android, iOS and desktop visitors to different URLs.
- Max visits and validity dates: links that expire.
- QR codes:
https://go.example.com/spring/qr-code. - Not-found redirects: send unknown slugs or the bare domain to your main site, instead of a 404.
- Bot detection: known crawlers aren’t counted as visits.
Privacy
Shlink can anonymise visitor IPs (enabled by default), and you can disable tracking per link or globally. Mention link tracking in your privacy policy. See Plausible Analytics for privacy-friendly site analytics.
Backups and updates
- Back up the database (
pg_dump). That’s all of the state. See pg_dump. - Update with
docker compose pull && docker compose up -d. Migrations run automatically on start. See updating self-hosted apps.
Quick reference
| Task | Command |
|---|---|
| Generate API key | shlink api-key:generate |
| Create link | shlink short-url:create <url> --custom-slug=x |
| List links | shlink short-url:list |
| Visits | shlink short-url:visits <slug> |
| QR code | /<slug>/qr-code |
Related: UTM tracking and analytics and Nginx reverse proxy.