diff --git a/cmd/uncloud/caddy/deploy.go b/cmd/uncloud/caddy/deploy.go index 5a790b90..dd99472c 100644 --- a/cmd/uncloud/caddy/deploy.go +++ b/cmd/uncloud/caddy/deploy.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "maps" + "os" "slices" "strings" @@ -18,9 +19,10 @@ import ( ) type deployOptions struct { - image string - machines []string - context string + caddyfile string + image string + machines []string + context string } func NewDeployCommand() *cobra.Command { @@ -37,6 +39,8 @@ func NewDeployCommand() *cobra.Command { }, } + cmd.Flags().StringVar(&opts.caddyfile, "caddyfile", "", + "Path to a custom global Caddy config (Caddyfile) that will be prepended to the auto-generated Caddy config.") cmd.Flags().StringVar(&opts.image, "image", "", "Caddy Docker image to deploy. (default caddy:LATEST_VERSION)") cmd.Flags().StringSliceVarP(&opts.machines, "machine", "m", nil, @@ -51,6 +55,15 @@ func NewDeployCommand() *cobra.Command { } func runDeploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error { + caddyfile := "" + if opts.caddyfile != "" { + data, err := os.ReadFile(opts.caddyfile) + if err != nil { + return fmt.Errorf("read Caddyfile: %w", err) + } + caddyfile = strings.TrimSpace(string(data)) + } + clusterClient, err := uncli.ConnectCluster(ctx, opts.context) if err != nil { return fmt.Errorf("connect to cluster: %w", err) @@ -91,7 +104,7 @@ func runDeploy(ctx context.Context, uncli *cli.CLI, opts deployOptions) error { placement := api.Placement{ Machines: cli.ExpandCommaSeparatedValues(opts.machines), } - d, err := clusterClient.NewCaddyDeployment(opts.image, "", placement) + d, err := clusterClient.NewCaddyDeployment(opts.image, caddyfile, placement) if err != nil { return fmt.Errorf("create caddy deployment: %w", err) } diff --git a/cmd/uncloud/service/run.go b/cmd/uncloud/service/run.go index 7df49f21..3ee5f6d4 100644 --- a/cmd/uncloud/service/run.go +++ b/cmd/uncloud/service/run.go @@ -17,6 +17,7 @@ import ( ) type runOptions struct { + caddyfile string command []string cpu dockeropts.NanoCPUs entrypoint string @@ -57,6 +58,9 @@ func NewRunCommand() *cobra.Command { }, } + cmd.Flags().StringVar(&opts.caddyfile, "caddyfile", "", + "Path to a custom Caddy config (Caddyfile) for the service. "+ + "Cannot be used together with non-@host published ports.") cmd.Flags().VarP(&opts.cpu, "cpu", "", "Maximum number of CPU cores a service container can use. Fractional values are allowed: "+ "0.5 for half a core or 2.25 for two and a quarter cores.") @@ -161,6 +165,15 @@ func run(ctx context.Context, uncli *cli.CLI, opts runOptions) error { func prepareServiceSpec(opts runOptions) (api.ServiceSpec, error) { var spec api.ServiceSpec + caddyfile := "" + if opts.caddyfile != "" { + data, err := os.ReadFile(opts.caddyfile) + if err != nil { + return spec, fmt.Errorf("read Caddyfile: %w", err) + } + caddyfile = strings.TrimSpace(string(data)) + } + env, err := parseEnv(opts.env) if err != nil { return spec, err @@ -218,6 +231,12 @@ func prepareServiceSpec(opts runOptions) (api.ServiceSpec, error) { Volumes: volumes, } + if caddyfile != "" { + spec.Caddy = &api.CaddySpec{ + Config: caddyfile, + } + } + // Overwrite the default ENTRYPOINT of the image or reset it if an empty string is passed. if opts.entrypoint != "" { spec.Container.Entrypoint = []string{opts.entrypoint}