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
=========================