README.md

earl

REUSE status Donate with fosspay Time spent on project

Personal shortlink generator

Features

Links are …

  • Editable
  • Removable
  • Four characters long (26 uppercase letters + 26 lowercase letters + 10 numbers = 14,776,336 possible shortened URLs)

Service has …

  • A simple API
  • A simple web UI
  • A simple backup procedure (database is a single directory)
  • No user management (this is a personal service after all)

Installation

  • Download the binary appropriate for your system or build from source with go build .
    List of latest binaries - [earl-darwin-amd64](https://earl.run/earl-darwin-amd64) - [earl-darwin-arm64](https://earl.run/earl-darwin-arm64) - [earl-dragonfly-amd64](https://earl.run/earl-dragonfly-amd64) - [earl-freebsd-amd64](https://earl.run/earl-freebsd-amd64) - [earl-freebsd-arm](https://earl.run/earl-freebsd-arm) - [earl-freebsd-i386](https://earl.run/earl-freebsd-i386) - [earl-illumos-amd64](https://earl.run/earl-illumos-amd64) - [earl-linux-amd64](https://earl.run/earl-linux-amd64) - [earl-linux-arm](https://earl.run/earl-linux-arm) - [earl-linux-arm64](https://earl.run/earl-linux-arm64) - [earl-linux-i386](https://earl.run/earl-linux-i386) - [earl-linux-mips](https://earl.run/earl-linux-mips) - [earl-linux-mips64](https://earl.run/earl-linux-mips64) - [earl-linux-mips64le](https://earl.run/earl-linux-mips64le) - [earl-linux-mipsle](https://earl.run/earl-linux-mipsle) - [earl-linux-ppc64](https://earl.run/earl-linux-ppc64) - [earl-linux-ppc64le](https://earl.run/earl-linux-ppc64le) - [earl-linux-riscv64](https://earl.run/earl-linux-riscv64) - [earl-linux-s390x](https://earl.run/earl-linux-s390x) - [earl-netbsd-amd64](https://earl.run/earl-netbsd-amd64) - [earl-netbsd-arm](https://earl.run/earl-netbsd-arm) - [earl-netbsd-i386](https://earl.run/earl-netbsd-i386) - [earl-openbsd-amd64](https://earl.run/earl-openbsd-amd64) - [earl-openbsd-arm](https://earl.run/earl-openbsd-arm) - [earl-openbsd-arm64](https://earl.run/earl-openbsd-arm64) - [earl-openbsd-i386](https://earl.run/earl-openbsd-i386) - [earl-plan9-amd64](https://earl.run/earl-plan9-amd64) - [earl-plan9-arm](https://earl.run/earl-plan9-arm) - [earl-plan9-i386](https://earl.run/earl-plan9-i386) - [earl-solaris-amd64](https://earl.run/earl-solaris-amd64) - [earl-windows-amd64.exe](https://earl.run/earl-windows-amd64.exe) - [earl-windows-arm64.exe](https://earl.run/earl-windows-arm64.exe) - [earl-windows-arm.exe](https://earl.run/earl-windows-arm.exe) - [earl-windows-i386.exe](https://earl.run/earl-windows-i386.exe)
  • On Unix-based OSes (which includes macOS), mark the binary as executable with chmod u+x path/to/binary
    • I don't think this is necessary with Windows.
  • On Unix-based OSes, execute the binary with ./path/to/binary
    • No clue how to execute the Windows binaries. Feel free to send a patch with this information!
  • Edit ./config.yaml and modify accessToken to something secure; earl won't start until the access token is changed.
  • Re-execute the binary and earl should be accessible on localhost:1313!
  • To make it accessible over the internet on a short domain, you'll need said short domain, a server, a reverse proxy, and a TLS certificate. How to obtain/configure those components is out-of-scope though.
    • Contributions adding a Caddyfile, an NGINX vhost, systemd/OpenRC/runit/etc. units are welcome.

API documentation

/create

Required parameters

  • url: percent-encoded URL being shortened

Optional parameters

  • name: percent-encoded short link the url will be mapped to. If this is not provided, a random, 4-character code will be generated instead.

Output

  • 401 Unauthorized: You do not have permission to create shortlinks if access token provided in Authorization header does not match the configured access token
  • 400 Bad Request: URL parameter is required
  • 406 Not Acceptable: A shortened URL with this name already exists if provided name already exists in the database
  • URL mapped to $NAME (200 OK)

/read

Required parameters

  • None

Optional parameters

  • None

Output

  • 401 Unauthorized: You do not have permission to view shortlinks if access token provided in Authorization header does not match the configured access token
  • JSON representation of the key/value database (200 OK)
    {
      "6H1g": "https://git.sr.ht/~amolith/earl/tree/dev",
      "N3yg": "https://secluded.site/"
    }
    

/update

Required parameters:

  • oldName: percent-encoded name the URL is currently referred to with
  • name: percent-encoded name the URL will be referred to with
  • url: percent-encoded URL being shortened

name and url are first set as a key/value pair. If name already exists, url is updated. If name does not already exist, it's created and oldName is deleted. If the user is only modifying url, oldName and name should both be submitted but their values should be identical.

Optional parameters:

  • None

Output:

  • 401 Unauthorized: You do not have permission to create shortlinks if access token provided in Authorization header does not match the configured access token
  • 400 Bad Request: oldName parameter is required
  • 400 Bad Request: name parameter is required
  • 400 Bad Request: URL parameter is required
  • 406 Not Acceptable: A shortened URL with this name already exists if provided name already exists in the database
  • $URL mapped to $NAME (200 OK)

/delete

Required parameters:

  • name: percent-encoded short link

Optional parameters:

  • None

Output:

  • 401 Unauthorized: You do not have permission to create shortlinks if access token provided in Authorization header does not match the configured access token
  • 400 Bad Request: name parameter is required
  • $URL has been deleted (200 OK)

But … why?

Good question. URL shorteners are (usually) terrible and useless. Except when used correctly :thinkingsmart:

I take a lot of hand-written notes on things and, having both a passion for and job in IT, my notes would be much more useful if they included links to the things I'm writing about. However, there's no way I'm going to hand-write a 50+ character URL.

That's where URL shorteners come in!

Most shortener services I've found that are both open source and self-hosted use something like 6-character-long paths for the links as they're meant for use by multiple people; 14.8m possible URLs (your cap with 4 character paths) aren't enough for public services.

Now six characters is fine but why write six characters when you could write four :D

And why deal with user management and a relational database when you're only going to have one user and a bunch of keys with values :D

I was also unsatisfied with the tech stack and feature sets of the alternatives; they were all either a pain to set up and update or they had click counters and link tracking and a bunch of other crap I have no use for.

So I decided to make my own that has exactly what I want and nothing more :D

Questions & Contributions

Questions, comments, and patches can always be sent to my public inbox, but I'm also in my IRC channel/XMPP room pretty much 24/7. However, I might not see messages right away because I'm working on something else (or sleeping) so please stick around!

If you're wanting to introduce a new feature and I don't feel like it fits with this project's goal, I encourage you to fork the repo and make whatever changes you like!

If you haven't used mailing lists before, please take a look at SourceHut's documentation, especially the etiquette section.