commit
93b32220f1
@ -0,0 +1,35 @@
|
|||||||
|
FROM golang:1.13-alpine as builder
|
||||||
|
RUN apk add --no-cache git gcc musl-dev
|
||||||
|
RUN mkdir /www /caddy
|
||||||
|
COPY builder.sh /usr/bin/builder.sh
|
||||||
|
ARG version="1.0.5"
|
||||||
|
ARG enable_telemetry="true"
|
||||||
|
RUN VERSION=${version} /bin/sh /usr/bin/builder.sh
|
||||||
|
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
ENV CADDY_VERSION=1.0.5
|
||||||
|
|
||||||
|
ENV CADDYPATH=/caddy/certs
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
ca-certificates \
|
||||||
|
git \
|
||||||
|
mailcap \
|
||||||
|
openssh-client \
|
||||||
|
tzdata
|
||||||
|
|
||||||
|
|
||||||
|
COPY --from=builder /install/caddy /usr/bin/caddy
|
||||||
|
|
||||||
|
RUN /usr/bin/caddy -version
|
||||||
|
RUN /usr/bin/caddy -plugins
|
||||||
|
|
||||||
|
EXPOSE 80 443 2015
|
||||||
|
VOLUME /root/.caddy /www
|
||||||
|
WORKDIR /www
|
||||||
|
|
||||||
|
COPY Caddyfile /caddy/Caddyfile
|
||||||
|
|
||||||
|
CMD ["caddy","--conf", "/caddy/Caddyfile", "--log", "stdout", "--agree"]
|
@ -0,0 +1,90 @@
|
|||||||
|
# caddy_docker
|
||||||
|
|
||||||
|
this is a docker image for Caddy. Thanks to [abiosoft](https://github.com/abiosoft/caddy-docker)
|
||||||
|
|
||||||
|
## why to build it
|
||||||
|
|
||||||
|
the docker image from abiosoft has something wrong. I think it may have some wrong links/packages to get, and I try to use an unfriendly way to fix it.
|
||||||
|
|
||||||
|
## version
|
||||||
|
|
||||||
|
caddy v1.0.5
|
||||||
|
|
||||||
|
## default plugins
|
||||||
|
|
||||||
|
```dnspod```, ```filter```, ```cache```, ```minify```, ```expires```, ```realip```, ```cors```
|
||||||
|
|
||||||
|
## how to add more plugins
|
||||||
|
|
||||||
|
### nomally
|
||||||
|
|
||||||
|
1. go to the [official website for plugins](https://caddyserver.com/v1/docs/http.filter).(for filter as example)
|
||||||
|
|
||||||
|
2. click the 'Full documentation' in the website.
|
||||||
|
|
||||||
|
3. copy the packages/repository link as like ```github.com/echocat/caddy-filter/```.
|
||||||
|
|
||||||
|
4. add it into 'builder.sh' following where you can see the word like that ```"import/path/here"```
|
||||||
|
(note: don't foget the ```_``` in front of it)
|
||||||
|
|
||||||
|
5. it's ok.
|
||||||
|
|
||||||
|
### specially
|
||||||
|
|
||||||
|
as I know. some plugins you need do more things.(as cors for example).
|
||||||
|
|
||||||
|
1. do the same things like 1&2 in 'nomally'
|
||||||
|
|
||||||
|
2. you can see ```caddy``` folder in the repository, and in it there is a ```corsPlugin.go``` file.
|
||||||
|
|
||||||
|
3. open it can copy the content into ```builder.sh```.(you could see what I did, and just follow it to add other plugins like cors)
|
||||||
|
|
||||||
|
## build
|
||||||
|
|
||||||
|
I use docker-compose to build the image.
|
||||||
|
|
||||||
|
```docker
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
build:
|
||||||
|
context: ./caddy
|
||||||
|
container_name: caddy
|
||||||
|
environment:
|
||||||
|
- TZ=
|
||||||
|
- DNSPOD_API_KEY=
|
||||||
|
- DNSPOD_HTTP_TIMEOUT=10
|
||||||
|
volumes:
|
||||||
|
- ./caddy/data/Caddyfile:/caddy/Caddyfile
|
||||||
|
- ./caddy/data/certs:/caddy/certs
|
||||||
|
- ./caddy/data/.caddy:/root/.caddy
|
||||||
|
- ./www:/www/:rw
|
||||||
|
ports:
|
||||||
|
- 2015:2015
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- net-default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
you need change ```context``` to where your Dockerfile is.
|
||||||
|
|
||||||
|
### change environment.
|
||||||
|
|
||||||
|
```TZ``` is time zone.
|
||||||
|
|
||||||
|
if you use dnspod, you need ```DNSPOD_API_KEY``` like ```id,api_tokens```.
|
||||||
|
|
||||||
|
if you use cloudflare, you need ```CLOUDFLARE_EMAIL``` and ```CLOUDFLARE_API_KEY```
|
||||||
|
you can get it from [cloudflare]( https://dash.cloudflare.com/profile/api-tokens)
|
||||||
|
|
||||||
|
## what's more
|
||||||
|
|
||||||
|
you can get 'cloudflare' plugins from [it](https://github.com/caddyserver/dnsproviders/blob/master/cloudflare/cloudflare.go)
|
||||||
|
then you can do like ```specially``` to add it or to see how I add the ```dnspod``` plugins.
|
||||||
|
|
||||||
|
## Thanks
|
||||||
|
|
||||||
|
Thanks to [abiosoft](https://github.com/abiosoft/caddy-docker) again.
|
||||||
|
What's more detail about build caddy v1 you can see [caddy v1.0.5](https://github.com/caddyserver/caddy/tree/v1.0.5)
|
@ -0,0 +1,245 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
VERSION=${VERSION:-"1.0.5"}
|
||||||
|
IMPORT="github.com/caddyserver/caddy"
|
||||||
|
|
||||||
|
# add `v` prefix for version numbers
|
||||||
|
[ "$(echo $VERSION | cut -c1)" -ge 0 ] 2>/dev/null && VERSION="v$VERSION"
|
||||||
|
|
||||||
|
stage() {
|
||||||
|
STAGE="$1"
|
||||||
|
echo
|
||||||
|
echo starting stage: $STAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
end_stage() {
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
>&2 echo error at \'$STAGE\'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo finished stage: $STAGE ✓
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module() {
|
||||||
|
mkdir -p /caddy
|
||||||
|
cd /caddy # build dir
|
||||||
|
|
||||||
|
# main and telemetry
|
||||||
|
cat > main.go <<EOF
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"github.com/caddyserver/caddy"
|
||||||
|
"github.com/caddyserver/caddy/caddy/caddymain"
|
||||||
|
"github.com/caddyserver/caddy/caddyhttp/httpserver"
|
||||||
|
"github.com/captncraig/cors"
|
||||||
|
// plug in plugins here, for example:
|
||||||
|
// _ "import/path/here"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/caddyserver/caddy/caddytls"
|
||||||
|
"github.com/go-acme/lego/v3/providers/dns/dnspod"
|
||||||
|
_ "github.com/echocat/caddy-filter"
|
||||||
|
_ "github.com/nicolasazrak/caddy-cache"
|
||||||
|
_ "github.com/hacdias/caddy-minify"
|
||||||
|
_ "github.com/epicagency/caddy-expires"
|
||||||
|
_ "github.com/captncraig/caddy-realip"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
caddytls.RegisterDNSProvider("dnspod", NewDNSProvider)
|
||||||
|
caddy.RegisterPlugin("cors", caddy.Plugin{
|
||||||
|
ServerType: "http",
|
||||||
|
Action: setup,
|
||||||
|
})
|
||||||
|
// optional: disable telemetry
|
||||||
|
caddymain.EnableTelemetry = false
|
||||||
|
caddymain.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDNSProvider(credentials ...string) (caddytls.ChallengeProvider, error) {
|
||||||
|
switch len(credentials) {
|
||||||
|
case 0:
|
||||||
|
return dnspod.NewDNSProvider()
|
||||||
|
case 1:
|
||||||
|
config := dnspod.NewDefaultConfig()
|
||||||
|
config.LoginToken = credentials[0]
|
||||||
|
return dnspod.NewDNSProviderConfig(config)
|
||||||
|
default:
|
||||||
|
return nil, errors.New("invalid credentials length")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type corsRule struct {
|
||||||
|
Conf *cors.Config
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup(c *caddy.Controller) error {
|
||||||
|
rules, err := parseRules(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
siteConfig := httpserver.GetConfig(c)
|
||||||
|
siteConfig.AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
||||||
|
return httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
for _, rule := range rules {
|
||||||
|
if httpserver.Path(r.URL.Path).Matches(rule.Path) {
|
||||||
|
rule.Conf.HandleRequest(w, r)
|
||||||
|
if cors.IsPreflight(r) {
|
||||||
|
return 200, nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRules(c *caddy.Controller) ([]*corsRule, error) {
|
||||||
|
rules := []*corsRule{}
|
||||||
|
|
||||||
|
for c.Next() {
|
||||||
|
rule := &corsRule{Path: "/", Conf: cors.Default()}
|
||||||
|
args := c.RemainingArgs()
|
||||||
|
|
||||||
|
anyOrigins := false
|
||||||
|
if len(args) > 0 {
|
||||||
|
rule.Path = args[0]
|
||||||
|
}
|
||||||
|
for i := 1; i < len(args); i++ {
|
||||||
|
if !anyOrigins {
|
||||||
|
rule.Conf.AllowedOrigins = nil
|
||||||
|
}
|
||||||
|
rule.Conf.AllowedOrigins = append(rule.Conf.AllowedOrigins, strings.Split(args[i], ",")...)
|
||||||
|
anyOrigins = true
|
||||||
|
}
|
||||||
|
for c.NextBlock() {
|
||||||
|
switch c.Val() {
|
||||||
|
case "origin":
|
||||||
|
if !anyOrigins {
|
||||||
|
rule.Conf.AllowedOrigins = nil
|
||||||
|
}
|
||||||
|
args := c.RemainingArgs()
|
||||||
|
for _, domain := range args {
|
||||||
|
rule.Conf.AllowedOrigins = append(rule.Conf.AllowedOrigins, strings.Split(domain, ",")...)
|
||||||
|
}
|
||||||
|
anyOrigins = true
|
||||||
|
case "origin_regexp":
|
||||||
|
if arg, err := singleArg(c, "origin_regexp"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
r, err := regexp.Compile(arg)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, c.Errf("could no compile regexp: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !anyOrigins {
|
||||||
|
rule.Conf.AllowedOrigins = nil
|
||||||
|
anyOrigins = true
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.Conf.OriginRegexps = append(rule.Conf.OriginRegexps, r)
|
||||||
|
}
|
||||||
|
case "methods":
|
||||||
|
if arg, err := singleArg(c, "methods"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
rule.Conf.AllowedMethods = arg
|
||||||
|
}
|
||||||
|
case "allow_credentials":
|
||||||
|
if arg, err := singleArg(c, "allow_credentials"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
var b bool
|
||||||
|
if arg == "true" {
|
||||||
|
b = true
|
||||||
|
} else if arg != "false" {
|
||||||
|
return nil, c.Errf("allow_credentials must be true or false.")
|
||||||
|
}
|
||||||
|
rule.Conf.AllowCredentials = &b
|
||||||
|
}
|
||||||
|
case "max_age":
|
||||||
|
if arg, err := singleArg(c, "max_age"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
i, err := strconv.Atoi(arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, c.Err("max_age must be valid int")
|
||||||
|
}
|
||||||
|
rule.Conf.MaxAge = i
|
||||||
|
}
|
||||||
|
case "allowed_headers":
|
||||||
|
if arg, err := singleArg(c, "allowed_headers"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
rule.Conf.AllowedHeaders = arg
|
||||||
|
}
|
||||||
|
case "exposed_headers":
|
||||||
|
if arg, err := singleArg(c, "exposed_headers"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
rule.Conf.ExposedHeaders = arg
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, c.Errf("Unknown cors config item: %s", c.Val())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
return rules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func singleArg(c *caddy.Controller, desc string) (string, error) {
|
||||||
|
args := c.RemainingArgs()
|
||||||
|
if len(args) != 1 {
|
||||||
|
return "", c.Errf("%s expects exactly one argument", desc)
|
||||||
|
}
|
||||||
|
return args[0], nil
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# setup module
|
||||||
|
go mod init caddy
|
||||||
|
go get -v $IMPORT@$VERSION
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# caddy source
|
||||||
|
stage "fetching caddy source"
|
||||||
|
git clone https://github.com/caddyserver/caddy -b "$VERSION" /go/src/$IMPORT \
|
||||||
|
&& cd /go/src/$IMPORT
|
||||||
|
end_stage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# check for modules support
|
||||||
|
export GO111MODULE=on
|
||||||
|
|
||||||
|
# add plugins and telemetry
|
||||||
|
stage "customising plugins and telemetry"
|
||||||
|
module
|
||||||
|
end_stage
|
||||||
|
|
||||||
|
# build
|
||||||
|
stage "building caddy"
|
||||||
|
go build -o caddy
|
||||||
|
end_stage
|
||||||
|
|
||||||
|
# copy binary
|
||||||
|
stage "copying binary"
|
||||||
|
mkdir -p /install \
|
||||||
|
&& mv caddy /install \
|
||||||
|
&& /install/caddy -version
|
||||||
|
end_stage
|
||||||
|
|
||||||
|
echo "installed caddy version $VERSION at /install/caddy"
|
Loading…
Reference in new issue