Deploy Shlink
Bitly Alternative. Short links, custom domains, QR codes & more
shlink
Just deployed
shlink-web-client
Just deployed
Redis
Just deployed
/data
Just deployed
/var/lib/postgresql/data
Deploy and Host Shlink on Railway
Shlink is an open source, API-first URL shortener that turns long links into branded short ones and records every click — device, browser, referrer, country — so teams can measure what they publish without handing their click data to a third party. It is the self-hosted answer to Bitly and Rebrandly, and because everything is exposed over a documented REST API it is as often used as link infrastructure inside another product as it is standalone.
Deploy Shlink on Railway and the pieces are already wired together: the Shlink server on its own public domain issuing redirects and serving the REST API, shlink-web-client on a second domain as the management UI, managed PostgreSQL holding short URLs and visits, and managed Redis providing the cache and the distributed locks Shlink needs to run more than one instance safely. An initial API key is generated at first boot, so you can self-host Shlink and be creating links minutes after the deploy finishes.

Getting Started with Shlink on Railway
Once both services are live, open the shlink-web-client URL. It is a browser-only app with no accounts of its own, so it starts on a Welcome screen. Click Add a server and fill in three fields: any name, the URL of the shlink service (the full https://…up.railway.app address, no trailing path), and the API key — copy INITIAL_API_KEY from the shlink service's Variables tab. The key lives only in your browser's local storage. After saving you land on the Overview dashboard, and the footer should read Server: v5.1.5. Paste a long URL into Create a short URL, optionally set a slug and tags, and press Save. Open the short link in a new tab — you should be redirected, and the visit appears in that link's stats within seconds.



About Hosting Shlink
Shlink is a PHP application on the RoadRunner application server, which keeps workers warm between requests and makes redirects fast enough for real campaign traffic. Self-hosting matters when click data is sensitive, when you need more short domains than a SaaS plan allows, or when links are created from code rather than a dashboard.
- REST API and CLI covering every operation, plus official PHP, JS and Python SDKs
- Visit analytics: date, referrer, browser, operating system, device, optional geolocation
- Custom slugs, tags, QR codes, titles resolved automatically from the target page
- Multiple short domains from one instance, with per-domain and device redirect rules
- Time windows and maximum-visit limits per link
- Orphan-visit tracking, so hits on deleted or unknown slugs are still recorded
Architecturally the shlink service owns everything: it answers redirects, serves the API, and processes visit tracking asynchronously in its own worker pool. PostgreSQL is the system of record. Redis holds the cache and the locks that let several Shlink containers share one database without racing. shlink-web-client is a static single-page app served by nginx that calls the Shlink API straight from the browser.
Why Deploy Shlink on Railway
Everything Shlink needs is provisioned and connected before you touch a setting.
- PostgreSQL and Redis attached over private networking, no connection strings to write
- Managed TLS on both domains, plus custom domains when you want branded short links
- An initial API key generated at deploy time — no shell access needed to bootstrap
- Health checks, restart policies and graceful draining already configured
- Scale Shlink to more replicas without changing any configuration
Common Use Cases
- Branded short links for email and social campaigns, with click analytics you own
- Link infrastructure inside an existing product, driven through the REST API
- QR codes for print, packaging or events, tracked back to a campaign
- Agencies running client brands as separate short domains on one instance
Dependencies for Shlink
- Shlink —
shlinkio/shlink:latest(GitHub). Redirect engine and REST API, on the RoadRunner runtime. - shlink-web-client —
shlinkio/shlink-web-client:latest(GitHub). Static management UI, nginx on 8080. - PostgreSQL — Railway managed. Stores short URLs, tags, API keys and every visit.
- Redis — Railway managed. Cache plus the locks required for multi-instance deployments.
Environment Variables Reference
| Variable | Description | Required |
|---|---|---|
INITIAL_API_KEY | API key created on first boot; paste into the web client | Yes |
DEFAULT_DOMAIN | Domain used when generating short URLs | Yes |
IS_HTTPS_ENABLED | Generate https:// short URLs | Yes |
TRUSTED_PROXIES | Proxy hop count used to resolve the real visitor IP | Yes |
WEB_WORKER_NUM | RoadRunner HTTP workers; unset means one per host core | Yes |
TASK_WORKER_NUM | RoadRunner visit-tracking workers | Yes |
DEFAULT_BASE_URL_REDIRECT | Where the short domain's root sends visitors | No |
GEOLITE_LICENSE_KEY | MaxMind key; enables per-visit geolocation | No |
ANONYMIZE_REMOTE_ADDR | Mask the last octet of visitor IPs, on by default | No |
Deployment Dependencies
Shlink runs on PHP 8.5 with RoadRunner 2025.1 and needs PostgreSQL, MySQL, MariaDB or MSSQL for anything beyond a toy install. Docs: shlink.io/documentation. Images: shlinkio/shlink and shlinkio/shlink-web-client.
The Shlink service starts with a command that trims the proxy headers Shlink reads a client IP from down to X-Forwarded-For alone. Without it a visitor can send a header such as CF-Connecting-IP and choose the IP recorded against their own click:
/bin/sh -c 'F=config/autoload/ip-address.global.php; sed -i "/.CF-Connecting-IP.,/d; /.X-Forwarded.,/d; /.Forwarded.,/d; /.True-Client-IP.,/d; /.X-Real-IP.,/d; /.X-Cluster-Client-Ip.,/d; /.Client-Ip.,/d" $F; php -l $F && exec /bin/sh ./docker-entrypoint.sh'
Server Requirements to Self-Host Shlink
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2–4 vCPU |
| RAM | 512 MB | 2 GB |
| Storage | 1 GB (database) | 10 GB+ as visit history grows |
| Runtime | PHP 8.4 | PHP 8.5 with RoadRunner |
Redirects are cheap; visit history is what grows. Size WEB_WORKER_NUM to the CPU you actually have — RoadRunner otherwise starts one PHP worker per core it can see, which on a large shared host is far more than the container can run.
How to Self-Host Shlink Outside Railway
The published image needs only a database to be useful:
docker run --name shlink -p 8080:8080 \
-e DEFAULT_DOMAIN=s.example.com \
-e IS_HTTPS_ENABLED=true \
-e INITIAL_API_KEY=change-me \
-e DB_DRIVER=postgres \
-e DB_HOST=postgres -e DB_NAME=shlink \
-e DB_USER=shlink -e DB_PASSWORD=secret \
shlinkio/shlink:latest
Add the management UI alongside it:
docker run --name shlink-web-client -p 8000:8080 shlinkio/shlink-web-client:latest
Leave SHLINK_SERVER_API_KEY unset on the web client unless it sits behind your own authentication — it writes the key into a file the browser downloads, publishing it to anyone who loads the page.
Is Shlink Free?
Shlink is free and open source under the MIT licence — no paid tier, no seat limits, no cap on links, domains or clicks. There is no official managed cloud version, which is exactly why a one-click deploy is useful. On Railway you pay for infrastructure alone: two small containers plus PostgreSQL and Redis, a few dollars a month at typical link volumes.
FAQ
What is Shlink? Shlink is an open source, self-hosted URL shortener with a REST API and built-in visit analytics. It creates short links on your own domain and records every click.
What does this Railway template deploy?
Four services: the Shlink server (redirects plus REST API) on a public domain, the shlink-web-client management UI on a second public domain, and private PostgreSQL and Redis instances.
Why does the template include PostgreSQL and Redis? PostgreSQL stores short URLs, tags, API keys and the full visit history — Shlink's SQLite fallback is not suitable for production. Redis provides the cache and the distributed locks that let you run more than one Shlink container against the same database.
How do I log in to the Shlink web client?
There is no login. The client runs entirely in your browser; you connect it to your server once by pasting the server URL and the INITIAL_API_KEY value from Railway, and it remembers that in local storage.
Can I use my own domain for short links?
Yes. Add a custom domain to the Shlink service in Railway, point your DNS at it, and set DEFAULT_DOMAIN to that hostname. Shlink also supports serving several short domains from one instance.
Can I create short URLs from my own code?
Yes — that is the primary interface. POST /rest/v3/short-urls with an X-Api-Key header creates a link, and official PHP, JavaScript and Python SDKs wrap the same API.
Template Content
