Friday, February 27, 2026

TetherFutureNet (dropping support for older Android N versions)

Future versions of TetherFuseNet will bring support for a brand new proxy engine backed by the powerful Netty library. The engine will be opt-in by default at first, only for the brave, but will eventually be made the default engine and then even later become the only engine.

The by-hand written proxy code is decent but struggling to adapt to the modern web with new clients and modern behaviors. Netty is a well supported, battle tested library that should better serve users.

The downside is that the latest versions of Netty ONLY supports Android API 26 and up (Oreo). There are <1% of pyamsoft users stuck on Android 7 and 7.1 (which are just about a decade old at this point), so while this change will largely not impact anyone, it will impact this sub-1-percent group. Sadly, the reality of technology is that the quick pace of the world around us requires the adoption of generally newer and newer technologies.

Going forward all pyamsoft Android applications will require a minimum Android version of Oreo (26), or higher if the required core functionality expects a newer API version. All existing users who are still on Android 7/7.1 can continue to use existing versions of applications, but they can not be supported moving forward.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyamsoftapps@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Tuesday, December 9, 2025

TetherFuseNet

Over the weekend I was informed that the name TetherFi was potentially infringing on a trademark registered by a private company in India.

The company has issued a notification to Google Play, and Google Play has thus restricted TetherFi from being distributed to users in India. This unfortunately will not resolvable until the company that initially issued the takedown will allow the application to be reinstated for distribution in India.

To avoid further market confusion, the TetherFi app will be renamed to TetherFuseNet in the next version.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyamsoftapps@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Tuesday, April 22, 2025

Is This Still On?

Hey there, been a little while.

Life moves fast and sometimes we have less time than we want to for the fun things like projects and open source. And by "we", I mean "me".

I just submitted TetherFi version 54 to the Play Store today, which should bring some additional fixes to the experimental SOCKS proxy mode as well as improving speed and fixing a couple crashes. I plan to have it sit in beta for a bit just because its a larger update. If you are interested in testing, you can join the Open Beta program on the Play Store, otherwise just sit tight. Hopefully 53 is working well enough for now :)

Over the past few months I've been playing around with reproducible setups. I have a dotfiles repository that I recently converted to "install as an ArchLinux package" where the package keeps track of dependencies and installs system files into expected locations. So far, it's pretty nice, though not nearly as advanced (or complex) as something like an Ansible. For now, that's how I like it to be.

I bought a cheap box off of AliExpress to use as a Opnsense router (which would replace a Google Fiber Wi-Fi 5 router that is now 3 years old). Opnsense is super cool, and I had just gotten everything setup (VLANs directly to my Omada AP, IDS and DNS blocklists) when suddenly, the cheap box just refused to boot. Even messing with the CMOS battery did not fix it, it just suddenly, randomly decided to die. Not a nice thing to wake up to, given that the router needs to have 100% uptime in order to achieve maximum Wife-Approval-Factor. For now I've ordered a second box to play around with (from Amazon this time, instead of AliExpress so I have the amazing return policy), and when it gets here hopefully I can make it into something neat again :)

The other night I also tried installing clamav onto my home server to see how it could help keep an eye on files on my server machine, given that the server is used by multiple people and not all files are mine. Well as fate would have it, I had just purchased an external enclosure off Amazon (I think it was a Terramaster) and had just gotten around to sticking an empty IronWolf Pro 12TB inside it. Clamav started scanning, and all was fine, until suddenly, it started hitting my drive at 4500MBps reads, and it did this constantly. Overnight. While I slept. I woke up to two drive alarms and 2 dead drives. RIP my old hard drive, you had served me for 5 years before being unceremoniously killed by clamav.

Needless to say, I have uninstalled clamav for now. I did not realize the configuration would need to be so specific to not cause problems.

Thankfully, I was able to recover most of the drive by copying off of a previous test drive used for setting up an LVM cache. After about a day or so of tinkering around and cp mv over an SSH session, all of the data should have migrated smoothly. I guess, even when your server files are "not important" it's still nice to have backups - but how can you afford large backup drives in this economy!

Anyway, I'm starting to ramble so I will wrap things up here. The tl;dr is, I'm still here but just very busy. I've got updates I want to make, and projects I want to try, and set ups I want to start (Home Assistant!). I've got some now, and more later.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyamsoftapps@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Sunday, November 3, 2024

Fork, Knife, TetherFi

Hey there, been a little bit.

A lot has happened in the world of pyamsoft, so lets get right down to business.

First thing's first, TetherFi is currently in version 49 beta on the Play Store. This release is particularly important as it brings new support for a few cool features:

1. Proxy over RNDIS: A long standing GitHub issue has been finally closed with this release - you can share your TetherFi proxy connection over USB Tethering/Ethernet instead of requiring Wi-Fi to be on and using Wi-Fi Direct. Currently this is an "Expert" level setting, so many people will not need to change it, especially if you do not know what it is. But, if this is a use-case you are interested in, the new 49 when it releases will support this.

2. Proxy over Cellular Data: Other past requests have wished that the proxy connection could use only cellular data while still ensuring that the device stays connected to a Wi-Fi network. With changes in 49 you will now be able to request that proxy connections go over cellular data strictly. To implement this, I had to do some interesting code changes in the KTOR library that TetherFi uses - more on that in a bit.

3. There has also been a long-standing crash issue on the Connection screen in the release 47 that I have been unable to pinpoint - it causes about 5% of users to crash sometimes and leads to instability (and reports from Google in the store Vitals). This release should fix the crash or at least lessen the chances of it occurring - but since I can't consistently reproduce it - who knows. I will keep looking.


Regarding forking KTOR - I have a simple fork of KTOR which applies 2 commits over the latest tagged release version and applies a single 1-line change. It is only supported for JVM, specifically for Android, and I will do absolutely zero support regarding the fork. This single line change added the ability for me to grab a socket BEFORE it was connected but AFTER it was built, so that I could then implement support on the Android side for binding a Socket to a Network connection.

If you are curious, see here and here

Future work on TetherFi will hopefully finally bring support for SOCKS connections. Like HTTP, SOCKS is just another way to connect devices together, but one important difference for SOCKS is that it has "generic" network support for just about anything - including UDP connections. A working SOCKS4/SOCKS4a/SOCKS5/SOCKS5H (at least for connect()) is currently on the developer mode branch for 49 and I look to release a version 50 with full production support. Finally after so many years, progress is being made on this issue

Other software of note these past few months have been the following for Linux systems

pstate-frequency gained support for the new amd-pstate driver's core-boost functionality. On supported Linux kernels (6.11+) you will be able to also set the turbo boost state for AMD CPU using amd-pstate as the driver.

I released iptables-geoblock, which is a simple shell script that uses an xtables DKMS module to block connections from IP addresses based on the country. I use this in my homelab/VPS setup to block connections from any countries that I do not reside in currently - because no legitimate users need access from outside of my friendship circle.

I released poke-monitor which I use on Linux to "wake up" my DP connected monitor after suspend. Before, after suspend, my DP monitor would just stay on a lit up black screen. Linux seems to have weird issues with this for whatever reason, but basically "poking" the monitor with something like xrandr to query the EDID seems to fix it. Though I don't run dual monitors anymore (1 large 34"), it was particularly helpful when I did.

I released adjust-pci-latency which is a micro-optimization tool that collects recommendations from the ArchLinux wiki around performance tuning for PCI devices and ships it as a simple script. You can use it to "finetune" your PCI devices for things like gaming (lower latency) or supposedly even realtime pro-audio production (though I lack the hardware for this and cannot actually confirm this).


Lots more changes in the future, and life gets busier and busier still. More to come.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Wednesday, May 1, 2024

TetherFinally

Hey, it's been a little while.

Back in February I started a new full-time day job, so updates both code and blog have obviously been sparse and slower. I did finally manage to get some stuff released though.

For nerds, PYDroid 27 is published which brings support for Material3 UI. The Material2 days are behind us now, but the M3 widgets are basically the same. Material You is supported but optional.

This new M3 support is best reflected in the newly beta released update to TetherFi, version 41. This version brings full Material3 and Material You support, and adds some new features.

The "Stubborn Proxy" optional tweak is being made default, so it will be On unless you explicitly turn it off. In a future TetherFi version, this tweak will be removed completely, since I believe the option works very well. The "Bind to All Interfaces" tweak has been turned off, and will be removed in the next version, as the default configuration is now faster and more reliable than the tweak was.

One significant feature additional is the ability to track and monitor the amount of data used by connected devices. You will be able to monitor how much data the connected device sends to and receives from the Internet. This feature work is done in preparation of a future feature additional requested by a community member on GitHub to implement Bandwidth limits.

Now that this release is out the door I can continue work on my two other apps, which have still not been released public as I am trying to figure out the final few steps to take them from "cool toy" to actual "production product", which is always the most-fun-but-most-time-consuming step of the process. Having new commitments at a new job doesn't do me any favors here - but I digress.

We'll get there when we get there!

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Sunday, February 18, 2024

Split Up Your bashrc

Have you ever found yourself in this situation?

You add a new line to your .bashrc to use some cool new something, you close your terminal, and then the next time you go to open your terminal, it crashes because something was invalid in your bashrc.

Bummer.

I'm here with a hot take today - you should split your bashrc up into individial "drop-in" config style files instead, so that you can:

1. Have cleanly separated responsibilities in each rc dropin file
2. Avoid killing your entire bashrc because of one bad line.

You can see how I use dropin config files as well as the contents of the dropins here.

By setting up my bashrc, bash_profile, and general environment files using the drop-in style, I can easily maintain and change one part of my configuration without worrying about it effecting another section - kind of like code.

More code stuff someday.
Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Wednesday, February 7, 2024

PXE and XYZ

If you are a giant nerd like I am, you may have dabbled with PXE boot to launch systems off of network devices instead of installing an operating system on to a physical drive.

Nerd.

Anyway, if you manage a fleet of devices all via PXE or you have a virtualized cluster or do whatever else in your lab with a random set of machines, you've probably heard of netboot.xyz. If you haven't you may be making life more difficult than it has to be.

You can set the image up in a container on a central machine, host whatever your custom standard image packages are supposed to be, and then deploy image updates centrally through the xyz delivery so that way you don't need to carry and pass around a USB stick, or deal with mass email chains about what the latest PXE should be.

Plus it's fun.

If you like that kind of thing, you nerd.


Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

TetherFi and the Older Devices

TetherFi supports "old" versions of Android, all the way down to Android N which was released in 2016! As far as developer toolchain is concerned, N is still "new enough" that most modern Android features work.

Recently though I was testing TetherFi on an Android N emulator and noticed that some visual differences made the app a little tricky to use on older versions.

For one thing, the bottom Navigation used in old versions of Android was showing as completely transparent in Light mode! White buttons on a white background are very hard to see. This is because TetherFi requests that the Navigation bar itself be completely transparent, and requests that the Navigation bar paint black icons using the new AndroidX compat edgeToEdge method.

What I didn't notice because I failed to read the documentation, or the documentation failed to note, is that while a Transparent Navigation bar works just fine on old Android N, the black-icon change does absolutely nothing! In the code it is intentionally left blank, a no-op. Thanks AndroidX.

A change in a developer version that should become the future version 41 will make the bar semi-transparent on older versions of Android to account for the fact that the dark icons do not show up.

Similarly, light status icons were not taking effect properly on old versions of Android, and various areas on screen which displayed some "fallback" text for unsupported features were very hard to read.

While modern Android feels like it is now at least Android 9 and above, all pyamsoft Android applications (currently only 1 public one :( ) will continue to support down to Android 7 (N) as long as it is feasibly possible.


The new TetherFi update will hopefully be arriving "soon TM".

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Tuesday, February 6, 2024

Running an OpenRCT2 multiplayer server from a jumphost

So, you want to run an OpenRCT2 server ey?
And you have a cheap remote VPS with a public IP, but you run all your server stuff selfhosted at home with a more powerful machine because VPS costs are bullshit ey?
Well, come take a looksie, here's how I got things to "kind-of-work".

I say "kind of" because there are still some issues, namely:
1. Effectively zero security :(
2. Manual park setup and pause/unpause :(
3. Unusable IP logs because all IPs connect as the VPS from the proxy :(

What I had to start:
1. A public domain name and IP address (I use an AWS Lightsail VPS)
2. Your selfhosting machine (I use a second computer at home)
3. A third, "client" machine to play the game with
4. Patience and some shell scripting ability

What I did to get things working:
1. Purchase Roller Coaster Tycoon 2 on Steam
2. Build a local podman container of OpenRCT 0.4.8 on your selfhosting machine
3. Launch the OpenRCT server using the container on your selfhosting machine
4. Setup a reverse proxy on the VPS and connect it with the selfhosting machine

Let's dive in!


1. A public domain name and an IP address

First you'll need a public IP address and preferably, a world-resolvable domain name. I use AWS Lightsail because they cost 5 dollars a month for Amazon backed unmanaged-hosting (soon to be 7.50 because of IPv4 migration costs). Not an advertisement, but just letting you know what I work with. Debian 12 running on a weak little VPS. I bought a domain name from the Cloudflare Registry, turned off the Cloudflare proxy (because non HTTP traffic through the Cloudflare proxy is against their TOS), and we are off to the races!

2. A selfhosting machine at home
My selfhosting machine is a server box running at home. I run as AsRock DeskMini X300 that I've wired into the wall with Cat 5, and swapped the Wifi card out for an Intel AX210. Running on a Ryzen 5600G that I've TDP limited to 35W. Again, not too important - you are hosting a multiplayer server for a 30 year old game.

3. Buy the game. You'll need Roller Coaster Tycoon 2, which I bought on Steam. Download the OpenRCT2 client as well (the latest at this time is 0.4.8). Make sure the game runs on your machine.

4. Launching the game as a dedicated server.
Ok finally.

So, we are going to spin up a container for the dedicated server, and run the container on our selfhosting machine. To do this, we will first need to build the OpenRCT2 server container, because while OpenRCT2 publishes the image on Docker Hub, it hasn't been updated since 0.4.4 (the latest at the time of writing is 0.4.8)

4a. First you'll need to build the OpenRCT2 container on your selfhosting machine. To do this easily for myself, I've written a small dockerize script, though you can roll your own - whatever gets 0.4.8 in a container on your machine.

4b. Next you'll first need to create a new save. First you'll need to launch the client and start any scenario you want. Immediately save the game. Find the OpenRCT2 game folder on your machine (for me it was in $HOME/.config/OpenRCT2), and copy the saved .park file out of the save directory.

4c. Volume mount the save file to the OpenRCT2 container, and launch the container as a dedicated server, providing it the file to your park. For this, I use a runner script.

4d. At this point your dedicated server should be running. You can test it by launching the game client, and clicking the "Add Server" button, providing localhost as the server address.

4e. You might notice when you connect that your game is paused. In order to unpause the game, you'll need to type into the openrct2> console in the container that is running (you allocated a PTY and attached stdio didn't you?), and issue the command context.executeAction("pausetoggle", {});

4f. You may also notice your connected player joins as a "Spectator", unable to do anything. To fix this, you need to grant your player admin level access to the Scenario, by running network.players[1].group = 0 in the openrct2 container console.

5. Opening the server to the world for others to join you
What's multiplayer without other players? This is the "port-forwarding" step, but a bit more complex.
You'll need a way to proxy raw TCP traffic from your VPS machine to your selfhosted machine. This was a little tricky for me, as I run Caddy for HTTP related proxy stuff, but Caddy doesn't speak raw TCP (it's a layer thing), so I needed something else. I decided to use frp.

5a. Run frps on the VPS

5b. Run frpc on the selfhosted machine

5c. Open the OpenRCT2 port on the firewalls for both the VPS and the selfhosted machine.

5d. At this point, you should be all done! Go into the OpenRCT2 client, and this time add a server using your VPS domain name. You should be able to connect!

--
To recap, here is what I run when starting my OpenRCT2 server

On the VPS
$ systemctl --user start frps@openrct2

On the selfhosted machine
$ systemctl --user start openrct2-server@my_save_file.park
$ systemctl --user start frpc@openrct2-server
$ podman attach openrct2-server
openrct2> context.executeAction("pausetoggle", {});
openrct2> network.players[1].group = 0


Some shortcomings are:
1. Zero security. Any person in the world can connect to your VPS now at the OpenRCT2 port and get access to your multiplayer game if they know/guess the password. Security at this point is left up to OpenRCT2, and being as it's a video game, security is not a first priority per-se.

2. No way to know the IP of the client connecting to your server. All player IPs in the openrct2 logs will come over as your network interface IP, since connections are being proxied through fprs and frpc, and OpenRCT2 itself does not have support for the PROXY TCP protocol. No way to know which IP is doing what because of this.

3. Despite using the "pause when empty" config option, your server always seems to start permanently paused, and does not pause the game when you leave. You'll need to manage pause/unpause state yourself, so it's not a "fully set and forget" style setup just yet.



Get out there and put people on Mr. Bones Wild Ride.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Saturday, February 3, 2024

Hardening Tailscale on a Modern System

Tailscale is cool, and it provides a guide to harden a modern system with some additional security practices here. One tiny problem, its for Ubuntu.

As superior Archlinux users, we need updated instructions for hardening stuff - so here it is.

1. Create a tailscale user
# useradd --no-create-home --user-group --shell /bin/nologin tailscale

2. Add the polkit rule to allow the tailscale user to change DNS settings
// Polkit rules are written in Javascript. LOL. Assume ES5
polkit.addRule(function(action, subject) {
  var isValidGroup = subject.isInGroup("tailscale") || subject.isInGroup("wheel");
  var isValidAction = action.id.lastIndexOf("org.freedesktop.resolve1.", 0) === 0;
  if (isValidGroup && isValidAction) {
    return polkit.Result.YES;
  }
});

3. Apply systemctl override to tailscaled.service
# https://tailscale.com/kb/1279/security-node-hardening
[Service]
User=tailscale
Group=tailscale

DeviceAllow=/dev/net/tun
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_MODULE
ProtectKernelModules=no
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
NoNewPrivileges=yes
PrivateTmp=yes
PrivateMounts=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
MemoryDenyWriteExecute=yes
LockPersonality=yes
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelLogs=yes
ProtectSystem=full
ProtectProc=noaccess
SystemCallArchitectures=native
SystemCallFilter=@known
SystemCallFilter=~@clock @cpu-emulation @raw-io @reboot @mount @obsolete @swap @debug @keyring @mount @pkey


That should give you a "more secure" daemon running as it's own user that drops root and severely restricts access and privs. I also lock down my zerotier-one.service as well, at least with the systemctl override file (not sure about whether zerotier can run under a non-root user, so steps 1 and 2 don't apply yet.)

Stay safe.

Stay tuned!

 ========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Friday, February 2, 2024

amd-pstate and pstate-frequency

pstate-frequency recently released version 3.14.0 which brought support for the new amd-pstate CPU driver, but only in "passive" mode. amd-pstate also supports and "active EPP" mode, which a new testing release for what will become pstate-frequency 3.15.0 supports as of today!

Changes were made to support the new active driver, and brought out support for the new --epp option which lets you change the Energy Performance Preference independent of CPU driver as long as the option is exposed by sysfs.

While the official release of 3.15.0 will not be for a while, if you have a recent (Zen 2 or Intel 11 Gen+) CPU that has support for EPP via ACPI CPPC (most modern processors do), then the latest git development version of amd-pstate will support your CPU with better, more specific options! Support is also added for EPP controls into the power-profiles for pstate-frequency, and it should gracefully fallback if you have an old CPU without any exposed EPP support.

Test today by pulling the latest script off of the Github or by using the -git AUR package. I'll update again when I have a release date in mind, but please be aware that it will not be for a little bit.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Sunday, January 28, 2024

The importance of a network namespace

Docker/Podman/Containers have the ability to put your network interfaces into a "network namespace" that hides them from the outside world, so instead of a container user seeing you have a wlan0 and an enp5s0, they'd see a loopback and a single eth0 fake device that routes to something like 10.0.2.3, which routes to a real gateway interface via a containerized network bridge. Very cool stuff, and generally recommended.

EXCEPT when you are running Caddy, or another webserver, on, oh let's say

A public AWS Lightsail instance...

Why do you ask? Oh, nothing, it's not like I had, for example, a public AWS Lightsail instance taken offline by a bot DDOS attempt or anything - no. Of course not...

When you use the network namespace in this case, all the IP addresses in your logs look like 10.0.2.3, instead of the correct X.Y.Z.A that you would generally want them to be. The reason this is of chief importance, is because nice tools like crowdsec and fail2ban rely on these client_ip addresses being valid to block repeat offenders. By using the network namespace that comes by default in a container, you are missing this information, and thus your important network security is effectively bypassed!

Keep all your other containers in a network namespace, but remember to run your reverse proxy entry point container on the host stack so that it can preserve IP address information for logging and reporting! And remember to test your security by using a VPN to make yourself appear as an attacker. Attempt to break into your own services!

Stay tuned

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Flatpak and You

Flatpak is cool. It seems to be positioning itself as the future of packaging on desktop Linux. But, as with all cool things, there are a few top-of-mind points that you should be aware of, even if nobody actively talks about them.

Your decision tree, when installing a flatpak should be as follows, where failing to answer any step with an emphatic "YES" would stop you from continuing down the chain of application installation.

1. Is this a verified flatpak?
2. Is this verified flatpak published by the developer or a trusted developing community member?
3. Is the project still alive, does the flatpak run on the latest runtime, or have a very good reason for why it's not?
4. Does the flatpak ship with a minimal number of extra libraries outside of the runtime?

If you've answered yes to all the above, then it's safe to install the flatpak via the flathub-verified subset, life is good! This is generally the hardest step, as a poorly maintained flatpak can lack security updates or be too open by default. Generally you'll want to pick projects which official publish builds under flatpak, ideally as the "only" distribution channel, to ensure that they are always maintained to the best of the developer's ability.


If you've answered no, then your decision tree splits under the following:

1. Is the package in my distro's official repositories?
2. Is the package maintained by a reliable third party in the AUR, can I vouch for their ability to script a build and maintain it with reasonable turnaround time?

If you've answered yes, then great, install the package. As far as getting the "flatpak sandbox" style experience, you need to remember that flatpak is not a SECURITY sandbox, it's chiefly a "hide my user-homedir from other apps" kind of sandbox. This kind of low-security/high-convenience sandbox can easily be replicated using "raw" bwrap or things like distrobox if you are so inclined. This option is always second to installing an official flatpak, as flatpak handles all of the security and seperation bits for us and we just need to much around in little override files, as opposed to understanding the intricacies of bwrap itself. Nevertheless, bwrap jailing is better than not jailing at all.


Finally, if bwrap is not a viable solution for your program, you can prevent as much "user-homedir" access as possible by running the app as a second user and setting up a kind of "user-jumphost" script.

--

For general reference, I run almost all of my "daily" applications via verified flatpaks with restrictive overrides

For apps that have no officially verified flatpak, like Android Studio and Webstorm, I run them as bwrap restricted jails via packages from either the distro repositories, or the AUR, which at least allow me to namespace UTS, PID, USERNS, and shadow directories like /var/, /proc, /run, and /tmp. I use my own jail script, that gives me access to X11, Wayland, and Pipewire by default, so that "general desktop usage" is seamless. Sharing files in and out of the jail just requires me to copy or move a file into the jail-home first, which is minimal effort.

And finally, for apps like Steam, which I like to run using gamescope which requires root access to the /tmp/.X11-unix socket location and thus cannot be jailed, I run as a delegated user that has minimal privileges, no sudo access, and is only able to be interacted with to run that specific command. Generally this delegated user is reserved only for very special apps, like gamescope, which create their own nested display servers. Basically every other "normal" app can be bwrap jailed with some configuration.

With a bit of extra configuration and some files in the right places, you can have a system which is nicely compartmentalized! If I need to uninstall or reset a flatpak, I delete it's folder in ~/.var/app. If I need to uninstall or reset a bwrap jailed program, I delete it's folder in ~/.local/etc/jails. And if I need to reset a delegated user style application, I delete it's user and all their related home files. Keeps things nicely separated and running with minimal permission where possible.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Sunday, January 14, 2024

TetherFi Is Stubborn

Some devices run into a weird unexplained problem when trying to launch the TetherFi hotspot - the Broadcast starts up fine but the Proxy hits a random unexplainable "Invalid argument" error and fails to start.

According to the internet and the ktor source code in examples, the proper way to handle this, is to not handle it, ignore it, and try again. So okay, fine. TetherFi now has support for an optional mode called "Stubborn Proxy" which, when it sees this "Invalid Argument" error, will ignore it and simply try again. If it fails to start 10 times in a row, then we consider it truly a problem and stop, but for devices which just have single time random failures, this change should allow them to launch the proxy.

Various bugfixes in bound for the first release of 2024, version 40! It will enter Alpha on the store in a few days time and hopefully hit a wide public release sometime later this week.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Thursday, January 4, 2024

Trickle Just Never Catches a Break

Trickle is sadly dead dead this time around :(

It's a long and technical explanation so brace yourself - but the tl;dr of it all is:

Trickle will sadly be unable to function reliably enough on Android 14 and beyond. As such, I do not feel comfortable continuing to publish it as I do not believe it upholds the high standard of performance and reliability that I have set for myself. As of today Trickle is unpublished from the Play Store and is no longer maintained or supported. Sorry!

Android 14 changes various bits and pieces of how the system works - but the war on "background work" continues. Google has this time around changed things so that

1. Any process that runs in the background that expects a "reliable" level of regular activity needs to declare itself a Foreground Service.
2. Declaration of an FGS requires you to fill out a Google Play Store policy document for your service (this was, for example, done for TetherFi, which was able to get approval because it fit into a pre-defined Google category for "allowed Foreground Services", but Trickle does not).

The two problems with this were that - Trickle would never be approved for FGS policy, and running the service as a foreground priority would actually end up using more battery than the service saved - so from day 1, using Trickle as a long-running foreground service was a "no-go" solution.

Back in July, some changes were made to how the Trickle service was used that allowed it to run reliably in the background without needing to declare itself a Foreground Service. At the time, I thought this would be a long term solution, and that would be the end of the worries about future version compatibility.

In October, Android 14 released and with it came one important implementation change regarding cached processes. To avoid a long technical talk, on Android 14+, when your app is NOT a foreground service, and your UI is not open, the operating system "suspends" your app and all of its services until you re-open the UI again. This "suspend" window is generally unfixed, but can be anywhere between 30 seconds and 10 minutes. Basically, after 30 seconds of not being an open UI on screen, Trickle would stop receiving the system screen-off and screen-on events, and would therefore not be reliable any longer. Any potential solutions to this problem would generally use more battery than they saved, and thusly, it is infeasible to continue Trickle development further given that the future direction of Android seems to only be continuing to lock itself down regarding these "background service" style applications.

A sad day, but a day I had known would come eventually, and it seems like despite my initial excitement for it back in July, the reality of the October release brought back my original fear.

Trickle is sadly gone, and probably for good this time. Unless the big G decides to publish an API specifically for apps like these, there are no reasonable alternatives. A sad day.

TetherFi continues to be fully supported and the next release (40) will even include some performance improvements and hopefully improve compatibility with various devices, particularly those running on Android 14.

Stay tuned!


========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Sunday, October 1, 2023

Security By Obscurity

Came across this post on the socials the other day which described a trojan attack on unix-like systems which stole sensitive tokens like SSH and cryto private keys.



What stuck out to me about the script that harvested information, was that it only looked in hardcoded, default paths. It wouldn't be able to attack your firefox data, for example, if you used a Firefox flatpak which stored it's data in .var/app. It wouldn't be able to extract your .profile or .bashrc, if your profile contained only a single line to source ~/.config/profile in it, instead of real contents. If your ETH tokens were held in ~/.cryptowallet/eth instead of the standard location, nothing could be stolen.

It speaks to how a simple obscure change like "changing the default storage location of a program" can sometimes help you avoid very simple attacks.

Is something as stupid as changing a default storage location the panacea to supply chain attacks or a replacement for proper security sandboxing? No.

But I guess it's better than nothing.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Tuesday, September 12, 2023

Selfhosting with a Jump Point

Long, nerdy, nerd post alert.

In my spare time I like to program.
But in my other spare time I like to - well - mess around with hosting random media services on a spare computer and broadcasting them out online. I know. So cool. So sexy.

My online-hobby is what's called "selfhosting" which is a fancy way of saying instead of paying 15 dollars a month for a Netflix subscription that I can't share outside of my house, I pay 10 dollars a year for a domain name and 3 dollars a month for a Virtual Private Server (VPS) that I can connect to anywhere.

Now, if you've never dabbled in VPS or cloud hosting or Amazon Web Services (AWS) or any of these hyper-nerd things, the only thing you need to know is that cloud hosting is very very expensive. We're talking every time you type a letter on your computer, Amazon is billing you for the amount of CPU time you are spending. These bills add up fast, when you are using your VPS on AWS to do things like host websites or store media like Big Buck Bunny and Linux ISOs.

To offset these ridiculous costs, if you have a spare machine laying around like I do (oh we privileged few), then you could run all of these media services on this spare machine and just have it do all the work instead of paying Amazon. This is called hosting your own server! Look at you go! You can put media and files on your server and then access it from any other computer at home. And when you go outside and want to access stuff on your phone, you can port-forward on your router and share your server with the Internet - which will get you immediately hacked and DDOSed, and your ISP will shut you down and now you don't have any Internet at home anymore. Fun. Realistically, exposing your machine directly to the world via a port-forward on your router just isn't going to work. It's horribly insecure and one DDOS attack can take down your entire home network. We need something slightly better.

--

Our solution has to meet three minimum constraints.

1, it needs to be accessible to you outside of your physical home (or your virtual home network). What's the point of having all these movies on a computer if I can't actually watch them on anything except the actual computer when I'm sitting next to it at home. I want to be able to login, just like someone would login to Netflix, and watch the media I've curated (so many copies and variations of Big Buck Bunny).

2, exposing the server to the Internet should not immediately make us susceptible to being hacked. Basically, the server running should not expose our home network directly as an attack vector.

3, low cost.

First off, let's actually tackle point number 3, the low cost. To reduce cost, instead of using a platform like Google Cloud or Amazon AWS, I strictly run all of my services and hosting on my spare server machine. I own all the data, I buy hard drives for storage, I directly manage the machine. This does require a little (a lot) of Linux knowledge. While this reduces the cost in raw dollars, it does come at a cost of my time both learning and maintaining stuff. Now since this is a hobby I don't mind, the goal is to reduce dollar cost. But be aware that self hosting can cost significant time and lose you significant points on the "Partner-Approval-Scale". Now, on to my self-hosting odyssey. 


-- Part 1: The Tunnel

I started my self-host journey spending 0 dollars and giving out 0 credit card information, by using Freenom for a domain name and Cloudflare Tunnels for access. Freenom was, at the time, a legit enough website that would give me a free domain name like "hellothere.tk". I was able to switch the domain DNS to Cloudflare for their additional security and global network via Cloudflare Free Tier. Then I used Cloudflare Tunnels so that all of the programs running on my local machine could be shared out over this domain name. It was a fully working, globally accessible setup that cost me 0 dollars to maintain. Cloudflare Tunnels made sure that I was not directly exposing my home network onto the Internet, which kept me relatively secure. The setup met all the requirements  (1, 2, and 3), and was fast enough to stream Big Buck Bunny to a laptop across the ocean with relatively little lag. Great!

The problem with the setup though, was that "technically" Cloudflare Tunnels only let you host normal websites. They don't let you do things like send video streams or host game servers. Just normal, look at my blog, boring old static websites. I say "techincally" because the only thing actually stopping you from streaming media over the tunnel was that it went against the Cloudflare Terms of Service. Also the Tunnel connection did have a maximum bandwidth cap of ~100MB, which while fast enough for streaming content, was significantly slower than my Internet 1Gig plan (thanks Google Fiber). I needed a different solution that wouldn't break any ToS agreements and would allow me to use as much of my network connection as possible.

-- Part 2: The Mesh

I had a working setup, but I needed to find something that was a bit more "above board" to feel comfortable. Constraint (3) was handled by my home server. I needed a replacement for (1) and (2) that didn't involve the Cloudflare Tunnel. I temporarily settled on a mesh network VPN setup. Now, TailScale or NetMaker or NetBird or ZeroTier could do this for you, easily, free of charge, effectively "super secure" with the only requirement being that all of your devices have the respective app installed. These apps create a network between your devices, so no matter where you are in the world, your phone can talk to your server running at home via the mesh network. Ezpz, job done. Worldwide access, free of charge, and effectively complete security. 1, 2, 3. End of post, see you next week.

For many people, a private mesh VPN network actually is the end game solution. It covers all three of our requirements, and is free. But what if you want to share this cool website you made with your friend, but you don't want them on your TailScale network, or you just don't want them to have to install an app to access your stuff? Well then there are tradeoffs. Again, we revisit "The Cloud" and the VPS. Which brings us to my current setup and solution.

-- Part 3: The Jump

Now wait, I thought we were self-hosting our stuff? I thought we have this awesome machine sitting in the living room just chugging away at Big Buck Bunny, why would we want to spend money to purchase a VPS? Well, remember our 3 requirements? Port-forwarding your home network accomplishes 1 and 3, but horribly fails the security requirement in 2. Putting all your stuff on a VPS directly accomplishes 1 and 2 but horribly fails the cost-effective requirement of 3. The "nice" middle ground is hosting all your content on your local machine, which is cheap (3), hosting your domain on a VPS which is globally accessible (1) and then bridging the VPS to your self-hosted server via TailScale or NetMaker or NetBird or ZeroTier, which avoids you directly exposing your home network to the Internet, so it's comparably safer (2). This is, I think, called a "jump host" setup.

The general idea of how this works is that you own a domain name, and you point the domain name at your VPS. Your friend connects to your public VPS using your domain name. Your VPS runs only a single program, a reverse proxy (I like Caddy) that forwards your friend from the VPS to your server at home via a mesh network VPN connection that is only accessible to the VPS and your server. This way, your home network is not publicly accessible, except through the controlled routes that you set up on your VPS. Connections from the public Internet "jump" over to your server and then "jump" back out.

Your VPS can be a shit tier machine that costs pennies per month, because all it's doing is running a single program to jump connections back and forth. All you need is a domain name from a registry like Cloudflare's (which is a yearly payment of like 10 bucks unless you want a very popular name). You can even cut costs even more using things like Oracle's VPS free tier for a 0 cost VPS.

---

I could have stayed fully-free, but I decided I would spend a little bit of money to ensure the providers I ended up using would be reliable and provide me with SLAs and uptime guarantees and all that fun stuff.

My current setup is a Cloudflare domain name - which costed me 80 bucks for 10 years, and an Amazon Lightsail instance which costs me $3.50 a month that I use as a jump host. All of my configuration, except for keys, are on Github in my dotfiles, public for anyone to view and copy. I can take the entire setup, move to any VPS provider I want, and set up a new jump host in minutes and be up and running. $3.50 a month. Lots of fun.

I'm still working on securing the VPS itself though. Since it's open to the world I get a lot of bots looking for exploits. I've had fun learning about honeypots and using CrowdSec and Fail2Ban to figure out how to keep my cloud secure. Hopefully when we chat again it will still be secure. We'll see.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Monday, August 28, 2023

Rootless Podman Privileged Port Binding

podman is a cool docker-replacement that is right at home on Linux. Among other cool party tricks, it is able to run containers (after some configuration) as a normal non-root user. This is good because a container breakout will not grant a root shell, but rather just a normal user shell (which you can further isolate to a "container-only" user). Great!

Just one problem - ye old "privileged ports", otherwise known as any port number below 1024 on Linux because trust and reasons. Thus, if you wanted to run things like nginx or AdGuardHome which bind to ports like 80 and 53, you have to run your container as root.

This is both not very nice for security, but also, limits you to things like network namespaces (as the root user podman will only know about the root user network namespaces) which is lame. Except for the one part where podman binds to privileged ports, a container like nginx or AdGuardHome can run entirely fine as non-root on the host machine.

You can do a fun little trick by running sudo sysctl net.ipv4.unprivileged_port_start and setting it to 0 which will remove protection from these ports < 1024, but this is also not great since that security does exist for a reason. But you can get the best of both worlds by running the dropping the port range, starting the container and binding the ports, and then resetting the port range back to the original 1024 in the background. I've just updated my container scripts to launch AdGuardHome and Cloudflared as a non-root user using this nice little trick.

It's brittle, since if the startup takes more than ~3 seconds, the port will protect again. I also haven't tested various scenarios in the no-worky path, but the happy path of container launches and services work is performing fine with this fun little shell workaround. Nerdy stuff.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Friday, August 4, 2023

Tears of the Kingdom is a Good Game, but an OK Zelda

Tears of the Kingdom (TOTK) came out a few months back. I had played it semi-religiously for some 50 or 60 hours before beating the final boss for the first time and honestly, I haven't had the drive to pick it up since. TOTK is a great game, and I enjoyed almost every minute of my playthrough, but its not a great Zelda game - it's just a painful OK Zelda game.

First, let me just say that I played the snot out of Breath of the Wild (BOTW). I clocked 200 hours on the Wii U version when it first came out, beat it, bought a Nintendo Switch, clocked another 100 hours in the game again and beat it again. Then restarted in Master mode and clocked another 100 hours and beat it again. I have played and beaten the game across multiple hundreds of hours across multiple consoles and game modes. I loved BOTW.

I believe I can condense my problem with TOTK into 3 main issues. 1 - It's not Breath of the Wild. 2 - It is Breath of the Wild though if you look at it with your head tilted to the side. 3 - Its confused on where it fits with Breath of the Wild.

1. Tears of the Kingdom took six years to make. It was a labor of love crafted by hundreds of workers over thousands of hours of development - and for what? The new additions to map - the sky and the depths, are sadly empty feeling with little to do. Aside from the Great Sky Island that you start the game on, there is very little reason to explore the sky or depth areas except for the parts of the game which force you into sky dungeons or depth dungeons. Other than these main story requirements, your exploration rewards you with - Zonai part dispensers, Zonai construct mini-boss fights, or copy-pasted take-off platforms that come with 2 or 3 gliders, and maybe if you are lucky some rockets or flame emitters or fairies. There's nothing to do in the sky, and very little opportunity to explore given how sparse the sky platforms are. The sky's most valuable asset is that it is a high jumping-off point so that you can glide over to a point of interest on the ground.

The depths are more interesting than the sky, but your exploration is limited because of the Gloom, which stops you from progressing after you take enough hits that you have no more food to "repair" your hearts and are forced to leave the area. Yes if you discover a lightroot you can restore your lost hearts, but there is no reprieve if you want to re-explore an area that you have lit-up already but have not combed over yet. You are subtly punished for returning to explore an area again as you have no heal that can save you from the Gloom unless you pack a bunch of sundelions.


2. Even though I paid 70 dollars for it, the more I played it, the more I thought that it was just a "big DLC." For all the things they managed to add into the game as mechanics, they didn't actually take any development time to solve the problems the game had. Underneath it all it was still Breath of the Wild. Suffered the same problems that BOTW had, like weapon durability and menu mania, and buffets during combat and all that.

Puzzles in shrines were a big problem of mine in BOTW. Due to it's non-linear nature, you were never able to have puzzles that were introduced in shrine A and then expanded on in shrine B. The closest we got were things like the dueling peaks which had two "paired" shrines. But any puzzle or setup had to be one-and-done in the shrine itself, since there was no practical way to ensure that a player would have discovered shrine A before getting to shrine B - so you couldn't assume the player had been introduced to any game mechanics at any point ever. Every shrine could potentially be the player's first shrine, so puzzles had to be introduced and finished with that idea in mind. This led to both ideas that repeated with effectively the same puzzle in multiple shrines (like the rolling ball with gyro puzzles), and deep ideas that could never be used again or inspected further (like EventTide island being a one-off idea). The non-linear nature honestly hindered the idea of puzzle-boxes in the game, which are by their very nature a linear activity.

The overworld map was also largely the same, so there was no real "reward" for exploring. In BOTW, everything was new, and so exploring an area, even without a treasure chest at the end, was still exciting because the discovery was in itself a rewarding experience. In TOTK, every area is either effectively untouched, been defaced by a magical crop-circle, or the same with with one quirky "change" to it. And the "change" always seemed to hinder progress. Found a new skyview tower, well you can't use it yet because the platform is broken! Went back to the Kakariko fairy, they aren't there anymore but if you find them in their new location you can't just pay them and upgrade you have to go find a trumpet. Or a flute. Or pull a wagon with your horse. Or a number of various other obstacles that just exist to stop you from progressing the way you used to. So many undocumented side-quests stop you in the middle of your current side-quest and tell you to go somewhere else. You can't just visit the goddess statue on the plateau anymore. You can't just go find the heroine statues in the desert. You can't just visit your house in Hateno, you can't just explore Kakariko. Every quest that re-visits a familiar area (where the reward should be the nostalgia hit of seeing the changed and unchanged bits) is stopped by some monotonous side quest. Link is never allowed to just exist and walk around. He always has to be doing something.


3. But seeing as every NPC in the game suffers from selective amnesia, I never know if it's even worth it to do things in the game in the first place. Teba knows me well, and I apparently know his tiny bird son too. Sidon and I are best friends apparently. But nobody seems to know that the Calamity ever existed. Bolson looks at me like I am a stranger. The champions are effectively written out of history except for the statues and rock walls that bear their faces. All the Sheikah tech is just gone, the Sheikah slate never existed, Guardians are nowhere to be seen. People talk to me like it's the first game in Hyrule. What's the point of fixing towers and killing pirates and building schools and rebuilding towns if in the next game everyone will forget all about my actions anyway. When almost no-one in-game acknowledges any of my accomplishments, what's my character motivation for even continuing?

3 Bonus. The game really suffered this time around from the non-linear story telling. In BOTW, Link had amnesia, so it made sense that he would remember bits and pieces out of order. In TOTK, Link is fine, minus 1 hand. So when I discover magical crop circle 11 before magical crop circle 3, it kind of messes up my flow. I learned that Zelda became a dragon before I learned she ever went back in time in the first place. Why was I even allowed to learn the story out of order. It doesn't make any in-game sense this time around. You're saying that within 15 minutes of landing on the ground again, Link learned Zelda was a dragon and told nobody? Just kept up with the charade of looking for her even though she obviously was a dragon? Really?

Also Ultrahand. Was not a fan of "just build a car bro." I'm long past the point where I can be creative enough to care about neat ways to solve problems. I build my 2 fan bike and just go, that's it. The spirit temple took me 3 days because I just could not be bothered anymore to make another random Ultrahand-whatever out of a box and rocket it over a gap for the third or fourth time. That's not a puzzle. That's just strapping a rocket to a shield, or a box, or combining 40 logs together into a long bridge. It's just tedious.


--

Ok that was a bit. Overall, I had a lot of fun with the game but ultimately left disappointed. It was a good game. It pushed the envelope on many game-mechanics, Fuse and Ascend are literal game changers and I can't wait to see how the industry further develops the idea of them. But as a Zelda game it was just "ok" in my eyes. Sad to think after so many years of waiting.


Nerdy code stuff soon maybe
Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================

Saturday, July 15, 2023

Revival of Trickle

Trickle has been revived! Brought back from the dead! Made fully compatible with Android 14!

Trickle is the pyamsoft Android application which puts your device automatically into Low-Power mode when the screen turns off, and turns off Low-Power mode when the screen turns back on. It is a very efficient power manager application, and much better than the other snake-oil applications on the store as it does not do any custom power logic itself - rather it simply calls to the Android OS power mode.

Recent changes have made it compatible with Android 14 and the new store policy around Foreground Service Restrictions. The has been re-published to the store as the new version 22 with support for Android 14! The publication will go live in a few days and then you will be able to download the new version.

Trickle will continue to be supported for the foreseeable future, until Play Store policy kills us again!


Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page
Check out my code on GitHub
=========================