YOURLS is the old-school option in the best possible sense.
It is a small PHP application that does one job: run your own URL shortener. You get an admin panel, short-link creation, click statistics, an API, bookmarklets, and a plugin system without adding Redis, ClickHouse, queue workers, object storage, or a serverless deployment model.
If you want the lightest practical self-hosted shortener with a long history, YOURLS is still worth considering.
What is YOURLS?
YOURLS stands for “Your Own URL Shortener”.
I inspected commit:
9add23549f4ef2d1a8a2c883778a8a60b3e64d07
The current branch reports:
1.10.7-dev
The latest release tag in the checked-out repo was:
1.10.6
For the Docker setup, I pinned the image to:
yourls:1.10.6-apache
What You Get
YOURLS includes the practical shortener basics:
- private admin interface;
- short-link creation and editing;
- custom keywords;
- click counters;
- per-link statistics pages;
- referrer and visitor reports;
- bookmarklets;
- REST-like API through
yourls-api.php; - plugin architecture;
- sample public front-end and public API files;
- support for running private or public instances.
The UI is not modern SaaS-style, but it is functional and fast. This is a small admin tool, not a marketing analytics suite.
Architecture
YOURLS is a traditional PHP web app.
The stack is:
- PHP 8.1+ application code.
- Apache in the official Docker image used here.
- PDO MySQL database access.
- MySQL or MariaDB for persistence.
- Server-rendered admin UI.
- Plugin hooks for extending core behavior.
- API endpoint at
yourls-api.php.
The request shape is simple:
Browser/API client -> YOURLS PHP app -> MariaDB
There are no required background workers, queue services, Redis caches, OLAP engines, or object-storage buckets.
Home-Lab Compose Review
There was already a YOURLS folder in Home-Lab.
The old setup worked as a rough reference, but it had avoidable problems:
- duplicated compose files;
- hardcoded database passwords;
- hardcoded LAN IP;
latestimage tags;- old
8080:80container-port mapping; - old Compose
versionfield; - no database healthcheck.
I replaced it with a single canonical compose file using .env, pinned images, MariaDB healthchecks, and the current official image port.
Self-Hosting with Docker
The reusable Home-Lab compose file is here:
The site includes the same Compose file from the local snippets folder:
assets/snippets/yourls/docker-compose.yml
Pre-Requisites - Docker
Install Docker on your system before proceeding:
- Linux: Official Docker Engine install guide
- Windows / Mac: Docker Desktop
Verify installation: docker --version && docker compose version
services:
yourls:
image: yourls:1.10.6-apache
restart: unless-stopped
depends_on:
database:
condition: service_healthy
ports:
- "${YOURLS_PORT:-8789}:8080"
environment:
YOURLS_SITE: "${YOURLS_SITE:-http://localhost:8789}"
YOURLS_USER: "${YOURLS_USER:?Set YOURLS_USER in .env}"
YOURLS_PASS: "${YOURLS_PASS:?Set YOURLS_PASS in .env}"
YOURLS_DB_HOST: database
YOURLS_DB_NAME: yourls
YOURLS_DB_USER: yourls
YOURLS_DB_PASS: "${MARIADB_PASSWORD:?Set MARIADB_PASSWORD in .env}"
volumes:
- yourls-data:/var/www/html
database:
image: mariadb:11.4
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD:?Set MARIADB_ROOT_PASSWORD in .env}"
MARIADB_DATABASE: yourls
MARIADB_USER: yourls
MARIADB_PASSWORD: "${MARIADB_PASSWORD:?Set MARIADB_PASSWORD in .env}"
volumes:
- yourls-db-data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
volumes:
yourls-data:
yourls-db-data:
Prepare the environment:
cd assets/snippets/yourls
cp .env.sample .env
Generate secrets:
openssl rand -base64 32
openssl rand -base64 32
openssl rand -base64 32
Use those generated values for:
YOURLS_PASS
MARIADB_ROOT_PASSWORD
MARIADB_PASSWORD
Start the stack:
docker compose up -d
The default local admin URL is:
http://localhost:8789/admin/
On the first run, go to:
http://localhost:8789/admin/install.php
and click the install button.
Domain Configuration
YOURLS_SITE must match the public URL you will actually use, without a trailing slash.
Local examples:
YOURLS_SITE=http://localhost:8789
YOURLS_SITE=http://192.168.1.2:8789
Public example:
YOURLS_SITE=https://s.example.com
For a public deployment, put YOURLS behind HTTPS:
https://s.example.com -> reverse proxy -> http://yourls:8080
If YOURLS_SITE does not match the browser-facing URL, generated short links and asset URLs can be wrong.
API Notes
YOURLS exposes API actions through:
/yourls-api.php
Common API use cases include:
- creating a short URL;
- requesting JSON, XML, or plain text output;
- checking link statistics;
- using a signature token instead of sending the password directly;
- adding custom API actions through plugins.
For private instances, keep the API private unless you have a specific public-use case.
Plugin Model
YOURLS has a long-standing plugin API.
Plugins live under:
user/plugins
That is one reason the compose file persists:
/var/www/html
so plugins, uploaded custom files, and generated config survive container replacement.
For a cleaner production setup, I would keep custom plugins under version control and mount only the plugin directories you intentionally manage.
Field Test
I smoke-tested the fixed Home-Lab compose with disposable containers and volumes.
Command shape:
YOURLS_PORT=8789 \
YOURLS_SITE=http://localhost:8789 \
YOURLS_USER=admin \
YOURLS_PASS=test-admin-password \
MARIADB_ROOT_PASSWORD=test-root-password \
MARIADB_PASSWORD=test-db-password \
docker compose -f /home/jalcocert/Desktop/Home-Lab/yourls/docker-compose.yml -p yourls_smoke up -d
Observed:
- MariaDB 11.4 became healthy.
- YOURLS copied its application files into
/var/www/html. GET /returned HTTP403, which is expected before adding a public front page.GET /admin/returned HTTP307to/admin/install.php.GET /admin/install.phpreturned HTTP200.POST /admin/install.phpcompleted the install with HTTP200.GET /admin/returned HTTP200after installation.- MariaDB contained the expected tables:
yourls_log,yourls_options, andyourls_url.
Then I removed the smoke-test containers and volumes:
docker compose -p yourls_smoke down -v --remove-orphans
YOURLS vs Shlink vs Kutt vs Dub
YOURLS is the simplest traditional option.
Compared with Shlink:
- YOURLS has a built-in admin UI.
- Shlink has a stronger API/CLI-first backend model.
- Shlink has a separate web client.
Compared with Kutt:
- YOURLS is older and simpler.
- Kutt feels more like a complete modern web app.
- YOURLS has a large plugin ecosystem.
Compared with Dub:
- YOURLS is tiny.
- Dub is a cloud-native attribution platform.
- YOURLS needs PHP plus MySQL/MariaDB; Dub expects several specialized services.
See also:
FAQ
Does YOURLS have a UI?
Yes. YOURLS has a built-in admin UI at /admin/.
Why does / return 403?
That is normal for the official Docker image unless you add a public front page. Use /admin/ for management, or create a public page using the sample files if you want visitors to create links.
Does YOURLS require MySQL or MariaDB?
Yes. YOURLS stores links, options, and visit logs in a MySQL-compatible database. The Home-Lab snippet uses MariaDB.
Does YOURLS require Redis?
No. Redis is not part of the default YOURLS stack.
What additional services does YOURLS use?
The default Home-Lab stack uses only:
YOURLS
MariaDB
Additional infrastructure is optional:
- MariaDB/MySQL: required database layer. MariaDB and MySQL are self-hostable; MariaDB is the FOSS default I used here.
- Reverse proxy: optional but recommended for HTTPS. Caddy, Nginx, Traefik, and Apache are all self-hostable open-source options.
- Plugins: optional. Plugin quality and dependencies vary by plugin; YOURLS itself does not require a plugin service.
- External analytics/marketing tools: not required by core YOURLS. Add them only through plugins if you want them.
YOURLS does not need ClickHouse, Redis, QStash, S3, object storage, or a cloud account for normal self-hosting.
Can YOURLS be public?
Yes, but decide what “public” means. You can expose only redirects and the admin UI behind authentication, or you can build a public front page that lets visitors create short links. For most home-lab uses, keep link creation private.
Can I run YOURLS behind Cloudflare Tunnel?
Yes. Put YOURLS behind your tunnel or reverse proxy, set YOURLS_SITE to the public HTTPS URL, and make sure /admin/ is protected with strong credentials.
Is YOURLS still maintained?
Yes. The checked-out repo has recent release tags up to 1.10.6, and the current branch points at 1.10.7-dev.
What is the simplest deployment?
One YOURLS container and one MariaDB container.
That is the setup in this post.
Verdict
YOURLS is the URL shortener I would choose when I want something classic, small, and boring in a good way.
It does not have the modern polish of Kutt, the API/CLI structure of Shlink, or the attribution pipeline of Dub. But it is easy to run, easy to understand, plugin-friendly, and perfectly fine for a personal or small-team branded short-link service.
Comments