I was excited to learn that S3 has natively supported redirects since 2012. That meant that I could use the power of the ✨ cloud ✨ to get my own link shortener for “free”–thanks to AWS’s Free Tier–without having to muck around with databases, web servers, or serverless-cloud-lambda-edge functions. Each link is just a zero-byte file in an bucket, which S3 itself magically turns into a redirect.
I wrote a script to shorten links from the terminal but you could easily make a GUI.
All it does is run aws s3api put-object
:
$ publish-link 'https://example.com/long/url/here/'
https://.../zZzZz
The downsides are that you need to bring your own:
- domain name and
- AWS account
But think of the advantages!
- even shorter links, because it’s just you
- ???
- it’s fun
I threw in CloudFront and Route 53 just so I could get HTTPS links. Route 53 is the only thing that doesn’t fit within the free tier AFAIK–it costs $0.50/mo. It should be pretty straightforward to delete Route 53 from the configuration below though.
The setup process is easy, assuming you have a domain name and AWS account lying around (!), but there’s a bit of waiting involved. You have to wait around 15 minutes for each of the following:
- DNS records to propagate, after replacing your domain registrar’s nameservers with Route 53’s
- AWS to issue an SSL certificate
- AWS to create a CloudFront distribution
Use that time to walk your dog!
I ended using 5-digit base-58 keys1 because I figured that if I live for 50 more years I definitely won’t shorten more than one link per second:
$$ \frac{\log 86400 \times 365 \times 50}{\log 58} \approx 5.2 $$
I guess if I were really worried about the Birthday Paradox I could square the total number of links, which doubles the keylength to $10.4$. If I pick $\sqrt{N}$ keys out of $N$ possibilities, the probability of at least one collision is around 50% (for the Birthday Paradox the actual number is $23 \approx 19.104 \approx \sqrt{365}$). But I’m fine with the odds as-is.
Another consideration is that short keys make it easier for someone else to iterate through all of them to find what links you’ve shortened.
Either don’t shorten secret links, or use a longer keylen.
Or set up an AWS WAF rule to rate-limit requests 😱.
The script I use to shorten links is called publish-link
.
On macOS pbcopy
copies standard input to my clipboard.
On Linux I’d use xclip -sel clip
and on Windows I’d use clip.exe
.
#!/bin/zsh
# Replace $bucket with your own domain.
bucket="example.com"
domain=""
keylen=5
if [; then
fi
while ; do
base58_alphabet="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
key=""
for; do
index=
key+=
done
if ! ; then
break
fi
done
url="https:// /"
|
The meat is in this Terraform file, which I place in main.tf
.
Caveat emptor, I’m not an expert at cloud infrastructure.
I based it off of a configuration I’ve been using to host static files for a few years now that works just fine.
If something looks funky it’s probably on me, not you.
# I don't think you actually need versions this new, but this is what I tested with.
# Replace link_domain with your own domain.
# Replace region with the region you prefer.
# CloudFront needs ACM certificates to be from us-east-1.
# Create an S3 bucket with public reads.
# Set up a website endpoint, which is what implements redirects.
# Set up Route 53. This is very much optional, I just wanted to have AWS manage
# the SSL certificate for me.
# Request an SSL certificate from AWS. This can take a while.
# Set up CloudFront. S3 doesn't support HTTPS so we put CloudFront in front.
# Point Route 53 to CloudFront.
To set things up, run:
$ terraform init
$ terraform apply
When you see:
aws_acm_certificate_validation.link: Still creating...
… go to “Hosted zones” in the Route 53 console–make sure to select the right AWS region–then take the nameservers from the NS record and plug them into your domain registrar.
Now you’re all set to create your own short links!
$ publish-link 'https://www.jonathanychan.com/blog/link-shortener/'
https://example.com/zZzZz
I used base-58 because I use shortened links when hand-writing notes.
Base58 omits characters that look similar, so e.g. 0
and O
are absent and only o
is present.