A minimal, self-hosted URL shortener written in Go using bbolt (BoltDB). This project is inspired by Erisa's worker-links. I wanted something that can do functionally the same as that project, without being fully locked into Cloudflare's services.
-
Shorten URLs with autogenerated 6-character keys
-
Create custom paths (or relative links with safe-mode disabled)
-
List stored URLs with cursor-based pagination
-
Unified API and redirect listener
-
Built-in lightweight, simple web UI (optional)
-
Simple token-based authorization for operations
-
Single-file embedded database (bbolt)
-
Tracking analytics with Rybbit (more soon), natively integrated (optional)
Prerequisites: Go 1.24 or Docker.
Run locally:
go build -o short-it .
APP_TOKEN=your-secret-token API_PORT=8080 WEB_UI=true ./short-itRun with Docker:
docker build -t short-it .
docker run -e APP_TOKEN=your-secret-token -e WEB_UI=true -p 8080:8080 -p 8090:8090 -v $(pwd)/data:/data short-itOr use the provided docker-compose.yml configuration:
docker-compose up -d
# edit docker-compose.yml to set APP_TOKEN or update the environmentThe primary API and redirect server listens on API_PORT (default 8080). If enabled, the Web UI listens on WEB_UI_PORT (default 8090).
The BoltDB file is stored at ./short-it.db by default, or /data/short-it.db in Docker configurations.
Or deploy it in one click:
Note: Ensure you update the environment variables to match the latest version when deploying.
Environment variables:
-
APP_TOKEN(required): Token used for authorization on protected API endpoints. -
API_PORT(optional): Port for the main API and URL redirection (default8080). -
API_URL(optional): Explicit base URL used for generating shortened links in the Web UI. Intelligently inferred if omitted. -
DB_PATH(optional): Filepath for the BoltDB database (defaultshort-it.db). -
ALLOW_UNSAFE_URLS(optional): Set totrueto allow relative paths (e.g.,/relative) or unsupported schemas (defaultfalse).
-
WEB_UI(optional): Set totrueto enable the built-in HTML creation page (defaultfalse). -
WEB_UI_PORT(optional): Port for the Web UI (default8090).
-
RYBBIT_SITE_ID: Your Rybbit Site ID. -
RYBBIT_SITE_KEY: Your Rybbit API Key. -
RYBBIT_SITE_URL: The URL to your Rybbit instance.
All management endpoints require the Authorization header to equal the APP_TOKEN value.
Base URL: http://localhost:8080 (or your API_PORT value)
-
Create a short URL
POST /- Headers:
Authorization,URL(or JSON body{ "url": "..." }) - Response:
{"key":"<generated-key>"}
-
List URLs (paginated)
GET /- Headers:
Authorization, optionalCursor, optionalLimit(default max 100, or unlimited with 0) - Response:
{ "items": [{"key":"...","value":"..."}], "next":"<cursor>" }
-
Create/Update custom path
PUT /{path}- Headers:
Authorization,URL(or JSON body{ "url": "..." }) - Response:
201 Created
-
Delete path
DELETE /{path}- Headers:
Authorization - Response:
204 No Content
-
Redirect (Public)
GET /{key}- Redirects (302 Found) to the stored URL if it exists.
If WEB_UI=true is set, a web interface is exposed on http://localhost:8090 (or WEB_UI_PORT).
-
GET /: Serves the HTML interface to easily create short URLs. -
POST /api/create: Internal endpoint used by the Web UI form.
-
The app uses a BoltDB bucket named
urlsto store key → URL mappings. -
The autogenerated keys are 6 characters drawn from
a-zA-Z0-9. -
/can be set as a short link as well and still function as the list URLs endpoint.