N.B. This is an old version of this document, archived for posterity. The main document is at README.md.
Like so many of us, I was sick and tired of being constantly tracked and monitored by Big Tech. But it was very much Rob Braxman's videos that got me started on actually doing something about it, so big thanks to him for that.
Midway through, I decided to document the project in this manner, both for myself and for anyone who might find it useful in any way. Some of it is very specific to my particular phone model, but much isn't.
This is no longer an ever evolving document.
I use a Samsung Galaxy S9 (codename starlte
). My most used Google apps on it were probably Keep, Youtube[*], and Drive. I host my own email since many years back, but I used the Gmail app to access it. I used Google Calendar, albeit with another app as frontend. And yes, I also synced my phone's photos with Google Photos. :-/
When backing up my computers, I also used Drive for storage; however, the files I sent were already encrypted by Duplicati, so at least I had some sense. And of course I use Firefox for browsing, and Duckduckgo for searching (only downsides: Google's image search is admittedly better[**], I can't seem to get rid of all those search results in Chinese, and the name "Duckduckgo").
[*] No, I will not spell it "YouTube". That is not how names are written.
[**] Edit: Not anymore; it seems they have fucked it up with some "Google Lens" nonsense.
My first choice was LineageOS. However, I soon learned I would need MicroG in order to receive push notifications and such stuff ... I think. My understanding of this is a bit patchy. Anyway, vanilla LineageOS does not include MicroG, the LineageOS for MicroG project doesn't have any builds for my phone (also, their site was down at the time), and I didn't want to make the installation more of a hassle than necessary (I don't really have a backup phone should I brick my current one).
Solution: I went for the impossibly named LineageOS fork /e/ (which I will henceworth refer to as "E", because that is how names are written).
I found that the E "easy installer" software actually worked like a charm with my device; check here to find out if it's available for yours. Only problem is it insists on encrypting your Data partition, which (as I understand it) makes it impossible for you to root your phone. But that can be fixed afterwards; more on that later.
I also played around quite a bit with manual installation. For this, I mostly followed the instructions here (with some assistance from here). I will now detail the process I ultimately landed upon:
Install Heimdall (specifically for Samsung phones) and adb.
Download:
- Custom recovery TWRP 3.2.3 for starlte - find a variant for your device here. The reason I didn't go for a later version is it resulted in the error "failed to mount /odm" later on, but your mileage may vary.
- Ramdisk modification stuff to remove forceful encryption and other things: Disable_Dm-Verity_ForceEncrypt_11.02.2020.zip
- Vendor stuff: VENDOR-27_ARI9.zip (specific to my phone model)
- Latest E image ZIP archive for my device; find yours here
- Magisk APK
Rename Disable_Dm-Verity_ForceEncrypt_11.02.2020.zip
to Disable_Dm-Verity_ForceEncrypt_quota_11.02.2020.zip
, because the filename holds significance and this disables disk quota. I honestly don't remember why I decided on this and if it's necessary in any way, but you can read more about it here.
(Also, the "official" guide instructs you to use no-verity-opt-encrypt-samsung-1.0.zip instead. I think this also worked for me, at least in combination with TWRP 3.2.3 (i.e. not the latest version), but that's just not the combination I ended up with.)
Rename Magisk-vXX.apk
to Magisk-vXX.zip
.
Boot to download mode (hold down Volume down
+ Bixby
+ Power
). Run:
sudo heimdall flash --RECOVERY twrp-3.2.3-0-starlte.img --no-reboot
(I don't know if it's always necessary to do this as root, but it was for me.)
Do not detach the USB cable before rebooting now, regardless of that the instructions say. I had some trouble getting it to reboot to recovery at this point; it would insist on rebooting normally, which would overwrite TWRP and render the whole exercise pointless. After some attempts, I discovered it actually worked with the USB cable still attached for some reason.
Power off device (Volume down
+ Power
).
Immediately when the screen turns black: boot to recovery (Volume up
+ Bixby
+ Power
).
IMPORTANT: This is the point of no return. The actions hereafter will wipe all data from your phone.
Now we're in TWRP. Do Wipe > Format Data > type "yes"
. Back to main menu, reboot to recovery again.
Run (with the correct filenames of course):
adb -d shell "twrp mount system"
adb -d shell "twrp wipe system"
adb -d shell "twrp wipe cache"
adb -d push Disable_Dm-Verity_ForceEncrypt_quota_11.02.2020.zip /sdcard
adb -d shell twrp install /sdcard/Disable_Dm-Verity_ForceEncrypt_quota_11.02.2020.zip
adb -d push VENDOR-27_ARI9.zip /sdcard
adb -d shell twrp install /sdcard/VENDOR-27_ARI9.zip
adb -d push e-0.20-o-20220118158074-stable-starlte.zip /sdcard
adb -d shell twrp install /sdcard/e-0.20-o-20220118158074-stable-starlte.zip
adb -d push Magisk-v24.1.zip /sdcard
adb -d shell twrp install /sdcard/Magisk-v24.1.zip
(The adb shell twrp install
commands may also be done directly in TWRP, by selecting Install from the main menu, saving you some tedious copy-pasting of filenames.)
Then, in TWRP: Wipe > Advanced wipe > Data > Repair or change file system > Resize file system
.
Still in TWRP, choose to reboot normally. It will prompt you to install the TWRP app; however, every time I have agreed to do this, the system has refused to start afterwards, so I don't let it do that. But again, your mileage may vary. And if you end up with a non-booting phone after letting it install this app, just look here.
Reboot, and the new OS plus Magisk should now be installed!
E sometimes prompts you to install an OS update, which you of course should. However, this also automatically encrypts the Data partition, making you lose your sweet root privileges. So, whenever it wants to update, here is what to do. Don't forget to uncheck the "install TWRP app" every time you exit TWRP, if you experience the same trouble as me with that one (see previous section).
- Manually back up any images, documents, etc that you want to keep. My preferred method of doing this:
N.B. Don't include the Android directory.
adb -d pull /storage/self/primary/Pictures . adb -d pull /storage/self/primary/Documents . etc.
- Boot to recovery a.k.a. TWRP (
Volume up
+Bixby
+Power
) - Do a backup of the Data partition, preferably to external SD card
- Reboot and let it upgrade and encrypt
- Reboot to recovery; E will probably have installed its own recovery now, just to fuck with you; in that case, reinstall TWRP:
- Boot to download mode (
Volume down
+Bixby
+Power
) - Run
sudo heimdall flash --RECOVERY twrp-3.2.3-0-starlte.img --no-reboot
- Boot to recovery again (
Volume down
+Power
, thenVolume up
+Bixby
+Power
) - This should land you in TWRP
- Boot to download mode (
- Wipe Data partition, possibly you need to reboot once more
- Re-install Magisk:
adb -d push Magisk-v24.1.zip /sdcard
- In TWRP, push Install and install this file
- Re-install ramdisk modification:
adb -d push Disable_Dm-Verity_ForceEncrypt_quota_11.02.2020.zip /sdcard
- In TWRP, push Install and install this file
- Restore backup of Data
- Reboot
- Restore backup from (1):
adb -d push Pictures /storage/self/primary/ adb -d push Documents /storage/self/primary/ etc.
- You're now updated and rooted! \o/
- Optional step: Remap the Bixby button
- Gmail -> K-9 Mail (simple because I really don't use my Gmail address for other than junk, and don't need to sync it on my phone; there probably is a way to do this, but I haven't bothered looking into it)
- Youtube -> Newpipe (with migration of my subscriptions etc via Google Takeout)
- Maps -> Osmand (I use the the map source "OsmAnd (online tiles)", which I think looks nicest. Unfortunately, app settings seem to reset after OS update, so make sure to back them all up as soon as you're satisfied with them)
- Google Authenticator -> AndOTP
First choice for us RMS wannabes is of course F-Droid.
For non-FOSS apps, I just use the preinstalled App Lounge application, where it seems you can access all of Play Store's apps anonymously, including my local Swedish services such as Swish and BankID (which work flawlessly, BTW). There are some annoying graphical bugs still, but basically it works fine.
I started out by installing a basic CalDAV server on my trusty Raspberry Pi. But then I realised I wanted to try out that Nextcloud thing everybody is raving about, so I installed that too on my poor Pi (with much help from this page, as I was already running Nginx). Not surprisingly, it runs a bit sluggish, and large imports tend to require some retries and also increasing the server timeout limits. But for my humble needs, it will probably suffice. Importing the .ics
file exported from Google Calendar was a breeze IIRC. On the phone, I just use E's preinstalled fork of the Etar calendar app.
I love lists; nay, I need lists. For all kinds of lists and short notes, I have been using Google Keep. I tried out a bunch of open source alternatives, but the one I landed on is Carnet. It looks like a more beautiful Keep and has all the features I want. Also, I can sync it with the Nextcloud I already installed, as well as import my old Keep items (via Google Takeout again) using their Nextcloud web app. The only major downside is that after clearing and restoring the Data partition, which I do when updating the OS, it tends to throw all my notes in the trash and behaving as a new install, forcing me to manually recover my old notes! But this is a nuisance at most.
I wasn't really satisfied with Carnet, so I set about creating my own note/checklist app, called Retain. It is open source, can sync its data via Nextcloud, SFTP, or Dropbox, and is available here. Please note that it's in beta. Already works good enough for me, though!
The downside of Nextcloud is of course that you have to host your files yourself, or rely on there existing a Nextcloud integration with your cloud storage provider of choice (and the supply of such integrations honestly leaves a lot to be desired). So, as I neither want to invest in a NAS (plus the fact that backups should really be hosted off-site), nor want to settle for Dropbox or Onedrive, I decided to outsource the "file storage" part of my cloud solution to Mega, who offer end-to-end encryption as well as native Linux (including Raspbian!) clients.
The only major downside is that there isn't a really efficient and reliable way to mount my Mega files as a local directory. The Mega CMD utils include tools to serve your files via WebDAV and FTP, which in turn enables you to mount using davfs2 or CurlFtpFS, respectively. But the WebDAV solution has been a bit janky for me, sometimes refusing to work because of filenames with some weird characters, and the FTP alternative is in beta and has also been a bit buggy for me.
The Mega SDK source code includes an example implementation of a FUSE module, but it's extremely basic and does not implement any caching. This makes transfers way too slow for usages such as video streaming. I have actually been working on my own FUSE module, but as my C++ skills leave a lot to be desired, the future for this project is uncertain.
This is probably where it makes the most sense to use open source software, since this app literally sees everything you type. Here is also where I ended up sinning, as Swiftkey is simply too damn good for me to switch, and none of the FOSS keyboards were to my satisfaction. But I did try!
Openboard looks to me like the best alternative, although Florisboard shows great promise.
The Openboard versions in the app stores didn't have a Swedish wordlist, though (although this may have changed by now). To get that, you either need to build the app from source or trust one of the user built packages (which you probably shouldn't).
I regularily used my Chromecast device for listening to music and watching video. This is obviously out of the question now, as casting to Chromecast requires proprietary Google services (with the exception of VLC, which somehow manages to do it anyway?!). I replaced it with a Raspberry Pi, on which I installed OSMC, which allows me to painlessly stream Netflix, Youtube, and local videos with Kodi, while at the same time offering the freedom and familiarity of a Debian installation. I control it from my phone using Kore.
In order to run Spotify on this Raspberry Pi, use Raspotify, which is a thin wrapper over Librespot:
sudo apt install curl apt-transport-https git python
curl -sL https://dtcooper.github.io/raspotify/install.sh | sh
Now edit /etc/raspotify/conf
with your account credentials and other settings to your liking. Then, to make librespot run as a daemon on startup, copy this to /etc/init/raspotify.conf
:
description "Daemonized librespot"
start on net-device-up
stop on runlevel [!2345]
respawn
script
set -a
. /etc/raspotify/conf
exec /usr/bin/librespot
end script
Your Raspberry Pi should now pop up as a device in your Spotify clients. Works like a charm for me (except for one issue that showed up in summer 2022):
My phone is one of those equipped with an extra button, originally hardcoded to invoke Samsung's stupid Bixby assistant. I used to reassign it however I wanted (specifically, short press: play/pause media, long press: "do not disturb" on/off, double press: flashlight on/off) with the brilliant BxActions, but apparently, this requires the Bixby software to be installed, which it's not now (nor would I want it to be). I ended up manually re-mapping the button to toggle playing/pausing media, which is what I mostly wanted it to do. Here is a little shell script I wrote to accomplish this:
#!/bin/sh
# N.B: DON'T USE THIS VERBATIM ON YOUR DEVICE! ONLY FOR INSPIRATION.
adb -d root
adb -d remount
adb -d shell "cd /system/usr/keylayout && cp gpio_keys.kl gpio_keys.kl.backup"
adb -d pull /system/usr/keylayout/gpio_keys.kl ./
grep -q '^key 703' gpio_keys.kl
if [ $? -eq 0 ]; then
# key found
sed -i 's/^key 703.*$/key 703 MEDIA_PLAY_PAUSE/' gpio_keys.kl
else
echo 'key 703 MEDIA_PLAY_PAUSE' >>gpio_keys.kl
fi
adb -d push gpio_keys.kl /system/usr/keylayout/
# Should not be needed, but just for safety:
adb -d shell "cd /system/usr/keylayout && chown root:root gpio_keys.kl && chmod 644 gpio_keys.kl"
# Now reboot the phone.
Basically, it's just re-mapping key 703 (which is the Bixby button) to trigger the MEDIA_PLAY_PAUSE
action. Nothing complicated.
For those instances where you need to use Google services on your computer, I can recommend the add-ons Firefox Multi-Account Containers and Google Container, which will at least keep your Google identity from leaking all over the place.
If Google requires two-factor authentication, you can select the option "Get a verification code from the Google Authenticator app", but use an open source TOTP app instead, like the excellent AndOTP.
This should normally be pretty straight forward:
adb -d kill-server
adb -d root
adb -d shell
(I add the -d
to make it work on the USB connected device, as I also have an emulated phone created in Android Studio.)
However, this normally results in this happening for me:
klaatu@jacob:~/e$ adb -d root
* daemon not running; starting now at tcp:5037
* daemon started successfully
restarting adbd as root
timeout expired while waiting for device
Solution: Go to Settings -> System -> Developer options on the phone, disable Android debugging and immediately re-enable it. adb -d shell
is now working.
Letting TWRP install its "official TWRP app" makes my phone refuse to boot for some reason. If this is the case for you, just follow these instructions for a really crude uninstall:
- Boot to recovery a.k.a. TWRP (
Volume up
+Bixby
+Power
) - Mount the required partitions:
- Press Mount
- Press Select Storage -> Internal Storage -> OK
- Select at least the System and Data partitions
- Make sure Mount system partition read-only is deselected
- Start a root shell using one of these methods:
- On a computer connected via USB, do this to get a root shell:
adb -d kill-shell adb -d root adb -d shell
- From the TWRP main menu, select
Advanced
, thenTerminal
- On a computer connected via USB, do this to get a root shell:
- Run
find / -name '*twrpapp*' -print -exec rm {} \; 2>/dev/null
The TWRP app should now be removed and the system able to start as usual. This solutions was found here.
In July 2022, my Raspotify installation suddenly refused to play anything; librespot panicked and complained about "channel closed". I found this issue, which suggested there is some problem with one of Spotify's access points. So I added this to /etc/hosts
on the Pi:
104.199.65.124 ap-gew4.spotify.com
... then restarted the Raspotify daemon, and it works again.