Jamdroid Server Manager

In the summer of 2021, I found myself using a friend’s game server management panel. This runs on the same server that he uses to run a number of game servers (mostly Minecraft, but with the ability to host other games too) and allows the operator to start, stop, and run commands on the servers with a nice user interface. This gave me the idea to work on my own server panel system, though with the ability to extend it in order to fulfill a number of different roles (such as the webhook integrations described later).

The server is hosted using the free tier of Google Cloud Platform’s (GCP) e2 family of machines, providing more than enough performance for the purposes of a web server. It does mean that, should I want to host any game servers, I would need to either use a separate server or increase the tier of machine being used by the web server.

The server is written in Python 3, specifically Python 3.9. I would have liked to use Python 3.10 since one of its new features was structural pattern matching (which would have made chat bot commands somewhat neater to implement), however that version was not yet readily available on Debian when I was setting up the server itself. The project utilises the Flask microframework, as well as the Gunicorn WSGI HTTP server.

User accounts on the site are handled by utilising GitHub’s OAuth functionality, meaning that features such as 2FA can be utilised without any additional effort. This also means that users’ passwords do not need to be saved on the server, helping to improve its security. As an additional touch, the user’s GitHub avatar is shown on the index page when they are logged in.

Overall, the site works on a concept of “apps”, which originally were intended to represent a game server. For a user that has logged in, and that has access to a given app, they will see it appear on the index page along with a number of controls related to that app (e.g. opening a settings page, starting/stopping the app, etc.). The current most fully fledged apps are:

  • Discord Bot
    Discord allows developers to create bots that can respond to chat messages. Recently, they also implemented a feature allowing users to explicitly run a bot’s application commands, including a UI within the client prompting for command parameters and alowing for some type restrictions. Jamdroid includes an endpoint to allow Discord to send interaction data via a webhook, with responses being returned as JSON objects. This method better fits a web server environment than the alternative, which requires a more active connection to Discord’s gateway in order to receive events.
  • GitHub Webhook Handler
    GitHub repositories and organisations can be set up to send webhooks when certain events take place, such as new commits being pushed or releases being created. Previously, I had a bot written using Hubot that would receive these webhooks and send messages to a specific Slack channel if something of importance had happened. This functionality has been implemented in Jamdroid, which means that the logic can now be written in Python rather than Coffeescript, which I am more comfortable with overall.
  • Twitter Webhook Handler
    Twitter’s webhook system is more complicated than the others, in that it requires the owner of the account that will generate events to log in to your website. As a result, Jamdroid implements a “Log In With Twitter” button, and can then register with Twitter to receive webhooks when new events take place. The only one that is important is when a new tweet has been sent, at which point a link to the tweet is forwarded to a specific Slack channel and a specific Discord channel. This set up allows messages to be sent nearly instantly, as opposed to somewhere between a few minutes and an hour or two when using a service such as IFTTT.
  • URL Shortener
    Somewhat simpler than the webhook handlers, Jamdroid powers a URL shortener hosted on a different domain name (jmy.fyi). This required setting up the main Flask app to care about the host header being sent by the browser, and allows the two different domain names to be served from the same server on the same IP address. As a result, urls such as jmy.fyi/about to be resolved without needing to set up more than one server in GCP.

In addition, there are some quality of life features that I have included, such as:

  • Automatic Updates
    As the source code for the server is hosted on GitHub, I can use the same system for handling GitHub webhooks and use it to pull any changes and restart the server to apply them automatically.
  • Logs
    Users with the correct permissions are able to see the server logs from the current day, and from any other day for which logs are still available.
  • Dark Mode
    The site has an automatic dark mode applied utilising the CSS @media (prefers-color-scheme: dark) rule, which (amongst other things) sets the page backgrounds to a dark gray and the text to white.

Written by James Cordon | First published: | Last updated:
Link to this page: https://mrjamesco.uk/projects/jamdroid/