🍩 Doughnut Reader 🍩

harsxv

51 comments

8 days ago

It generates a simple, responsive static HTML page for those of you running self-hosted services and wanting to share their status page. It checks things like HTTP pages, open ports, or pings IP addresses.

Check the demo here: https://status.harry.id

harsxv

8 days ago

> clean, responsive web page

Consider adding a screenshot.

remram

8 days ago

I was also looking for a screenshot in the readme. I somehow missed the link to the demo until it was posted at the top of this thread.

Neat project. Thank you for sharing.

lundstrj

8 days ago

Why he need screenshot when there's a perfectly good demo?

8n4vidtmkvmk

8 days ago

Assuming this isn't snark - because if I am looking for a tool to do a job, seeing an immediate visual representation of what I am likely to expect is very helpful. I don't want to go through the full installation to view a demo and then immediately realise it was not remotely close to what I was expecting.

mrroryflint

8 days ago

I also think a screenshot in a README is very helpful, but do note that the demo requires no install. The linked GitHub repository has a homepage set, and it is https://status.harry.id which I think is pretty obviously a demo just from the URL.

fmbb

8 days ago

Generally I'd agree, but the link he posted is a single click, requires no install, no login, no nothing. Nevertheless, here I took a screenshot for you: https://i.imgur.com/63kPIh9.png

8n4vidtmkvmk

6 days ago

[deleted]

8 days ago

Thanks!

Screenshot added.

harsxv

8 days ago

It follows the UNIX philosophy: do one thing well. Nice work!

russfink

8 days ago

Looks nice. I'm confused by the hover effect which moves each service up a few pixels—this suggest interactivity, but there doesn't seem to be any.

oneeyedpigeon

8 days ago

Very nice. But for me the Tailscale dashboard fulfills this function, what would make this super usefully for me if it integrated with something like https://ntfy.sh and I could set conditions for notifications.

teekert

8 days ago

Might be nice to offer a generalized version of async def check_ping(host):

For doing something like

  - name: MySQL
    type: exec
    command:
    - /usr/bin/mysqladmin
    - --defaults-file=/path/to/file/handling/credentials
    - ping
Not sure about others, but MySQL after a while blocks a host if there are too many connection attempts without successful signin and the ping code in the repo already calls out to an external process, so it should be quite straight ahead to add.

johannes1234321

8 days ago

Why not put these .env variables inside the checks.yaml config file? What is the advantage of two config files with two separate syntaxes?

remram

8 days ago

The idea is the values in .env files can be configured via environment variables, while checks.yaml is for things that can be hard coded.

In this case it's a bit moot because the yaml file works like a database, but when you deploy this using, say, Docker or k8s, you can use a different method to configure environment variables and skip .env files.

selcuka

8 days ago

Why can't I change the port of my database server via an environment variable? This would be required for e.g. Nomad support.

If this is a goal, why is it a goal for only half the configuration?

remram

8 days ago

Something I do in my yaml configs is support ${ENV} template variables with the string Template's substitute method using *os.environ.

jpitz

8 days ago

good question and answer … on a tangent, it makes me wonder if YAMLscript could be used to preload .env values on startup

librasteve

8 days ago

Very cool. Nicely done. I really like projects like this.

iJohnDoe

8 days ago

Man, this is cool! I would love if each tile would be clickable! I have a homelab and this would be a great landing page to be able to give out to family to see the status and links to all services in the house.

loganmarchione

8 days ago

If you’d like something with a GUI for configuration, I’ve been using [Uptime Kuma](https://github.com/louislam/uptime-kuma) for a couple years now with an “internal” status page for all services in my homelab, and a “public” page for family to see the few services they would care about. I also think [Homepage](https://github.com/gethomepage/homepage) might be a good fit since it links to the services on the page, and has a little indicator dot for if it’s online or not.

alargemoose

8 days ago

Suggestion: It would be cool if it could be packaged as a deb package, install itself as a systemd service, and accept a configuration in /etc somewhere.

Adding nohup commands to /etc/rc.local is a little hacky.

dheera

8 days ago

Thank you for the suggestion!

harsxv

8 days ago

Is the demo currently down?

It's currently 16:20 UTC and the last update timestamp on the bottom of the demo is 06:36 (unknown timezone).

8organicbits

8 days ago

Hi, it’s up now. I made some updates and ran a few tests earlier

harsxv

8 days ago

Useful for my own status page. Thanks!

oars

8 days ago

Can this be run as a AWS Lamba instance?

vocram

8 days ago

Yea, you can create a website on S3 and set up a Lambda trigger every minute. To schedule this, you can use a CloudWatch rule with a 'Schedule' expression to trigger the Lambda function.

Alternatively, you could use GitHub Actions and schedule the workflow to run every minute.

However, I prefer the Lambda approach.

mariocesar

8 days ago

Note: Running your status page on Lambda is a bad idea if your main site is on AWS. You want your status page to be on separate infrastructure so that it can be used during an outage.

nicoburns

8 days ago

Wow, great work. This is exactly something I was getting geared up to do for myself. Thanks for sharing!

atebyagrue

8 days ago

Thank you for sharing this project! This is exactly what I am looking for.

xFuture

8 days ago

simple and gets the job done. nice.

kaan_keskin

8 days ago

Python in a nutshell

aucisson_masque

8 days ago

nice, i love this

masdzub

8 days ago

[deleted]

8 days ago

[flagged]

thebabayaga29

8 days ago

There is no reason to take on the added cost of Python for this.

thelastparadise

8 days ago

The vast majority of work this script does is over the network, which your choice of language will do little to speed up (latency-wise).

pphysch

8 days ago

What added cost? It generates a flat file.

oneeyedpigeon

8 days ago

The usage of ping require that to run as root. And this can open a big security issue as the paramater host of the function "check_ping" can be used for a root command injection.

I know that this is not going to be exposed on Internet, but I think it should be fixed in any case. I am at work, but I can open a PR fixing it later.

lormayna

8 days ago

It doesn't need to be fixed. There isn't an issue here.

Depending on the OS, ping is either set setuid[1] as root, or more commonly these days, ping is granted a "capability"[2], such as CAP_NET_RAW on Linux. macOS does things a little different[3].

This allows non-root users to run stuff like ping without granting them full root access. You do not need to, nor should you, run the script as root.

    % ls -l /usr/bin/ping
    -rwxr-xr-x 1 root root 89768 Apr  8 09:00 /usr/bin/ping
    
    % getcap /usr/bin/ping
    /usr/bin/ping cap_net_raw=ep

    ~
    % whoami
    jake
    
    ~
    % id
    uid=1000(jake) gid=1000(jake) groups=1000(jake),4(adm),24(cdrom)
    
    % ping -c 3 8.8.8.8
    PING 8.8.8.8 (8.8.8.8): 56 data bytes
    64 bytes from 8.8.8.8: icmp_seq=0 ttl=117 time=9.195 ms
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=117 time=8.837 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=117 time=10.998 ms
    
    --- 8.8.8.8 ping statistics ---
    3 packets transmitted, 3 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 8.837/9.677/10.998/0.946 ms
Hope that helps. Happy to elaborate on any unclear points.

1. https://unix.stackexchange.com/questions/382771/why-does-pin...

2. https://unix.stackexchange.com/questions/592911/how-does-pin...

3. https://apple.stackexchange.com/questions/312857/how-does-ma...

Edit: updated explanation a bit.

runjake

8 days ago

Further, I'm not sure you can do command injection, as the the `host` variable is treated as a single token in the shell call. `host = "google.com; wget exploit"` won't run `wget exploit`.

Happy to learn if there's a more nefarious trick that gets around this, though.

gertlex

8 days ago

On Linux, "net.ipv4.ping_group_range" is typically used to allow unprivileged users to do ICMP echo requests. Setting the setuid bit or granting a capability are both very old ways of doing this.

trulyrandom

8 days ago

This is new to me.

So, here's what I see on Ubuntu 24.04 LTS:

    $ sudo sysctl -a | grep net.ipv4.ping
    net.ipv4.ping_group_range = 1 0
The man page[1] states:

    ping_group_range (two integers; default: see below; since Linux 2.6.39)
    Range of the group IDs (minimum and maximum group IDs,
    inclusive) that are allowed to create ICMP Echo sockets.
    >>The default is "1 0", which means no group is allowed to
    create ICMP Echo sockets.<<
This would seem to indicate this isn't being used -- at least on Ubuntu? What am I missing?

1. https://www.man7.org/linux/man-pages/man7/icmp.7.html

runjake

8 days ago

Asking because I genuinely don't know, but why not use Python's `urllib.request` instead of `ping`?

loganmarchione

8 days ago

TL;DR: apples and oranges. Plus, monitoring is hard.

"urllib.request" sends an HTTP request. It implies that the thing you want to monitor is an HTTP endpoint. Even if that's true, you still have to decide whether you're okay with just getting a 200 status code back, or whether you want to scrape the page for a certain result as your signal of healthy or broken.

"ping" is an ICMP echo/reply. Ignoring that ICMP messages can be blocked by routers, an ICMP reply can tell you that the host's network interface is alive and that's about all. It doesn't mean any service on that host is online. I have seen hosts that send ICMP replies but were otherwise fully hung by some storage or kernel issue.

bityard

8 days ago