mirror of
https://github.com/funkypenguin/geek-cookbook/
synced 2026-10-22 08:43:24 +00:00
Improve title on recipes
This commit is contained in:
41 files changed
+1057
-31
No files matched your search
@@ -4,6 +4,7 @@ FROM ${FROM_SOURCE}
|
|||||||
RUN apk add --no-cache py3-pip py3-pillow py3-cffi py3-brotli gcc musl-dev python3-dev pango build-base libffi-dev jpeg-dev libxslt-dev
|
RUN apk add --no-cache py3-pip py3-pillow py3-cffi py3-brotli gcc musl-dev python3-dev pango build-base libffi-dev jpeg-dev libxslt-dev
|
||||||
|
|
||||||
RUN pip install \
|
RUN pip install \
|
||||||
|
beautifulsoup4==4.9.3 \
|
||||||
mkdocs-autolinks-plugin \
|
mkdocs-autolinks-plugin \
|
||||||
mkdocs-htmlproofer-plugin \
|
mkdocs-htmlproofer-plugin \
|
||||||
mkdocs-git-revision-date-localized-plugin \
|
mkdocs-git-revision-date-localized-plugin \
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: Pre-made ansible playbooks to deploy our self-hosted recipes
|
||||||
|
---
|
||||||
# Premix Repository
|
# Premix Repository
|
||||||
|
|
||||||
"Premix" is a private repository shared with [GitHub sponsors](https://github.com/sponsors/funkypenguin), which contains the necessary files and automation to quickly deploy any recipe, or even an entire [swarm](/docker-swarm/) / [cluster](/kubernetes/)! :muscle:
|
"Premix" is a private repository shared with [GitHub sponsors](https://github.com/sponsors/funkypenguin), which contains the necessary files and automation to quickly deploy any recipe, or even an entire [swarm](/docker-swarm/) / [cluster](/kubernetes/)! :muscle:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: A self-hosted internet archiving solution
|
title: Archivebox - bookmark manager for your self-hosted stack
|
||||||
---
|
---
|
||||||
# Archivebox
|
# Archivebox
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Run linuxserver bookstack in Docker
|
title: How to run BookStack in Docker
|
||||||
description: BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information. Here's how to integrate linuxserver's bookstack image into your Docker Swarm stack.
|
description: BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information. Here's how to integrate linuxserver's bookstack image into your Docker Swarm stack.
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Duplicati - Yet another option to backup your exciting stuff. It's good to have options.
|
title: Use Duplicati in Docker to backup to backblaze / b2 and friends
|
||||||
|
description: Duplicati - Yet another boring option to backup your exciting stuff, especially to Backblaze / B2 - It's good to have options.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Duplicati
|
# Duplicati
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
title: Use Duplicity in Docker to backup to backblaze / b2 and friends
|
||||||
description: A boring recipe to backup your exciting stuff. Boring is good.
|
description: A boring recipe to backup your exciting stuff. Boring is good.
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Real heroes backup their shizz!
|
title: Use elkarbackup in Docker to backup to backblaze / b2 and friends
|
||||||
|
description: ElkarBackup is a free open-source backup solution based on RSync/RSnapshot. It's basically a web wrapper around rsync/rsnapshot, which means that your backups are just files on a filesystem, utilising hardlinks for tracking incremental changes.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Elkar Backup
|
# Elkar Backup
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Ghost - Beautiful online publicatio (who you gonna call?)
|
title: Blog with Ghost in Docker
|
||||||
|
description: How to run the beautiful, publication-focused blogging engine "Ghost" using Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Ghost
|
# Ghost
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: Gitlab Runner - A gopher for GitLab
|
title: How to run Gitlab Runner in Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Gitlab Runner
|
# Gitlab Runner
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
---
|
||||||
|
title: How to run Gitlab in Docker
|
||||||
|
---
|
||||||
# GitLab
|
# GitLab
|
||||||
|
|
||||||
GitLab is a self-hosted [alternative to GitHub](https://about.gitlab.com/pricing/self-managed/feature-comparison/). The most common use case is (a set of) developers with the desire for the rich feature-set of GitHub, but with unlimited private repositories.
|
GitLab is a self-hosted [alternative to GitHub](https://about.gitlab.com/pricing/self-managed/feature-comparison/). The most common use case is (a set of) developers with the desire for the rich feature-set of GitHub, but with unlimited private repositories.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: Gollum - A recipe for your own git-based wiki. My preciousssss
|
title: Run Gollum in Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Gollum
|
# Gollum
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: A self-hosted, hackable version of IFFTT / Zapier
|
title: Run Huggin in Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Huginn
|
# Huginn
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Automate your fake Instagram life with automated fakery!
|
title: How to run InstaPy in Docker
|
||||||
|
description: Automate your fake Instagram life with automated fakery using InstaPy in Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# InstaPy
|
# InstaPy
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: How to build an IPFS cluster in Docker
|
||||||
|
description: IPFS is a peer-to-peer distributed file system that seeks to connect all computing devices with the same system of files. In some ways, IPFS is similar to the World Wide Web, but IPFS could be seen as a single BitTorrent swarm, exchanging objects within one Git repository.
|
||||||
|
---
|
||||||
# IPFS
|
# IPFS
|
||||||
|
|
||||||
!!! danger "This recipe is a work in progress"
|
!!! danger "This recipe is a work in progress"
|
||||||
@@ -8,7 +12,7 @@ The intention of this recipe is to provide a local IPFS cluster for the purpose
|
|||||||
|
|
||||||
{ loading=lazy }
|
{ loading=lazy }
|
||||||
|
|
||||||
Description. IPFS is a peer-to-peer distributed file system that seeks to connect all computing devices with the same system of files. In some ways, IPFS is similar to the World Wide Web, but IPFS could be seen as a single BitTorrent swarm, exchanging objects within one Git repository.
|
IPFS is a peer-to-peer distributed file system that seeks to connect all computing devices with the same system of files. In some ways, IPFS is similar to the World Wide Web, but IPFS could be seen as a single BitTorrent swarm, exchanging objects within one Git repository.
|
||||||
|
|
||||||
## Ingredients
|
## Ingredients
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Get your personal kanban on!
|
title: How to run Kanboard using Docker
|
||||||
|
description: Run Kanboard with Docker to get your personal kanban on!
|
||||||
---
|
---
|
||||||
|
|
||||||
# Kanboard
|
# Kanboard
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Integrate LDAP server with Keycloak for user federation
|
||||||
|
description: Here's how we'll add an LDAP provider to our KeyCloak server for user federation.
|
||||||
|
---
|
||||||
# Authenticate KeyCloak against OpenLDAP
|
# Authenticate KeyCloak against OpenLDAP
|
||||||
|
|
||||||
!!! warning
|
!!! warning
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
# Create KeyCloak Users
|
---
|
||||||
|
title: Create users in Keycloak
|
||||||
|
description: Unless you plan to authenticate against an outside provider (OpenLDAP, below, for example_), you'll want to create some local users..
|
||||||
|
---
|
||||||
|
# Create Keycloak Users
|
||||||
|
|
||||||
!!! warning
|
!!! warning
|
||||||
This is not a complete recipe - it's an optional component of the [Keycloak recipe](/recipes/keycloak/), but has been split into its own page to reduce complexity.
|
This is not a complete recipe - it's an optional component of the [Keycloak recipe](/recipes/keycloak/), but has been split into its own page to reduce complexity.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
title: How to setup OIDC server in Docker with KeyCloak
|
||||||
description: Kick-ass OIDC and identity management
|
description: Kick-ass OIDC and identity management
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: How to setup OIDC provider in KeyCloak
|
||||||
|
description: Having an authentication provider is not much use until you start authenticating things against it! In order to authenticate against KeyCloak using OpenID Connect (OIDC), which is required for Traefik Forward Auth, we'll setup a client in KeyCloak...
|
||||||
|
---
|
||||||
# Add OIDC Provider to KeyCloak
|
# Add OIDC Provider to KeyCloak
|
||||||
|
|
||||||
!!! warning
|
!!! warning
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Bazinga! Comic book management FTW!
|
title: How to run Komga with Docker
|
||||||
|
description: Run Komga under Docker Swarm in docker-compose syntax
|
||||||
---
|
---
|
||||||
|
|
||||||
# Komga
|
# Komga
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: A self-contained mailserver with spam-fighting friends
|
title: Run postfix / dovecot with docker-mailserver
|
||||||
|
description: A self-contained mailserver (postfix, dovecot) in Docker with spam-fighting friends (spamassassin, clamav)
|
||||||
---
|
---
|
||||||
|
|
||||||
# Mail Server
|
# Mail Server
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: A lightweight minimalist RSS reader
|
title: Read RSS in peace with miniflux on Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Miniflux
|
# Miniflux
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Self-hosted S3-compatible object storage
|
title: Run Minio on Docker (using compose format in swarm)
|
||||||
|
description: How to run Minio's self-hosted S3-compatible object storage under Docker Swarm, using docker-compose v3 syntax
|
||||||
---
|
---
|
||||||
|
|
||||||
# Minio
|
# Minio
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Share docs. Backup files. Share stuff.
|
title: How to run Nextcloud in Docker (behind Traefik)
|
||||||
|
description: We can now run Nextcloud in our Docker Swarm, with LetsEncrypt SSL termination handled by Traefik
|
||||||
---
|
---
|
||||||
|
|
||||||
# NextCloud
|
# NextCloud
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Authenticate like it's 1990!
|
title: Run OpenLDAP in Docker
|
||||||
|
description: How to run an OpenLDAP server in Docker Swarm, with LDAP Account Manager. Authenticate like it's 1990!
|
||||||
---
|
---
|
||||||
|
|
||||||
# OpenLDAP
|
# OpenLDAP
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: Spy on yourself.
|
title: Run OwnTracks under Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# OwnTracks
|
# OwnTracks
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
---
|
---
|
||||||
description: Easily index, search, and view archive all of your scanned dead-tree documents
|
title: Run paperless-ngx under Docker
|
||||||
|
description: Easily index, search, and view archive all of your scanned dead-tree documents with Paperless NGX, under Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Paperless NG
|
# Paperless NGX
|
||||||
|
|
||||||
Paper is a nightmare. Environmental issues aside, there’s no excuse for it in the 21st century. It takes up space, collects dust, doesn’t support any form of a search feature, indexing is tedious, it’s heavy and prone to damage & loss. [^1] Paperless NG will OCR, index, and store data about your documents so they are easy to search and view, unlike that hulking metal file cabinet you have in your office.
|
Paper is a nightmare. Environmental issues aside, there’s no excuse for it in the 21st century. It takes up space, collects dust, doesn’t support any form of a search feature, indexing is tedious, it’s heavy and prone to damage & loss. [^1] Paperless NG will OCR, index, and store data about your documents so they are easy to search and view, unlike that hulking metal file cabinet you have in your office.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Is that IP address in use?
|
title: Run phpIPAM under Docker
|
||||||
|
description: Is that IP address in use? Do some DHP / Discovery with phpIPAM under Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# phpIPAM
|
# phpIPAM
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: A UI to make Docker less geeky
|
title: Run Portainer in Docker Swarm (now with Dark Mode!)
|
||||||
|
description: Portainer is a UI to make Docker less geeky, runs under Docker Swarm (and Kubernetes!) and most importantly, now supports dark mode!
|
||||||
---
|
---
|
||||||
|
|
||||||
# Portainer
|
# Portainer
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
title: Realms is a git-based wiki, and it runs under Docker!
|
||||||
description: A git-based wiki with auth and registration
|
description: A git-based wiki with auth and registration
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: Read-it-later, mate!
|
title: Run Wallabag under Docker (compose), mate!
|
||||||
---
|
---
|
||||||
|
|
||||||
# Wallabag
|
# Wallabag
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: A self-hosted Trello
|
title: Run Wekan under Docker
|
||||||
---
|
---
|
||||||
|
|
||||||
# Wekan
|
# Wekan
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
description: Terminal in a browser, baby!
|
title: Use wetty under Docker for SSH in the browser
|
||||||
|
description: Use weTTY to run a terminal in a browser, baby!
|
||||||
---
|
---
|
||||||
|
|
||||||
# Wetty
|
# Wetty
|
||||||
|
|||||||
+405
@@ -0,0 +1,405 @@
|
|||||||
|
site_name: Funky Penguin's Geek Cookbook
|
||||||
|
site_description: 'The Geek Cookbook is a collection of guides for establishing your own highly-available docker container cluster (swarm). This swarm enables you to run self-hosted services such as GitLab, Plex, NextCloud, etc.'
|
||||||
|
site_author: 'David Young'
|
||||||
|
site_url: 'https://geek-cookbook.funkypenguin.co.nz'
|
||||||
|
edit_uri: 'edit/master/manuscript/'
|
||||||
|
|
||||||
|
# Fail to build if we have broken links
|
||||||
|
# strict: true
|
||||||
|
|
||||||
|
# Repository
|
||||||
|
repo_name: 'geek-cookbook'
|
||||||
|
repo_url: 'https://github.com/geek-cookbook/geek-cookbook'
|
||||||
|
|
||||||
|
# Set this to "manuscript" so that we can produce leanpub content
|
||||||
|
docs_dir: 'manuscript'
|
||||||
|
|
||||||
|
# Copyright
|
||||||
|
copyright: 'Copyright © 2016 - 2021 David Young, Funky Penguin Limited'
|
||||||
|
|
||||||
|
# Plugins
|
||||||
|
plugins:
|
||||||
|
privacy:
|
||||||
|
search:
|
||||||
|
minify:
|
||||||
|
minify_html: true
|
||||||
|
git-revision-date-localized:
|
||||||
|
type: date
|
||||||
|
autolinks:
|
||||||
|
macros:
|
||||||
|
verbose: true
|
||||||
|
# htmlproofer:
|
||||||
|
# raise_error: True
|
||||||
|
# raise_error_excludes:
|
||||||
|
# 504: ['https://www.mkdocs.org/']
|
||||||
|
# 404: ['https://github.com/manuzhang/mkdocs-htmlproofer-plugin']
|
||||||
|
# 400: ['*']
|
||||||
|
git-committers:
|
||||||
|
repository: geek-cookbook/geek-cookbook
|
||||||
|
token: !ENV GH_TOKEN
|
||||||
|
meta-descriptions: # If not provided, auto-generate a description (https://pypi.org/project/mkdocs-meta-descriptions-plugin/)
|
||||||
|
|
||||||
|
#theme_dir: mkdocs-material
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
- Docker Swarm:
|
||||||
|
- docker-swarm/index.md
|
||||||
|
- Preparation:
|
||||||
|
- Design: docker-swarm/design.md
|
||||||
|
- Nodes: docker-swarm/nodes.md
|
||||||
|
- Shared Storage (Ceph): docker-swarm/shared-storage-ceph.md
|
||||||
|
- Shared Storage (GlusterFS): docker-swarm/shared-storage-gluster.md
|
||||||
|
- Keepalived: docker-swarm/keepalived.md
|
||||||
|
- Docker Swarm Mode: docker-swarm/docker-swarm-mode.md
|
||||||
|
- Traefik: docker-swarm/traefik.md
|
||||||
|
- Traefik Forward Auth:
|
||||||
|
- docker-swarm/traefik-forward-auth/index.md
|
||||||
|
- Dex (static): docker-swarm/traefik-forward-auth/dex-static.md
|
||||||
|
- Google: docker-swarm/traefik-forward-auth/google.md
|
||||||
|
- KeyCloak: docker-swarm/traefik-forward-auth/keycloak.md
|
||||||
|
- Authelia: docker-swarm/authelia.md
|
||||||
|
- Registry: docker-swarm/registry.md
|
||||||
|
- Mail Server: recipes/mail.md
|
||||||
|
- Duplicity: recipes/duplicity.md
|
||||||
|
- Chef's Favorites:
|
||||||
|
- Auto Pirate:
|
||||||
|
- recipes/autopirate/index.md
|
||||||
|
- Headphones: recipes/autopirate/headphones.md
|
||||||
|
- Heimdall: recipes/autopirate/heimdall.md
|
||||||
|
- Jackett: recipes/autopirate/jackett.md
|
||||||
|
- Lazy Librarian: recipes/autopirate/lazylibrarian.md
|
||||||
|
- Lidarr: recipes/autopirate/lidarr.md
|
||||||
|
- Mylar: recipes/autopirate/mylar.md
|
||||||
|
- NZBGet: recipes/autopirate/nzbget.md
|
||||||
|
- NZBHydra: recipes/autopirate/nzbhydra.md
|
||||||
|
- Prowlarr: recipes/autopirate/prowlarr.md
|
||||||
|
- Ombi: recipes/autopirate/ombi.md
|
||||||
|
- Radarr: recipes/autopirate/radarr.md
|
||||||
|
- Readarr: recipes/autopirate/readarr.md
|
||||||
|
- Rtorrent: recipes/autopirate/rtorrent.md
|
||||||
|
- SABnzbd: recipes/autopirate/sabnzbd.md
|
||||||
|
- Sonarr: recipes/autopirate/sonarr.md
|
||||||
|
- End: recipes/autopirate/end.md
|
||||||
|
- Emby: recipes/emby.md
|
||||||
|
- Home Assistant: recipes/homeassistant.md
|
||||||
|
- Huginn: recipes/huginn.md
|
||||||
|
- Jellyfin: recipes/jellyfin.md
|
||||||
|
- Kanboard: recipes/kanboard.md
|
||||||
|
- KeyCloak:
|
||||||
|
- recipes/keycloak/index.md
|
||||||
|
- Users: recipes/keycloak/create-user.md
|
||||||
|
- OIDC Provider: recipes/keycloak/setup-oidc-provider.md
|
||||||
|
- OpenLDAP: recipes/keycloak/authenticate-against-openldap.md
|
||||||
|
- Miniflux: recipes/miniflux.md
|
||||||
|
- Munin: recipes/munin.md
|
||||||
|
- NextCloud: recipes/nextcloud.md
|
||||||
|
- phpIPAM: recipes/phpipam.md
|
||||||
|
- Plex: recipes/plex.md
|
||||||
|
- Portainer: recipes/portainer.md
|
||||||
|
- PrivateBin: recipes/privatebin.md
|
||||||
|
- Restic: recipes/restic.md
|
||||||
|
- Swarmprom: recipes/swarmprom.md
|
||||||
|
- Recipes:
|
||||||
|
- Archive Box: recipes/archivebox.md
|
||||||
|
- Bitwarden: recipes/bitwarden.md
|
||||||
|
- Bookstack: recipes/bookstack.md
|
||||||
|
- Calibre-Web: recipes/calibre-web.md
|
||||||
|
- Collabora Online: recipes/collabora-online.md
|
||||||
|
- CyberChef: recipes/cyberchef.md
|
||||||
|
- Duplicati: recipes/duplicati.md
|
||||||
|
- ElkarBackup: recipes/elkarbackup.md
|
||||||
|
- Funkwhale: recipes/funkwhale.md
|
||||||
|
- Ghost: recipes/ghost.md
|
||||||
|
- GitLab: recipes/gitlab.md
|
||||||
|
- GitLab Runner: recipes/gitlab-runner.md
|
||||||
|
- Gollum: recipes/gollum.md
|
||||||
|
- InstaPy: recipes/instapy.md
|
||||||
|
- KeyCloak:
|
||||||
|
- recipes/keycloak/index.md
|
||||||
|
- Users: recipes/keycloak/create-user.md
|
||||||
|
- OIDC Provider: recipes/keycloak/setup-oidc-provider.md
|
||||||
|
- OpenLDAP: recipes/keycloak/authenticate-against-openldap.md
|
||||||
|
- Komga: recipes/komga.md
|
||||||
|
- Linx: recipes/linx.md
|
||||||
|
- Mealie: recipes/mealie.md
|
||||||
|
- Minio: recipes/minio.md
|
||||||
|
- NightScout: recipes/nightscout.md
|
||||||
|
- OpenLDAP: recipes/openldap.md
|
||||||
|
- OwnTracks: recipes/owntracks.md
|
||||||
|
- Photoprism: recipes/photoprism.md
|
||||||
|
- Paperless NG: recipes/paperless-ng.md
|
||||||
|
- Portainer: recipes/portainer.md
|
||||||
|
- Realms: recipes/realms.md
|
||||||
|
- Restic: recipes/restic.md
|
||||||
|
- RSS Bridge: recipes/rss-bridge.md
|
||||||
|
- Tiny Tiny RSS: recipes/tiny-tiny-rss.md
|
||||||
|
- Traefik: docker-swarm/traefik.md
|
||||||
|
- Traefik Forward Auth:
|
||||||
|
- docker-swarm/traefik-forward-auth/index.md
|
||||||
|
- Dex (static): docker-swarm/traefik-forward-auth/dex-static.md
|
||||||
|
- Google: docker-swarm/traefik-forward-auth/google.md
|
||||||
|
- KeyCloak: docker-swarm/traefik-forward-auth/keycloak.md
|
||||||
|
- Wallabag: recipes/wallabag.md
|
||||||
|
- Wekan: recipes/wekan.md
|
||||||
|
- Wetty: recipes/wetty.md
|
||||||
|
- Reference:
|
||||||
|
- OAuth Proxy: reference/oauth_proxy.md
|
||||||
|
- Data Layout: reference/data_layout.md
|
||||||
|
- Networks: reference/networks.md
|
||||||
|
- OpenVPN : reference/openvpn.md
|
||||||
|
- Troubleshooting: reference/troubleshooting.md
|
||||||
|
- ⛴ Kubernetes:
|
||||||
|
- Preparation:
|
||||||
|
- kubernetes/index.md
|
||||||
|
- Introduction: kubernetes/index.md
|
||||||
|
- Cluster:
|
||||||
|
- kubernetes/cluster/index.md
|
||||||
|
- Digital Ocean: kubernetes/cluster/digitalocean.md
|
||||||
|
# - Bare Metal: kubernetes/cluster/baremetal.md
|
||||||
|
# - Home Lab: kubernetes/cluster/baremetal.md
|
||||||
|
- k3s: kubernetes/cluster/k3s.md
|
||||||
|
# - The Hard Way: kubernetes/cluster/the-hard-way.md
|
||||||
|
- Deployment:
|
||||||
|
- kubernetes/deployment/index.md
|
||||||
|
# - YAML: kubernetes/wip.md
|
||||||
|
# - Helm: kubernetes/wip.md
|
||||||
|
# - GitHub Actions: kubernetes/wip.md
|
||||||
|
- Flux:
|
||||||
|
- kubernetes/deployment/flux/index.md
|
||||||
|
- Install: kubernetes/deployment/flux/install.md
|
||||||
|
- Design: kubernetes/deployment/flux/design.md
|
||||||
|
- Operate: kubernetes/deployment/flux/operate.md
|
||||||
|
- Essentials:
|
||||||
|
- Load Balancer:
|
||||||
|
- kubernetes/loadbalancer/index.md
|
||||||
|
- k3s: kubernetes/loadbalancer/k3s.md
|
||||||
|
- MetalLB:
|
||||||
|
- kubernetes/loadbalancer/metallb/index.md
|
||||||
|
- pfSense: kubernetes/loadbalancer/metallb/pfsense.md
|
||||||
|
- Sealed Secrets: kubernetes/sealed-secrets.md
|
||||||
|
- External DNS: kubernetes/external-dns.md
|
||||||
|
- SSL Certificates:
|
||||||
|
- kubernetes/ssl-certificates/index.md
|
||||||
|
- Cert-Manager: kubernetes/ssl-certificates/cert-manager.md
|
||||||
|
- LetsEncrypt Issuers: kubernetes/ssl-certificates/letsencrypt-issuers.md
|
||||||
|
- Wildcard Certificate: kubernetes/ssl-certificates/wildcard-certificate.md
|
||||||
|
- Secret Replicator: kubernetes/ssl-certificates/secret-replicator.md
|
||||||
|
- Ingress:
|
||||||
|
- kubernetes/ingress/index.md
|
||||||
|
- Traefik:
|
||||||
|
- kubernetes/ingress/traefik/index.md
|
||||||
|
# - Dashboard: kubernetes/ingress/traefik/dashboard.md
|
||||||
|
- Nginx: kubernetes/ingress/nginx.md
|
||||||
|
- Persistence:
|
||||||
|
- kubernetes/persistence/index.md
|
||||||
|
- Local Path Provisioner: kubernetes/persistence/local-path-provisioner.md
|
||||||
|
- TopoLVM: kubernetes/persistence/topolvm.md
|
||||||
|
# - Rook Ceph: kubernetes/persistence/rook-ceph.md
|
||||||
|
# - OpenEBS: kubernetes/persistence/openebs.md
|
||||||
|
# - LongHorn: kubernetes/persistence/longhorn.md
|
||||||
|
# - Backup:
|
||||||
|
# - kubernetes/backup/index.md
|
||||||
|
# - kubernetes/wip.md
|
||||||
|
# - Logging:
|
||||||
|
# - fluent-bit, graylog, etc.
|
||||||
|
|
||||||
|
|
||||||
|
# - Monitoring:
|
||||||
|
# - kubernetes/monitoring/index.md
|
||||||
|
# - Prometheus: kubernetes/wip.md
|
||||||
|
# - Grafana: kubernetes/wip.md
|
||||||
|
# - AlertManager: kubernetes/wip.md
|
||||||
|
# - Goldilocks: kubernetes/wip.md
|
||||||
|
# - Reloader: kubernetes/wip.md
|
||||||
|
# - Dashboard: kubernetes/wip.md
|
||||||
|
# - Kured: kubernetes/wip.md
|
||||||
|
# - KeyCloak: kubernetes/wip.md
|
||||||
|
# - Recipes:
|
||||||
|
# - Harbor:
|
||||||
|
# - recipes/kubernetes/harbor/index.md
|
||||||
|
# Istio: recipes/kubernetes/harbor/istio.md
|
||||||
|
# - GitHub Actions Runners: kubernetes/wip.md
|
||||||
|
# - Cilium: kubernetes/wip.md
|
||||||
|
# - Concourse: kubernetes/wip.md
|
||||||
|
# - Flagger: kubernetes/wip.md
|
||||||
|
# - Flagger: kubernetes/wip.md
|
||||||
|
# - Flux: recipes/kubernetes/wip.md
|
||||||
|
# - FoundationDB: kubernetes/wip.md
|
||||||
|
# - Istio: recipes/kubernetes/wip.md
|
||||||
|
# - Jaeger: kubernetes/wip.md
|
||||||
|
# - Kiali: kubernetes/wip.md
|
||||||
|
# - Minio: kubernetes/wip.md
|
||||||
|
# - NGINX Ingress: kubernetes/wip.md
|
||||||
|
# - Polaris: kubernetes/wip.md
|
||||||
|
# - Portainer: kubernetes/wip.md
|
||||||
|
# - Prometheus: kubernetes/wip.md
|
||||||
|
# - Traefik: kubernetes/wip.md
|
||||||
|
# - Vault: kubernetes/wip.md
|
||||||
|
# - Webook Receiver: kubernetes/wip.md
|
||||||
|
- 🚀 Get Premix!:
|
||||||
|
- premix/index.md
|
||||||
|
- Operation: premix/ansible/operation.md
|
||||||
|
- Design: premix/ansible/design.md
|
||||||
|
# - Swarm: premix/swarm.md
|
||||||
|
# - Kubernetes: premix/kubernetes.md
|
||||||
|
- CHANGELOG: CHANGELOG.md
|
||||||
|
- Support: support.md
|
||||||
|
- Contribute: community/contribute.md
|
||||||
|
- Community:
|
||||||
|
- Discord: community/discord.md
|
||||||
|
- Reddit: community/reddit.md
|
||||||
|
- Support: support.md
|
||||||
|
- Contribute: community/contribute.md
|
||||||
|
- Code of Conduct: community/code-of-conduct.md
|
||||||
|
|
||||||
|
# # - Discourse: community/discourse.md
|
||||||
|
# # - GitHub: community/github.md
|
||||||
|
|
||||||
|
theme:
|
||||||
|
name: 'material'
|
||||||
|
custom_dir: 'overrides'
|
||||||
|
# disqus: 'geeks-cookbook'
|
||||||
|
logo: 'images/site-logo.svg'
|
||||||
|
favicon: 'images/site-logo.svg'
|
||||||
|
features:
|
||||||
|
- navigation.tabs
|
||||||
|
- navigation.tabs.sticky
|
||||||
|
- navigation.instant
|
||||||
|
- navigation.sections
|
||||||
|
- navigation.indexes
|
||||||
|
- navigation.top
|
||||||
|
- navigation.pruning
|
||||||
|
- search.suggest
|
||||||
|
- search.share
|
||||||
|
- content.code.annotate
|
||||||
|
- header.autohide
|
||||||
|
- announce.dismiss
|
||||||
|
- toc.follow
|
||||||
|
icon:
|
||||||
|
repo: 'fontawesome/brands/github'
|
||||||
|
palette:
|
||||||
|
|
||||||
|
# Palette toggle for automatic mode
|
||||||
|
- media: "(prefers-color-scheme)"
|
||||||
|
toggle:
|
||||||
|
icon: material/brightness-auto
|
||||||
|
name: Switch to light mode
|
||||||
|
|
||||||
|
# Toggle light mode
|
||||||
|
- media: "(prefers-color-scheme: light)"
|
||||||
|
scheme: default
|
||||||
|
primary: 'black'
|
||||||
|
accent: 'orange'
|
||||||
|
toggle:
|
||||||
|
icon: material/toggle-switch
|
||||||
|
name: Burn my eyes!
|
||||||
|
|
||||||
|
# Toggle dark mode
|
||||||
|
- media: "(prefers-color-scheme: dark)"
|
||||||
|
scheme: slate
|
||||||
|
primary: 'black'
|
||||||
|
accent: 'orange'
|
||||||
|
toggle:
|
||||||
|
icon: material/toggle-switch-off-outline
|
||||||
|
name: Love my eyes!
|
||||||
|
|
||||||
|
font:
|
||||||
|
text: 'Ubuntu'
|
||||||
|
code: 'Ubuntu Mono'
|
||||||
|
|
||||||
|
extra:
|
||||||
|
social:
|
||||||
|
- icon: 'fontawesome/brands/github'
|
||||||
|
link: 'https://github.com/funkypenguin'
|
||||||
|
- icon: 'fontawesome/brands/twitter'
|
||||||
|
link: 'https://twitter.com/funkypenguin'
|
||||||
|
- icon: 'fontawesome/brands/stack-overflow'
|
||||||
|
link: 'https://stackoverflow.com/cv/funkypenguin'
|
||||||
|
- icon: 'material/rss'
|
||||||
|
link: 'https://www.funkypenguin.co.nz/'
|
||||||
|
- icon: 'fontawesome/brands/linkedin'
|
||||||
|
link: 'https://www.linkedin.com/in/funkypenguin'
|
||||||
|
- icon: 'material/mailbox'
|
||||||
|
link: 'mailto:davidy@funkypenguin.co.nz?Subject=Hello%2C%20from%20a%20geek-cookbook%20reader%20%3B%29'
|
||||||
|
generator: false
|
||||||
|
# Plausible doesn't use cookies, so no need for this!
|
||||||
|
# consent:
|
||||||
|
# title: 'Would you like a cookie? 🍪'
|
||||||
|
# description: >
|
||||||
|
|
||||||
|
# I know. cookies suck (<I>except the fresh, warm, choc-chip ones!</I>), and so does invasive tracking. Thing is, without cookies,
|
||||||
|
# analytics can't record your visit, and I can't work out where/how to invest time to make the cookbook better.
|
||||||
|
|
||||||
|
# <p>So, with your consent, I'd like to record what you look at and where you're from, so that I can make the
|
||||||
|
# cookbook even better. My analytics are public - here's <A HREF='https://plausible.io/geek-cookbook.funkypenguin.co.nz' target="_blank">all</A> I know about you! - David</p>
|
||||||
|
# cookies:
|
||||||
|
# custom: Plausible Analytics
|
||||||
|
analytics:
|
||||||
|
provider: plausible
|
||||||
|
data_domain: geek-cookbook.funkypenguin.co.nz
|
||||||
|
feedback:
|
||||||
|
title: Was this page helpful?
|
||||||
|
ratings:
|
||||||
|
- icon: material/emoticon-happy-outline
|
||||||
|
name: This page was helpful
|
||||||
|
data: 1
|
||||||
|
note: >-
|
||||||
|
Thanks for your feedback!
|
||||||
|
- icon: material/emoticon-sad-outline
|
||||||
|
name: This page could be improved
|
||||||
|
data: 0
|
||||||
|
note: >-
|
||||||
|
Thanks for your feedback!
|
||||||
|
|
||||||
|
# Help us improve this page by
|
||||||
|
# using our <a href="..." target=_blank>feedback form</a>.
|
||||||
|
|
||||||
|
extra_css:
|
||||||
|
- extras/css/icons.css
|
||||||
|
|
||||||
|
extra_javascript:
|
||||||
|
- extras/javascript/discord.js
|
||||||
|
- extras/javascript/sortable-tables.js
|
||||||
|
- extras/javascript/feedback.js
|
||||||
|
- https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/tablesort.min.js
|
||||||
|
|
||||||
|
|
||||||
|
# Extensions
|
||||||
|
markdown_extensions:
|
||||||
|
- attr_list
|
||||||
|
- admonition
|
||||||
|
- codehilite:
|
||||||
|
linenums: true
|
||||||
|
- toc:
|
||||||
|
permalink: true
|
||||||
|
- footnotes
|
||||||
|
- pymdownx.critic
|
||||||
|
- pymdownx.arithmatex
|
||||||
|
- pymdownx.betterem:
|
||||||
|
smart_enable: all
|
||||||
|
- pymdownx.caret
|
||||||
|
- pymdownx.details
|
||||||
|
- pymdownx.snippets:
|
||||||
|
check_paths: true
|
||||||
|
base_path: _snippets
|
||||||
|
- pymdownx.emoji:
|
||||||
|
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||||
|
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||||
|
- pymdownx.inlinehilite
|
||||||
|
- pymdownx.magiclink:
|
||||||
|
repo_url_shorthand: true
|
||||||
|
user: funkypenguin
|
||||||
|
repo: geek-cookbook
|
||||||
|
- pymdownx.mark
|
||||||
|
- pymdownx.smartsymbols
|
||||||
|
- pymdownx.superfences:
|
||||||
|
custom_fences:
|
||||||
|
- name: mermaid
|
||||||
|
class: mermaid
|
||||||
|
format: !!python/name:pymdownx.superfences.fence_code_format
|
||||||
|
- pymdownx.tasklist:
|
||||||
|
custom_checkbox: true
|
||||||
|
- pymdownx.tilde
|
||||||
|
- pymdownx.tabbed
|
||||||
|
- meta
|
||||||
|
- md_in_html
|
||||||
@@ -13,7 +13,7 @@ plugins:
|
|||||||
back_cover: true
|
back_cover: true
|
||||||
#cover_title: TITLE TEXT
|
#cover_title: TITLE TEXT
|
||||||
#cover_subtitle: SUBTITLE TEXT
|
#cover_subtitle: SUBTITLE TEXT
|
||||||
#custom_template_path: TEMPLATES PATH
|
# custom_template_path: pdf_templates
|
||||||
#toc_title: TOC TITLE TEXT
|
#toc_title: TOC TITLE TEXT
|
||||||
#heading_shift: true
|
#heading_shift: true
|
||||||
toc_level: 3
|
toc_level: 3
|
||||||
@@ -30,10 +30,16 @@ plugins:
|
|||||||
text: ALTERNATE TEXT
|
text: ALTERNATE TEXT
|
||||||
- src: ...
|
- src: ...
|
||||||
# two_columns_level: 3
|
# two_columns_level: 3
|
||||||
render_js: true
|
render_js: false
|
||||||
# headless_chrome_path: headless-chromium
|
headless_chrome_path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
|
||||||
|
|
||||||
output_path: funky-penguins-geek-cookbook.pdf
|
output_path: funky-penguins-geek-cookbook.pdf
|
||||||
debug_html: true
|
debug_html: true
|
||||||
show_anchors: true
|
show_anchors: true
|
||||||
verbose: true
|
verbose: true
|
||||||
|
|
||||||
|
extra_css: []
|
||||||
|
extra_javascript: []
|
||||||
|
|
||||||
|
theme:
|
||||||
|
font: false
|
||||||
Binary file not shown.
@@ -0,0 +1,528 @@
|
|||||||
|
<html><head><meta charset="utf-8"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="My collection of how-to guides and tutorials for establishing your own container-based awesome selfhosted platform, using either Docker or Kubernetes." name="description"/><meta content="David Young" name="author"/><link href="https://geek-cookbook.funkypenguin.co.nz/" rel="canonical"/><link href="file:///Users/davidy/Documents/Personal/Projects/geek-cookbook/site/images/site-logo.svg" rel="icon"/><meta content="mkdocs-1.3.0, mkdocs-material-8.3.9" name="generator"/><title>How I do "awesome selfhosted" |・∀・</title><link href="file:///Users/davidy/Documents/Personal/Projects/geek-cookbook/site/assets/stylesheets/main.1d29e8d0.min.css" rel="stylesheet"/><link href="file:///Users/davidy/Documents/Personal/Projects/geek-cookbook/site/assets/stylesheets/palette.cbb835fc.min.css" rel="stylesheet"/><script>__md_scope=new URL(".",location),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script><!-- <script src="https://cdn.jsdelivr.net/npm/@widgetbot/crate@3" async defer></script> --><script src="/js/i-am-groot.js"></script><script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script><!-- RightMessage --><script type="text/javascript">
|
||||||
|
(function(p, a, n, d, o, b, c) {
|
||||||
|
o = n.createElement('script'); o.type = 'text/javascript'; o.async = true; o.src = 'https://tb.rightmessage.com/'+p+'.js';
|
||||||
|
b = n.getElementsByTagName('script')[0]; d = function(h, u, i) { var c = n.createElement('style'); c.id = 'rmcloak'+i;
|
||||||
|
c.type = 'text/css'; c.appendChild(n.createTextNode('.rmcloak'+h+'{visibility:hidden}.rmcloak'+u+'{display:none}'));
|
||||||
|
b.parentNode.insertBefore(c, b); return c; }; c = d('', '-hidden', ''); d('-stay-invisible', '-stay-hidden', '-stay');
|
||||||
|
setTimeout(o.onerror = function() { c.parentNode && c.parentNode.removeChild(c); }, a); b.parentNode.insertBefore(o, b);
|
||||||
|
})('1802694484', 20000, document);
|
||||||
|
</script><link href="file:///Users/davidy/Documents/Personal/Projects/geek-cookbook/site/assets/stylesheets/extra-style.w7lhf_wh.min.css" rel="stylesheet"/><style>@charset "UTF-8";
|
||||||
|
:root {
|
||||||
|
string-set: author 'David Young', copyright 'Copyright © 2016 - 2021 David Young, Funky Penguin Limited', title 'Funky Penguin\27s Geek Cookbook'; }
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
string-set: chapter content(); }
|
||||||
|
@page {
|
||||||
|
size: a4 portrait;
|
||||||
|
margin: 25mm 10mm 25mm 10mm;
|
||||||
|
counter-increment: page;
|
||||||
|
white-space: pre;
|
||||||
|
color: grey;
|
||||||
|
@top-right {
|
||||||
|
font-size: 7pt;
|
||||||
|
content: string(chapter); }
|
||||||
|
@bottom-center {
|
||||||
|
font-size: 8pt;
|
||||||
|
content: "- " counter(page) "/" counter(pages) " -"; }
|
||||||
|
@bottom-right {
|
||||||
|
font-size: 6pt;
|
||||||
|
content: string(copyright); } }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body {
|
||||||
|
background: none;
|
||||||
|
background-color: #fff; } }
|
||||||
|
|
||||||
|
article,
|
||||||
|
section + section {
|
||||||
|
page-break-before: always;
|
||||||
|
min-height: 100vh;
|
||||||
|
/* Defining all page breaks */ }
|
||||||
|
article,
|
||||||
|
article h1,
|
||||||
|
article h2,
|
||||||
|
article h3,
|
||||||
|
article h4,
|
||||||
|
article h5,
|
||||||
|
article h6,
|
||||||
|
article div.tabbed-content--wrap > .tabbed-content,
|
||||||
|
section + section,
|
||||||
|
section + section h1,
|
||||||
|
section + section h2,
|
||||||
|
section + section h3,
|
||||||
|
section + section h4,
|
||||||
|
section + section h5,
|
||||||
|
section + section h6,
|
||||||
|
section + section div.tabbed-content--wrap > .tabbed-content {
|
||||||
|
clear: both; }
|
||||||
|
article h1,
|
||||||
|
article h2,
|
||||||
|
article h3,
|
||||||
|
article h4,
|
||||||
|
article h5,
|
||||||
|
article h6,
|
||||||
|
article img,
|
||||||
|
section + section h1,
|
||||||
|
section + section h2,
|
||||||
|
section + section h3,
|
||||||
|
section + section h4,
|
||||||
|
section + section h5,
|
||||||
|
section + section h6,
|
||||||
|
section + section img {
|
||||||
|
page-break-after: avoid;
|
||||||
|
page-break-inside: avoid; }
|
||||||
|
article a,
|
||||||
|
article blockquote,
|
||||||
|
article table,
|
||||||
|
article ul,
|
||||||
|
article ol,
|
||||||
|
section + section a,
|
||||||
|
section + section blockquote,
|
||||||
|
section + section table,
|
||||||
|
section + section ul,
|
||||||
|
section + section ol {
|
||||||
|
page-break-before: avoid;
|
||||||
|
page-break-inside: avoid; }
|
||||||
|
article pre,
|
||||||
|
article dt + dd,
|
||||||
|
section + section pre,
|
||||||
|
section + section dt + dd {
|
||||||
|
page-break-before: avoid; }
|
||||||
|
article h1 + ul,
|
||||||
|
article h2 + ul,
|
||||||
|
article h3 + ul,
|
||||||
|
article h4 + ul,
|
||||||
|
article h5 + ul,
|
||||||
|
article h6 + ul,
|
||||||
|
article h1 + ol,
|
||||||
|
article h2 + ol,
|
||||||
|
article h3 + ol,
|
||||||
|
article h4 + ol,
|
||||||
|
article h5 + ol,
|
||||||
|
article h6 + ol,
|
||||||
|
section + section h1 + ul,
|
||||||
|
section + section h2 + ul,
|
||||||
|
section + section h3 + ul,
|
||||||
|
section + section h4 + ul,
|
||||||
|
section + section h5 + ul,
|
||||||
|
section + section h6 + ul,
|
||||||
|
section + section h1 + ol,
|
||||||
|
section + section h2 + ol,
|
||||||
|
section + section h3 + ol,
|
||||||
|
section + section h4 + ol,
|
||||||
|
section + section h5 + ol,
|
||||||
|
section + section h6 + ol {
|
||||||
|
page-break-inside: auto; }
|
||||||
|
article div.admonition,
|
||||||
|
section + section div.admonition {
|
||||||
|
page-break-inside: avoid; }
|
||||||
|
article div.tabbed-content--wrap,
|
||||||
|
section + section div.tabbed-content--wrap {
|
||||||
|
page-break-inside: avoid; }
|
||||||
|
article * + div.highlight,
|
||||||
|
article * + div.tabbed-set,
|
||||||
|
section + section * + div.highlight,
|
||||||
|
section + section * + div.tabbed-set {
|
||||||
|
page-break-before: avoid; }
|
||||||
|
|
||||||
|
section.two-columns {
|
||||||
|
columns: 2;
|
||||||
|
column-gap: 1cm; }
|
||||||
|
|
||||||
|
article h1 {
|
||||||
|
border-bottom: 2px solid #f00; }
|
||||||
|
|
||||||
|
article h2 {
|
||||||
|
border-bottom: 1px solid #f99; }
|
||||||
|
|
||||||
|
article h3 {
|
||||||
|
border-bottom: 0.5px solid #eee; }
|
||||||
|
|
||||||
|
article h1 > .pdf-order,
|
||||||
|
article h2 > .pdf-order,
|
||||||
|
article h3 > .pdf-order {
|
||||||
|
padding-left: 6px; }
|
||||||
|
|
||||||
|
article#doc-toc {
|
||||||
|
margin: 0 .8rem 1.2rem;
|
||||||
|
padding-top: .6rem;
|
||||||
|
font-size: 12pt;
|
||||||
|
line-height: 1.6; }
|
||||||
|
article#doc-toc > h1 {
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
color: rgba(0, 0, 0, 0.54);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: -.01em;
|
||||||
|
page-break-after: auto;
|
||||||
|
page-break-inside: auto;
|
||||||
|
bookmark-level: none; }
|
||||||
|
article#doc-toc > h1::before {
|
||||||
|
display: block;
|
||||||
|
margin-top: -9px;
|
||||||
|
padding-top: 9px;
|
||||||
|
content: ""; }
|
||||||
|
article#doc-toc ul {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
margin-left: 1em;
|
||||||
|
font-size: 8pt;
|
||||||
|
page-break-inside: auto !important; }
|
||||||
|
article#doc-toc li {
|
||||||
|
list-style: none; }
|
||||||
|
article#doc-toc li > a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
padding-top: 0.4rem;
|
||||||
|
border-bottom: 1px dotted #ddd;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%; }
|
||||||
|
article#doc-toc li > a > .pdf-order {
|
||||||
|
padding-right: 0.5em; }
|
||||||
|
article#doc-toc li > a::after {
|
||||||
|
float: right;
|
||||||
|
content: target-counter(attr(href), page); }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
html {
|
||||||
|
font-size: 95%;
|
||||||
|
font-family: 'Kelmscott Roman NF', 'Noto Serif JP', serif; }
|
||||||
|
body {
|
||||||
|
font-size: 10.5pt;
|
||||||
|
font-family: 'Classico URW T OT', 'Noto Serif JP', serif; }
|
||||||
|
article {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1.6; }
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
label {
|
||||||
|
font-family: 'Gentium Book Basic', 'Helvetica Neue', Helvetica, Arial, 'Noto Sans JP', 'Roboto', sans-serif; }
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
var,
|
||||||
|
samp,
|
||||||
|
kbd,
|
||||||
|
tt {
|
||||||
|
font-family: 'Noto Sans Mono CJK JP', 'Courier New', monospace, serif;
|
||||||
|
font-size: 0.8em; }
|
||||||
|
pre code,
|
||||||
|
pre var,
|
||||||
|
pre samp,
|
||||||
|
pre kbd,
|
||||||
|
pre tt {
|
||||||
|
font-size: 100%; } }
|
||||||
|
@page :first {
|
||||||
|
@top-right {
|
||||||
|
content: normal; }
|
||||||
|
@bottom-center {
|
||||||
|
content: normal; }
|
||||||
|
@bottom-right {
|
||||||
|
content: normal; } }
|
||||||
|
|
||||||
|
article#doc-cover {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh; }
|
||||||
|
article#doc-cover > .wrapper {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 3rem; }
|
||||||
|
article#doc-cover > .wrapper.upper {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
max-height: 30vh; }
|
||||||
|
article#doc-cover > .wrapper.upper > .logo {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-position: center bottom;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: contain; }
|
||||||
|
article#doc-cover > .wrapper h1 {
|
||||||
|
font-size: 36pt;
|
||||||
|
line-height: 1.4; }
|
||||||
|
article#doc-cover > .wrapper h2 {
|
||||||
|
border: none;
|
||||||
|
bookmark-level: none; }
|
||||||
|
article#doc-cover > .properties {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 2rem; }
|
||||||
|
article#doc-cover > .properties p#copyright {
|
||||||
|
font-size: 80%; }
|
||||||
|
|
||||||
|
article#doc-back_cover {
|
||||||
|
page: back_cover;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center; }
|
||||||
|
article#doc-back_cover .wrapper {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
display: inline-block;
|
||||||
|
background: #eee; }
|
||||||
|
article#doc-back_cover .qrcode {
|
||||||
|
display: inline-block;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
background: #eee; }
|
||||||
|
article#doc-back_cover .qrcode > a {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.5em 2em;
|
||||||
|
border-radius: 1em;
|
||||||
|
background-color: #fff; }
|
||||||
|
article#doc-back_cover .qrcode > a img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto; }
|
||||||
|
|
||||||
|
@page back_cover {
|
||||||
|
background-color: #eee;
|
||||||
|
@top-right {
|
||||||
|
content: normal; }
|
||||||
|
@bottom-center {
|
||||||
|
content: normal; }
|
||||||
|
@bottom-left {
|
||||||
|
font-size: 8pt;
|
||||||
|
content: string(title); }
|
||||||
|
@bottom-right {
|
||||||
|
font-size: 8pt;
|
||||||
|
content: string(copyright); } }
|
||||||
|
@media print {
|
||||||
|
html {
|
||||||
|
font-size: 95%;
|
||||||
|
font-family: 'Ubuntu'; }
|
||||||
|
body {
|
||||||
|
font-size: 11.5pt;
|
||||||
|
font-family: 'Ubuntu'; }
|
||||||
|
article {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1.6; }
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
label {
|
||||||
|
font-family: 'Gentium Book Basic', 'Helvetica Neue', Helvetica, Arial, 'Noto Sans JP', 'Roboto', sans-serif; }
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
var,
|
||||||
|
samp,
|
||||||
|
kbd,
|
||||||
|
tt {
|
||||||
|
font-family: 'Noto Sans Mono CJK JP', 'Courier New', monospace, serif;
|
||||||
|
font-size: 0.8em; }
|
||||||
|
pre code,
|
||||||
|
pre var,
|
||||||
|
pre samp,
|
||||||
|
pre kbd,
|
||||||
|
pre tt {
|
||||||
|
font-size: 100%; } }
|
||||||
|
</style><style>@media print {
|
||||||
|
.md-typeset .tabbed-set {
|
||||||
|
display: block; }
|
||||||
|
.md-typeset .tabbed-set .tabbed-content--wrap {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 0.25rem; }
|
||||||
|
.md-typeset .tabbed-set .tabbed-content--wrap > input {
|
||||||
|
display: none; }
|
||||||
|
.md-typeset .tabbed-set .tabbed-content--wrap > label {
|
||||||
|
background-color: rgba(170, 170, 170, 0.2);
|
||||||
|
padding: 0.2rem 2rem;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #666;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
border-bottom-color: transparent; }
|
||||||
|
.md-typeset .tabbed-set .tabbed-content--wrap > .tabbed-content {
|
||||||
|
display: block;
|
||||||
|
box-shadow: none; }
|
||||||
|
.md-typeset .admonition-title + .tabbed-set:last-child,
|
||||||
|
.md-typeset summary + .tabbed-set:last-child {
|
||||||
|
margin-top: 0.5rem; }
|
||||||
|
.md-typeset > details summary::after {
|
||||||
|
display: none; }
|
||||||
|
.md-typeset > div, .md-typeset > div.admonition, .md-typeset > details, .md-typeset > div.tabbed-set, .md-typeset > blockquote, .md-typeset > mark, .md-typeset > table, .md-typeset > p {
|
||||||
|
margin-left: 0.7rem; }
|
||||||
|
.md-typeset > table.highlighttable {
|
||||||
|
margin: 0 0 0 0.7rem; }
|
||||||
|
.md-typeset table.highlighttable,
|
||||||
|
.md-typeset table.highlighttable > tbody {
|
||||||
|
width: 100%; }
|
||||||
|
.md-typeset table.highlighttable {
|
||||||
|
padding-bottom: 0.5em; }
|
||||||
|
.md-typeset table.highlighttable .linenos {
|
||||||
|
padding-bottom: 0; }
|
||||||
|
.md-typeset > ul {
|
||||||
|
margin-left: 1.5rem; }
|
||||||
|
.md-typeset h4,
|
||||||
|
.md-typeset h5,
|
||||||
|
.md-typeset h6 {
|
||||||
|
margin-left: 0.25rem; }
|
||||||
|
.md-typeset *:not(h3) + h4 {
|
||||||
|
margin-top: 1.5rem; }
|
||||||
|
.md-typeset hr {
|
||||||
|
border-bottom: 1px dotted #999; }
|
||||||
|
.md-typeset .footnote {
|
||||||
|
line-height: 1.1; }
|
||||||
|
.md-typeset table:not([class]) th, .md-typeset table:not([class]) td {
|
||||||
|
padding: 0.5em 1.25rem 0.4em; }
|
||||||
|
.md-typeset table:not([class]) td {
|
||||||
|
border-bottom: 1px solid #eee; }
|
||||||
|
.md-typeset span.twemoji {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1.125rem;
|
||||||
|
display: inline-block; }
|
||||||
|
.md-typeset span.twemoji > img {
|
||||||
|
height: 1.125rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block; } }
|
||||||
|
.md-typeset kbd {
|
||||||
|
vertical-align: middle;
|
||||||
|
border-color: #b8b8b8;
|
||||||
|
border-style: outset;
|
||||||
|
border-width: .05rem .075rem .1rem .075rem;
|
||||||
|
border-radius: .25rem;
|
||||||
|
box-shadow: none; }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--print-md-admonition-icon--note: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23448aff"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z"/></svg>');
|
||||||
|
--print-md-admonition-icon--abstract: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2300b0ff"><path d="M4 5h16v2H4V5m0 4h16v2H4V9m0 4h16v2H4v-2m0 4h10v2H4v-2z"/></svg>');
|
||||||
|
--print-md-admonition-icon--info: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2300b8d4"><path d="M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 002 12a10 10 0 0010 10 10 10 0 0010-10A10 10 0 0012 2z"/></svg>');
|
||||||
|
--print-md-admonition-icon--tip: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2300bfa5"><path d="M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 01-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z"/></svg>');
|
||||||
|
--print-md-admonition-icon--success: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2300c853"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2m-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>');
|
||||||
|
--print-md-admonition-icon--question: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2364dd17"><path d="M15.07 11.25l-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 00-2-2 2 2 0 00-2 2H8a4 4 0 014-4 4 4 0 014 4 3.2 3.2 0 01-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 002 12a10 10 0 0010 10 10 10 0 0010-10c0-5.53-4.5-10-10-10z"/></svg>');
|
||||||
|
--print-md-admonition-icon--warning: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ff9100"><path d="M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z"/></svg>');
|
||||||
|
--print-md-admonition-icon--failure: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ff5252"><path d="M12 2c5.53 0 10 4.47 10 10s-4.47 10-10 10S2 17.53 2 12 6.47 2 12 2m3.59 5L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41 15.59 7z"/></svg>');
|
||||||
|
--print-md-admonition-icon--danger: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ff1744"><path d="M11.5 20l4.86-9.73H13V4l-5 9.73h3.5V20M12 2c2.75 0 5.1 1 7.05 2.95C21 6.9 22 9.25 22 12s-1 5.1-2.95 7.05C17.1 21 14.75 22 12 22s-5.1-1-7.05-2.95C3 17.1 2 14.75 2 12s1-5.1 2.95-7.05C6.9 3 9.25 2 12 2z"/></svg>');
|
||||||
|
--print-md-admonition-icon--bug: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23f50057"><path d="M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 00-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 00-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z"/></svg>');
|
||||||
|
--print-md-admonition-icon--example: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23651fff"><path d="M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 01.75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z"/></svg>');
|
||||||
|
--print-md-admonition-icon--quote: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%239e9e9e"><path d="M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z"/></svg>'); }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.md-typeset .admonition-title {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .admonition-title::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--note); }
|
||||||
|
.md-typeset .note > .admonition-title, .md-typeset .note > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .note > .admonition-title::before, .md-typeset .note > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--note); }
|
||||||
|
.md-typeset .abstract > .admonition-title, .md-typeset .tldr > .admonition-title, .md-typeset .summary > .admonition-title, .md-typeset .abstract > summary, .md-typeset .tldr > summary, .md-typeset .summary > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .abstract > .admonition-title::before, .md-typeset .tldr > .admonition-title::before, .md-typeset .summary > .admonition-title::before, .md-typeset .abstract > summary::before, .md-typeset .tldr > summary::before, .md-typeset .summary > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--abstract); }
|
||||||
|
.md-typeset .info > .admonition-title, .md-typeset .todo > .admonition-title, .md-typeset .info > summary, .md-typeset .todo > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .info > .admonition-title::before, .md-typeset .todo > .admonition-title::before, .md-typeset .info > summary::before, .md-typeset .todo > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--info); }
|
||||||
|
.md-typeset .tip > .admonition-title, .md-typeset .important > .admonition-title, .md-typeset .hint > .admonition-title, .md-typeset .tip > summary, .md-typeset .important > summary, .md-typeset .hint > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .tip > .admonition-title::before, .md-typeset .important > .admonition-title::before, .md-typeset .hint > .admonition-title::before, .md-typeset .tip > summary::before, .md-typeset .important > summary::before, .md-typeset .hint > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--tip); }
|
||||||
|
.md-typeset .success > .admonition-title, .md-typeset .done > .admonition-title, .md-typeset .check > .admonition-title, .md-typeset .success > summary, .md-typeset .done > summary, .md-typeset .check > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .success > .admonition-title::before, .md-typeset .done > .admonition-title::before, .md-typeset .check > .admonition-title::before, .md-typeset .success > summary::before, .md-typeset .done > summary::before, .md-typeset .check > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--success); }
|
||||||
|
.md-typeset .question > .admonition-title, .md-typeset .faq > .admonition-title, .md-typeset .help > .admonition-title, .md-typeset .question > summary, .md-typeset .faq > summary, .md-typeset .help > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .question > .admonition-title::before, .md-typeset .faq > .admonition-title::before, .md-typeset .help > .admonition-title::before, .md-typeset .question > summary::before, .md-typeset .faq > summary::before, .md-typeset .help > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--question); }
|
||||||
|
.md-typeset .warning > .admonition-title, .md-typeset .attention > .admonition-title, .md-typeset .caution > .admonition-title, .md-typeset .warning > summary, .md-typeset .attention > summary, .md-typeset .caution > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .warning > .admonition-title::before, .md-typeset .attention > .admonition-title::before, .md-typeset .caution > .admonition-title::before, .md-typeset .warning > summary::before, .md-typeset .attention > summary::before, .md-typeset .caution > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--warning); }
|
||||||
|
.md-typeset .failure > .admonition-title, .md-typeset .missing > .admonition-title, .md-typeset .fail > .admonition-title, .md-typeset .failure > summary, .md-typeset .missing > summary, .md-typeset .fail > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .failure > .admonition-title::before, .md-typeset .missing > .admonition-title::before, .md-typeset .fail > .admonition-title::before, .md-typeset .failure > summary::before, .md-typeset .missing > summary::before, .md-typeset .fail > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--failure); }
|
||||||
|
.md-typeset .danger > .admonition-title, .md-typeset .error > .admonition-title, .md-typeset .danger > summary, .md-typeset .error > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .danger > .admonition-title::before, .md-typeset .error > .admonition-title::before, .md-typeset .danger > summary::before, .md-typeset .error > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--danger); }
|
||||||
|
.md-typeset .bug > .admonition-title, .md-typeset .bug > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .bug > .admonition-title::before, .md-typeset .bug > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--bug); }
|
||||||
|
.md-typeset .example > .admonition-title, .md-typeset .example > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .example > .admonition-title::before, .md-typeset .example > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--example); }
|
||||||
|
.md-typeset .quote > .admonition-title, .md-typeset .cite > .admonition-title, .md-typeset .quote > summary, .md-typeset .cite > summary {
|
||||||
|
padding: .6rem .6rem .4rem 2.2rem; }
|
||||||
|
.md-typeset .quote > .admonition-title::before, .md-typeset .cite > .admonition-title::before, .md-typeset .quote > summary::before, .md-typeset .cite > summary::before {
|
||||||
|
margin-top: -0.15rem;
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-admonition-icon--quote); } }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--print-md-footnotes-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23000000de"><path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.42L5.83 13H21V7h-2z"/></svg>'); }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.md-typeset .footnote-backref::before {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-footnotes-icon); } }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--print-md-details-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="hsla(0, 0%, 0%, 0.87)"><path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/></svg>'); }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.md-typeset summary::after {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-details-icon);
|
||||||
|
-webkit-mask-image: none;
|
||||||
|
mask-image: none; } }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--print-md-tasklist-icon: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23ddd"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2m-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>');
|
||||||
|
--print-md-tasklist-icon--checked: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%2300e676"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2m-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>'); }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.md-typeset .task-list-control .task-list-indicator::before {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-tasklist-icon); }
|
||||||
|
.md-typeset .task-list-control [type=checkbox]:checked + .task-list-indicator::before {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: var(--print-md-tasklist-icon--checked); } }
|
||||||
|
|
||||||
|
/*# sourceMappingURL=material-polyfills.css.map*/
|
||||||
|
</style></head><body>I am a cover!<article id="doc-toc"><h1>Table of contents</h1><ul><li><a href="#.:lets-build-your-awesome-selfhosted-platform-together">Let's build your awesome selfhosted platform together!</a><ul><li><a href="#.:what-to-expect">What to expect</a></li><li><a href="#.:how-will-this-benefit-me">How will this benefit me?</a></li><li><a href="#.:testimonials">Testimonials</a></li><li><a href="#.:who-made-this">Who made this?</a><ul><li><a href="#.:hi-im-david">👋 Hi, I'm David</a></li><li><a href="#.:what-do-you-want-from-me">What do you want from me?</a></li><li><a href="#.:sponsored-projects">Sponsored Projects</a></li></ul></li></ul></li><li><a href="#IRXWG23FOIQFG53BOJWQ/">Docker Swarm</a><ul><li><a href="#docker-swarm/:highly-available-docker-swarm-design">Highly Available Docker Swarm Design</a><ul><li><a href="#docker-swarm/:design-decisions">Design Decisions</a></li><li><a href="#docker-swarm/:security">Security</a></li><li><a href="#docker-swarm/:high-availability">High availability</a></li></ul></li><li><a href="#IRXWG23FOIQFG53BOJWQ/KBZGK4DBOJQXI2LPNY/">Preparation</a><ul><li><a href="#docker-swarm/design/:highly-available-docker-swarm-design">Highly Available Docker Swarm Design</a></li><li><a href="#docker-swarm/nodes/:nodes">Nodes</a></li></ul></li></ul></li><li><a href="#4KN3IICLOVRGK4TOMV2GK4Y/">⛴ Kubernetes</a><ul><li><a href="#4KN3IICLOVRGK4TOMV2GK4Y/KBZGK4DBOJQXI2LPNY/">Preparation</a><ul><li><a href="#kubernetes/">Introduction</a></li></ul></li></ul></li></ul></article><article class="md-content__inner md-typeset" data-url="/." id=".:"> <h1 id=".:lets-build-your-awesome-selfhosted-platform-together">Let's build your awesome selfhosted platform together!</h1> <p>Welcome, fellow geek <img alt="👋" class="twemoji" src="https://twemoji.maxcdn.com/v/latest/svg/1f44b.svg" title=":wave:"/> If you're impatient, just start here <img alt="👇" class="twemoji" src="https://twemoji.maxcdn.com/v/latest/svg/1f447.svg" title=":point_down:"/></p> <div class="grid cards"> <ul> <li> <p><strong>Dive into <span class="twemoji docker lg middle"><img class="converted-twemoji" src="data:image/svg+xml;charset=utf-8;base64,PHN2ZyBoZWlnaHQ9IjI0IiBzdHlsZT0iZmlsbDogY3VycmVudENvbG9yOyIgdmlld2JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIxLjgxIDEwLjI1Yy0uMDYtLjA0LS41Ni0uNDMtMS42NC0uNDMtLjI4IDAtLjU2LjAzLS44NC4wOC0uMjEtMS40LTEuMzgtMi4xMS0xLjQzLTIuMTRsLS4yOS0uMTctLjE4LjI3Yy0uMjQuMzYtLjQzLjc3LS41MSAxLjE5LS4yLjgtLjA4IDEuNTYuMzMgMi4yMS0uNDkuMjgtMS4yOS4zNS0xLjQ2LjM1SDIuNjJjLS4zNCAwLS42Mi4yOC0uNjIuNjMgMCAxLjE1LjE4IDIuMy41OCAzLjM4LjQ1IDEuMTkgMS4xMyAyLjA3IDIgMi42MS45OC42IDIuNTkuOTQgNC40Mi45NC43OSAwIDEuNjEtLjA3IDIuNDItLjIyIDEuMTItLjIgMi4yLS41OSAzLjE5LTEuMTZBOC4zIDguMyAwIDAgMCAxNi43OCAxNmMxLjA1LTEuMTcgMS42Ny0yLjUgMi4xMi0zLjY1aC4xOWMxLjE0IDAgMS44NS0uNDYgMi4yNC0uODUuMjYtLjI0LjQ1LS41My41OS0uODdsLjA4LS4yNC0uMTktLjE0bS0xNy45Ni45OWgxLjc2Yy4wOCAwIC4xNi0uMDcuMTYtLjE2VjkuNWMwLS4wOC0uMDctLjE2LS4xNi0uMTZIMy44NWMtLjA5IDAtLjE2LjA3LS4xNi4xNnYxLjU4Yy4wMS4wOS4wNy4xNi4xNi4xNm0yLjQzIDBoMS43NmMuMDggMCAuMTYtLjA3LjE2LS4xNlY5LjVjMC0uMDgtLjA3LS4xNi0uMTYtLjE2SDYuMjhjLS4wOSAwLS4xNi4wNy0uMTYuMTZ2MS41OGMuMDEuMDkuMDcuMTYuMTYuMTZtMi40NyAwaDEuNzVjLjEgMCAuMTctLjA3LjE3LS4xNlY5LjVjMC0uMDgtLjA2LS4xNi0uMTctLjE2SDguNzVjLS4wOCAwLS4xNS4wNy0uMTUuMTZ2MS41OGMwIC4wOS4wNi4xNi4xNS4xNm0yLjQ0IDBoMS43N2MuMDggMCAuMTUtLjA3LjE1LS4xNlY5LjVjMC0uMDgtLjA2LS4xNi0uMTUtLjE2aC0xLjc3Yy0uMDggMC0uMTUuMDctLjE1LjE2djEuNThjMCAuMDkuMDcuMTYuMTUuMTZNNi4yOCA5aDEuNzZjLjA4IDAgLjE2LS4wOS4xNi0uMThWNy4yNWMwLS4wOS0uMDctLjE2LS4xNi0uMTZINi4yOGMtLjA5IDAtLjE2LjA2LS4xNi4xNnYxLjU3Yy4wMS4wOS4wNy4xOC4xNi4xOG0yLjQ3IDBoMS43NWMuMSAwIC4xNy0uMDkuMTctLjE4VjcuMjVjMC0uMDktLjA2LS4xNi0uMTctLjE2SDguNzVjLS4wOCAwLS4xNS4wNi0uMTUuMTZ2MS41N2MwIC4wOS4wNi4xOC4xNS4xOG0yLjQ0IDBoMS43N2MuMDggMCAuMTUtLjA5LjE1LS4xOFY3LjI1YzAtLjA5LS4wNy0uMTYtLjE1LS4xNmgtMS43N2MtLjA4IDAtLjE1LjA2LS4xNS4xNnYxLjU3YzAgLjA5LjA3LjE4LjE1LjE4bTAtMi4yOGgxLjc3Yy4wOCAwIC4xNS0uMDcuMTUtLjE2VjVjMC0uMS0uMDctLjE3LS4xNS0uMTdoLTEuNzdjLS4wOCAwLS4xNS4wNi0uMTUuMTd2MS41NmMwIC4wOC4wNy4xNi4xNS4xNm0yLjQ2IDQuNTJoMS43NmMuMDkgMCAuMTYtLjA3LjE2LS4xNlY5LjVjMC0uMDgtLjA3LS4xNi0uMTYtLjE2aC0xLjc2Yy0uMDggMC0uMTUuMDctLjE1LjE2djEuNThjMCAuMDkuMDcuMTYuMTUuMTYiPjwvcGF0aD48L3N2Zz4="/></span> <a href="/docker-swarm/design/">Docker Swarm</a></strong></p> <hr/> <p>The quickest way to get started, and to get your head around the basics.</p> </li> <li> <p><strong>Kick it with <span class="twemoji kubernetes lg middle"><img class="converted-twemoji" src="data:image/svg+xml;charset=utf-8;base64,PHN2ZyBoZWlnaHQ9IjI0IiBzdHlsZT0iZmlsbDogY3VycmVudENvbG9yOyIgdmlld2JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEzLjk1IDEzLjVoLS4yM2MtLjE4LjExLS4yNi4zMi0uMTguNWwuODYgMi4xMWMuODMtLjUzIDEuNDYtMS4zMiAxLjc5LTIuMjVsLTIuMjMtLjM2aC0uMDFtLTMuNDUuMjlhLjQxNS40MTUgMCAwIDAtLjM4LS4yOWgtLjA4bC0yLjIyLjM3Yy4zMy45Mi45NiAxLjcgMS43OSAyLjIzbC44NS0yLjA3VjE0Yy4wNC0uMDUuMDQtLjE0LjA0LS4yMW0xLjgzLjgxYS4zNzguMLine truncated
|
||||||
|
-A INPUT -s <span class="m">192</span>.168.31.0/24 -j ACCEPT
|
||||||
|
</code></pre></div> <p>And restart iptables with <code>systemctl restart iptables</code></p> <h6 id="docker-swarm/nodes/:ubuntu">Ubuntu</h6> <p>Install the (<em>non-default</em>) persistent iptables tools, by running <code>apt-get install iptables-persistent</code>, establishing some default rules (<em>dkpg will prompt you to save current ruleset</em>), and then add something like this to <code>/etc/iptables/rules.v4</code>:</p> <div class="highlight"><pre><span></span><code><span class="c1"># Allow all inter-node communication</span>
|
||||||
|
-A INPUT -s <span class="m">192</span>.168.31.0/24 -j ACCEPT
|
||||||
|
</code></pre></div> <p>And refresh your running iptables rules with <code>iptables-restore < /etc/iptables/rules.v4</code></p> <h5 id="docker-swarm/nodes/:enable-hostname-resolution">Enable hostname resolution</h5> <p>Depending on your hosting environment, you may have DNS automatically setup for your VMs. If not, it's useful to set up static entries in /etc/hosts for the nodes. For example, I setup the following:</p> <ul> <li>192.168.31.11 ds1 ds1.funkypenguin.co.nz</li> <li>192.168.31.12 ds2 ds2.funkypenguin.co.nz</li> <li>192.168.31.13 ds3 ds3.funkypenguin.co.nz</li> </ul> <h5 id="docker-swarm/nodes/:set-timezone">Set timezone</h5> <p>Set your local timezone, by running:</p> <div class="highlight"><pre><span></span><code>ln -sf /usr/share/zoneinfo/<your timezone> /etc/localtime
|
||||||
|
</code></pre></div> <h4 id="docker-swarm/nodes/:serving">Serving</h4> <p>After completing the above, you should have:</p> <div class="admonition summary"> <p class="admonition-title">Summary</p> <p>Deployed in this recipe:</p> <ul class="task-list"> <li class="task-list-item"><label class="task-list-control"><input checked="" disabled="" type="checkbox"/><span class="task-list-indicator"></span></label> 3 x nodes (<em>bare-metal or VMs</em>), each with:<ul> <li>A mainstream Linux OS (<em>tested on either <a href="https://www.centos.org">CentOS</a> 7+ or <a href="http://releases.ubuntu.com">Ubuntu</a> 16.04+</em>)</li> <li>At least 2GB RAM</li> <li>At least 20GB disk space (<em>but it'll be tight</em>)</li> </ul> </li> <li class="task-list-item"><label class="task-list-control"><input checked="" disabled="" type="checkbox"/><span class="task-list-indicator"></span></label> Connectivity to each other within the same subnet, and on a low-latency link (<em>i.e., no WAN links</em>)</li> </ul> </div> <hr/> <div class="md-source-file"> <small> Last update: <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">July 9, 2022</span> </small> </div> </section></section></article><article class="md-content__inner md-typeset" data-url="/4KN3IICLOVRGK4TOMV2GK4Y/" id="4KN3IICLOVRGK4TOMV2GK4Y/:"><h1 id="4KN3IICLOVRGK4TOMV2GK4Y/">⛴ Kubernetes</h1><section class="md-typeset" data-url="/4KN3IICLOVRGK4TOMV2GK4Y/KBZGK4DBOJQXI2LPNY/" id="4KN3IICLOVRGK4TOMV2GK4Y/KBZGK4DBOJQXI2LPNY/:"><h2 id="4KN3IICLOVRGK4TOMV2GK4Y/KBZGK4DBOJQXI2LPNY/">Preparation</h2><section class="md-typeset" data-url="/kubernetes/" id="kubernetes/:"> <h3 id="kubernetes/">Introduction</h3> <p>My first introduction to Kubernetes was a children's story:</p> <!-- markdownlint-disable MD033 --> <iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/R9-SOzep73w" width="560"></iframe> <h4 id="kubernetes/:why-kubernetes">Why Kubernetes?</h4> <p>Why would you want to Kubernetes for your self-hosted recipes, over simple <a href="/docker-swarm/">Docker Swarm</a>? Here's my personal take..</p> <h5 id="kubernetes/:docker-swarm-is-dead">Docker Swarm is dead</h5> <p>Sorry to say, but from where I sit, there's no innovation or development happening in docker swarm.</p> <p>Yes, I know, after Docker Inc <a href="https://www.mirantis.com/blog/mirantis-acquires-docker-enterprise-platform-business/">sold its platform business to Mirantis in Nov 2019</a>, in Feb 2020 Mirantis <a href="https://www.mirantis.com/blog/mirantis-will-continue-to-support-and-develop-docker-swarm/">back-tracked</a> on their original plan to sunset swarm after 2 years, and stated that they'd continue to invest in swarm. But seriously, look around. Nobody is interested in swarm right now...</p> <p>... Not even Mirantis! As of Nov 2021, the Mirantis blog tag "<a href="https://www.mirantis.com/tag/kubernetes/">kubernetes</a>" had 8 posts within the past month. The tag "<a href="https://www.mirantis.com/tag/docker/">docker</a>" has 8 posts in the past <strong>2 years</strong>, the 8<sup>th</sup> being the original announcement of the Docker aquisition. The tag "<a href="https://www.mirantis.com/tag/docker-swarm/">docker swarm</a>" has only 2 posts, <strong>ever</strong>.</p> <p>Dead. <a href="https://youtu.be/NxnZC9L_YXE?t=47">Extinct. Like the doodoo</a>.</p> <h5 id="kubernetes/:once-you-go-kubernetes-you-cant-go-back">Once you go Kubernetes, you can't go back</h5> <p>For years now, <a href="https://www.funkypenguin.co.nz/work-with-me/">I've provided Kubernetes design consulting</a> to small clients and large enterprises. The implementation details in each case vary widely, but there are some primitives which I've come to take for granted, and I wouldn't easily do without. A few examples:</p> <ul> <li><strong>CLI drives API from anywhere</strong>. From my laptop, I can use my credentials to manage any number of Kubernetes clusters, simply by switching kubectl "context". Each interaction is an API call against an HTTPS endpoint. No SSHing to hosts and manually running docker command as root!</li> <li><strong>GitOps is magic</strong>. There are multiple ways to achieve it, but having changes you commit to a repo automatically applied to a cluster, "Just Works™". The process removes so much friction from making changes that it makes you more productive, and a better "gitizen" ;P</li> <li><strong>Controllers are trustworthy</strong>. I've come to trust that when I tell Kubernetes to run 3 replicas on separate hosts, to scale up a set of replicas based on CPU load metrics, or provision a blob of storage for a given workloa, that this will be done in a consistent and visible way. I'll be able to see logs / details for each action taken by the controller, and adjust my own instructions/configuration accordingly if necessary.</li> </ul> <h4 id="kubernetes/:uggh-itLine truncated
|
||||||
|
<div class="wrapper"></div><div class="qrcode">
|
||||||
|
<a href="https://geek-cookbook.funkypenguin.co.nz/">
|
||||||
|
<img src="data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4KPHN2ZyB3aWR0aD0iMzdtbSIgaGVpZ2h0PSIzN21tIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzNyAzNyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNIDMwIDI1IEwgMzAgMjYgTCAzMSAyNiBMIDMxIDI1IHogTSAyMyA0IEwgMjMgNSBMIDI0IDUgTCAyNCA0IHogTSAxMiAxMyBMIDEyIDE0IEwgMTMgMTQgTCAxMyAxMyB6IE0gMjMgMTMgTCAyMyAxNCBMIDI0IDE0IEwgMjQgMTMgeiBNIDQgOSBMIDQgMTAgTCA1IDEwIEwgNSA5IHogTSAxNSA5IEwgMTUgMTAgTCAxNiAxMCBMIDE2IDkgeiBNIDQgMjcgTCA0IDI4IEwgNSAyOCBMIDUgMjcgeiBNIDE1IDI3IEwgMTUgMjggTCAxNiAyOCBMIDE2IDI3IHogTSAxNCAzMSBMIDE0IDMyIEwgMTUgMzIgTCAxNSAzMSB6IE0gMjkgMjkgTCAyOSAzMCBMIDMwIDMwIEwgMzAgMjkgeiBNIDggNiBMIDggNyBMIDkgNyBMIDkgNiB6IE0gMjYgMTQgTCAyNiAxNSBMIDI3IDE1IEwgMjcgMTQgeiBNIDcgMTAgTCA3IDExIEwgOCAxMSBMIDggMTAgeiBNIDI2IDIzIEwgMjYgMjQgTCAyNyAyNCBMIDI3IDIzIHogTSAyNiAzMiBMIDI2IDMzIEwgMjcgMzMgTCAyNyAzMiB6IE0gNyAyOCBMIDcgMjkgTCA4IDI5IEwgOCAyOCB6IE0gMTggMjggTCAxOCAyOSBMIDE5IDI5IEwgMTkgMjggeiBNIDMwIDIwIEwgMzAgMjEgTCAzMSAyMSBMIDMxIDIwIHogTSAzMCAyOSBMIDMwIDMwIEwgMzEgMzAgTCAzMSAyOSB6IE0gMTIgOCBMIDEyIDkgTCAxMyA5IEwgMTMgOCB6IE0gMjMgOCBMIDIzIDkgTCAyNCA5IEwgMjQgOCB6IE0gNCA0IEwgNCA1IEwgNSA1IEwgNSA0IHogTSA0IDEzIEwgNCAxNCBMIDUgMTQgTCA1IDEzIHogTSAyOSAxNSBMIDI5IDE2IEwgMzAgMTYgTCAzMCAxNSB6IE0gMjYgOSBMIDI2IDEwIEwgMjcgMTAgTCAyNyA5IHogTSAxOCA1IEwgMTggNiBMIDE5IDYgTCAxOSA1IHogTSA3IDE0IEwgNyAxNSBMIDggMTUgTCA4IDE0IHogTSAxOCAxNCBMIDE4IDE1IEwgMTkgMTUgTCAxOSAxNCB6IE0gNyAyMyBMIDcgMjQgTCA4IDI0IEwgOCAyMyB6IE0gMTggMjMgTCAxOCAyNCBMIDE5IDI0IEwgMTkgMjMgeiBNIDcgMzIgTCA3IDMzIEwgOCAzMyBMIDggMzIgeiBNIDE4IDMyIEwgMTggMzMgTCAxOSAzMyBMIDE5IDMyIHogTSAzMCA2IEwgMzAgNyBMIDMxIDcgTCAzMSA2IHogTSAzMCAyNCBMIDMwIDI1IEwgMzEgMjUgTCAzMSAyNCB6IE0gMTUgOCBMIDE1IDkgTCAxNiA5IEwgMTYgOCB6IE0gMjkgMTAgTCAyOSAxMSBMIDMwIDExIEwgMzAgMTAgeiBNIDE0IDIxIEwgMTQgMjIgTCAxNSAyMiBMIDE1IDIxIHogTSAxNCAzMCBMIDE0IDMxIEwgMTUgMzEgTCAxNSAzMCB6IE0gNiAyNiBMIDYgMjcgTCA3IDI3IEwgNyAyNiB6IE0gMjYgNCBMIDI2IDUgTCAyNyA1IEwgMjcgNCB6IE0gMjYgMTMgTCAyNiAxNCBMIDI3IDE0IEwgMjcgMTMgeiBNIDE4IDkgTCAxOCAxMCBMIDE5IDEwIEwgMTkgOSB6IE0gMjYgMjIgTCAyNiAyMyBMIDI3IDIzIEwgMjcgMjIgeiBNIDcgMTggTCA3IDE5IEwgOCAxOSBMIDggMTggeiBNIDI2IDMxIEwgMjYgMzIgTCAyNyAzMiBMIDI3IDMxIHogTSAzMCAxMCBMIDMwIDExIEwgMzEgMTEgTCAzMSAxMCB6IE0gMzIgMjkgTCAzMiAzMCBMIDMzIDMwIEwgMzMgMjkgeiBNIDIyIDYgTCAyMiA3IEwgMjMgNyBMIDIzIDYgeiBNIDExIDE1IEwgMTEgMTYgTCAxMiAxNiBMIDEyIDE1IHogTSAyMiAxNSBMIDIyIDE2IEwgMjMgMTYgTCAyMyAxNSB6IE0gMjUgMTcgTCAyNSAxOCBMIDI2IDE4IEwgMjYgMTcgeiBNIDEwIDI4IEwgMTAgMjkgTCAxMSAyOSBMIDExIDI4IHogTSAxNCA3IEwgMTQgOCBMIDE1IDggTCAxNSA3IHogTSA2IDEyIEwgNiAxMyBMIDcgMTMgTCA3IDEyIHogTSA2IDMwIEwgNiAzMSBMIDcgMzEgTCA3IDMwIHogTSAyNiA4IEwgMjYgOSBMIDI3IDkgTCAyNyA4IHogTSA3IDQgTCA3IDUgTCA4IDUgTCA4IDQgeiBNIDI2IDE3IEwgMjYgMTggTCAyNyAxOCBMIDI3IDE3IHogTSAxOCAyMiBMIDE4IDIzIEwgMTkgMjMgTCAxOSAyMiB6IE0gMjEgMjQgTCAyMSAyNSBMIDIyIDI1IEwgMjIgMjQgeiBNIDMyIDI0IEwgMzIgMjUgTCAzMyAyNSBMIDMzIDI0IHogTSAxMyAyOSBMIDEzIDMwIEwgMTQgMzAgTCAxNCAyOSB6IE0gMTAgMTQgTCAxMCAxNSBMIDExIDE1IEwgMTEgMTQgeiBNIDI1IDIxIEwgMjUgMjIgTCAyNiAyMiBMIDI2IDIxIHogTSAxMCAzMiBMIDEwIDMzIEwgMTEgMzMgTCAxMSAzMiB6IE0gMjUgMzAgTCAyNSAzMSBMIDI2IDMxIEwgMjYgMzAgeiBNIDE0IDExIEwgMTQgMTIgTCAxNSAxMiBMIDE1IDExIHogTSA2IDcgTCA2IDggTCA3IDggTCA3IDcgeiBNIDYgMTYgTCA2IDE3IEwgNyAxNyBMIDcgMTYgeiBNIDI5IDE4IEwgMjkgMTkgTCAzMCAxOSBMIDMwIDE4IHogTSAyNiAxMiBMIDI2IDEzIEwgMjcgMTMgTCAyNyAxMiB6IE0gMTcgMzEgTCAxNyAzMiBMIDE4IDMyIEwgMTggMzEgeiBNIDcgOCBMIDcgOSBMIDggOSBMIDggOCB6IE0gMzIgMTAgTCAzMiAxMSBMIDMzIDExIEwgMzMgMTAgeiBNIDEzIDE1IEwgMTMgMTYgTCAxNCAxNiBMIDE0IDE1IHogTSA5IDI2IEwgOSAyNyBMIDEwIDI3IEwgMTAgMjYgeiBNIDIxIDI4IEwgMjEgMjkgTCAyMiAyOSBMIDIyIDI4IHogTSAzMiAyOCBMIDMyIDI5IEwgMzMgMjkgTCAzMyAyOCB6IE0gMTAgOSBMIDEwIDEwIEwgMTEgMTAgTCAxMSA5IHogTSAxMCAxOCBMIDEwIDE5IEwgMTEgMTkgTCAxMSAxOCB6IE0gMTAgMjcgTCAxMCAyOCBMIDExIDI4IEwgMTEgMjcgeiBNIDI5IDQgTCAyOSA1IEwgMzAgNSBMIDMwIDQgeiBNIDE0IDE1IEwgMTQgMTYgTCAxNSAxNiBMIDE1IDE1IHogTSAxNyAxNyBMIDE3IDE4IEwgMTggMTggTCAxOCAxNyB6IE0gMjggMTcgTCAyOCAxOCBMIDI5IDE4IEwgMjkgMTcgeiBNIDE3IDI2IEwgMTcgMjcgTCAxOCAyNyBMIDE4IDI2IHogTSAyOCAyNiBMIDI4IDI3IEwgMjkgMjcgTCAyOSAyNiB6IE0gMjAgMjIgTCAyMCAyMyBMIDIxIDIzIEwgMjEgMjIgeiBNIDIwIDMxIEwgMjAgMzIgTCAyMSAzMiBMIDIxIDMxIHogTSAyMSA1IEwgMjEgNiBMIDIyIDYgTCAyMiA1IHogTSAzMiA1IEwgMzIgNiBMIDMzIDYgTCAzMyA1IHogTSA5IDEyIEwgOSAxMyBMIDEwIDEzIEwgMTAgMTIgeiBNIDIxIDE0IEwgMjEgMTUgTCAyMiAxNSBMIDIyIDE0IHogTSA5IDIxIEwgOSAyMiBMIDEwIDIyIEwgMTAgMjEgeiBNIDEzIDE5IEwgMTMgMjAgTCAxNCAyMCBMIDE0IDE5IHogTSAyMSAzMiBMIDIxIDMzIEwgMjIgMzMgTCAyMiAzMiB6IE0gMTAgNCBMIDEwIDUgTCAxMSA1IEwgMTEgNCB6IE0gMTAgMjIgTCAxMCAyMyBMIDExIDIzIEwgMTEgMjIgeiBNIDI0IDI0IEwgMjQgMjUgTCAyNSAyNSBMIDI1IDI0IHogTSAxNCAxMCBMIDE0IDExIEwgMTUgMTEgTCAxNSAxMCB6IE0gMTYgMjkgTCAxNiAzMCBMIDE3IDMwIEwgMTcgMjkgeiBNIDYgNiBMIDYgNyBMIDcgNyBMIDcgNiB6IE0gNiAxNSBMIDYgMTYgTCA3IDE2IEwgNyAxNSB6IE0gMTcgMTIgTCAxNyAxMyBMIDE4IDEzIEwgMTggMTIgeiBNIDI4IDEyIEwgMjggMTMgTCAyOSAxMyBMIDI5IDEyIHogTSA1IDE5IEwgNSAyMCBMIDYgMjAgTCA2IDE5IHogTSAxNyAyMSBMIDE3IDIyIEwgMTggMjIgTCAxOCAyMSB6IE0gMjggMjEgTCAyOCAyMiBMIDI5IDIyIEwgMjkgMjEgeiBNIDIwIDE3IEwgMjAgMTggTCAyMSAxOCBMIDIxIDE3IHogTSAxNyAzMCBMIDE3IDMxIEwgMTggMzEgTCAxOCAzMCB6IE0gMLine truncated
|
||||||
|
<div>https://geek-cookbook.funkypenguin.co.nz/</div>
|
||||||
|
</a>
|
||||||
|
</div> <div class="wrapper"></div>
|
||||||
|
</article></body></html>
|
||||||
Submodule
+1
Submodule sample added at ccf20e5a12.
@@ -2,9 +2,9 @@
|
|||||||
set -e
|
set -e
|
||||||
# docker build --build-arg FROM_SOURCE=ghcr.io/geek-cookbook/mkdocs-material-insiders . -t funkypenguin/mkdocs-material --platform amd64
|
# docker build --build-arg FROM_SOURCE=ghcr.io/geek-cookbook/mkdocs-material-insiders . -t funkypenguin/mkdocs-material --platform amd64
|
||||||
|
|
||||||
# Prepare slimmed-down versions for PDFing
|
# Prepare slimmed-down versions for PDFing (replace gsed with sed for linux)
|
||||||
cp -rf manuscript docs_to_pdf
|
cp -rf manuscript docs_to_pdf
|
||||||
find docs_to_pdf -type f -exec sed -i -e 's/recipe-footer.md/common-links.md/g' {} \;
|
find docs_to_pdf -type f -exec gsed -i -e 's/recipe-footer.md/common-links.md/g' {} \;
|
||||||
|
|
||||||
# Build PDF from slimmed recipes
|
# Build PDF from slimmed recipes
|
||||||
docker run --rm --name mkdocs-material -e ENABLE_PDF_EXPORT=1 -v ${PWD}/docs_to_pdf:/docs funkypenguin/mkdocs-material build -f mkdocs-pdf-print.yml
|
docker run --rm --name mkdocs-material -e ENABLE_PDF_EXPORT=1 -v ${PWD}/docs_to_pdf:/docs funkypenguin/mkdocs-material build -f mkdocs-pdf-print.yml
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
I am a cover!
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
@media print {
|
||||||
|
html {
|
||||||
|
font-size: 95%;
|
||||||
|
font-family: 'Ubuntu';
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 11.5pt;
|
||||||
|
font-family: 'Ubuntu';
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
label {
|
||||||
|
font-family: 'Gentium Book Basic', 'Helvetica Neue', Helvetica, Arial, 'Noto Sans JP', 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
var,
|
||||||
|
samp,
|
||||||
|
kbd,
|
||||||
|
tt {
|
||||||
|
font-family: 'Noto Sans Mono CJK JP', 'Courier New', monospace, serif;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code,
|
||||||
|
pre var,
|
||||||
|
pre samp,
|
||||||
|
pre kbd,
|
||||||
|
pre tt {
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user