Automate everything you possibly can.
Date published: 2017-12-28
Last updated: 2018-09-05
Automate everything, starting with your environment.
Automate everything you possibly can from the very beginning before writing the first line of project code. This includes the set up of your development workstation, production servers, and QA environments. Although this can take a significant amount of time at the onset, it pays dividends later. You may be tempted to skip this step and go straight to project coding — don’t. At some point in time, you will have to reset your development machine or servers. You might as well be ready for the inevitable.
Ideally, you want the setting up of a machine/server environment down to a single command. Once this command is issued, your automated process (be it a script with resources, binary tool you’ve created, or boot image on a USB stick), walks you though all required steps of configuration, and at the same time asks for minimal input from you, the user.
Your automated process will detect errors along the way and terminate immediately upon failures. Because your automated method is so simple, painless, repeatable, well-thought out, and time-saving, you will never hesitate to run it. In a similar manner, automate your data backup and auditing, and keep them isolated. If you had to quickly reset your development OS environment and get back to work, how long would this take you?
Check your entire automated “process” into a version control system, because it too is a project. Running this process on a regular basis has the great side-effect of preparing you for future emergencies, minimizing downtime of production servers and development workstations, and also ensures that you keep your automation and its installation dependencies up-to-date.
The only time you should not consider automating an environment (or project) is in the case of a small server test or project prototype which has zero chance of going into production. Bear in mind, prototypes have a funny way of winding up in production.
If you have automated the set up of development and production servers and workstations, this paves the way for easier on-boarding of new team members.
Automate your project builds, testing, and deployment.
Once you have your environment configuration automated, the next step is to move towards automating your development workflow (builds, testing, and production deployments). For QA and production, you’ll likely need some sort of continuous integration server for running tests and rendering builds upon new commits, such as Gitlab (gitlab.com) + Docker images. If you've already created a non-interactive command line build tool that accepts arguments, integration with a CI server will be less painful when that time comes.
For a day-to-day development/test workflow, if possible, aim to get the whole thing down to a single command line tool.
Imagine how much faster your workflow could be if after making a code change, this single tool might do the following, given the right arguments:
- Provide the option to select a build variant
- Build the project
- Run any tests
- Deploy the build to various servers if the tests pass
- Tag a release
Bonus points for:
- Accepting command line arguments so the entire build process can be run non-interactively by your IDE or CI server
- Adding some spice to your script (bell for prompts, colored text, pv for showing progress indicators, speech output for fun, etc.)
- Having only one build to rule them all
- Getting any runtime project configs from the environment (not inside the build)
- Building in an update methodology for your project from the very beginning
- Providing an easy way to get logs during production
Case study: Raspberry Pi Captive Portal + Server
This personal project is running on a Raspberry Pi Zero W. When the Rpizw boots, it automatically starts a WIFI hotspot (a captive portal), which redirects all client requests (for all hosts) to an internal server. No internet-thru access is provided to AP guests and they are isolated from talking with one another. The server is written in plain old Java (no frameworks), with only two libraries (gson and sqlite-jdbc), and is deployed as a fat JAR with bundled resources. Oracle 32 bit hard float is being utilized on the Rpizw. There are cron jobs that monitor and restart the server, as well as update the LCD once per minute.
The Rpizw environment is configured with a single script, which has only a few user prompts along the way. The entire process takes about 15 minutes to prepare the Rpizw for development/production.
It performs the following steps:
- Unmounts all Raspbian images and SD cards on the desktop (OS X in this case)
- Locates the latest Raspbian lite image and hash from raspberrypi.org
- Checks to see if that image is cached locally and its hash is correct
- Downloads the Raspbian image if necessary, verifying hash after download
- Once downloaded and verified, extracts and mounts the image, and updates some options in the Rpizw boot partition
- creates an empty SSH file on the image (to enable SSH on the Rpizw), then unmounts the image
- Prompts the user to insert an SD card, asks the user to verify device location, writes the modified image to the SD card, then unmounts the SD card.
- Once writing is complete, it prompts the user to eject and insert the SD card into the Rpizw and connect it to the desktop via the OTG USB connector.
- Waits for the Rpizw to come online, automatically accepts its host signature and copies the workstation SSH key to the Rpizw using the default Raspbian user/pw combo, then prompts the user to create a new password for the pi user.
- It uses an Expect script to change the password for the pi user. From this point on, it uses the SSH key for auth and the password method is removed from the Rpizw.
- Installs all dependencies, scripts, crontab, iptable rules, writes/modifies various config files, installs Oracle Java 8 from a tarball, updates all libraries, and so on.
- After about 15 minutes, the Rpizw environment is ready and it asks the user if they’d like to run the server build script (build.sh)
Other articles on this web site:
- Certbot Automation for Java-based Servers (Cheat Sheet) | 2018-04-11
Ideas on how to automate Letsencrypt's certbot when you are running a Java-based server such as TomCat.
- Automating the set up of a Linux-based VPS (Cheat Sheet) | 2018-03-21
Considerations when configuring a Debian-based Linux VPS.
- Secure Server Implementation (Cheat Sheet) | 2018-09-05
Creating a secure Java server without using a framework.
- Designing a Server Monitoring and Alerting Service (Cheat Sheet) | 2018-09-05
A checklist of items when rolling your own server monitoring service.