A web user interface for Bash scripts


© Lead Image © Elnur Amikishiyev, 123RF.com

© Lead Image © Elnur Amikishiyev, 123RF.com

Article from Issue 263/2022

Create a user-friendly front end for your Bash scripts without writing a single line of HTML, CSS, or JavaScript.

While Bash scripts are the glue that holds the GNU/Linux back end together, a web-based front end makes these scripts more user-friendly for end users. In the last decade, web user interfaces (web UIs) have become the front end of choice, even for daily local desktop usage. However, creating a web UI takes some effort, even for very simple interfaces, because a web UI requires using HTML, CSS, JavaScript, and more.

Luckily, two free and open source utilities, OliveTin and Script Server, let you create a web UI for your scripts without writing a single line of HTML, CSS, and JavaScript (and its hundreds of web UI libraries). In this article, I will show you how to create a simple web UI to drive your scripts with OliveTin, followed by a more feature-rich interface using Script Server.


OliveTin [1] lets you create a web interface that allows your end users to access predefined shell commands. The OliveTin interface consists of various buttons used to invoke configured shell commands. OliveTin uses declarative programming driven by a YAML configuration: You just create a simple declarative configuration, feed it to OliveTin, and out pops a web page that functions as an interface for the shell commands available on your system. Instead of memorizing and typing the actual commands into the command line, OliveTin lets you automate your daily tasks with a user-friendly button. Because of its simplicity, OliveTin lets you open up your system to internal non-command-line users.

OliveTin is distributed as a Golang static binary, so you do not need to install it. Just grab the proper binary version for your machine architecture, put the executable in a system-wide accessible location, and you are done. Because a Docker Engine is very common on most GNU/Linux distributions, I prefer to run OliveTin out of the box with Docker. If you are running native commands that cannot be run with Docker, you can also install OliveTin as a system service using distribution specific packages. Refer to the documentation [2] to set up OliveTin natively with DEB/RPM packages.

To generate a simple web interface with OliveTin, first create the config.yaml file in Listing 1 and then execute the following command in your terminal:

Listing 1



docker run -d --rm -v ${PWD}/config.yaml:/etc/OliveTin/config.yaml:ro -v /var/run/docker.sock:/var/run/docker.sock:ro -p 51337:1337 jamesread/olivetin

Once the command is executed successfully, go to localhost:51337 in your web browser to access the web interface shown in Figure 1.

Figure 1: The OliveTin web interface generated from Listing 1.

You now have an interface with two buttons. Try pressing both buttons individually or at the same time to see how the interface behaves. OliveTin simply runs the command specified for each button in Listing 1. Following the standard Unix-like convention, OliveTin treats commands with a non-zero return as a failure. OliveTin executes each button command with a default time out, which you can configure in seconds using the timeout value in Listing 1. Once the time out is reached, the command is killed.

To customize the action button icon as shown in Listing 1, you can use either an HTML image from the web or a Unicode emoji. You can find the HTML codes for many Unicode emojis online [3]. You can also save and use the icons in an offline mode (see the OliveTin documentation for instructions [2]).

Clicking on the Logs button (top right corner in Figure 1) displays the logs (Figure 2) of the commands that were executed when an action button was pressed.

Figure 2: The command log shows the actions executed for each button.

OliveTin offers further customization options. You can configure OliveTin to display command options as a text box or drop-down list showing the exact option type to validate. You can also hide the Actions and Logs buttons (top right) with hideNavigation: true in your config.yaml file or set logLevel to DEBUG, ERROR, WARN, or INFO. Listing 2 shows these configuration customizations in action in the updated config.yaml.

Listing 2

Updated config.yaml


Once you've updated the configuration file, you then need to run the following command for the new customizations to display in your web UI:

docker restart $(docker ps|grep olivetin|awk '{print $1}')

Thanks to the updates in Listing 2, your OliveTin web UI now has hidden navigation (Figure 3), a drop-down box to select delay time (Figure 4), and an error message that flashes when you try to ping with a non-int count (Figure 5).

Figure 3: Navigation is now hidden: You can no longer see the Actions and Logs buttons.
Figure 4: Delay the execution of the Hello FLOSS Rockstar!!! button via the delay drop-down field.
Figure 5: You get an error message if you enter an invalid argument.

Script Server

Script Server, a web UI for scripts, renders a web front end that will display all of your scripts configured to execute. You can configure each script execution with various visual controls to accept and verify different types of options and parameters that are passed to the respective script.

The Script Server web UI also provides different access control methods, making it a multiuser scripts execution portal. You can further configure the portal to filter who can see and execute the scripts.

To run Script Server out of the box, you can use Docker, with bind-mounted configurations and scripts. If some of your scripts cannot be run in a Docker container, you can run Script Server natively (see the Script Server wiki [4] for instructions).

To run a test version of Script Server, you first need to prepare the necessary configurations and scripts by executing the code from Listing 3 in a terminal. Then, launch the Script Server container using the command in Listing 4. Now, navigate to localhost:55000 in your web browser: The Script Server web UI is ready to execute your scripts (Figure 6).

Listing 3

Configuring and Preparing Scripts


Listing 4

Launching Script Server


Figure 6: The Script Server web interface.

If you click on the sleep hello script, you will see script controls, such as the drop-down list to select a delay value (Figure 7), as well as the EXECUTE and STOP buttons. You can also configure an option checkbox as shown in Figure 8. Other options include adding files for upload/download, IP input, and more, but these options are beyond the scope of this article. If you are interested in learning more about Script Server's other options, see the Script Server wiki [4] and the Script Server examples on GitHub [5].

Figure 7: A drop-down list lets you select a delay value.
Figure 8: Configure a checkbox to give your scripts additional control options.

In the bottom left corner of the main web page, you will find the HISTORY button, which lets you browse through a script's execution output (Figure 9).

Figure 9: History for the docker image prune script.

To fix the missing Docker command shown in the history in Figure 9, you need to create a Docker image with the missing Docker command-line interface necessary to successfully execute the docker image prune script. You can do this by executing the code in Listing 5.

Listing 5

Updated Docker Image


I have also added some basic authentication for the web UI using htpasswd. I used an online htpasswd generator [6] to generate .htpasswd file entries. Listing 6 generates an updated conf.json to showcase some new Script Server features that I added.

Listing 6

Updated conf.json


To remove the existing Script Server container, execute the following command:

docker rm -f $(docker ps|grep script-server|awk '{print $1}')

Then, launch a new instance of Script Server with the newly created image using the command shown in Listing 7.

Listing 7

Launching New Image


Once you refresh your browser page, you should see a login screen asking for your username and password (Figure 10). I also added test and admin users (the password is the same as the respective username) in the new Docker image; only these two users can log in to Script Server. In addition, I added a new log out functionality below HISTORY (bottom left), which allows switching between the configured users (Figure 11). You will also notice in Figure 11 that docker image prune now executes successfully.

Figure 10: Script Server login page.
Figure 11: Configured users can log out (bottom left), and docker image prune executes successfully.

When you switch to the admin user, you will see a wheel control (upper left, Figure 12). Clicking on this wheel will take you to an admin page where you can interactively add and/or configure the back-end scripts with all the possible properties (Figures 13 and 14), which is handy when you want to add your scripts quickly without swimming through the documentation and JSON configuration files. To successfully save your changes in interactive mode, you must remove the ro (read only) option from the Docker commands used (with the exception of the Docker socket bind mount).

Figure 12: Logged in as the admin user.
Figure 13: The Script Server admin page.
Figure 14: The Script Server interactive page lets you add and configure scripts.

With the information covered here, you should be able to get started and be productive right away with Script Server. The documentation [4] and examples [5] will help you to unleash Script Server's full potential.


With these simple, yet powerful utilities, you can create user-friendly front ends for your scripts without needing to delve into web programming. When it comes to wrapping your predefined shell commands in a web UI, OliveTin offers a simple button-based web UI that is quick to deploy. For more complicated use cases, Script Server provides a feature-rich web UI that offers detailed configuration and controls to drive your back-end scripts in controlled multiuser environments. As an added bonus, I've created a set of driver scripts, Dockerfiles, and Docker Compose manifests to set up and maintain the lifecycle of these Dockerized utilities using only single line commands available on my GitHub repository [7].

The Author

Ankur Kumar, a passionate free and open source hacker/researcher and seeker of mystical life knowledge, loves to explore cutting edge technologies, ancient sciences, quantum spirituality, various genres of music, and mystical literature and art. You can reach him at https://www.linkedin.com/in/richnusgeeks or visit his GitHub page (https://github.com/richnusgeeks) for other useful FOSS pieces.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Docker with OwnCloud

    Run your application smoothly and portably in the cloud with the Docker container system. This workshop takes a practical look deploying Docker with the OwnCloud cloud environment.

  • Tutorials – Docker

    You might think Docker is a tool reserved for gnarly sys admins, useful only to service companies that run complicated SaaS applications, but that is not true: Docker is useful for everybody.

  • Perl: Testing Modules with Docker

    If you want to distribute your programs across multiple platforms, you need to prepare them to run in foreign environments from the start. Linux container technology and the resource-conserving Docker project let you test your own Perl modules on several Linux distributions in one fell swoop.

  • Ansible Container Auto Deploy

    Streamline software deployment with Ansible and Docker containers.

  • Apache Suexec

    For many admins, the security of a web application is more important than its performance. If you have a web server with multiple users, the Suexec module can help you avoid problems associated with globally writable directories.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.