Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
110

The Raspberry Pi 5 is no match for a tini-mini-micro PC

from Louwrentius - Solar [alt+shift+b] in technology

I've always been fond of the idea of the Raspberry Pi. An energy efficient, small, cheap but capable computer. An ideal home server. Until the Pi 4, the Pi was not that capable, and only with the relatively recent Pi 5 (fall 2023) do I feel the Pi is OK performance wise, although still hampered by SD card performance1. And the Pi isn't that cheap either. The Pi 5 can be fitted with an NVME SSD, but for me it's too little, too late. Because I feel there is a type of computer on the market, that is much more compelling than the Pi. I'm talking about the tinyminimicro home lab 'revolution' started by servethehome.com about four years ago (2020). A 1L mini PC (Elitedesk 705 G4) with a Raspberry Pi 5 on top During the pandemic, the Raspberry Pi was in short supply and people started looking for alternatives. The people at servethehome realised that these small enterprise desktop PCs could be a good option. Dell (micro), Lenovo (tiny) and HP (mini) all make these small desktop PCs, which are also known as 1L (one liter) PCs. These Mini PC are not cheap2 when bought new, but older models are sold at a very steep discount as enterprises offload old models by the thousands on the second hand market (through intermediates). Although these computers are often several years old, they are still much faster than a Raspberry Pi (including the Pi 5) and can hold more RAM. I decided to buy two HP Elitedesk Mini PCs to try them out, one based on AMD and the other based on Intel. The Hardware Elitedesk Mini G3 800 Elitedesk Mini G4 705 CPU Intel i5-6500 (65W) AMD Ryzen 3 PRO 2200GE (35W) RAM 16 GB (max 32 GB) 16 GB (max 32 GB) HDD 250 GB (SSD) 250 GB (NVME) Network 1Gb (Intel) 1Gb (Realtek) WiFi Not installed Not installed Display 2 x DP, 1 x VGA 3 x DP Remote management Yes No Idle power 4 W 10 W Price €160 €115 The AMD-based system is cheaper, but you 'pay' in higher idle power usage. In absolute terms 10 watt is still decent, but the Intel model directly...
16th Jun 2024

Stay updated

Get a weekly newsletter with the top 5 articles worth reading every week.

More from Louwrentius - Solar

Bose SoundLink on-ear headphones battery replacement

Skip to the bottom two paragraph for instructions on how to replace the battery. I bought my Bose SoundLink on-ear Bluetooth headphones for 250 Euros around 2017 and I really like them. They are small, light, comfortable and can easily fit in a coat pocket when folded. Up until now (about 7 years later) I have replaced the ear cushions in 2019 (€25) and 2024 (€18). Early 2025, battery capacity had deteriorated to a point where it became noticeable. The battery was clearly dying. Unfortunately these headphones aren't designed for easy battery replacement: Bose hasn't published instructions on how to replace the battery, doesn't offer a replacement battery and hasn't documented which battery type/model is used. The left 'head phone' has two Torx security screws and most people won't have the appropriate screwdriver for this size There is soldering involved I wanted to try a battery replacement anyway as I hate to throw away a perfectly good, working product just because the battery has worn out. Maybe at some point the headband needs replacing, but with a fresh battery, these headphones can last another 7 years. Let's prevent a bit of e-waste with a little bit of cost and effort. Most of all, the cost of this battery replacement is much lower than a new pair of headphones as the battery was €18 including taxes and shipping. Right to repair should include easy battery replacement Although my repair seemed to have worked out fine, it requires enough effort that most people won't even try. For this reason, I feel that it should be mandatory by law that: Batteries in any product must be user-replaceable (no special equipment or soldering required) Batteries must be provided by the vendor until 10 years after the last day the product was sold (unless it's a standard format like AA(A) or 18650). Batteries must be provided at max 10% of the cost of the original product The penalty for non-compliance should be high enough such that it won't be regarded as the cost of doing business For that matter, all components that may wear down over time should be user-replaceable. What you need to replace the battery Buy the exact battery type: ahb571935pct-01 (350mAh) (notice the three wires!) A Philips #0 screwdriver / bit A Torx T6H security screwdriver / bit (iFixit kits have them) A soldering iron Solder Heat shrink for 'very thin wire' Multimeter (optional) a bit of tape to 'cap off' bare battery leads Please note that I found another battery ahb571935pct-03 with similar specifications (capacity and voltage) but I don't know if it will fit. Putting the headphone ear cushion back on can actually be the hardest part of the process, you need to be firm and this process is documented by Bose. Battery replacement steps I took Make sure you don't short the wires on the old or new battery during replacement The battery is located in the left 'head phone'. Use a multimeter to check if your new battery isn't dead (should be 3+ volt) Remove the ear cushion from the left 'head phone' very gently as not to tear the rim Remove the two philips screws that keep the driver (speaker) in place Remove the two Torx screws (you may have to press a bit harder) Remove the speaker and be carefull not to snap the wire Gently remove the battery from the 'head phone' Cut the wires close to the old battery (one by one!) and cover the wires on the battery to prevent a short Strip the three wires from the headphones a tiny bit (just a few mm) Put a short piece of heat shrink on each of the three wires of the battery Solder each wire to the correct wire in the ear cup Adjust the location of the heat shrink over the freshly soldered joint. Use the soldering iron close to the heat shrink to shrink it (don't touch anything), this can take some time, be patient Check that the heat shrink is fixed in place and can't move Put the battery into it's specific location in the back of the 'head phone' Test the headphones briefly before reassembling the headphones Reassemble the 'head phone' (consider leaving out the two Torx screws) Dispose of the old battery in a responsible manner

25th Feb 2025 • 71 votes
My 71 TiB ZFS NAS after 10 years and zero drive failures

My 4U 71 TiB ZFS NAS built with twenty-four 4 TB drives is over 10 years old and still going strong. Although now on its second motherboard and power supply, the system has yet to experience a single drive failure (knock on wood). Zero drive failures in ten years, how is that possible? Let's talk about the drives first The 4 TB HGST drives have roughly 6000 hours on them after ten years. You might think something's off and you'd be right. That's only about 250 days worth of runtime. And therein lies the secret of drive longevity (I think): Turn the server off when you're not using it. According to people on Hacker News I have my bearings wrong. The chance of having zero drive failures over 10 years for 24 drives is much higher than I thought it was. So this good result may not be related to turning my NAS off and keeping it off most off the time. My NAS is turned off by default. I only turn it on (remotely) when I need to use it. I use a script to turn the IoT power bar on and once the BMC (Baseboard Management Controller) is done booting, I use IPMI to turn on the NAS itself. But I could have used Wake-on-Lan too as an alternative. Once I'm done using the server, I run a small script that turns the server off, wait a few seconds and then turn the wall socket off. It wasn't enough for me to just turn off the server, but leave the motherboard, and thus the BMC powered, because that's just a constant 7 watts (about two Raspberry Pis at idle) being wasted (24/7). This process works for me because I run other services on low-power devices such as Raspberry Pi4s or servers that use much less power when idling than my 'big' NAS. This proces reduces my energy bill considerably (primary motivation) and also seems great for hard drive longevity. Although zero drive failures to date is awesome, N=24 is not very representative and I could just be very lucky. Yet, it was the same story with the predecessor of this NAS, a machine with 20 drives (1 TB Samsung Spinpoint F1s (remember those?)) and I also had zero drive failures during its operational lifespan (~5 years). The motherboard (died once) Although the drives are still ok, I had to replace the motherboard a few years ago. The failure mode of the motherboard was interesting: it was impossible to get into the BIOS and it would occasionally fail to boot. I tried the obvious like removing the CMOS battery and such but to no avail. Fortunately, the [motherboard]1 was still available on Ebay for a decent price so that ended up not being a big deal. ZFS ZFS worked fine for all these years. I've switched operating systems over the years and I never had an issue importing the pool back into the new OS install. If I would build a new storage server, I would definitely use ZFS again. I run a zpool scrub on the drives a few times a year2. The scrub has never found a single checksum error. I must have run so many scrubs, more than a petabyte of data must have been read from the drives (all drives combined) and ZFS didn't have to kick in. I'm not surprised by this result at all. Drives tend to fail most often in two modes: Total failure, drive isn't even detected Bad sectors (read or write failures) There is a third failure mode, but it's extremely rare: silent data corruption. Silent data corruption is 'silent' because a disk isn't aware it delivered corrupted data. Or the SATA connection didn't detect any checksum errors. However, due to all the low-level checksumming, this risk is extremely small. It's a real risk, don't get me wrong, but it's a small risk. To me, it's a risk you mostly care about at scale, in datacenters4 but for residential usage, it's totally reasonable to accept the risk3. But ZFS is not that difficult to learn and if you are well-versed in Linux or FreeBSD, it's absolutely worth checking out. Just remember! Sound levels (It's Oh So Quiet) This NAS is very quiet for a NAS (video with audio). But to get there, I had to do some work. The chassis contains three sturdy 12V fans that cool the 24 drive cages. These fans are extremely loud if they run at their default speed. But because they are so beefy, they are fairly quiet when they run at idle RPM5, yet they still provide enough airflow, most of the time. But running at idle speeds was not enough as the drives would heat up eventually, especially when they are being read from / written to. Fortunately, the particular Supermicro motherboard I bought at the time allows all fan headers to be controlled through Linux. So I decided to create a script that sets the fan speed according to the temperature of the hottest drive in the chassis. I actually visited a math-related subreddit and asked for an algorithm that would best fit my need to create a silent setup and also keep the drives cool. Somebody recommended to use a "PID controller", which I knew nothing about. So I wrote some Python, stole some example Python PID controller code, and tweaked the parameters to find a balance between sound and cooling performance. The script has worked very well over the years and kept the drives at 40C or below. PID controllers are awesome and I feel it should be used in much more equipment that controls fans, temperature, and so on, instead of 'dumb' on/of behaviour or less 'dumb' lookup tables. Networking I started out with quad-port gigabit network controllers and I used network bonding to get around 450 MB/s network transfer speeds between various systems. This setup required a ton of UTP cables so eventually I got bored with that and I bought some cheap Infiniband cards and that worked fine, I could reach around 700 MB/s between systems. As I decided to move away from Ubuntu and back to Debian, I faced a problem: the Infiniband cards didn't work anymore and I could not figure out how to fix it. So I decided to buy some second-hand 10Gbit Ethernet cards and those work totally fine to this day. The dead power supply When you turn this system on, all drives spin up at once (no staggered spinup) and that draws around 600W for a few seconds. I remember that the power supply was rated for 750W and the 12 volt rail would have been able to deliver enough power, but it would sometimes cut out at boot nonetheless. UPS (or lack thereof) For many years, I used a beefy UPS with the system, to protect against power failure, just to be able to shutdown cleanly during an outage. This worked fine, but I noticed that the UPS used another 10+ watts on top of the usage of the server and I decided it had to go. Losing the system due to power shenanigans is a risk I accept. Backups (or a lack thereof) My most important data is backed up trice. But a lot of data stored on this server isn't important enough for me to backup. I rely on replacement hardware and ZFS protecting against data loss due to drive failure. And if that's not enough, I'm out of luck. I've accepted that risk for 10 years. Maybe one day my luck will run out, but until then, I enjoy what I have. Future storage plans (or lack thereof) To be frank, I don't have any. I built this server back in the day because I didn't want to shuffle data around due to storage space constraints and I still have ample space left. I have a spare motherboard, CPU, Memory and a spare HBA card so I'm quite likely able to revive the system if something breaks. As hard drive sizes have increased tremendously, I may eventually move away from the 24-drive bay chassis into a smaller form-factor. It's possible to create the same amount of redundant storage space with only 6-8 hard drives with RAIDZ2 (RAID 6) redundancy. Yet, storage is always expensive. But another likely scenario is that in the coming years this system eventually dies and I decide not to replace it at all, and my storage hobby will come to an end. I needed the same board, because the server uses four PCIe slots: 3 x HBA and 1 x 10Gbit NIC. ↩ It takes ~20 hours to complete a scrub and it uses a ton of power while doing so. As I'm on a dynamic power tariff, I run it on 'cheap' days. ↩ every time I listen to ZFS enthusiasts you get the impression you are taking insane risks with your data if you don't run ZFS. I disagree, it all depends on context and circumstances. ↩ enterprise hard drives used in servers and SANs had larger sector sizes to accommodate even more checksumming data to prevent against silent data corruption. ↩ Because there is little airflow by default, I had to add a fan to cool the four PCIe cards (HBA and networking) or they would have gotten way too hot. ↩

14th Sep 2024 • 52 votes
AI is critically important but not for you

Before Chat-GPT caused a sensation, big tech companies like Facebook and Apple were betting their future growth on virtual reality. But I'm convinced that virtual reality will never be a mainstream thing. If you ever used VR you know why: A heavy thing on your head that messes up your hair Nausea The focus on virtual reality felt like desperation to me. The desperation of big tech companies trying to find new growth, ideally a monopoly they control1, to satisfy the demands of shareholders. And then OpenAI dropped ChatGPT and all the big tech companies started to pivot so fast because in contrary to VR, AI doesn't involve making people nauseated and look silly. It's probably obvious that I feel it's not about AI itself. It is really about huge tech companies that have found a new way to sustain growth a bit longer, now that all other markets have been saturated. Flush with cash, they went nuts and bought up all the AI accelerator hardware2, which in turn uses unspeakable amounts of energy to train new large language models. Despite all the hype, current AI technology is at it's core a very sophisticated statistical model. It's all about probabilities, it can't actually reason. As I see it, work done by AI can't thus be trusted. Depending on the specific application, that may be less of an issue, but that is a fundamental limitation of current technology. And this gives me pause as it limits the application where it is most wanted: to control labour. To reduce the cost of headcount and to suppress wages. As AI tools become capable enough, it would be irresponsible towards shareholders not to pursue this direction. All this just to illustrate that the real value of AI is not for the average person in the street. The true value is for those bigger companies who can keep on growing, and the rest is just collateral damage. But I wonder: when the AI hype is over, what new hype will take it's place? I can't see it. I can't think of it. But I recognise that the internet created efficiencies that are convenient, yet social media weaponised this convenience to exploit our fundamental human weaknesses. As shareholder value rose, social media slowly chips away at the fabric of our society: trust. I've sold my Oculus Rift CV1 long ago, I lost hundreds of dollars of content but I refuse to create a Facebook/Meta account. ↩ climate change accelerators ↩

14th May 2024 • 47 votes
How to run victron veconfigure on a mac

Introduction Victron Multiplus-II inverter/charges are configured with the veconfigure1 tool. Unforntunately this is a Windows-only tool, but there is still a way for Apple users to run this tool without any problems. Tip: if you've never worked with the Terminal app on MacOS, it might not be an easy process, but I've done my best to make it as simple as I can. A tool called 'Wine' makes it possible to run Windows applications on MacOS. There are some caveats, but none of those apply to veconfigure, this tool runs great! I won't cover in this tutorial how to make the MK-3 USB cable work. This tutorial is only meant for people who have a Cerbo GX or similar device, or run VenusOS, which can be used to remotely configure the Multipluss device(s). Step 1: install brew on macos Brew is a tool that can install additional software Visit https://brew.sh and copy the install command open the Terminal app on your mac and paste the command now press 'Enter' or return It can take a few minutes for 'brew' to install. Step 2: install wine Enter the following two commands in the terminal: brew tap homebrew/cask-versions brew install --cask --no-quarantine wine-stable Download Victron veconfigure Visit this page Scroll to the section "VE Configuration tools for VE.Bus Products" Click on the link "Ve Configuration Tools" You'll be asked if it's OK to download this file (VECSetup_B.exe) which is ok Start the veconfigure installer with wine Open a terminal window Run cd Enter the command wine Downloads\VECSetup_B.exe Observe that the veconfigure Windows setup installer starts Click on next, next, install and Finish veconfigure will run for the first time Click on the top left button on the video to enlarge These are the actual install steps: How to start veconfigure after you close the app Open a terminal window Run cd Run cd .wine/drive_c/Program\ Files\ \(x86\)/VE\ Configure\ tools/ Run wine VEConfig.exe Observe that veconfigure starts Allow veconfigure access to files in your Mac Download folder Open a terminal window Run cd run cd .wine/drive_c/ run ls -n ~/Downloads We just made the Downloads directory on your Mac accessible for the vedirect software. If you put the .RSVC files in the Downloads folder, you can edit them. Please follow the instructions for remote configuration of the Multiplus II. Click on the "Ve Configuration Tools" link in the "VE Configuration tools for VE.Bus Products" section. ↩

4th Mar 2024 • 77 votes

More in technology

Clothes Rail

[Misc] Tubular

2 days ago • 1 votes
List of Vim forks

Here are the Vim forks I know about: Neovim: “a Vim-based text editor engineered for extensibility and usability, to encourage new applications and contributions.” Vim Classic: “a stable, long-term support fork of the ubiquitous text editor, maintained without the assistance of generative AI tools.” EVi: “a hard-fork of Vim v9.1.0 (Jan 2024) before AI was used in the project.” MacVim: “a macOS version of the Vim text editor, providing a graphical user interface for Vim, while tightly integrating with macOS and providing features specific to the platform.” This list doesn’t include Vim-inspired editors like Kakoune, Vim-style plugins for other editors like IdeaVim, or Vim “distributions” like LazyVim. Contact me if you know of other forks!

2 days ago • 1 votes
iOS 27 has some weird Dynamic Island behavior

Thought I’d make a quick blog post about some weird behavior I’m seeing on iOS 27 and Dynamic Island live activities, that I initially thought was restricted to the Duo, but turns out affects everything. Yay. Maybe this post can save some others some time, and hopefully Apple can fix it. Long story short, ever since iOS 16.1 introduced “Live Activities”, where we can display handy little widgets in the Dynamic Island, there’s been a bunch of different configurations for showing things up there: something on the left, the right, when expanded, when two apps are showing things and yours gets a bit smaller, and on the lock screen. One interesting one is if you only need to show a small indicator in the Dynamic Island (screen recording indicator, electric vehicle charging status, etc.) you can do so, which just shows on the left on older iPhones, and on the Duo a single one below the camera cutout. Apple describes how to do this in their developer documentation (emphasis added): If you can’t find a solution to display views for leading and trailing compact presentations with limited width, provide a compact leading presentation that best represents your Live Activity, such as the view you use for the minimal presentation, and an empty view for the trailing compact presentation. The system hides the empty trailing view automatically. Unfortunately, in iOS 27 (and 27.1, and 27.2), this only half works, due to a new addition in iOS 27: isDynamicIslandLimitedInWidth. It’s a variable that basically tells you if the Dynamic Island is even narrower than normal, presumably because they knew the Duo was coming with its vertical Dynamic Island, but also because as of iOS 27, Live Activities now show in the Dynamic Island when the device is in landscape too. So it’s handy to know if you have a bit less space than usual. In this new narrow view however, it seems like they didn’t test all the configurations thoroughly, as if you provide EmptyView for that trailing compact presentation, it’s not empty at all, and in fact enforces a quite large minimum size so the Dynamic Island looks hilariously tall. In other words: The system hides the empty trailing view automatically Left: what it should look like. Right: reality You can imagine this is especially rough on the Duo, where navigation buttons, toolbar buttons, tab bar buttons, etc. are all competing for precious space on the right. But that’s only half true. It displays perfectly fine (hiding it) when isDynamicIslandLimitedInWidth is false (AKA how it always used to be), but in the new cases where it can be true, like the Duo and iPhones in landscape, that’s when it breaks. So tl;dr: In iOS 27, Dynamic Island Live Activities are improperly sized if you use the listed EmptyView configuration and isDynamicIslandLimitedInWidth is true. This makes it especially bad on the Duo, womp womp. Complications Now, you might be saying “That’s weird, I haven’t seen that behavior! This is nothing but hogwash!”. But it is not hogwash, just a little complicated. There’s basically three categories of apps. Apple apps Maps, for instance, displays this single, small Dynamic Island live activity perfectly well and sized, and has been beautifully compiled with the iOS 27.2 SDK. By all accounts it should show this bug, too! Apple apps don’t have to use the same APIs as us normies, so funnily enough through really cool tools like REA we can disassemble the iOS Simulator and see that it’s in fact true, the Apple Maps live activity just completely bypasses WidgetKit and instead just renders plain UIKit through MapsBannerViewController which shows the cute little cyan widget through a ManeuverAccessoryView and then for the hidden trailing view simply returns a DistanceAccessoryView with CGSizeZero, which iOS actually respects, unlike our paltry SwiftUI EmptyView. Third-party apps NOT updated to iOS 27 If your app hasn’t been compiled with any of the iOS 27 SDKs, it only knows about iOS 26, and thus doesn’t know about (or have to worry about) the new, troublesome isDynamicIslandLimitedInWidth property, so it just… displays perfectly well. Here’s the Rivian app, which hasn’t been updated for iOS 27 yet, which shows the Live Activity displaying perfectly sized on the Duo (indicating vehicle charging): (Technical disassembly detail for the nerds: iOS shows the app’s minimal config, a smaller config normally used when multiple apps are in the Dynamic Island together, rather than the normal compact config, so it bypasses this issue entirely.) Developers who updated their apps for iOS 27 Surprise! That picture from before? On the left is just me compiling with the old 26 SDK that works! Unfortunately if you are a good developer who updated their app for iOS 27 and all the new features, you kind of get punished through this bug, because your live activity displays the improperly sized way described above, and you can’t just use raw UIKit like Apple. So you’re kinda stuck where I am: do I ship a weirdly sized Dynamic Island experience for everyone? Do I shove something extraneous in the compactTrailing spot just so it doesn’t look as empty? Do I not update the app at all until Apple fixes this bug? Widgets are techincally a separate extension from your main app, so you could compile them with a different SDK (26) than your main app (27) which fixes this bug, but I’m not sure Apple approves of that. Apple On the bright side hopefully it’s an easy enough fix, treating EmptyView like you used to on iOS 26 and per the documentation (the part that is weirdly right beside the mention of the new API that introduces this craziness in the first place). Radar/feedback assistant ID: FB25301955 Easy reproduction code if you’re curious: import ActivityKit import SwiftUI import WidgetKit struct CircleAttributes: ActivityAttributes { struct ContentState: Codable, Hashable {} } struct BlueCircle: View { var body: some View { Circle() .fill(.blue) .frame(width: 20, height: 20) } } @main struct CircleLiveActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: CircleAttributes.self) { _ in BlueCircle() } dynamicIsland: { _ in DynamicIsland { DynamicIslandExpandedRegion(.center) { BlueCircle() } } compactLeading: { BlueCircle() } compactTrailing: { EmptyView() // pls respect me } minimal: { BlueCircle() } } } }

2 days ago • 1 votes
Going Somewhere

Vicky, driving me home from O'Hare, got sixteen dollars for the best conversation I had in months. The last line is hers.

5 days ago • 1 votes
An AI usage statement for bryanbraun.com

I’ve had “AI usage statements” in the back of my mind ever since I read Ethan Marcott’s blog post sharing a round-up of his favorite ones. I didn’t consider writing one for this site, since it had the smell of status-signaling. Like a quasi-political declaration of allegiance to some sort of in-group (be it pro-AI, anti-AI, etc). I couldn’t be less interested in that.1 But then something happened that caught me completely off-guard. I was reading a post on my friend’s personal blog. This was a guy that I knew personally and looked up to. I’ve been reading everything he had been writing for years. About two-thirds of the way through a long (and fairly insightful) blog post, I had a sudden realization that the post had been written by AI. I’m not the best at detecting this kind of thing, but once I saw it, I couldn’t unsee it. It was unmistakable. And the thing is, I didn’t feel indifferent or even disappointed, as I might have predicted. I felt betrayed. For somebody who considers themselves open-minded—even optimistic—towards the development of AI, I didn’t know where this feeling was coming from. I have theories… maybe it has something to do with the social contract between the writer and the reader. Whatever it is, I didn’t want anyone who was reading my blog (hi mom 👋) to feel the same thing. So for the sake of transparency, here is my AI usage statement: The content of this website is written by me. I do not use AI to generate the text you are reading because writing from scratch helps me process my thoughts (which is one of the main reasons I blog in the first place). I don’t currently use AI-powered writing tools (grammar-check, spell-check, dictation tools, etc), but I may experiment with them as long as they don’t undermine the thinking process. The code for this website was originally hand-written, but I have since used AI to make several useful updates. I expect to continue using AI to write code for this website and other personal coding projects. When I create a public project exclusively with AI, I mention that fact in the project README.2 I am experimenting and my AI usage may change. When it does, I’ll update the policy here on my /about page, which is where it will live long-term. To explain why, see Paul Graham's Keep your Identity Small. ↩ For an example, see s-tier ↩ Thanks for reading this post via RSS! Let me know your thoughts by leaving a comment on the original post or sending me an email.

6 days ago • 1 votes
📚 BoredReading

You seem to be enjoying this.

Join free to unlock everything.

Create free account

Already have an account? Sign in