I’m using Caddy to serve this site, and I wanted to use a Caddyfile, but with a little bit of JSON added on top to configure Layer4.

Basically I write my standard Caddyfile with my preferred options, convert the Caddyfile with caddy adapt and then use jq to add the Layer4 configuration.

I’ve got a shell script that does this for me, and I’ve got it running as a GitHub Action to automatically update my Caddyfile when I push changes to my repository.

My repository has a caddy folder with the following files:

./caddy
-- caddyfile
-- build-caddy.sh
-- layer4.txt

build-caddy.sh

#!/bin/bash

echo "Removing existing caddy.json file"
rm ./caddy.json

echo "Formatting Caddyfile"
caddy fmt --overwrite ./caddyfile
echo "Generating caddy.json file"
caddy adapt --config ./caddyfile --pretty --validate > caddy.json

echo "Reading layer4.txt"
layer4_content=$(<./layer4.txt)

echo "Inserting layer4 content into caddy.json"
jq --argjson layer4 "$layer4_content" '.apps.layer4 = $layer4' ./caddy.json > ./temp.json && mv ./temp.json ./caddy.json

deploy-caddy.yml

name: Deploy-caddy

on:
  push:
    branches:
      - main
    paths:
      - 'caddy/**'
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - uses: actions/checkout@v3

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

      - name: Execute build-caddy.sh
        run: |
          cd ./caddy
          chmod +x ./build-caddy.sh
          ./build-caddy.sh          
        shell: bash

      - name: Deploy-caddy
        uses: easingthemes/ssh-deploy@main
        with:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
          ARGS: "-rlgoDzvc -i"
          SOURCE: "./caddy/"
          REMOTE_HOST: drew.onl
          REMOTE_USER: <SSH USER>
          TARGET: <Caddyfile location>
          SCRIPT_AFTER: |
            sudo /usr/bin/systemctl reload caddy            
          

layer4.txt

This is based on the suggested configuration for reverse proxying ZNC.

ZNC > Reverse Proxy

{
    "servers": {
        "znc": {
            "listen": [
                ":1337"
            ],
            "routes": [
                {
                    "handle": [
                        {
                            "handler": "tls",
                            "connection_policies": [
                                {
                                    "alpn": [
                                        "http/1.1",
                                        "http/1.0"
                                    ],
                                    "default_sni": "drew.onl"
                                }
                            ]
                        },
                        {
                            "handler": "proxy",
                            "upstreams": [
                                {
                                    "dial": [
                                        "localhost:8090"
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    }
}