Skip to content

Environments/Variables

What are Environments?

Let’s assume you already have a production version of your project with active users. This means you should test your project before pushing any updates to production, not just locally but also on a server environment, simulating the experience of an external user. This ensures that any issues are caught before they affect production.

Here is where environments come in. They allow you to separate different versions of your application. For example, you can have two environments: production and testing. You decide what should be included in each environment and what can be shared across them. Usually, a Git branch corresponds to an environment, each with its own environment variables that can connect your app to resources like databases.

This chapter describes how to deploy different environments for the same application.

Defining Requirements for Our Environments

  • Each Git branch should represent a separate environment.
  • You can set environment variables that are accessible during runtime by your projects.
  • Each environment should have its own domain.

As before, we won’t be developing a new service from scratch. Instead, we’ll use a bash script that will be called by Caddy (a proxy server). To implement logic for environments, we will modify the script created for CI in the "CI and GitOps" chapter. This time, however, we will parse the body of a webhook received from a remote Git repository.

Creating a Script to Handle Webhooks from GitHub

Note: Bitbucket and GitLab use different webhook formats, which we will cover in a future version of this handbook.

  • Install the Caddy-CGI module to forward the webhook request to our deployment script. More details about this module can be found at Caddy CGI GitHub.
# Install Go
sudo wget https://go.dev/dl/go1.22.6.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.22.6.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

# Install Caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-xcaddy.list
sudo apt update
sudo apt install xcaddy

# Build Caddy with the exec module
xcaddy build --with github.com/aksdb/caddy-cgi/v2
sudo mv caddy /usr/bin/

# Set up the Caddy user and group
sudo groupadd --system caddy
sudo useradd --system --gid caddy --create-home --home-dir /var/lib/caddy --shell /usr/sbin/nologin --comment "Caddy web server" caddy
wget https://raw.githubusercontent.com/caddyserver/dist/master/init/caddy.service -O /etc/systemd/system/caddy.service
  • Install jq, a command-line JSON processor, to parse the webhook body in the deployment bash script:
sudo apt-get install jq
  • Create a script to check that webhooks are parsed correctly and save it to /usr/local/bin/deploy.sh:
#!/bin/bash

log_file="/var/log/deploy-log"

if [ "$REQUEST_METHOD" = "POST" ] && [ -n "$CONTENT_LENGTH" ]; then
  read -n "$CONTENT_LENGTH" POST_DATA
fi

REPOURL=$(jq -r ".repository.clone_url" <<< "$POST_DATA")
REPONAME=$(jq -r ".repository.name" <<< "$POST_DATA")

printf "New GitHub webhook \n\n" >> $log_file
printf "Repository URL:         [%s]\n" "$REPOURL"  >> $log_file
printf "Repository Name:        [%s]\n" "$REPONAME"  >> $log_file

exit 0
  • Update the Caddyfile to start the deployment script when the server receives a request at deploy.turbocloud.dev (replace with your own URL):
:80 {
  handle /deploy* {
    exec /usr/local/bin/deploy.sh
  }
}
  • Push changes to your remote Git repository and check the log file at /var/log/deploy-log to confirm that it contains the repository URL and name.

That’s it! You can now deploy different environments directly from GitHub.