• 3 Posts
  • 21 Comments
Joined 1 year ago
cake
Cake day: July 2nd, 2023

help-circle
  • The problem with using seaweedfs to a back your DBs is more on the filesystem than the implementations of POSIX features. When you are writing to a file, and the connection to seaweedfs breaks (container restart, wifi, you name it), then you might end up with a half-written file. If you upload pictures, this is unlikely, but DBs are doing several writes per second usually. So it is more likely one of those gets interrupted. In my case, my grafana sqlite DB would get corrupted every other week.

    What I recommend is using DBs natively in your node’s filesystem, and backing them up to seaweedfs periodically instead. That way your DBs ‘work’ but you can get them running again, and the backup is replicated in the distributed filesystem.


  • I struggled a bit to get it up and running well, but now I am happy with it. It’s not too hard to deploy (at least easier than the alternatives), it has CSI which for me was big, and it has erasure coding. The dev that maintains it (yes, the one dev) is very responsive.

    It has trade offs, so depending on your needs, I recommend it. Backing store for stateful workloads like postgres DBs? Absolutely not. Large S3 store (with an option for filesystem mount) for storing lots of files? Yes! In that regard it’s good for stuff like Lemmy’s pictrs or immich. I use it as my own Google drive. You can easily replicate in your own cluster, or back it up to an external cloud provider. You can mount it via FUSE on your personal machine too.

    Feel free to browse through my setup - if you have specific questions I am happy to answer them.


  • I see no one else commented my stack, so I suggest:

    Nomad for managing containers if you want something high availability. Essentially the same as k8s but much much much simpler to deploy, learn, and maintain. Perfect for homelabs imo. Most of the concepts of Nomad translate well to k8s if you do want to learn it later. It integrates really well with Terraform too if you are also hoping to learn that, but it’s not a requirement.

    NixOS for managing the bare metal. It’s a lot more work to learn than say, Debian, but it is just as stable, and all configuration will be defined as code, down to the bootloader config (no bash scripts!). This makes it super robust. You can also deploy it remotely. Once you grow beyond a handful of nodes it’s important to use a confirmation management tool, and Nix has been by far my favourite so far.

    If you really want everything to be infra-as-code, you can manage cloud providers via Terraform too.

    For networking I use wireguard, and configure it with NixOS. Specifically, I have a mesh network where every node can reach every node without extra hops. This is a requirement if you don’t want a single point of failure (hub and spoke) to disconnect your entire cluster.

    Everything in my setup is defined ‘as-code’, immutable, and multi-node (I have 7 machines) which seems to be what you want, from what you say in your post. I’ll leave my repo here, and I’m happy to answer questions!

    My opinions on the alternatives:

    Docker compose is great but doesn’t scale if you want high availability (ie, have a container be rescheduled on node failure). If you don’t want higher availability, anything more than docker might be overkill.

    Ansible and Puppet are alright but are super stateful, and require scripting. If you want immutability you will love Nix/NixOS

    k8s works (I use it at work) but is extremely hard to get right, even for well-resourced infra teams. Nomad achieves the same but with the leanings of having come afterwards, and without the history.


  • I think there are two approaches to infrastructure as code (and even code in general):

    • as steps (ansible, web UI like pihole…)
    • declarative (nix, k8s, nomad, terraform…)

    Both should scale (in my company we use templating a lot) but I find the latter easier to debug, because you can ‘see’ the expected end result. But it boils down to personal preference really.

    As for your case, ideally you don’t write custom code to generate your template (I agree with you in that it’s tedious!), but you use the templating tool of your framework of choice. You can see this example, it’s on grimd (what I forked leng from) and Nomad, but it might be useful to you.

    P.S also added to the docs on the signal reloading here


  • I have a similar use case where I also need my records to change dynamically.

    Leng doesn’t support nsupdate (feel free to make an issue!), but it supports changing the config file at runtime and having leng reread it by issuing a SIGUSR1 signal. I have not documented this yet (I’ll get to it today), but you can see the code here

    Alternatively, you can just reload the service like you do with pihole - I don’t know how quick pihole is to start, but leng should be quick enough that you won’t notice the interim period when it is restarting. This is what I used to do before I implemented signal reloading.

    Edit: my personal recommendation is you use templating to render the config file with your new records, then reload via SIGUSR1 or restart the service. nsupdate would make leng stateful, which is not something I desire (I consider it an advantage that the config file specifies the server’s behaviour exactly)









  • What you described is correct! How to replicate this will depend heavily on your setup.

    In my specific scenario, I make the containers of all my apps use leng as my DNS server. If you use plain docker see here, if you use docker compose you can do:

    version: 2
    services:
     application:
      dns: [10.10.0.0] # address of leng server here!
    

    Personally, I use Nomad, so I specify that in the job file of each service.

    Then I use wireguard as my VPN and (in my personal devices) I set the DNS field to the address of the leng server. If you would like more details I can document this approach better in leng’s docs :). But like I said, the best way to do this won’t be the same if you don’t use docker or wireguard.

    If you are interested in Nomad and calling services by name instead of IP, you can see this tangentially related blog post of mine as well









    • Can you show the diff with your previous WG config?
    • Is 10.11.12.0/24 also on enp3s0?

    I am able to connect and can ping 10.11.12.77, the IP address of the server, but nothing else

    Including the wider internet, if you set your phone’s AllowedIPs to 0.0.0.0/0? This makes me think it’s a problem with the NAT, not so much wireguard. Also make sure ipv4 forwarding is enabled:

    sysctl -w net.ipv4.conf.default.forwarding=1
    sysctl -w net.ipv4.conf.enp3s0.forwarding=1
    

    Reading this article might help! I know this is not what you asked, but otherwise, my approach to accessing devices on my LAN is to also include them in the WG VPN - so that they all have an IP address on the VPN subnet (in your case 10.11.13.0/24). Bonus points for excluding your LAN guests from your selfhosted subnet.


  • Yep I am using traefik -> nginx. I simply add the traefik tags to the nginx service. I didn’t include that in the example file to keep it simple.

    As for the storage, I use SeaweedFS (has a CSI plugin, really cool, works well with nomad) but as a CSI volume it’s not suitable for backing postgres’ filesystem. The lookups are so noticeably slower that your Lemmy instance will be laggy. So I decided to use a normal host volume, so the DB writes to disk directly, and you can back that up to an S3-compatible storage with this (also cool). Could be SeaweedFS, AWS, Backblaze…

    I think SeaweedFS is suitable for your pictrs storage though, be it through its S3 API (supported by pictrs) or through a SeaweedFS CSI volume that stores the files directly.

    I hope that answers it! Do let me know what you end up with