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
- List stored URLs with cursor-based pagination
- Simple token-based authorization
- Single-file embedded database (bbolt)
- Tracking analytics with Rybbit (other providers soon to come)
Prerequisites: Go 1.24 or Docker.
Run locally:
go build -o short-it ./cmd/short-it
APP_TOKEN=your-secret-token DB_PATH=short-it.db PORT=8080 ./short-itRun with Docker:
docker build -t short-it .
docker run -e APP_TOKEN=your-secret-token -p 8080:8080 -v $(pwd)/data:/data short-itOr use the provided docker-compose configuration:
docker-compose up -d
# edit docker-compose.yml to set APP_TOKEN or update the environmentThe server listens on PORT (default 8080) and stores the BoltDB file at DB_PATH (default short-it.db).
Or deploy it in one click:
Environment variables:
APP_TOKEN(required): token used for authorization on protected endpointsPORT(optional): HTTP port (default8080)DB_PATH(optional): path to BoltDB file (defaultshort-it.db)RYBBIT_SITE_ID(optional): Site ID provided by RybbitRYBBIT_SITE_KEY(optional): API key found in account settings for RybbitRYBBIT_SITE_URL(optional): Base URL for your Rybbit instance
All endpoints that modify or list data require the Authorization header to equal the APP_TOKEN 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(max 100) - Response:
{ "items": [{"key":"...","value":"..."}], "next":"<cursor>" }
-
Redirect
GET /{key}- Redirects (302) to the stored URL if found
-
Create/Update custom path
PUT /{path}- Headers:
Authorization,URL(or JSON body) - Response:
201 Created
-
Delete path
DELETE /{path}- Headers:
Authorization - Response:
204 No Content
Examples:
# shorten a URL (using header)
curl -X POST -H "Authorization: your-secret-token" -H "URL: https://example.com" http://localhost:8080/
# get redirect
curl -v http://localhost:8080/:key
# create custom path
curl -X PUT -H "Authorization: your-secret-token" -H "URL: https://custom.example" http://localhost:8080/custom
# delete
curl -X DELETE -H "Authorization: your-secret-token" http://localhost:8080/custom
# list
curl -H "Authorization: your-secret-token" http://localhost:8080/Run unit tests:
go test ./cmd/short-itKey implementation files:
- cmd/short-it/main.go — HTTP handlers and core logic
- cmd/short-it/main_test.go — unit tests for handlers and DB ops
- Dockerfile — container build
- docker-compose.yml — example compose configuration
- The app uses a BoltDB bucket named
urlsto store key → URL mappings. - The autogenerated keys are 6 characters drawn from
a-zA-Z0-9. - Sends pageview events to Rybbit if configured with the hostname, language, pathname, user-agent, referrer, and IP address gathered from
X-Forwarded-For.