├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Caddyfile ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── docker-compose.travis.yml ├── examples ├── Caddyfile.proxy.example ├── docker-compose.example.yml └── docker-compose.proxy-example.yml ├── public └── index.html └── tests └── caddy.bats /.dockerignore: -------------------------------------------------------------------------------- 1 | LICENSE* 2 | README* 3 | .git 4 | .dockerignore 5 | .travis.yml 6 | public/ 7 | .imdone 8 | .gitignore 9 | CONTRIBUTING.md 10 | docker-compose.travis.yml 11 | SECURITY.md 12 | tests/ 13 | examples/ 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 4 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.yml linguist-language=Dockerfile 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | ehthumbs.db 9 | Thumbs.db 10 | .imdone 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: go 3 | services: 4 | - docker 5 | env: 6 | global: 7 | - DOCKER_VERSION=1.12.0-0~trusty 8 | - DOCKER_COMPOSE_VERSION=1.7.0 9 | branches: 10 | except: 11 | - /^v\d/ 12 | before_install: 13 | - apt-cache madison docker-engine 14 | - sudo apt-get update -q 15 | # - sudo apt-get -o Dpkg::Options::="--force-confnew" install -y --force-yes docker-engine=${DOCKER_VERSION} 16 | - sudo rm /usr/local/bin/docker-compose 17 | - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname 18 | -s`-`uname -m` > docker-compose 19 | - chmod +x docker-compose 20 | - sudo mv docker-compose /usr/local/bin 21 | - sudo add-apt-repository ppa:duggan/bats --yes 22 | - sudo apt-get update -qq 23 | - sudo apt-get install -qq bats 24 | - curl -s https://raw.githubusercontent.com/ZZROTDesign/docker-clean/master/docker-clean | sudo tee /usr/local/bin/docker-clean > /dev/null && sudo chmod +x /usr/local/bin/docker-clean 25 | install: 26 | - docker-compose -f docker-compose.travis.yml build 27 | script: 28 | - docker version 29 | - docker-compose version 30 | - bats tests/caddy.bats 31 | notifications: 32 | email: 33 | on_success: never 34 | slack: 35 | secure: Q9Iaa3DQacVbmEhCiBUj6JxVPHm3CrBHBmIgDolp7A4pe4U4GJytrTXJVRArWfu6HA9FP678Hm+h3Mh1xNiCB28VIpESHqQ4qaYKuPidM7YVLVezGXgL473fjdc3W9yZ/+GyHolqWdncXC4530IvcmLN6gIi8mUm+wYKjnZNHN/DUfBOQ52VtRs+HiriFZVFL3NNHAJJgtSkaNVs7f//KQidMTqFvnmkvnpQnOEjWSYIMJ+f7AxPdXis0wOIADhC0/r6fhHddrjIQ93JaHbji8kpWLSoQH9RAmHBCglE94cINd4nOGoTuAK+eZjGNaxJAWgSilc1mZYWdibv2kRXaMHVf1K801whqXyMLL6f3ikUB6KsEQuYIPgOkKas+gI0YzAlicRc3Tbvk94FNnS3XPM5D1jzX4iluqDPoABZ66JNts/EGuHJ3i2dPuJCfxOVJVoBXbkJiIhNicpfrBiw+W5Od+ZJswGys3TsCV6Ou0WdUKk6WFYTnOb3ND2tAn9R+LiFffNBxd+pymaSGAINH/SsWeAWF9pjjcOiUzJzsNuz5hXk3sE+PKBlnamuxaG0NmefWrLtRW7CvTET+G/+EIoaOw2qJxqeoqytRdm9qjekSkJ5Twc226vue1nLl9XgLRcn/PGCyDG4Z3jNEZ5a+sqL21Qvknum7YTnQQSL7ns= 36 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Alpine-Caddy 2 | 3 | ## Team members 4 | 5 | * [Sean Kilgarriff](https://github.com/Skilgarriff) sean@zzrot.com T: [@seankilgarriff](https://twitter.com/SeanKilgarriff) 6 | * [Killian Brackey](https://github.com/killianbrackey) killian@zzrot.com T: [@kmbrackey](https://twitter.com/kmbrackey) 7 | 8 | Don't hesitate to get in contact with either one of us with problems, questions, etc. 9 | 10 | 11 | ## Adding new features 12 | 13 | * Fork it! 14 | * Create your feature branch: git checkout -b my-new-feature 15 | * Commit your changes: git commit -am 'Add some feature' 16 | * Push to the branch: git push origin my-new-feature 17 | * Submit a pull request :D 18 | 19 | 20 | Don’t get discouraged! We estimate that the response time from the 21 | maintainers is around: 24 hours. 22 | -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | 0.0.0.0:80 2 | 3 | root /var/www/html 4 | 5 | log stdout 6 | 7 | errors stdout 8 | 9 | ext .html .htm .php 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:edge 2 | MAINTAINER ZZROT LLC 3 | 4 | RUN apk --no-cache add tini git openssh-client \ 5 | && apk --no-cache add --virtual devs tar curl 6 | 7 | #Install Caddy Server, and All Middleware 8 | RUN curl "https://caddyserver.com/download/build?os=linux&arch=amd64&features=DNS%2Cawslambda%2Ccors%2Cexpires%2Cfilemanager%2Cgit%2Chugo%2Cipfilter%2Cjsonp%2Cjwt%2Clocale%2Cmailout%2Cminify%2Cmultipass%2Cprometheus%2Cratelimit%2Crealip%2Csearch%2Cupload%2Ccloudflare%2Cdigitalocean%2Cdnsimple%2Cdyn%2Cgandi%2Cgooglecloud%2Clinode%2Cnamecheap%2Crfc2136%2Croute53%2Cvultr" \ 9 | | tar --no-same-owner -C /usr/bin/ -xz caddy 10 | 11 | #Remove build devs 12 | RUN apk del devs 13 | 14 | #Copy over a default Caddyfile 15 | COPY ./Caddyfile /etc/Caddyfile 16 | 17 | #USER caddy 18 | 19 | ENTRYPOINT ["/sbin/tini"] 20 | 21 | CMD ["caddy", "-quic", "--conf", "/etc/Caddyfile"] 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 ZZROT LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Caddy Server on Alpine Linux 2 | 3 | [![](https://badge.imagelayers.io/zzrot/alpine-caddy:latest.svg)](https://imagelayers.io/?images=zzrot/alpine-caddy:latest 'Get your own badge on imagelayers.io') [![Build Status](https://travis-ci.org/ZZROTDesign/alpine-caddy.svg?branch=master)](https://travis-ci.org/ZZROTDesign/alpine-caddy) [![Docker Pulls](https://img.shields.io/docker/pulls/zzrot/alpine-caddy.svg?maxAge=2592000)](https://hub.docker.com/r/zzrot/alpine-caddy/) 4 | 5 | This is a [Docker](https://www.docker.com/) image for [Caddyserver](https://caddyserver.com/). This image runs with a base of [Alpine-Linux](http://www.alpinelinux.org/) making it extremely small, secure and fast. 6 | 7 | This image can also be found on [Docker Hub](https://hub.docker.com/r/zzrot/alpine-caddy/). 8 | 9 | ## Usage 10 | We recommend using our images in conjunction with [Docker-Compose](https://docs.docker.com/compose/). This allows for easier creation of containers with the proper volumes and ports enabled. 11 | 12 | We have included an [example docker-compose](https://github.com/ZZROTDesign/alpine-caddy/tree/master/examples/docker-compose.example.yml) file for use in a real project. 13 | 14 | This image works with two defaults 15 | 16 | 1. A default [Caddyfile](https://github.com/ZZROTDesign/alpine-caddy/tree/master/Caddyfile) 17 | 2. A default location inside the container for static files: /var/www/html 18 | 19 | In order to use this image, we recommend running it with a volume connecting your static files to the root location of the docker file: 20 | 21 | docker run -d -p 80:80 -v $(pwd)/public:/var/www/html zzrot/alpine-caddy 22 | 23 | The server will be available at your.docker.machine.ip. 24 | 25 | This is the bare minimum needed to use this image. Although further customization is made easier with a docker-compose file. 26 | 27 | The benefits of building an image with a overrideable Caddyfile are that you can include your own by including another volume. To see a fully configured docker-compose file see this [example](https://github.com/ZZROTDesign/alpine-caddy/tree/master/examples/docker-compose.example.yml). 28 | 29 | For writing a custom Caddyfile please read [this](https://caddyserver.com/docs/caddyfile). 30 | 31 | ### Middleware 32 | 33 | Alpine-Caddy includes all Caddy Middleware and features. You can read more on these specific features in the [Caddy User Guide](https://caddyserver.com/docs). 34 | 35 | ### Caddy as a reverse proxy 36 | 37 | This image can also effectively be used as a reverse proxy. Included in the examples/ folder is an [example Caddyfile](https://github.com/ZZROTDesign/alpine-caddy/tree/master/examples/Caddyfile.proxy.example). 38 | 39 | The [example docker-compose](https://github.com/ZZROTDesign/alpine-caddy/tree/master/examples/docker-compose.proxy-example.yml) shows how to include your custom Caddyfile as a volume as well as an example proxy set up with containers. 40 | 41 | ## Volumes 42 | 43 | Alpine-Caddy has three locations where volumes can be linked to. 44 | 45 | ### Static Files 46 | 47 | In order to serve static content, alpine-caddy needs to be able to access your static files from inside of the container. To do this, link the directory of your static files with /var/www/html inside of the container. 48 | 49 | For docker-compose.yml files, under the volumes declaration, include: 50 | 51 | - ./public:/var/www/html 52 | 53 | or 54 | 55 | docker run -v $(pwd)/public:/var/www/html 56 | 57 | ### Custom Caddyfile 58 | 59 | To upload a custom Caddyfile, link your Caddyfile to the directory /etc/Caddyfile in the container. 60 | For docker-compose.yml files, under the volumes declaration, include: 61 | 62 | - ./Caddyfile:/etc/Caddyfile 63 | 64 | or 65 | 66 | docker run -v $(pwd)/Caddyfile:/etc/Caddyfile zzrot/alpine-caddy 67 | 68 | ### Certificate Persistance 69 | 70 | If you use alpine-caddy to generate SSL certificates from [Let's Encrypt](https://letsencrypt.org/), you should persist those certificates outside of the container. In the instance of a container failure, this allows the container to reuse the same certificates, instead of generating new ones from Let's Encrypt. 71 | 72 | For information on including this into your Caddyfile see the [Caddyfile tls specification](https://caddyserver.com/docs/tls). 73 | 74 | The certificates are stored in /root/.caddy inside of the container, and thus you must connect an outside directory to that directory to allow persistance. For docker-compose.yml files, under the volumes declaration, include: 75 | 76 | - ./.caddy:/root/.caddy 77 | 78 | or 79 | 80 | docker run -v $(pwd)/.caddy:/root/.caddy 81 | 82 | ## Contributing to Alpine-Caddy 83 | 84 | ### Team members 85 | 86 | * [Sean Kilgarriff](https://github.com/Skilgarriff) sean@zzrot.com T: [@seankilgarriff](https://twitter.com/SeanKilgarriff) 87 | * [Killian Brackey](https://github.com/killianbrackey) killian@zzrot.com T: [@kmbrackey](https://twitter.com/kmbrackey) 88 | 89 | Don't hesitate to get in contact with either one of us with problems, questions, etc. 90 | 91 | 92 | ### Adding new features 93 | 94 | * Fork it! 95 | * Create your feature branch: git checkout -b my-new-feature 96 | * Commit your changes: git commit -am 'Add some feature' 97 | * Push to the branch: git push origin my-new-feature 98 | * Submit a pull request :D 99 | 100 | 101 | Don’t get discouraged! We estimate that the response time from the 102 | maintainers is around: 24 hours. 103 | 104 | 105 | ### Reporting Security Issues 106 | 107 | If you discover a security issue in this Docker image, please report it by sending an email to docker@zzrot.com 108 | 109 | This will allow us to assess the risk, and make a fix available before we add a bug report to the GitHub repository. 110 | 111 | Thanks for helping make this image safe for everyone! 112 | 113 | ### License 114 | 115 | The code is available under the [MIT License](https://github.com/ZZROTDesign/alpine-caddy/tree/master/LICENSE). 116 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Issues 2 | 3 | If you discover a security issue in this Docker image, please report it by sending an email to docker@zzrot.com 4 | 5 | This will allow us to assess the risk, and make a fix available before we add a bug report to the GitHub repository. 6 | 7 | Thanks for helping make this image safe for everyone! 8 | -------------------------------------------------------------------------------- /docker-compose.travis.yml: -------------------------------------------------------------------------------- 1 | #THIS FILE IS FOR TESTING ONLY! DO NOT BIND A IP TO A PORT IN DOCKER UNLESS YOU ARE TESTING 2 | version: '2' 3 | services: 4 | caddy: 5 | build: . 6 | ports: 7 | - 127.0.0.1:80:80 8 | volumes: 9 | - ./public:/var/www/html 10 | -------------------------------------------------------------------------------- /examples/Caddyfile.proxy.example: -------------------------------------------------------------------------------- 1 | ##Example Caddyfile config for a reverse proxy 2 | 3 | www.example.com, example.com { 4 | 5 | proxy / example-server:80 {#This is the name of your container 6 | proxy_header Host {host} 7 | proxy_header X-Real-IP {remote} 8 | proxy_header X-Forwarded-Proto {scheme} 9 | } 10 | 11 | header / { 12 | #Include any headers for your site here 13 | } 14 | 15 | gzip 16 | 17 | tls example@example.com #Your email for Let's Encrypt Verification 18 | } 19 | 20 | blog.example.com { 21 | proxy / example-blog:2368 { 22 | proxy_header Host {host} 23 | proxy_header X-Real-IP {remote} 24 | proxy_header X-Forwarded-Proto {scheme} 25 | } 26 | 27 | header / { 28 | #Include any headers for your site here 29 | } 30 | 31 | gzip 32 | 33 | tls example@example.com #Your email for Let's Encrypt Verification 34 | } 35 | -------------------------------------------------------------------------------- /examples/docker-compose.example.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | web: 4 | image: zzrot/alpine-caddy 5 | ports: 6 | - 80:80 7 | volumes: 8 | - ./Caddyfile:/etc/Caddyfile 9 | - ./public:/var/www/html 10 | - ./.caddy:/root/.caddy 11 | -------------------------------------------------------------------------------- /examples/docker-compose.proxy-example.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | proxy: 4 | image: zzrot/alpine-caddy 5 | ports: 6 | - 80:80 7 | volumes: 8 | - ./Caddyfile:/etc/Caddyfile 9 | - ./.caddy:/root/.caddy 10 | networks: 11 | - frontend 12 | 13 | example-server: 14 | image: zzrot/alpine-caddy 15 | expose: 16 | - 80 17 | volumes: 18 | - ./public:/var/www/html 19 | networks: 20 | - frontend 21 | 22 | example-blog: 23 | image: zzrot/alpine-ghost 24 | expose: 25 | - 2368 26 | networks: 27 | - frontend 28 | 29 | networks: 30 | frontend: 31 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | Hello World! 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/caddy.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | @test "Run Test Docker Container" { 4 | run docker-compose -f docker-compose.travis.yml up -d 5 | } 6 | 7 | @test "Caddy should be version v0.10" { 8 | run docker run alpinecaddy_caddy caddy --version 9 | [[ "$output" =~ "0.10" ]] 10 | } 11 | 12 | @test "Caddy Should Be The User" { 13 | skip 14 | run docker run alpinecaddy_caddy whoami 15 | [[ "$output" =~ "caddy" ]] 16 | } 17 | 18 | @test "It should respond with HTTP 200 Okay" { 19 | run curl --write-out "%{http_code}\n" --silent --output /dev/null 127.0.0.1 20 | [[ "$output" =~ "200" ]] 21 | } 22 | 23 | @test "It should show the hello world page" { 24 | run curl 127.0.0.1 25 | [[ "$output" =~ "Hello World!" ]] 26 | } 27 | 28 | @test "Build Proxy Container" { 29 | skip "Waiting on Caddy v.9 for testing ssl" 30 | } 31 | 32 | @test "Proxies to container 1" { 33 | skip 34 | } 35 | 36 | @test "Proxies to container 2" { 37 | skip 38 | } 39 | 40 | @test "Proxies to container 3" { 41 | skip 42 | } 43 | 44 | @test "SSL Certificates" { 45 | skip "" 46 | } 47 | 48 | @test "Force Headers" { 49 | skip 50 | } 51 | --------------------------------------------------------------------------------