Storage was growing quickly (~80Gb during its peak); I am hosting my instance on a RPi4 (w/ 8Gb RAM) and the SSD was filling up rapidly,
I wanted something speedy to serve (big and cacheable) content (i.e. a CDN).
While I didn’t care much about storage any more, I still wanted to make sure it was kept in check, also for two reasons:
Mastodon downloads a copy of all content it says on the Fediverse, and keeps it until purged. So every instance has all the content from other instances. This could theoretically lead to you hosting illegal content and getting in trouble for it,
Cloudflare used to be my employer, and I have free access to R2. However, there’s always a risk they’ll disable my employee benefits one day and get me to pay for my used storage.
I run my Mastodon in a Docker instance, so your commands may vary (basically tootctl X Y is what matters). I run most of these commands once a week using systemd (except the media remover, that runs every day).
This will clear:
accounts (you never interacted with)
header files (big picture every account can upload)
link preview cards
orphaned media (uploaded media but not posted)
media (from other accounts)
statuses (from other accounts)
and as a bonus include updating Elasticsearch indices (which sound run every once in a while to optimise search)
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl accounts prune
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl media remove --remove-headers --days 15
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl media remove--prune-profiles --days 30
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl preview_cards remove --days 15
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl media remove-orphans
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl media remove --days 30
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl statuses remove --days 30
/usr/bin/docker compose -f /srv/mastodon/docker-compose.yml run --rm shell tootctl search deploy
Note that you should play with the --days X to find something that works for you (i.e.: you can scroll back in the history and still see posts/media, but not overload your storage).
I’ve included all the systemd files that’s needed here. Again, will only work in a Docker environment using the same paths as me.
The systemd files will need to be activated using something similar to this (but again, don’t blindly run these commands as it’ll likely not work):
The token/API key is a bit hard to find, but it’s on the top right.
Then (re)deploy your site.
I did set up a new server (my RPi4 started to struggle, and I guess if I'm half serious about Mastodon, I shouldn't host it at home), so I started afresh... But there's a way to migrate existing data to R2 as well, following this guide.
If you’re using Mastodon with Cloudflare CDN/protection and minify turned on, you’ll notice the site may look broken (after a few visits, when hitting Cloudflare cache).
And you’ll notice errors in the webdev tools similar to Failed to find a valid digest in the 'integrity' attribute, with computed SHA-256 integrity:
Failed to find a valid digest in the 'integrity' attribute for resource 'https://mastodon.yeri.be/packs/js/common-997d98113e1e433a9a9f.js' with computed SHA-256 integrity 'YgEhHmwjKL88zKfUOMt/qRulYurIuHzhn4SZC9QQ5Mg='. The resource has been blocked.
@yeri:1 Failed to find a valid digest in the 'integrity' attribute for resource 'https://mastodon.yeri.be/packs/js/locale_en-f70344940a5a8f625e92.chunk.js' with computed SHA-256 integrity '1VgpQjY/9w/fgRLw1QH2pfzqr36p3hINvg9ahpBiI2U='. The resource has been blocked.
@yeri:1 Failed to find a valid digest in the 'integrity' attribute for resource 'https://mastodon.yeri.be/packs/js/public-a52a3460655116c9cf18.chunk.js' with computed SHA-256 integrity 'onh6vHxzykkVgJkiww+OCPk0tKC48KMUD9GVJ8/LKJQ='. The resource has been blocked.
Basically, the sha256 hash doesn’t match the js or css static files.
This happens because Cloudflare minifies those files and thus the hash has been changed.
To get it to work correctly, you’ll need to create a Page Rule via Rules > Page Rules > Create Page Rule with the following info:
Settings: Auto Minify: off (do not select anything)
Rocket Loader: slider off
Don’t forget to purge your cache via the dashboard (for the Mastodon domain) via Caching > Custom Purge > Hostname > YourMastodonURL.com.
Shan uses her iPad a lot, but a lot of the more serious (interior design) work needs to happen on AutoCAD or Photoshop. That is just not going to work on an iPad.
When we’re travelling (read: holiday) she’s carrying an old Lenovo ThinkPad 13 (great device!) just “in case” she needs to open AutoCAD and edit something minor or read the drawings/dimensions. But honestly, most of the time that device is turned off and dead weight.
But all the above is just an excuse to “I was bored, and I wanted to test something”: can I use an old Raspberry Pi (zero W) to remotely wake her Intel NUC, and then use Tailscale to use RD on her iPad? Well, yes I can.
I completed this using:
Tailscale to remote desktop from anywhere to home
Cloudflare Tunnels, Access and DNS to have a web interface to wake the desktop
A Linux device that’s always on and in the same LAN, and that’ll run a PHP script.
Prep work: enable WOL
First off: enable Wake-on-LAN (WOL) in the BIOS and in your Windows settings. This article explains it for Intel NUCs, but would be similar enough for most devices. The Device Manager pane looked different on our i5 NUC, but was close enough.
On Mac, you just need to enable it in the Energy preference pane, for Linux I have no clue. 🤷♂️
Second step: have a working Raspberry Pi (or any Linux device) in the same LAN. This device needs to be turned on 24/7, so use something that uses very little power.
I do have a more powerful RPi4 I wish I could've reused (running Docker and some other "serious" stuff; however it's currently in a different VLAN, and it's quite crucial the Linux device is in the same LAN as the device(s) you want to wake up), so I went with an old Raspberry Pi Zero W that was collecting dust (it used to run pwnagotchi).
On the Linux device, install etherwake. The command to run is quite simply etherwake aa:bb:cc:11:22:33 (= the ethernet MAC address of your device).
If this doesn’t wake your desktop, something is wrong and there’s no point continuing. Go and troubleshoot.
Install Tailscale and RD
On the (Windows) desktop and your iPad, install Tailscale. Login, and make sure it works by pinging from one to the other.
Then set up Remote Desktop on both (Windows, iPad). You should test and make sure you can properly connect using the LAN IP address and then the Tailscale IP address.
Fun fact: I create a DNS record for all my devices using Cloudflare DNS with the syntax of device-name.ts.yeri.be, so I don't need to ever remember IPs, and can easily ssh or ping devices without having to look up IPs.
Fun fact side track: I actually have a dynamic script that runs (on Linux) and creates hostname.ts.yeri.be for the Tailscale IP, hostname.wg.yeri.be based on the Wireguard IP, hostname.lan.yeri.be based on the LAN IP. This dyndns script runs every so often and updates IPs if needed. All this is running using Cloudflare DNS and their API. Super convenient.
Nginx, php and etherwake
I'm a 80s kid, so I'll use dirty PHP to run this script. I'm sure I'll go straight to hell for this, but yolo.
Optionally, but recommended: lock down Nginx to only allow connections from localhost (127.0.0.0/8 and ::1) if using Cloudflare Tunnels, or Cloudflare IPs if using port forwarding with Cloudflare Access in front.
We used Tailscale to create a VPN network between the desktop and the iPad. The big benefit is that Tailscale works effortlessly across NAT networks without having to open ports,
We used Cloudflare DNS so we don’t need to remember hostnames :),
We used Cloudflare Tunnels to make sure the RPi web interface is accessible across NAT (without port forwarding) and from anywhere,
We used Cloudflare Acces and locked down access to the right people using ACLs,
We used etherwake running on a RPi to wake up devices that are hibernating or turned off.
And that’s it really.
PS: technically WoL works with WiFi, but when I enabled WoL on the WiFi adapter, the NUC refused to hibernate/sleep for more than a minute, and kept waking itself up. So, there seems to be some kind of trigger in my network that keeps waking it up. Also, not sure if WoL via WiFi would work if the device is turned off (as opposed to sleep or hibernate). I just ended up using ethernet.
PPS: both Cloudflare Tunnels and Tailscale use Wireguard tech in the background, so that's really cool.