docs: improve Caddyfile header and note about misconfigured caddy service, minor docs update

This commit is contained in:
Pasha Sviderski
2025-12-22 16:31:15 +10:00
parent 65e9cdd444
commit 2345ee9856
6 changed files with 50 additions and 24 deletions
+8 -3
View File
@@ -12,14 +12,16 @@ import (
"strconv"
"strings"
"text/template"
"time"
"github.com/psviderski/uncloud/internal/machine/store"
"github.com/psviderski/uncloud/pkg/api"
)
const (
caddyfileHeader = `# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
caddyfileHeaderFmt = `# Caddyfile autogenerated by Uncloud (DO NOT EDIT): %s
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
`
caddyfileTemplate = `# Health check endpoint to verify Caddy reachability on this machine.
http:// {
@@ -56,7 +58,9 @@ https://{{$hostname}} {
}{{end}}
`
caddyfileUnavailabeFooter = `# NOTE: User-defined configs for services were skipped because Caddy is not running on this machine
# or the latest generated config is invalid. Please check the Caddy logs if it's running.
# (not accessible via the shared admin socket /run/uncloud/caddy/admin.sock) or the latest
# generated config is invalid. Please check the service 'caddy' is running (uc inspect caddy)
# and its logs for more details (uc logs caddy).
`
)
@@ -120,6 +124,7 @@ func (g *CaddyfileGenerator) Generate(
return "", fmt.Errorf("generate base Caddyfile from service ports: %w", err)
}
caddyfileHeader := fmt.Sprintf(caddyfileHeaderFmt, time.Now().UTC().Format(time.RFC3339))
if !includeCustom {
return fmt.Sprintf("%s\n%s\n%s", caddyfileHeader, caddyfile, caddyfileUnavailabeFooter), nil
}
+30 -13
View File
@@ -3,6 +3,7 @@ package caddyconfig
import (
"context"
"errors"
"regexp"
"strings"
"testing"
"time"
@@ -17,8 +18,17 @@ import (
"github.com/stretchr/testify/require"
)
const testCaddyfileHeader = `# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
// generatedTimestampRegex matches the "(DO NOT EDIT): <RFC3339 timestamp>" part of the header.
var generatedTimestampRegex = regexp.MustCompile(`\(DO NOT EDIT\): \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z`)
// normaliseGeneratedTimestamp replaces dynamic timestamps with a placeholder for test comparison.
func normaliseGeneratedTimestamp(caddyfile string) string {
return generatedTimestampRegex.ReplaceAllString(caddyfile, "(DO NOT EDIT): TIMESTAMP_PLACEHOLDER")
}
const testCaddyfileHeader = `# Caddyfile autogenerated by Uncloud (DO NOT EDIT): TIMESTAMP_PLACEHOLDER
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
# Health check endpoint to verify Caddy reachability on this machine.
http:// {
@@ -190,7 +200,7 @@ https://secure.example.com {
}
require.NoError(t, err)
assert.Equal(t, tt.want, config, "Generated Caddyfile doesn't match")
assert.Equal(t, tt.want, normaliseGeneratedTimestamp(config), "Generated Caddyfile doesn't match")
})
}
}
@@ -216,8 +226,9 @@ func TestCaddyfileGeneratorWithCustomConfigs(t *testing.T) {
time.Now(),
),
},
want: `# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
want: `# Caddyfile autogenerated by Uncloud (DO NOT EDIT): TIMESTAMP_PLACEHOLDER
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
# User-defined global config from service 'caddy'.
# Global Caddy configuration
@@ -412,8 +423,9 @@ web.example.com {
time.Now(),
),
},
want: `# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
want: `# Caddyfile autogenerated by Uncloud (DO NOT EDIT): TIMESTAMP_PLACEHOLDER
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
# User-defined global config from service 'caddy'.
# Global config
@@ -649,8 +661,9 @@ badconfig.com {
time.Now(),
),
},
want: `# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
want: `# Caddyfile autogenerated by Uncloud (DO NOT EDIT): TIMESTAMP_PLACEHOLDER
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
# User-defined global config from service 'caddy'.
# Global config from test machine
@@ -831,7 +844,7 @@ valid.example.com {
}
require.NoError(t, err)
assert.Equal(t, tt.want, config, "Generated Caddyfile doesn't match")
assert.Equal(t, tt.want, normaliseGeneratedTimestamp(config), "Generated Caddyfile doesn't match")
})
}
}
@@ -926,7 +939,9 @@ http://api.example.com {
}
# NOTE: User-defined configs for services were skipped because Caddy is not running on this machine
# or the latest generated config is invalid. Please check the Caddy logs if it's running.
# (not accessible via the shared admin socket /run/uncloud/caddy/admin.sock) or the latest
# generated config is invalid. Please check the service 'caddy' is running (uc inspect caddy)
# and its logs for more details (uc logs caddy).
`,
},
{
@@ -950,7 +965,9 @@ http://api.example.com {
}
# NOTE: User-defined configs for services were skipped because Caddy is not running on this machine
# or the latest generated config is invalid. Please check the Caddy logs if it's running.
# (not accessible via the shared admin socket /run/uncloud/caddy/admin.sock) or the latest
# generated config is invalid. Please check the service 'caddy' is running (uc inspect caddy)
# and its logs for more details (uc logs caddy).
`,
},
}
@@ -964,7 +981,7 @@ http://api.example.com {
config, err := generator.Generate(ctx, tt.containers, false)
require.NoError(t, err)
assert.Equal(t, tt.want, config, "Generated Caddyfile doesn't match")
assert.Equal(t, tt.want, normaliseGeneratedTimestamp(config), "Generated Caddyfile doesn't match")
})
}
}
+2 -2
View File
@@ -293,7 +293,7 @@ func TestDeployment(t *testing.T) {
config, err := cli.Caddy.GetConfig(ctx, nil)
require.NoError(t, err)
assert.Contains(t, config.Caddyfile, "# This file is autogenerated by Uncloud")
assert.Contains(t, config.Caddyfile, "# Caddyfile autogenerated by Uncloud")
assert.Contains(t, config.Caddyfile, "handle /.uncloud-verify")
})
@@ -423,7 +423,7 @@ myapp.example.com {
}, 5*time.Second, 100*time.Millisecond,
"Expected both custom configs to be included in the Caddyfile")
assert.Contains(t, config.Caddyfile, "# This file is autogenerated by Uncloud")
assert.Contains(t, config.Caddyfile, "# Caddyfile autogenerated by Uncloud")
assert.Contains(t, config.Caddyfile, "handle /.uncloud-verify")
assert.Contains(t, config.Caddyfile, caddyCaddyfile,
"Expected user-defined global Caddy config to be included in the Caddyfile")
@@ -10,7 +10,7 @@ with [Let's Encrypt](https://letsencrypt.org/), and route requests to your servi
## How it works
By default, Caddy runs as a global service `caddy` on every machine in your cluster, listening on the host ports 80
(HTTP) and 443 (HTTPS).
(HTTP), 443 (HTTPS), and 443/UDP (HTTP/3).
It's deployed during cluster initialisation (`uc machine init`) unless you use the `--no-caddy` flag.
See [Managing Caddy](3-managing-caddy.md) for deployment and customisation instructions.
@@ -197,8 +197,9 @@ debugging and verifying your `x-caddy` configs.
Example output:
```caddyfile
# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
# Caddyfile autogenerated by Uncloud (DO NOT EDIT): 2025-12-20T22:43:56Z
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
# User-defined global config from service 'caddy'.
*.example.com {
@@ -94,6 +94,7 @@ services:
x-ports:
- 80:80@host
- 443:443@host
- 443:443/udp@host
x-caddy: Caddyfile
deploy:
mode: global
@@ -138,7 +139,8 @@ internal.example.com {
:::info note
The specified `command`, `environment`, `volumes`, and `x-ports` properties are essential for Caddy to function
correctly in the Uncloud cluster.
correctly in the Uncloud cluster. Do not change the source paths of the volume mounts as the Uncloud daemon relies on
them to communicate with Caddy and update its configuration.
:::
@@ -160,8 +162,9 @@ uc caddy config
Example output:
```caddyfile
# This file is autogenerated by Uncloud based on the configuration of running services.
# Do not edit manually. Any manual changes will be overwritten on the next update.
# Caddyfile autogenerated by Uncloud (DO NOT EDIT): 2025-12-22T10:30:12Z
# Automatically updated on service or health status changes.
# Docs: https://uncloud.run/docs/concepts/ingress/overview
# User-defined global config from service 'caddy'.
# Global options.