A self-hosted link shortener
  • Rust 96.1%
  • Just 3.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-04-22 13:39:36 -07:00
.sqlx Sanding off more rough edges related to migrations 2026-04-15 12:37:14 -07:00
migrations Sanding off more rough edges related to migrations 2026-04-15 12:37:14 -07:00
src Add license & source endpoints 2026-04-22 13:39:36 -07:00
systemd Adding example systemd service 2026-04-15 13:43:43 -07:00
.env.template Add license & source endpoints 2026-04-22 13:39:36 -07:00
.gitignore Starting in on migration tooling, updated PORT to have default 2026-03-12 19:10:17 -07:00
agpl-3.0.txt Adding LICENSE 2026-04-21 16:21:20 -07:00
Cargo.lock Probably complete 2026-04-15 10:44:40 -07:00
Cargo.toml Probably complete 2026-04-15 10:44:40 -07:00
justfile Sanding off more rough edges related to migrations 2026-04-15 12:37:14 -07:00
LICENSE Adding LICENSE 2026-04-21 16:21:20 -07:00
README.md Add license & source endpoints 2026-04-22 13:39:36 -07:00

Fleck

A self-hosted link shortener

CLI Usage

Run Server

Make sure to set up .env as a fully filled copy of .env.template or otherwise provide the necessary env variables like HOST_ROOT, PORT, SOURCE_URL, and DATABASE_URL.

fleck serve

Add API User

fleck add-user USER_NAME

Add API Key for User

fleck add-key --user-name USER_NAME --key-name KEY_NAME --key-secret KEY_SECRET

This will generate a TOTP QR code in ASCII and print it out to the terminal. It will also print out the necessary url in plain text. I suggest using your password manager of choice to generate a good random KEY_SECRET to use.

fleck put-link TARGET --short-code SHORT_CODE

Note: --short-code SHORT_CODE is optional. The system will generate one for you.

API Usage

Example

See project justfile for some examples of how to call the API with a valid HMAC generated by openSSL

Authenticate

-H 'Authorization: {"name":"API_KEY_NAME","nonce":"2FA_CODE","hash":"HMAC_OF_NONCE_WITH_SECRET"}'

  • Provide "name" to identify which api_key we are authenticating as.
  • Provide "nonce" as a time based 2FA code to make this request unrepeatable.
    • Must be timely (+-30s)
    • Must not be reused between requests
  • Provide "secret" as a sha512 hmac of the nonce utilizing the shared api_secret

All endpoints may produce the following error if this is incorrectly applied.

401 UNAUTHORIZED text/plain
Authorization Not Recognized

curl -X PUT https://host/api/link/{SHORT_CODE} -H 'Authorization: ...' -H 'Content-Type: text/plain' -d 'TARGET_LINK'

OR

curl -X PUT https://host/api/link -H 'Authorization: ...' -H 'Content-Type: text/plain' -d 'TARGET_LINK'

200 OK text/plain
https://host/{SHORT_CODE}
400 BAD_REQUEST text/plain
Shortcode Already Exists

curl -X DELETE https://host/api/link/{SHORT_CODE} -H 'Authorization: ...'

200 OK application/json
{"short_url": "https://host/{SHORT_CODE}", "url": "TARGET_URL"}
404 NOT_FOUND text/plain
Not Found

curl -X GET https://host/{SHORT_CODE}

303 SEE OTHER
404 NOT_FOUND text/plain
Not Found