├── .cloud ├── docker │ └── Dockerfile └── nginx │ └── nginx.conf ├── .github └── FUNDING.yml ├── .gitignore ├── 401.html ├── 403.html ├── 404.html ├── 429.html ├── 500.html ├── 502.html ├── 503.html ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── _config.yml ├── _layouts └── default.html ├── assets ├── css │ └── application.css └── img │ ├── 403.svg │ ├── 404.svg │ ├── 500.svg │ └── 503.svg ├── netlify.toml └── robots.txt /.cloud/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # jekyll 2 | FROM jekyll/builder:latest as jekyll 3 | WORKDIR /tmp 4 | COPY . /tmp 5 | RUN chown -R jekyll:jekyll /tmp 6 | RUN gem install bundler:1.16.6 7 | RUN jekyll build 8 | 9 | # nginx 10 | FROM nginx:alpine as nginx 11 | 12 | COPY .cloud/nginx/nginx.conf /etc/nginx/conf.d/default.conf 13 | COPY --from=jekyll /tmp/_site/ /var/www/public/ 14 | -------------------------------------------------------------------------------- /.cloud/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | index index.php index.html index.htm; 4 | root /var/www/public/; 5 | 6 | try_files $uri =404; 7 | error_page 401 403 404 429 /404.html; 8 | } 9 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: guillaumebriday 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | .jekyll-metadata 4 | .jekyll-cache 5 | -------------------------------------------------------------------------------- /401.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Unauthorized 4 | code: 401 5 | asset: 403.svg 6 | --- 7 | 8 | Sorry, you are not authorized to access this page. 9 | -------------------------------------------------------------------------------- /403.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Forbidden 4 | code: 403 5 | asset: 403.svg 6 | --- 7 | 8 | Sorry, you are forbidden from accessing this page. 9 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Page Not Found 4 | code: 404 5 | asset: 404.svg 6 | --- 7 | 8 | Sorry, the page you are looking for could not be found. 9 | -------------------------------------------------------------------------------- /429.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Too Many Requests 4 | code: 429 5 | asset: 403.svg 6 | --- 7 | 8 | Sorry, you are making too many requests to our servers. 9 | -------------------------------------------------------------------------------- /500.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Error 4 | code: 500 5 | asset: 500.svg 6 | --- 7 | 8 | Whoops, something went wrong on our servers. 9 | -------------------------------------------------------------------------------- /502.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Bad Gateway 4 | code: 502 5 | asset: 503.svg 6 | --- 7 | 8 | Sorry, the page you are looking for is not available. Please check back soon. 9 | -------------------------------------------------------------------------------- /503.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Service Unavailable 4 | code: 503 5 | asset: 503.svg 6 | --- 7 | 8 | Sorry, we are doing some maintenance. Please check back soon. 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Hello! This is where you manage which Jekyll version is used to run. 4 | # When you want to use a different version, change it below, save the 5 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 6 | # 7 | # bundle exec jekyll serve 8 | # 9 | # This will help ensure the proper Jekyll version is running. 10 | # Happy Jekylling! 11 | gem "jekyll" 12 | 13 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 14 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 15 | # gem "github-pages", group: :jekyll_plugins 16 | 17 | # If you have any plugins, put them here! 18 | group :jekyll_plugins do 19 | gem "octopress-minify-html" 20 | gem "jekyll-assets" 21 | end 22 | 23 | # needed for jekyll-assets 24 | gem "sprockets", "~> 3.7" 25 | 26 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 27 | gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] 28 | 29 | # Performance-booster for watching directories on Windows 30 | gem "wdm", "~> 0.1.0" if Gem.win_platform? 31 | 32 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (5.2.4.3) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (>= 0.7, < 2) 7 | minitest (~> 5.1) 8 | tzinfo (~> 1.1) 9 | addressable (2.6.0) 10 | public_suffix (>= 2.0.2, < 4.0) 11 | colorator (1.1.0) 12 | concurrent-ruby (1.1.5) 13 | css_press (0.3.2) 14 | csspool-st (= 3.1.2) 15 | json 16 | csspool-st (3.1.2) 17 | em-websocket (0.5.1) 18 | eventmachine (>= 0.12.9) 19 | http_parser.rb (~> 0.6.0) 20 | eventmachine (1.2.7) 21 | execjs (2.7.0) 22 | extras (0.3.0) 23 | forwardable-extended (~> 2.5) 24 | fastimage (2.1.7) 25 | ffi (1.10.0) 26 | forwardable-extended (2.6.0) 27 | html_press (0.8.2) 28 | htmlentities 29 | multi_css (>= 0.1.0) 30 | multi_js (>= 0.1.0) 31 | htmlentities (4.3.4) 32 | http_parser.rb (0.6.0) 33 | i18n (0.9.5) 34 | concurrent-ruby (~> 1.0) 35 | jekyll (3.8.5) 36 | addressable (~> 2.4) 37 | colorator (~> 1.0) 38 | em-websocket (~> 0.5) 39 | i18n (~> 0.7) 40 | jekyll-sass-converter (~> 1.0) 41 | jekyll-watch (~> 2.0) 42 | kramdown (~> 1.14) 43 | liquid (~> 4.0) 44 | mercenary (~> 0.3.3) 45 | pathutil (~> 0.9) 46 | rouge (>= 1.7, < 4) 47 | safe_yaml (~> 1.0) 48 | jekyll-assets (3.0.12) 49 | activesupport (~> 5.0) 50 | execjs (~> 2.7) 51 | extras (~> 0.2) 52 | fastimage (~> 2.0, >= 1.8) 53 | jekyll (>= 3.5, < 4.0) 54 | jekyll-sanity (~> 1.2) 55 | liquid-tag-parser (~> 1.0) 56 | nokogiri (~> 1.8) 57 | pathutil (~> 0.16) 58 | sprockets (>= 3.3, < 4.1.beta) 59 | jekyll-sanity (1.6.0) 60 | jekyll (>= 3.1, < 5.0) 61 | pathutil (~> 0.16) 62 | jekyll-sass-converter (1.5.2) 63 | sass (~> 3.4) 64 | jekyll-watch (2.1.2) 65 | listen (~> 3.0) 66 | json (2.3.1) 67 | kramdown (1.17.0) 68 | liquid (4.0.3) 69 | liquid-tag-parser (1.9.0) 70 | extras (~> 0.3) 71 | liquid (>= 3.0, < 5.0) 72 | listen (3.1.5) 73 | rb-fsevent (~> 0.9, >= 0.9.4) 74 | rb-inotify (~> 0.9, >= 0.9.7) 75 | ruby_dep (~> 1.2) 76 | mercenary (0.3.6) 77 | mini_portile2 (2.4.0) 78 | minitest (5.14.1) 79 | multi_css (0.1.0) 80 | css_press 81 | multi_js (0.1.0) 82 | uglifier (~> 2) 83 | nokogiri (1.10.10) 84 | mini_portile2 (~> 2.4.0) 85 | octopress-hooks (2.6.2) 86 | jekyll (>= 2.0) 87 | octopress-minify-html (1.3.1) 88 | html_press (~> 0.8) 89 | jekyll (>= 2.0) 90 | octopress-hooks 91 | pathutil (0.16.2) 92 | forwardable-extended (~> 2.6) 93 | public_suffix (3.0.3) 94 | rack (2.2.3) 95 | rb-fsevent (0.10.3) 96 | rb-inotify (0.10.0) 97 | ffi (~> 1.0) 98 | rouge (3.3.0) 99 | ruby_dep (1.5.0) 100 | safe_yaml (1.0.5) 101 | sass (3.7.3) 102 | sass-listen (~> 4.0.0) 103 | sass-listen (4.0.0) 104 | rb-fsevent (~> 0.9, >= 0.9.4) 105 | rb-inotify (~> 0.9, >= 0.9.7) 106 | sprockets (3.7.2) 107 | concurrent-ruby (~> 1.0) 108 | rack (> 1, < 3) 109 | thread_safe (0.3.6) 110 | tzinfo (1.2.7) 111 | thread_safe (~> 0.1) 112 | uglifier (2.7.2) 113 | execjs (>= 0.3.0) 114 | json (>= 1.8.0) 115 | 116 | PLATFORMS 117 | ruby 118 | 119 | DEPENDENCIES 120 | jekyll 121 | jekyll-assets 122 | octopress-minify-html 123 | sprockets (~> 3.7) 124 | tzinfo-data 125 | 126 | BUNDLED WITH 127 | 1.16.6 128 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Guillaume Briday 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 | [](https://www.paypal.me/guillaumebriday) 2 | [](https://hub.docker.com/r/guillaumebriday/traefik-custom-error-pages/) 3 | [](https://hub.docker.com/r/guillaumebriday/traefik-custom-error-pages/) 4 | [](https://app.netlify.com/sites/traefik-custom-error-pages/deploys) 5 | 6 | # ⚠️ DEPRECATION WARNING ⚠️ 7 | 8 | I'm not using this image anymore. I switched from Traefik to [Caddy](https://caddyserver.com) because Traefik is far too complicated for **my** needs. This image works as it. If you want new features, feel free to fork the project. An alternative project for the traefik error pages is [tarampampam/error-pages](https://github.com/tarampampam/error-pages). It also supports the theme used in this project. 9 | 10 | # Custom error pages for Traefik 11 | 12 | A bunch of custom error pages for Traefik built with [Jekyll](https://jekyllrb.com/). 13 | 14 | ## Development 15 | 16 | Install dependencies 17 | 18 | ```bash 19 | $ bundle install 20 | ``` 21 | 22 | If you want to build the project on your host: 23 | 24 | ```bash 25 | $ jekyll build 26 | ``` 27 | 28 | If you want to preview the pages before building the Docker image : 29 | 30 | ```bash 31 | $ jekyll serve 32 | ``` 33 | 34 | Open [http://127.0.0.1:4000/](http://127.0.0.1:4000/). 35 | 36 | ## How to use with Traefik and Docker in Production 37 | 38 | Run the container with labels, **change with your needs**: 39 | 40 | ```yml 41 | # docker-compose.yml 42 | 43 | errorpage: 44 | image: guillaumebriday/traefik-custom-error-pages 45 | restart: unless-stopped 46 | networks: 47 | - web 48 | labels: 49 | - traefik.enable: "true" 50 | - traefik.docker.network: "web" 51 | - traefik.http.routers.errorpage.entrypoints: "websecure" 52 | - traefik.http.routers.errorpage.rule: "HostRegexp(`{host:.+}`)" 53 | - traefik.http.services.globalerrorpage.loadbalancer.server.port: "80" 54 | ``` 55 | 56 | ## Build the image 57 | 58 | This is a [multi-stage build](https://docs.docker.com/develop/develop-images/multistage-build/), to build the final image: 59 | 60 | ```bash 61 | $ docker build -f .cloud/docker/Dockerfile -t traefik-custom-error-pages . 62 | ``` 63 | 64 | ## How it works? 65 | 66 | As you can see in the Dockerfile, I use [Nginx](https://www.nginx.com/) as Web server to serve static files. To generate this pages, I use [Jekyll](https://jekyllrb.com/) in the first step of the build. 67 | 68 | You will find in this article [https://www.techjunktrunk.com/docker/2017/11/03/traefik-default-server-catch-all](https://www.techjunktrunk.com/docker/2017/11/03/traefik-default-server-catch-all/) why I set up `rule` this way. 69 | 70 | It's very useful because this container will respond to all requests only if there is no container with a real rule. 71 | 72 | ## Credits 73 | 74 | I used the [Laravel](https://laravel.com/) default HTTP error pages. 75 | 76 | ## Contributing 77 | 78 | Do not hesitate to contribute to the project by adapting or adding features ! Bug reports or pull requests are welcome. 79 | 80 | ## License 81 | 82 | This project is released under the [MIT](http://opensource.org/licenses/MIT) license. 83 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process. 10 | 11 | # Site settings 12 | # These are used to personalize your new site. If you look in the HTML files, 13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. 14 | # You can create any custom variable you would like, and they will be accessible 15 | # in the templates via {{ site.myvariable }}. 16 | baseurl: "" # the subpath of your site, e.g. /blog 17 | url: "" # the base hostname & protocol for your site, e.g. http://example.com 18 | 19 | # Build settings 20 | markdown: kramdown 21 | 22 | plugins: 23 | - octopress-minify-html 24 | - jekyll-assets 25 | 26 | # Exclude from processing. 27 | # The following items will not be processed, by default. Create a custom list 28 | # to override the default setting. 29 | exclude: 30 | - Gemfile 31 | - Gemfile.lock 32 | - LICENSE 33 | - feed.xml 34 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |27 | {{ content }} 28 |
29 |