• 5 Posts
  • 137 Comments
Joined 3 years ago
cake
Cake day: December 12th, 2023

help-circle


  • Aah you did mention that, my eyes just decided to skip that when I read your post.

    This reminds me of another issue I ran into but I use Alpine Linux so I don’t know if it’s a distribution specific issue. I’ll share the issue and workaround solution anyways as something to consider.

    Networking on Alpine Linux is controlled by a process called networking and for reasons I don’t understand and can’t see by any logs, it just stops working. I can’t ssh or access the reverse proxy port. I don’t remember if ping was working or not as it’s been a while since I dealt with it now.

    My work around was to have a script on my server ping a known location and restart networking if it couldn’t ping out. If a second ping after restarting the process failed, it would then restart the device. This script would run every 15 minutes.

    It’s a bandage solution that doesn’t solve the problem but it does keep my server running. However it seems like pings still work with your server so you might need to get creative in how you test your server’s connectivity.


  • It sounds to me like ssdh may have stopped working. That may explain why you can’t ssh into your server but pings still respond. I have a Raspberry Pi4 and a Pi5 and have had similar issues in the past.

    I would probably approach this issue by writing a small script that checks every so often if the process sshd is still alive and if not restart sshd. Maybe SystemD can so something similar but I am not familiar with SystemD.

    Edit: A quick and simple script looks like this

    #!/bin/sh
    
    # Check if `sshd` process is running; If not running, `pgrep` returns
    # an exit status of '1' and restarts `sshd`
    pgrep 'sshd' > /dev/null || systemctl restart sshd
    

    Make the script executable with chmod +x /home/user_name/sshd_check

    Add the following line to /etc/crontabs/root to run the script every 15 minutes

     */15    *       *       *       *       /home/user_name/sshd-check
    

    I don’t use SystemD but I am pretty sure systemctl restart sshd is correct, otherwise it can be changed to whatever your operating system uses to control services



  • I tried what you said. I sent a ping from my computer to the server and this was the output of nft monitor trace:

    trace id 1d01c81e ip ping_trace prerouting packet: iif "eth0" ether saddr b0:7d:64:e8:8f:3c ether daddr d8:3a:dd:de:28:99 ip saddr 192.168.40.201 ip daddr 192.168.40.203 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 65074 ip length 84 icmp type echo-request icmp code 0 icmp id 35586 icmp sequence 0 
    trace id 1d01c81e ip ping_trace prerouting rule icmp type { echo-reply, echo-request } meta nftrace set 1 (verdict continue)
    trace id 1d01c81e ip ping_trace prerouting policy accept 
    trace id 1d01c81e inet filter input conntrack: ct direction original ct state new ct id 271120081 
    trace id 1d01c81e inet filter input packet: iif "eth0" ether saddr b0:7d:64:e8:8f:3c ether daddr d8:3a:dd:de:28:99 ip saddr 192.168.40.201 ip daddr 192.168.40.203 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 65074 ip protocol icmp ip length 84 icmp type echo-request icmp code 0 icmp id 35586 icmp sequence 0 
    trace id 1d01c81e inet filter input rule ip protocol icmp icmp type { echo-reply, destination-unreachable, echo-request, time-exceeded, parameter-problem } accept comment "Accept ICMP" (verdict accept)
    

    I sort of get what’s happening and it looks like the ping request has been accepted.

    From my computer when I send a ping it shows:

    15:55 dell:/tmp/ $ ping -c1 192.168.40.203
    PING 192.168.40.203 (192.168.40.203): 56 data bytes
    
    --- 192.168.40.203 ping statistics ---
    1 packets transmitted, 0 packets received, 100% packet loss
    

    So even though it’s being accepted, I still get nothing going back to my computer, at least that’s how I understand it.


  • I tried your suggested rules and still nothing

    I went a step further and simply enabled all incoming connections with:

    table inet filter {
    	chain input {
    		type filter hook input priority 0; policy allow;
    	}
    }
    

    Again I can connect with SSH and WireGuard but I still can’t ping my server. If I restore to my last backup with iptables, I can get a response from ping again.

    I also tried directly translating the rules from iptables with:

    iptables-save > /tmp/iptables.dump
    iptables-restore-translate -f /tmp/iptables.dump > nftables.dump
    

    and adding the rules:

    #!/usr/sbin/nft -f
    
    define WIREGUARD_PORT = 51820
    define WIREGUARD_ADDRESS = 10.0.0.0/24
    define SSH_PORT = 5025
    define SSH_ADDRESSES = { $WIREGUARD_ADDRESS . $SSH_PORT, 192.168.40.204 . $SSH_PORT }
    define PUBLIC_PORTS = { 5050 }
    
    table inet filter {
            chain input {
                    udp dport $WIREGUARD_PORT accept \
                    comment "Accept WireGuard connections"
    
                    ip saddr . tcp dport $SSH_ADDRESSES accept \
                    comment "Accept SSH connections from known devices or WireGuard"
    
                    tcp dport $PUBLIC_PORTS accept \
                    comment "Accept public connections"
    
                    icmp type echo-request limit rate 5/second burst 10 packets counter accept
                    icmp type echo-request limit rate 30/minute burst 120 packets counter accept
                    icmp type echo-request limit rate 1/minute burst 2 packets counter log prefix " PING-PONG-FLOOD "
                    icmp type echo-request counter drop
    
                    icmp type destination-unreachable counter accept
                    icmp type time-exceeded counter accept
                    icmp type parameter-problem counter accept
                    icmp type echo-request counter accept
            }
            chain forward {
                    icmp type destination-unreachable counter accept
                    icmp type time-exceeded counter accept
                    icmp type parameter-problem counter accept
                    icmp type echo-request counter accept
            }
    }
    

    and still no ping from my server…

    I will agree, the documentation for nftables is just not as accessible or consistent as iptables. It’s a bit frustrating.



  • That’s fair

    I have a very different view on data, physical property and familial relationships. Everything is temporary to me and I’ve prefer my stuff to be reused rather than act as an archive to my own life.

    My pictures, music and technology related projects are just for myself. Anything I wish to share after my death is stored on an unencrypted drive connected to a Raspberry Pi that acts as my web facing server that serves only static data. It’s mainly a bunch of wikis, linux/shell scripting references, some of my git repositories, some survival type ebooks and some other random stuff.

    I’ve lost data multiple times throughout my life so I know I’d be disappointed but not sad if I lost all my data one more time. I do have multiple backups now so I at least have some data resilience compared to the past.


  • I am the same way. My backup is on the other side of the room. If my house goes up in flames, I’ll have bigger issues to deal with, like my house going up in flames.

    Data is just data. It wasn’t there when I was born and it’s all encrypted now so when I die, I want the next person to wipe it clean and use the hardware for themselves.

    Having a backup is convenient but it’s not the end of the world if I lose it.



  • I used to work as an electrician in the automation industry (robots that welded the frame of automobiles) but I was only an apprentice. I worked alongside robot and PLC programmers and absorbed information through them. I lost the motivation to finish my apprenticeship due to a changed perspective on the harmful affects of too much progress. That was as close as I got to any coding.

    I decided to enjoy a mid-life retirement after protesting my way into getting fired which gave me time to explore hobbies. Along the way I ended up buying a used Raspberry Pi 4 and 5 and found some joy in both self hosting and shell scripting. Fortunately shell scripting supplements self hosting. I have been slowly crafting a low resource, low maintenance, minimal server.

    Both Pi’s run Alpine Linux, the Pi 4 is dedicated to HomeAssistant which controls a handful of lights and switches. The Pi 5 runs Caddy and Kiwix. Right now it just hosts a bunch of wikis and a static file server with Caddy. Eventually I plan to run a blog created only by a single Bash script.

    This is all completely outside of any workplace skill and I think I’d like to keep it that way. Programming for money would likely kill the wonder I still have for computers.


  • I use Alpine Linux for my two Rasberry Pi servers and for my laptop with Sway. I enjoy it a lot. The setup scripts are quite nice to work with.

    Documentation is decent but I found myself supplementing the Alpine wiki with the Gentoo and Arch wikis.

    Building a system from the minimal starting point felt quite rewarding and I really enjoy tinkering with it still. Learning to script for ash has been quite the experience too.


  • Everything I have currently is pretty much working and maintaining itself. My logs are quiet and predictable. It’s been nice.

    I do have two things to do. One is it switch from iptables to nftables because podman is depreciating support for iptables. I absolutely hate working with firewalls, the syntax is always awful. For some reason ufw isn’t working with nftables like I hoped so now I’m working up the energy to learn nftables itself.

    The other thing to do is to update Alpine Linux to the latest release version. I’m trying to figure out how to properly update the cache of installed packages on my main computer. After that I should be able to run my upgrade script and things should take care of itself. I hope. With Alpine I usually wait a month or two after the initial release of a new version, things always seem to break if I update immediately and I don’t want to trouble shoot too many things.

    Other than that, I’ve gone back to making functional scripts again. Currently I am working on a new backup script that handles logging and automated rotation of backup snapshots. It’ll be POSIX portable and easy to integrate with crontab. It’s essentially the culmination of all my POSIX shell scripting knowledge. I just have to figure out one last and huge hurdle and I’ll be happy with the script.


  • I too was upset with the use of Claude/AI/LLM’s in the rsync project. The maintainer received a lot of public backlash and as a result people have offered their time to help the maintainer with this project.

    Since the backlash, the use of agents has been drastically reduced. That seems like a very human and overall positive response. It sucks that it happened. It’s nice that people are now doing the work again. The response could have been a lot worse. I can be forgiving in this specific situation.


  • I also haven’t seen any bot activity after I started using wildcard sub domains. My ISP blocks all incoming on common ports so I also use uncommon ports. I assume the combination of the two makes it too time consuming to find me.

    I hid my ssh port with a wireguard connection so I also don’t see any attempts on my ssh port anymore either. My logs, including fail2ban, are quiet and boring.

    It’s nice to have a quiet corner of the internet for myself.


  • I’m going to post all the commands I use because I think that may be easier to follow. All the commands I’m posting will include the --dry-run option so if anyone tries to copy/paste this into their terminal, no actions will be taken. Instead it will show you what is going to happen if you ran the command without any changes.

    As I mentioned before, each partition will require it’s own command. The easiest way is using lsblk. Below is my current setup and here you can see I have 5 partitions. One partition is a swap so I will only be working with 4 partitions, /, /boot, /boot/efi and /home:

    dell:~ $ lsblk
    NAME                  MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
    nvme0n1               259:0    0 953.9G  0 disk  
    ├─nvme0n1p1           259:1    0   500M  0 part  /boot/efi
    ├─nvme0n1p2           259:2    0  62.5G  0 part  
    │ └─luks1-dell        253:0    0  62.5G  0 crypt 
    │   ├─vg_dell-lv_boot 253:1    0   500M  0 lvm   /boot
    │   ├─vg_dell-lv_swap 253:2    0     8G  0 lvm   [SWAP]
    │   ├─vg_dell-lv_root 253:3    0    38G  0 lvm   /
    │   └─vg_dell-lv_home 253:4    0    16G  0 lvm   /home
    ├─nvme0n1p3           259:3    0   600G  0 part  
    ├─nvme0n1p4           259:4    0 270.9G  0 part  
    └─nvme0n1p5           259:5    0    20G  0 part 
    

    It’s good to first check what partitions you are using. My Raspberry Pi’s (ARM) only have / and /boot for example.

    The following rsync commands are what I use to make a complete backup of my system. I do exclude a number of directories because they are for temporary stuff like ram, processes or even devices/drives. It’s also important to exclude the specified backup directory to avoid recursing into the backup directory and filling up your storage space.

    I have a manual backup location and automated backup location. The following is for my manual backup location in /backup/main on my system. This location can be changed to wherever you want your backup.

    # Backup
    # /
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=/backup/* --exclude=/boot/* --exclude=home/* --exclude=proc/* --exclude=sys/* --exclude=dev/* --exclude=tmp/* --exclude=run/* --exclude=mnt/* --exclude=media/* '/' '/backup/main/'
    
    # /boot/
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=lost+found '/boot/' '/backup/main/boot/'
    
    # /boot/efi/
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=lost+found '/boot/efi/' '/backup/main/boot/efi/'
    
    # /home/
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=lost+found --exclude=.cache/* '/home/' '/backup/main/home/'
    
    rsync restore commands
    # Restore
    # /
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=/backup/* --exclude=/boot/* --exclude=home/* --exclude=proc/* --exclude=sys/* --exclude=dev/* --exclude=tmp/* --exclude=run/* --exclude=mnt/* --exclude=media/* '/backup/main/' '/'
    
    # /boot/
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=lost+found '/backup/main/boot/' '/boot/'
    
    #/boot/efi/
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=lost+found '/backup/main/boot/efi/' '/boot/efi/'
    
    # /home
    rsync --dry-run --archive --acls --one-file-system --xattrs --hard-links --sparse --verbose --human-readable --partial --progress --numeric-ids --delete --exclude=lost+found --exclude=.cache/* '/backup/main/home/' '/home/'
    

    It’s been a while since I last researched these options so I’ll give a brief explanation of the types of options I used. I’d suggest having a look online or at the man page to get a better idea of what each option does.

    Options:

    --dry-run Only displays what rsync will do, remove this once you are ready to commit any syncs/changes

    archive --acls --one-file-system --xattrs --hard-links --sparse Helps preserve file attributes and other information. I think hard-links is also used to reduce backup size. There are many rsync guides that will give a better explanation of how hard-links work

    verbose --human-readable --partial --progress will display visual data about what rsync will do

    --numeric-ids I use this because I store multiple device backups on a single drive which gets copied to other storage devices. This stores file ownership information as numeric values to prevent ownership issues when restoring

    --delete this will force the destination directory to match the source directory completely. If you delete a file from the source directory, when you perform a sync, it will delete the same fie in the destination directory. This can be dangerous if you are not prepared for it. This is why --dry-run is so important and useful.

    Extra options: My automated scripts use 2 additional options. I keep a rolling set of 4 backups (One month of weekly backups). I create a new directory /backup/updating and use a symlink from/backup/latest that points to the most recent automated backup. After the backup is created, I rename /backup/updating to something with a timestamp like /backup/backup_2026-07-01_1782882013

    --mkpath will create any non existing directories specified in the command

    --link-dest=/backup/latest/ will use the unchanged files from this directory to help reduce backup sizes. I think this is called an incremental backup

    This has been the most reliable way to handle backups for myself. I do run into issues with docker/podman containers sometimes and will have to manually delete those directories. I haven’t figured out how to deal with that issue yet but fortunately it’s easy to find those directories. Running the command will give errors about what directories can’t be removed which makes it easy to hand delete them in another terminal window.


  • Timeshift is essentially a gui on top of rsync anyway, if you look at what it’s doing behind the scenes.

    That’s the reason why I chose to learn rsync. I was frustrated with Timeshift. It failed to restore some changes multiple times. It gave me issues with docker. It also had default excludes that were annoying to change as well.

    I then learned how to make a complete system backup with rsync itself. /, /boot/ and /boot/efi/ has to be done on separate rsync commands. Basically one command per partition.

    A restore involves flipping the source and destination in the rsync command. It also allows me to boot into a live USB and perform a restore in the event that I really mess up and can’t perform a restore normally through the installed OS.

    By leaving behind the GUI, I got a lot more flexibility. It’s also a lot more reliable and I’ve had a lot less restore issues.



  • I’ve been trying to find a balance between what I currently own, what I can do with it and using as little outside resources to self host. I’m also cautious about what has access to the internet which limits what I host.

    I have two Raspberry Pi’s. One is only accessible through my home’s local network through my WiFi Extender network. That WiFi extender also helps hide my personal network from my ISP which see’s everything connected to the main modem/router. This Pi is strictly for my IoT devices.

    My other Pi is a web facing server. It has Caddy and Kiwix. It hosts a static blog, simple file server which servers my git repositories, some survival ebooks, plain text recipes and a bunch of programming related resources. Kiwix has a bunch of wikis, Wikipedia to survival stuff, vegetarianism, coding stuff and things surrounding those topics generally. I generally avoid anything that uses databases because I don’t have the energy to learn, maintain and protect that. Plus I have a focus on small, low powered minimalism.

    Those Pi’s both use Alpine Linux. I chose Alpine because it’s small and uses less common tools. doas over sudo, OpenRC over SystemD, and Musl over glibc. It’s a bit of security by obscurity but I’ve also made efforts to harden Alpine Linux itself too. I’ve disabled a lot of kernel modules, made strict firewall rules, and made sure to include the use of apparmor. I’ve also written all my backup solutions and maintenance scripts myself and tested as thoroughly as I am capable of. I also avoid complexity by keeping things as minimal as possible to reduce the surface area of any possible attacks.

    I use podman containers to keep everything in the userspace. Caddy is my reverse proxy which means only one port is freely accessible to the internet. I also use a wildcard cert to obscure my publicly available information and use an uncommon port instead of the standard 80/433 ports. Because of the wildcard cert/uncommon port, I receive no bot traffic so I don’t feel the need to use Cloudflare or Anubis. I’m hidden enough and the only people I want on my blog/file server/Kiwix wiki’s are close friends.

    For SSH, I’ve hidden all those behind WireGuard so the second open port to my web server looks hidden from scanners (at least that’s how I understand it). I used to use a custom port which only got about 15 hits a week from bots appearing from the Netherlands. That number has since dropped to zero after setting up WireGuard. I’m sure the bots are attempting but they aren’t making any appearances in my logs and that’s good enough for me.

    I’m happy more talk about security has been popping up lately. So many websites focus on getting things running and just don’t take any time to talk about security. I had to switch from docker to podman because docker had so much control over iptables that never got reported to ufw which was a concern for me. That point is rarely talked about since it’s so easy to copy and run a docker-compose.yml file.


  • I often see claims that Alpine linux is just for embedded systems. I wanted to highlight to other people that there is far more to Alpine than embedded systems or being used for containers.

    It’s mininal like void but still very flexible and capable if people are willing to work with Musl, BusyBox or OpenRC. It’s a nice option for anyone who has issues with SystemD or may want to depend less on GNU tools.

    Like any distribution, it doesn’t fill everyone’s wants or needs but it seems to have grown more than serving just embedded systems.