caddygit icon indicating copy to clipboard operation
caddygit copied to clipboard

Support for Caddyfile

Open rigon opened this issue 3 years ago • 50 comments

rigon avatar Jan 03 '22 14:01 rigon

Hey @rigon This looks pretty good. I’ll try it out once and merge it today! Thanks for the PR

vrongmeal avatar Jan 04 '22 05:01 vrongmeal

Wow, that's awesome. Quite the PR! :smile:

mholt avatar Jan 04 '22 06:01 mholt

I would be onboard with testing this! I am completely new to Caddy and I need this plugin to replace my existing setup on my Apache server.

joeworkman avatar Jan 05 '22 08:01 joeworkman

Hey @joeworkman ! Definitely go for it :)

vrongmeal avatar Jan 05 '22 08:01 vrongmeal

I am a super n00b with Caddy. How would I take the source to compile it into a custom Caddy build? I have used xcaddy. Although I learned that I need to get it installed on my linux server in order to get a custom build working on that server.

I am happy to test if you can help me figure out how to build it.

joeworkman avatar Jan 05 '22 08:01 joeworkman

You don't need to install it on your Linux server in order to use a custom build there... Where did you learn that?

You can compile caddy from any machine, for any machine. Instructions are on this page: https://caddyserver.com/docs/build

mholt avatar Jan 05 '22 08:01 mholt

I thought that I would need to use xcaddy to build this on my linux server. When I built a custom build on my Mac earlier today, it would not run on my server (you helped me with that).

Its 1am now though. I'll check back in the morning.

joeworkman avatar Jan 05 '22 09:01 joeworkman

I thought that I would need to use xcaddy to build this on my linux server. When I built a custom build on my Mac earlier today, it would not run on my server (you helped me with that).

You can do what's called a cross-build on any machine, to build for a different OS/architecture. You just need to set the GOOS and GOARCH environment variables to the appropriate one for the target machine you're building for. (It's also how the https://caddyserver.com/download page works, you choose the OS/arch from the selection and the build server will make you a build for that platform)

Assuming your Linux server is x86 (not ARM) and 64-bit, then you would do:

GOOS=linux GOARCH=amd64 xcaddy build --with ...

Caddy works on almost every platform combination. There's a list of all the OSes and architectures Go supports here: https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63

francislavoie avatar Jan 05 '22 13:01 francislavoie

I would love to test this today. How can I use xcaddy to build with the version from this PR?

joeworkman avatar Jan 10 '22 19:01 joeworkman

I think this should work:

$ xcaddy build --with github.com/vrongmeal/caddygit=github.com/rigon/caddygit

mholt avatar Jan 10 '22 19:01 mholt

@mholt Thanks. That got me close. That errored out saying that I needed a local directory. I clone the other repo and an built it like this...

xcaddy build --with github.com/vrongmeal/caddygit=./caddygit

joeworkman avatar Jan 10 '22 21:01 joeworkman

I build caddy like this on my local Mac. Server is running Ubuntu.

GOOS=linux GOARCH=amd64 xcaddy build --with github.com/caddy-dns/cloudflare --with github.com/vrongmeal/caddygit/module/git=./caddygit

Here is my Caddyfile

{
    email [email protected]
    acme_dns cloudflare API_KEY_HERE
    order git before file_server
}
aspecthq.com {
    redir https://www.aspecthq.com{uri}
}
www.aspecthq.com {
    git /update "https://gitlab.com/joeworkman/aspecthq.com" /var/www/aspecthq.com
    root * /var/www/aspecthq.com
    log {
        output file /var/log/caddy/aspecthq.com/access.log {
            roll_size 3MiB
            roll_keep 5
            roll_keep_for 48h
        }
        format console
    }
    encode gzip zstd
    php_fastcgi unix//run/php/php8.1-fpm.sock
    file_server
    push
}

When I try to run caddy, I am getting the following error that the git directive is not registered.

adapting config using caddyfile: parsing caddyfile tokens for 'order': /etc/caddy/Caddyfile:13 - Error during parsing: git is not a registered directive

joeworkman avatar Jan 10 '22 22:01 joeworkman

Make sure you run the binary you built, not another version.

mholt avatar Jan 10 '22 22:01 mholt

Yes. I have verified that it's the server being used.

CleanShot 2022-01-10 at 15 09 17

joeworkman avatar Jan 10 '22 23:01 joeworkman

I don't know what that is, but it looks like there are two there that look the same.

mholt avatar Jan 10 '22 23:01 mholt

That is from the update-alternatives command from the Caddy docs...

https://caddyserver.com/docs/build#package-support-files-for-custom-builds-for-debianubunturaspbian

It does mean that /usr/bin/caddy is pointing to my version that is compile with Cloudflare and Git modules.

joeworkman avatar Jan 10 '22 23:01 joeworkman

Taking my server out of the mix...

  • I built caddy just as above for my Mac
  • I saved the above Caddyfile to my Mac
  • Then I started the newly compiled caddy on my Mac pointing to that config file.
caddy run --config Caddyfile

Here is the error that it produces.

2022/01/10 23:40:37.377	INFO	using provided configuration	{"config_file": "Caddyfile", "config_adapter": ""}
run: adapting config using caddyfile: parsing caddyfile tokens for 'order': Caddyfile:4 - Error during parsing: git is not a registered directive

joeworkman avatar Jan 10 '22 23:01 joeworkman

That's odd. And that's the only Caddy binary on your Mac? I'd feel more sure with a direct path like ./caddy instead of PATH usage, i.e. caddy.

If that's not it, I'm not sure... never seen that happen before. And you have verified the output of caddy list-modules?

mholt avatar Jan 10 '22 23:01 mholt

It's not my only caddy binary. However, if I run it with ./ it's the same results.

joeworkman avatar Jan 10 '22 23:01 joeworkman

The list-modules command does not list git.

admin.api.load
admin.api.metrics
admin.api.reverse_proxy
caddy.adapters.caddyfile
caddy.config_loaders.http
caddy.listeners.tls
caddy.logging.encoders.console
caddy.logging.encoders.filter
caddy.logging.encoders.filter.delete
caddy.logging.encoders.filter.ip_mask
caddy.logging.encoders.filter.replace
caddy.logging.encoders.json
caddy.logging.encoders.single_field
caddy.logging.writers.discard
caddy.logging.writers.file
caddy.logging.writers.net
caddy.logging.writers.stderr
caddy.logging.writers.stdout
caddy.storage.file_system
http
http.authentication.hashes.bcrypt
http.authentication.hashes.scrypt
http.authentication.providers.http_basic
http.encoders.gzip
http.encoders.zstd
http.handlers.acme_server
http.handlers.authentication
http.handlers.encode
http.handlers.error
http.handlers.file_server
http.handlers.headers
http.handlers.map
http.handlers.metrics
http.handlers.push
http.handlers.request_body
http.handlers.reverse_proxy
http.handlers.rewrite
http.handlers.static_response
http.handlers.subroute
http.handlers.templates
http.handlers.vars
http.matchers.expression
http.matchers.file
http.matchers.header
http.matchers.header_regexp
http.matchers.host
http.matchers.method
http.matchers.not
http.matchers.path
http.matchers.path_regexp
http.matchers.protocol
http.matchers.query
http.matchers.remote_ip
http.matchers.vars
http.matchers.vars_regexp
http.precompressed.br
http.precompressed.gzip
http.precompressed.zstd
http.reverse_proxy.selection_policies.cookie
http.reverse_proxy.selection_policies.first
http.reverse_proxy.selection_policies.header
http.reverse_proxy.selection_policies.ip_hash
http.reverse_proxy.selection_policies.least_conn
http.reverse_proxy.selection_policies.random
http.reverse_proxy.selection_policies.random_choose
http.reverse_proxy.selection_policies.round_robin
http.reverse_proxy.selection_policies.uri_hash
http.reverse_proxy.transport.fastcgi
http.reverse_proxy.transport.http
pki
tls
tls.certificates.automate
tls.certificates.load_files
tls.certificates.load_folders
tls.certificates.load_pem
tls.certificates.load_storage
tls.handshake_match.remote_ip
tls.handshake_match.sni
tls.issuance.acme
tls.issuance.internal
tls.issuance.zerossl
tls.stek.distributed
tls.stek.standard

  Standard modules: 83

dns.providers.cloudflare

  Non-standard modules: 1

  Unknown modules: 0

Is this command correct?

xcaddy build --with github.com/caddy-dns/cloudflare --with github.com/vrongmeal/caddygit=./caddygit 

joeworkman avatar Jan 10 '22 23:01 joeworkman

Ah... no, it's not. After looking closely at the structure of this repo, it turns out the module registration is NOT in the root of this repository. My bad for assuming.

The module is registered in github.com/vrongmeal/caddygit/module/git: https://github.com/vrongmeal/caddygit/blob/main/module/git/app.go

That's a bit unusual, so I didn't think to check for it.

mholt avatar Jan 10 '22 23:01 mholt

OK. This command works...

xcaddy build --with github.com/vrongmeal/caddygit/module/git

But this does not...

xcaddy build  --with github.com/vrongmeal/caddygit/module/git=./caddygit 

I need to reference the local folder since it contains this PR.

joeworkman avatar Jan 11 '22 00:01 joeworkman

Try:

xcaddy build  --with github.com/vrongmeal/caddygit/module/git=./caddygit/module/git

Edit: never mind...

github.com/vrongmeal/caddygit/module/git: module /Users/mohammed/caddygit/module/git: reading ../caddygit/module/git/go.mod: open /Users/mohammed/caddygit/module/git/go.mod: no such file or directory

The replace directive works on Go modules, not on packages, which is where the issue. We need to import github.com/vrongmeal/caddygit/module/git but replace github.com/vrongmeal/caddygit, which is tricky with xcaddy. Just a sec...

mohammed90 avatar Jan 11 '22 00:01 mohammed90

Got it. Try:

xcaddy build --with github.com/vrongmeal/caddygit/module/git  --with github.com/vrongmeal/caddygit=./caddygit

This will underscore-import github.com/vrongmeal/caddygit/module/git and github.com/vrongmeal/caddygit (the latter of which is harmless), but replaces github.com/vrongmeal/caddygit with the local directory.

mohammed90 avatar Jan 11 '22 00:01 mohammed90

I build caddy like this on my local Mac. Server is running Ubuntu.

GOOS=linux GOARCH=amd64 xcaddy build --with github.com/caddy-dns/cloudflare --with github.com/vrongmeal/caddygit/module/git=./caddygit

Here is my Caddyfile

{
    email [email protected]
    acme_dns cloudflare API_KEY_HERE
    order git before file_server
}
aspecthq.com {
    redir https://www.aspecthq.com{uri}
}
www.aspecthq.com {
    git /update "https://gitlab.com/joeworkman/aspecthq.com" /var/www/aspecthq.com
    root * /var/www/aspecthq.com
    log {
        output file /var/log/caddy/aspecthq.com/access.log {
            roll_size 3MiB
            roll_keep 5
            roll_keep_for 48h
        }
        format console
    }
    encode gzip zstd
    php_fastcgi unix//run/php/php8.1-fpm.sock
    file_server
    push
}

When I try to run caddy, I am getting the following error that the git directive is not registered.

adapting config using caddyfile: parsing caddyfile tokens for 'order': /etc/caddy/Caddyfile:13 - Error during parsing: git is not a registered directive

Adapter result (removing cloudflare):

{
	"logging": {
		"logs": {
			"default": {
				"exclude": [
					"http.log.access.log0"
				]
			},
			"log0": {
				"writer": {
					"filename": "/var/log/caddy/aspecthq.com/access.log",
					"output": "file",
					"roll_keep": 5,
					"roll_keep_days": 2,
					"roll_size_mb": 3
				},
				"encoder": {
					"format": "console"
				},
				"include": [
					"http.log.access.log0"
				]
			}
		}
	},
	"apps": {
		"http": {
			"servers": {
				"srv0": {
					"listen": [
						":443"
					],
					"routes": [
						{
							"match": [
								{
									"host": [
										"www.aspecthq.com"
									]
								}
							],
							"handle": [
								{
									"handler": "subroute",
									"routes": [
										{
											"handle": [
												{
													"handler": "vars",
													"root": "/var/www/aspecthq.com"
												},
												{
													"encodings": {
														"gzip": {},
														"zstd": {}
													},
													"handler": "encode",
													"prefer": [
														"gzip",
														"zstd"
													]
												},
												{
													"handler": "push"
												}
											]
										},
										{
											"handle": [
												{
													"handler": "static_response",
													"headers": {
														"Location": [
															"{http.request.uri.path}/"
														]
													},
													"status_code": 308
												}
											],
											"match": [
												{
													"file": {
														"try_files": [
															"{http.request.uri.path}/index.php"
														]
													},
													"not": [
														{
															"path": [
																"*/"
															]
														}
													]
												}
											]
										},
										{
											"handle": [
												{
													"handler": "rewrite",
													"uri": "{http.matchers.file.relative}"
												}
											],
											"match": [
												{
													"file": {
														"split_path": [
															".php"
														],
														"try_files": [
															"{http.request.uri.path}",
															"{http.request.uri.path}/index.php",
															"index.php"
														]
													}
												}
											]
										},
										{
											"handle": [
												{
													"handler": "reverse_proxy",
													"transport": {
														"protocol": "fastcgi",
														"split_path": [
															".php"
														]
													},
													"upstreams": [
														{
															"dial": "unix//run/php/php8.1-fpm.sock"
														}
													]
												}
											],
											"match": [
												{
													"path": [
														"*.php"
													]
												}
											]
										},
										{
											"handle": [
												{
													"commands_after": [
														{}
													],
													"handler": "git",
													"hook": null,
													"repo": {
														"path": "/var/www/aspecthq.com",
														"url": "https://gitlab.com/joeworkman/aspecthq.com"
													}
												}
											],
											"match": [
												{
													"path": [
														"/update"
													]
												}
											]
										},
										{
											"handle": [
												{
													"handler": "file_server",
													"hide": [
														"./Caddyfile"
													]
												}
											]
										}
									]
								}
							],
							"terminal": true
						},
						{
							"match": [
								{
									"host": [
										"aspecthq.com"
									]
								}
							],
							"handle": [
								{
									"handler": "subroute",
									"routes": [
										{
											"handle": [
												{
													"handler": "static_response",
													"headers": {
														"Location": [
															"https://www.aspecthq.com{http.request.uri}"
														]
													},
													"status_code": 302
												}
											]
										}
									]
								}
							],
							"terminal": true
						}
					],
					"logs": {
						"logger_names": {
							"www.aspecthq.com": "log0"
						},
						"skip_hosts": [
							"aspecthq.com"
						]
					}
				}
			}
		},
		"tls": {
			"automation": {
				"policies": [
					{
						"subjects": [
							"www.aspecthq.com",
							"aspecthq.com"
						],
						"issuers": [
							{
								"email": "[email protected]",
								"module": "acme"
							},
							{
								"email": "[email protected]",
								"module": "zerossl"
							}
						]
					}
				]
			}
		}
	}
}

mohammed90 avatar Jan 11 '22 00:01 mohammed90

That seems to have worked! I never would have guessed to try that.

joeworkman avatar Jan 11 '22 00:01 joeworkman

Thanks @mohammed90.

@joeworkman It's a nuance of how Go modules does replacements, I guess.

@vrongmeal Most Caddy modules have their registrations in the root of the repo, that does simplify some things. Please consider that, if you would :)

mholt avatar Jan 11 '22 00:01 mholt

So should this module not be using github.com/vrongmeal/caddygit/module/git? I assume that changing it to be github.com/vrongmeal/caddygit/ would break some backward compatibility? Or not since it's built into static binaries anyways.

joeworkman avatar Jan 11 '22 00:01 joeworkman

I have been trying to figure out the configuration here. I tried to look through the code of the plugin to figure out what is going on. I am completely new to Caddy and Go so it's a bit of overload. Here is what I have so far...

www.aspecthq.com {
    root * /var/www/aspecthq.com
    encode gzip zstd
    php_fastcgi unix//run/php/php8.1-fpm.sock
    file_server
    push
    git /update {
        url https://gitlab.com/joeworkman/aspecthq.com
        path /var/www/aspecthq.com
        branch master
    }
}

I thought that this may mean that if you go to URL https://aspecthq.com/update that it would simply trigger a git pull. That is not happening. This site is currently on GitLab but can easily move it to Github if I need to.

joeworkman avatar Jan 11 '22 02:01 joeworkman

I see this error in syslog

Jan 10 21:15:03 **** caddy[120153]: {"level":"error","ts":1641867303.8984256,"logger":"http.handlers.git","msg":"repository not setup","error":"cannot setup repository: worktree contains unstaged changes","path":"/var/www/aspecthq.com"}

It says that there are unstaged changes. However, there aren't any changes in /var/www/aspecthq.com

joeworkman avatar Jan 11 '22 02:01 joeworkman