As I was almost done with my academic work, I embarked on a quick side-project to create a dashboard to monitor server status in my lab.
There used be one made by a former lab member,
but it was no longer being maintained and becoming outdated.
My main focus on the implementation was to make it 1. simple 2. maintainable 3. modestly secure and 4. look nice. The final product looks like this (some details have been redacted):
My choice of frameworks was heavily dependent on maintainability of the project.
Since most of the lab members are already familiar with python and has no prior knowledge on popular frontend framework such as React,
I decided to implement the web server with fastapi, a popular choice of ASGI framework in python.
All of the UIs are written in vanilla HTML/CSS with jinja templates and DasiyUI1 for a nice-looking component library.
I also employed HTMX for client interactivity (refer to my previous post for more details).
Since I am not using any JS runtime, I put a minified JS libs for HTMX, Tailwind, and DaisyUI along with stylesheets to static folder.
Thankfully, fastapi already provides an api for mounting static files, so that they can be served automatically:
The HTML templates were written with the help of jinja2-fragments2, which allows partial rendering of template by referring to the block name.
This makes for a concise template files for easier maintenance when coupled with HTMX.
For instance, we have the index.html with content block.
Depending on the routes and the type of request, we can choose to return the entire template or parts of them like so.
Here, /on-premise returns the content block if moving from another page and the entire page if not.
The /on-premise/instances returns the partially rendered block upon refresh.
I have decided to use paramiko to remotely execute commands to gather information from different servers.
paramiko is a python implementation of the SSHv2 protocol, which makes it relatively safer than executing commands with subprocess or its alternatives.
Even though the information is gathered concurrently, execution takes time, especially when gathering the GPU information via nvidia-smi command.
Hence, I decided to use lazy-loading and pagination to hide the loading overhead.
Thankfully, HTMX provides this functionality via hx-trigger.
We can implement a simple lazy-loading by calling paginated endpoint if the last loaded element is revealed to the user:
To further speed up the loading process, I also implemented a time-to-live cache.
Because all of service methods are implemented as async functions, I had to implement a wrapper for caching.
You can refer to this post for more details.
I also implemented a quick and simple session management service so that only authorized users can access the information (our lab has a history of ).
Since the server rarely undergoes OS and software updates, I have decided to dockerize the application to ensure consistency and security.
My favorite choice of base image for python web framework is always slim-buster type, which is an extremely light-weight python image built on top of alpine linux.
In addition to a nice documentation outlining the deployment process, I created a Github workflow that runs automatically upon creating a release tag.
Overall, the project took less than a day to finish the basic features thanks to the simplicity that FastAPI and HTMX bring to the development.
I had to make minor changes to make the dashboard more mobile friendly and maintainable, but otherwise the dashboard was well-received by the lab members.
Hopefully it is put to good use.