Railway

Deploy Shlink

Bitly Alternative. Short links, custom domains, QR codes & more

Deploy Shlink

Just deployed

Just deployed

Just deployed

/data

/var/lib/postgresql/data

Shlink logo

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.

Shlink Railway architecture

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.

Shlink overview dashboard counting visits, short URLs and tags

Shlink visit analytics charting operating systems, browsers and referrers

Shlink short URL list showing tags and per-link visit counts

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

  • Shlinkshlinkio/shlink:latest (GitHub). Redirect engine and REST API, on the RoadRunner runtime.
  • shlink-web-clientshlinkio/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

VariableDescriptionRequired
INITIAL_API_KEYAPI key created on first boot; paste into the web clientYes
DEFAULT_DOMAINDomain used when generating short URLsYes
IS_HTTPS_ENABLEDGenerate https:// short URLsYes
TRUSTED_PROXIESProxy hop count used to resolve the real visitor IPYes
WEB_WORKER_NUMRoadRunner HTTP workers; unset means one per host coreYes
TASK_WORKER_NUMRoadRunner visit-tracking workersYes
DEFAULT_BASE_URL_REDIRECTWhere the short domain's root sends visitorsNo
GEOLITE_LICENSE_KEYMaxMind key; enables per-visit geolocationNo
ANONYMIZE_REMOTE_ADDRMask the last octet of visitor IPs, on by defaultNo

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

ResourceMinimumRecommended
CPU1 vCPU2–4 vCPU
RAM512 MB2 GB
Storage1 GB (database)10 GB+ as visit history grows
RuntimePHP 8.4PHP 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

More templates in this category

View Template
Rocky Linux
[Jul'26] Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
42
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
52