diff --git a/manuscript/book.txt b/manuscript/book.txt index 1c4a4fb..fd7468d 100644 --- a/manuscript/book.txt +++ b/manuscript/book.txt @@ -11,6 +11,8 @@ ha-docker-swarm/shared-storage-gluster.md ha-docker-swarm/keepalived.md ha-docker-swarm/docker-swarm-mode.md ha-docker-swarm/traefik.md +ha-docker-swarm/traefik-forward-auth.md +ha-docker-swarm/traefik-forward-auth/keycloak.md ha-docker-swarm/registry.md sections/chefs-favorites-docker.md diff --git a/manuscript/ha-docker-swarm/design.md b/manuscript/ha-docker-swarm/design.md index 613d14b..b11e967 100644 --- a/manuscript/ha-docker-swarm/design.md +++ b/manuscript/ha-docker-swarm/design.md @@ -92,10 +92,4 @@ In summary, although I suffered an **unplanned power outage to all of my infrast [^1]: Since there's no impact to availability, I can fix (or just reinstall) the failed node whenever convenient. -## Chef's Notes - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +## Chef's Notes 📓 \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/docker-swarm-mode.md b/manuscript/ha-docker-swarm/docker-swarm-mode.md index 00151e5..c909fbb 100644 --- a/manuscript/ha-docker-swarm/docker-swarm-mode.md +++ b/manuscript/ha-docker-swarm/docker-swarm-mode.md @@ -173,10 +173,4 @@ Launch shepherd by running ```docker stack deploy shepherd -c /var/data/config/s * [X] [Docker swarm cluster](/ha-docker-swarm/design/) -## Chef's Notes - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +## Chef's Notes 📓 \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/keepalived.md b/manuscript/ha-docker-swarm/keepalived.md index fa2fdb5..84b9d77 100644 --- a/manuscript/ha-docker-swarm/keepalived.md +++ b/manuscript/ha-docker-swarm/keepalived.md @@ -65,13 +65,7 @@ docker run -d --name keepalived --restart=always \ That's it. Each node will talk to the other via unicast (no need to un-firewall multicast addresses), and the node with the highest priority gets to be the master. When ingress traffic arrives on the master node via the VIP, docker's routing mesh will deliver it to the appropriate docker node. -## Chef's notes +## Chef's notes 📓 1. Some hosting platforms (*OpenStack, for one*) won't allow you to simply "claim" a virtual IP. Each node is only able to receive traffic targetted to its unique IP, unless certain security controls are disabled by the cloud administrator. In this case, keepalived is not the right solution, and a platform-specific load-balancing solution should be used. In OpenStack, this is Neutron's "Load Balancer As A Service" (LBAAS) component. AWS, GCP and Azure would likely include similar protections. -2. More than 2 nodes can participate in keepalived. Simply ensure that each node has the appropriate priority set, and the node with the highest priority will become the master. - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +2. More than 2 nodes can participate in keepalived. Simply ensure that each node has the appropriate priority set, and the node with the highest priority will become the master. \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/nodes.md b/manuscript/ha-docker-swarm/nodes.md index 83db364..373045c 100644 --- a/manuscript/ha-docker-swarm/nodes.md +++ b/manuscript/ha-docker-swarm/nodes.md @@ -76,10 +76,4 @@ After completing the above, you should have: * At least 20GB disk space (_but it'll be tight_) * [X] Connectivity to each other within the same subnet, and on a low-latency link (_i.e., no WAN links_) -## Chef's Notes - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +## Chef's Notes 📓 \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/registry.md b/manuscript/ha-docker-swarm/registry.md index f0b5bfd..234e6f7 100644 --- a/manuscript/ha-docker-swarm/registry.md +++ b/manuscript/ha-docker-swarm/registry.md @@ -110,10 +110,4 @@ systemctl restart docker-latest !!! tip "" Note the extra comma required after "false" above -## Chef's notes - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +## Chef's notes 📓 \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/shared-storage-ceph.md b/manuscript/ha-docker-swarm/shared-storage-ceph.md index 4e30eda..717acd8 100644 --- a/manuscript/ha-docker-swarm/shared-storage-ceph.md +++ b/manuscript/ha-docker-swarm/shared-storage-ceph.md @@ -189,15 +189,9 @@ After completing the above, you should have: [X] Resiliency in the event of the failure of a single node ``` -## Chef's Notes +## Chef's Notes 📓 Future enhancements to this recipe include: 1. Rather than pasting a secret key into /etc/fstab (which feels wrong), I'd prefer to be able to set "secretfile" in /etc/fstab (which just points ceph.mount to a file containing the secret), but under the current CentOS Atomic, we're stuck with "secret", per https://bugzilla.redhat.com/show_bug.cgi?id=1030402 2. This recipe was written with Ceph v11 "Jewel". Ceph have subsequently releaesd v12 "Kraken". I've updated the recipe for the addition of "Manager" daemons, but it should be noted that the [only reader so far](https://discourse.geek-kitchen.funkypenguin.co.nz/u/ggilley) to attempt a Ceph install using CentOS Atomic and Ceph v12 had issues with OSDs, which lead him to [move to Ubuntu 1604](https://discourse.geek-kitchen.funkypenguin.co.nz/t/shared-storage-ceph-funky-penguins-geek-cookbook/47/24?u=funkypenguin) instead. - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 diff --git a/manuscript/ha-docker-swarm/shared-storage-gluster.md b/manuscript/ha-docker-swarm/shared-storage-gluster.md index 064a4fb..34cffb7 100644 --- a/manuscript/ha-docker-swarm/shared-storage-gluster.md +++ b/manuscript/ha-docker-swarm/shared-storage-gluster.md @@ -159,15 +159,9 @@ After completing the above, you should have: [X] Resiliency in the event of the failure of a single (gluster) node ``` -## Chef's Notes +## Chef's Notes 📓 Future enhancements to this recipe include: 1. Migration of shared storage from GlusterFS to Ceph ()[#2](https://gitlab.funkypenguin.co.nz/funkypenguin/geeks-cookbook/issues/2)) -2. Correct the fact that volumes don't automount on boot ([#3](https://gitlab.funkypenguin.co.nz/funkypenguin/geeks-cookbook/issues/3)) - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +2. Correct the fact that volumes don't automount on boot ([#3](https://gitlab.funkypenguin.co.nz/funkypenguin/geeks-cookbook/issues/3)) \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/traefik-forward-auth.md b/manuscript/ha-docker-swarm/traefik-forward-auth.md index 498b93a..db69b3f 100644 --- a/manuscript/ha-docker-swarm/traefik-forward-auth.md +++ b/manuscript/ha-docker-swarm/traefik-forward-auth.md @@ -4,24 +4,30 @@ Now that we have Traefik deployed, automatically exposing SSL access to our Dock ..Wait, why not? Well, Traefik doesn't provide any form of authentication, it simply secures the **transmission** of the service between Docker Swarm and the end user. If you were to deploy a service with no native security (*[Radarr](/recipes/autopirate/radarr/) or [Sonarr](/recipes/autopirate/sonarr/) come to mind*), then anybody would be able to use it! Even services which _may_ have a layer of authentication **might** not be safe to expose publically - often open source projects may be maintained by enthusiasts who happily add extra features, but just pay lip service to security, on the basis that "*it's the user's problem to secure it in their own network*". -To give us confidence that **we** can access our services, but BadGuys(tm) cannot, we'll deploy a layer of authentication **in front** of Traefik, using [Forward Authentication](https://docs.traefik.io/configuration/entrypoints/#forward-authentication). +To give us confidence that **we** can access our services, but BadGuys(tm) cannot, we'll deploy a layer of authentication **in front** of Traefik, using [Forward Authentication](https://docs.traefik.io/configuration/entrypoints/#forward-authentication). You can use your own [KeyCloak](/recipes/keycloak/) instance for authentication, but to lower the barrier to entry, this recipe will assume you're authenticating against your own Google account. ## Ingredients -1. [Docker swarm cluster](/ha-docker-swarm/design/) with [persistent shared storage](/ha-docker-swarm/shared-storage-ceph) -2. [Traefik](/ha-docker-swarm/traefik/) configured per design -3. An account with an OpenID-Connect provider (Google, [KeyCloak](/recipes/keycloak/), Microsoft, etc..) +!!! summary "Ingredients" + Existing: + + * [X] [Docker swarm cluster](/ha-docker-swarm/design/) with [persistent shared storage](/ha-docker-swarm/shared-storage-ceph) + * [X] [Traefik](/ha-docker-swarm/traefik/) configured per design + + New: + + * [ ] Client ID and secret from an OpenID-Connect provider (Google, [KeyCloak](/recipes/keycloak/), Microsoft, etc..) ## Preparation -### Create OAuth credentials +### Obtain OAuth credentials !!! note - This recipe will demonstrate using Google OAuth for traefik forward authentication, but it's also possible to use a self-hosted KeyCloak instance - see the [KeyCloak](/recipes/keycloak/) recipe for more details! + This recipe will demonstrate using Google OAuth for traefik forward authentication, but it's also possible to use a self-hosted KeyCloak instance - see the [KeyCloak OIDC Provider](/recipes/keycloak/setup-oidc-provider/) recipe for more details! Log into https://console.developers.google.com/, create a new project then search for and select "Credentials" in the search bar. -Fill out the "OAuth Consent Screen" tab, and then click, "**Create Credentials**" > "**OAuth client ID**". Select "**Web Application**", fill in the name of your app, skip "**Authorized JavaScript origins**" and fill "**Authorized redirect URIs**" with either all the domains you will allow authentication from, appended with the url-path (*e.g. https://radarr.example.com/_oauth, https://radarr.example.com/_oauth, etc*), or if you don't like frustration, use a "auth host" URL instead, like "*https://auth.example.com/_oauth*" (see below for details) +Fill out the "OAuth Consent Screen" tab, and then click, "**Create Credentials**" > "**OAuth client ID**". Select "**Web Application**", fill in the name of your app, skip "**Authorized JavaScript origins**" and fill "**Authorized redirect URIs**" with either all the domains you will allow authentication from, appended with the url-path (*e.g. https://radarr.example.com/_oauth, https://radarr.example.com/_oauth, etc*), or if you don't like frustration, use a "auth host" URL instead, like "*https://auth.example.com/_oauth*" (*see below for details*) Store your client ID and secret safely - you'll need them for the next step. @@ -91,12 +97,18 @@ Redeploy traefik with ```docker stack deploy traefik-app -c /var/data/traefik/tr Browse to https://whoami.example.com (*obviously, customized for your domain and having created a DNS record*), and all going according to plan, you should be redirected to a Google login. Once successfully logged in, you'll be directed to the basic whoami page. -### Dessert +## Summary What have we achieved? By adding an additional three simple labels to any service, we can secure any service behind our choice of OAuth provider, with minimal processing / handling overhead. +!!! summary "Summary" + Created: -## Chef's Notes + * [X] Traefik-forward-auth configured to authenticate against an OIDC provider + + + +## Chef's Notes 📓 1. Traefik forward auth replaces the use of [oauth_proxy containers](/reference/oauth_proxy/) found in some of the existing recipes 2. [@thomaseddon's original version](https://github.com/thomseddon/traefik-forward-auth) of traefik-forward-auth only works with Google currently, but I've created a [fork](https://www.github.com/funkypenguin/traefik-forward-auth) of a [fork](https://github.com/noelcatt/traefik-forward-auth), which implements generic OIDC providers. diff --git a/manuscript/ha-docker-swarm/traefik-forward-auth/keycloak.md b/manuscript/ha-docker-swarm/traefik-forward-auth/keycloak.md new file mode 100644 index 0000000..3bc230f --- /dev/null +++ b/manuscript/ha-docker-swarm/traefik-forward-auth/keycloak.md @@ -0,0 +1,122 @@ +# Using Traefik Forward Auth with KeyCloak + +While the [Traefik Forward Auth](/ha-docker-swarm/traefik-forward-auth/) recipe demonstrated a quick way to protect a set of explicitly-specified URLs using OIDC credentials from a Google account, this recipe will illustrate how to use your own KeyCloak instance to secure **any** URLs within your DNS domain. + +## Ingredients + +!!! Summary + Existing: + + * [X] [KeyCloak](/recipes/keycloak/) recipe deployed successfully, with a [local user](/recipes/keycloak/create-user/) and an [OIDC client](/recipes/keycloak/setup-oidc-provider/) + + New: + + * [ ] DNS entry for your auth host (*"auth.yourdomain.com" is a good choice*), pointed to your [keepalived](ha-docker-swarm/keepalived/) IP + +## Preparation + +### What is AuthHost mode + +Under normal OIDC auth, you have to tell your auth provider which URLs it may redirect an authenticated user back to, post-authentication. This is a security feture of the OIDC spec, preventing a malicious landing page from capturing your session and using it to impersonate you. When you're securing many URLs though, explicitly listing them can be a PITA. + +[@thomaseddon's traefik-forward-auth](https://github.com/thomseddon/traefik-forward-auth) includes an ingenious mechanism to simulate an "*auth host*" in your OIDC authentication, so that you can protect an unlimited amount of DNS names (*with a common domain suffix*), without having to manually maintain a list. + +#### How does it work? + +Say you're protecting **radarr.example.com**. When you first browse to **https://radarr.example.com**, Traefik forwards your session to traefik-forward-auth, to be authenticated. Traefik-forward-auth redirects you to your OIDC provider's login (*KeyCloak, in this case*), but instructs the OIDC provider to redirect a successfully authenticated session **back** to **https://auth.example.com/_oauth**, rather than to **https://radarr.example.com/_oauth**. + +When you successfully authenticate against the OIDC provider, you are redirected to the "*redirect_uri*" of https://auth.example.com. Again, your request hits Traefik, whichforwards the session to traefik-forward-auth, which **knows** that you've just been authenticated (*cookies have a role to play here*). Traefik-forward-auth also knows the URL of your **original** request (*thanks to the X-Forwarded-Whatever header*). Traefik-forward-auth redirects you to your original destination, and everybody is happy. + +This clever workaround only works under 2 conditions: + + +1. Your "auth host" has the same domain name as the hosts you're protecting (*i.e., auth.example.com protecting radarr.example.com*) +2. You explictly tell traefik-forward-auth to use a cookie authenticating your **whole** domain (*i.e. example.com*) + +### Setup environment + +Create `/var/data/config/traefik/traefik-forward-auth.env` as follows (*change "master" if you created a different realm*): + +``` +CLIENT_ID= +CLIENT_SECRET= +OIDC_ISSUER=https:///auth/realms/master +SECRET= +AUTH_HOST= +COOKIE_DOMAINS= +``` + +### Prepare the docker service config + +This is a small container, you can simply add the following content to the existing `traefik-app.yml` deployed in the previous [Traefik](/recipes/traefik/) recipe: + +``` + traefik-forward-auth: + image: thomseddon/traefik-forward-auth + env_file: /var/data/config/traefik/traefik-forward-auth.env + networks: + - traefik_public + deploy: + labels: + - traefik.port=4181 + - traefik.frontend.rule=Host:auth.example.com + - traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181 + - traefik.frontend.auth.forward.trustForwardHeader=true +``` + +If you're not confident that forward authentication is working, add a simple "whoami" test container, to help debug traefik forward auth, before attempting to add it to a more complex container. + +``` + # This simply validates that traefik forward authentication is working + whoami: + image: containous/whoami + networks: + - traefik_public + deploy: + labels: + - traefik.frontend.rule=Host:whoami.example.com + - traefik.port=80 + - traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181 + - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User + - traefik.frontend.auth.forward.trustForwardHeader=true +``` + +!!! tip + I share (_with my [patreon patrons](https://www.patreon.com/funkypenguin)_) a private "_premix_" git repository, which includes necessary docker-compose and env files for all published recipes. This means that patrons can launch any recipe with just a ```git pull``` and a ```docker stack deploy``` 👍 + +## Serving + +### Launch + +Redeploy traefik with ```docker stack deploy traefik-app -c /var/data/traefik/traeifk-app.yml```, to launch the traefik-forward-auth container. + +### Test + +Browse to https://whoami.example.com (*obviously, customized for your domain and having created a DNS record*), and all going according to plan, you'll be redirected to a KeyCloak login. Once successfully logged in, you'll be directed to the basic whoami page. + +### Protect services + +To protect any other service, ensure the service itself is exposed by Traefik (*if you were previously using an oauth_proxy for this, you may have to migrate some labels from the oauth_proxy serivce to the service itself*). Add the following 3 labels: + +``` +- traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181 +- traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User +- traefik.frontend.auth.forward.trustForwardHeader=true +``` + +And re-deploy your services :) + +## Summary + +What have we achieved? By adding an additional three simple labels to any service, we can secure any service behind our KeyCloak OIDC provider, with minimal processing / handling overhead. + +!!! summary "Summary" + Created: + + * [X] Traefik-forward-auth configured to authenticate against KeyCloak + + + +## Chef's Notes 📓 + +1. KeyCloak is very powerful. You can add 2FA and all other clever things outside of the scope of this simple recipe ;) \ No newline at end of file diff --git a/manuscript/ha-docker-swarm/traefik.md b/manuscript/ha-docker-swarm/traefik.md index 7698015..d65e21b 100644 --- a/manuscript/ha-docker-swarm/traefik.md +++ b/manuscript/ha-docker-swarm/traefik.md @@ -234,12 +234,6 @@ You should now be able to access your traefik instance on http://:8080 * [X] Automatic SSL support for all proxied resources -## Chef's Notes +## Chef's Notes 📓 -1. Did you notice how no authentication was required to view the Traefik dashboard? Eek! We'll tackle that in the next section, regarding [Traefik Forward Authentication](/ha-docker-swarm/traefik-forward-auth/)! - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +1. Did you notice how no authentication was required to view the Traefik dashboard? Eek! We'll tackle that in the next section, regarding [Traefik Forward Authentication](/ha-docker-swarm/traefik-forward-auth/)! \ No newline at end of file diff --git a/manuscript/recipes/bitwarden.md b/manuscript/recipes/bitwarden.md index d3b7ca5..1176fd2 100644 --- a/manuscript/recipes/bitwarden.md +++ b/manuscript/recipes/bitwarden.md @@ -94,7 +94,7 @@ Browse to your new instance at https://**YOUR-FQDN**, and create a new user acco Once you've created your account, jump over to https://bitwarden.com/#download and download the apps for your mobile and browser, and start adding your logins! -## Chef's Notes +## Chef's Notes 📓 1. You'll notice we're not using the *official* container images (*[all 6 of them required](https://help.bitwarden.com/article/install-on-premise/#install-bitwarden)!)*, but rather a [more lightweight version ideal for self-hosting](https://hub.docker.com/r/mprasil/bitwarden). All of the elements are contained within a single container, and SQLite is used for the database backend. 2. As mentioned above, readers should refer to the [dani-garcia/bitwarden_rs wiki](https://github.com/dani-garcia/bitwarden_rs) for details on customizing the behaviour of Bitwarden. diff --git a/manuscript/recipes/bookstack.md b/manuscript/recipes/bookstack.md index 2a063c2..fe05804 100644 --- a/manuscript/recipes/bookstack.md +++ b/manuscript/recipes/bookstack.md @@ -141,12 +141,6 @@ Launch the BookStack stack by running ```docker stack deploy bookstack -c **Users**, and then click **Add User** at the top right: @@ -21,6 +22,8 @@ Populate your new user's username (it's the only mandatory field) ![Populating a username in the add user interface in Keycloak](/images/keycloak-add-user-2.png) +### Set User Credentials + Once your user is created, to set their password, click on the "**Credentials**" tab, and procede to reset it. Set the password to non-temporary, unless you like extra work! ![Resetting a user's password in Keycloak](/images/keycloak-add-user-3.png) diff --git a/manuscript/recipes/keycloak/setup-oidc-provider.md b/manuscript/recipes/keycloak/setup-oidc-provider.md index 927427a..6348846 100644 --- a/manuscript/recipes/keycloak/setup-oidc-provider.md +++ b/manuscript/recipes/keycloak/setup-oidc-provider.md @@ -50,4 +50,6 @@ We've setup an OIDC client in KeyCloak, which we can now use to protect vulnerab !!! Summary Created: - * [X] Client ID and Client Secret used to authenticate against KeyCloak with OpenID Connect \ No newline at end of file + * [X] Client ID and Client Secret used to authenticate against KeyCloak with OpenID Connect + +## Chef's Notes 📓 \ No newline at end of file diff --git a/manuscript/recipes/mail.md b/manuscript/recipes/mail.md index 9e4fbc6..d05e60e 100644 --- a/manuscript/recipes/mail.md +++ b/manuscript/recipes/mail.md @@ -178,14 +178,8 @@ SSL_TYPE=letsencrypt Launch the mail server stack by running ```docker stack deploy docker-mailserver -c ``` -## Chef's Notes +## Chef's Notes 📓 1. One of the elements of this design which I didn't appreciate at first is that since the config is entirely file-based, **setup.sh** can be run on any container host, provided it has the shared data mounted. This means that even though docker-mailserver was not designed with docker swarm in mind, it works perfectl with swarm. I.e., from any node, regardless of where the container is actually running, you're able to add/delete email addresses, view logs, etc. 2. If you're using sieve with Rainloop, take note of the [workaround](https://discourse.geek-kitchen.funkypenguin.co.nz/t/mail-server-funky-penguins-geek-cookbook/70/15) identified by [ggilley](https://discourse.geek-kitchen.funkypenguin.co.nz/u/ggilley) - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 diff --git a/manuscript/recipes/mattermost.md b/manuscript/recipes/mattermost.md index 48ba077..2ccd766 100644 --- a/manuscript/recipes/mattermost.md +++ b/manuscript/recipes/mattermost.md @@ -116,12 +116,6 @@ Launch the MatterMost stack by running ```docker stack deploy mattermost -c Integration** page. - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +1. Find the bookmarklet under the **Settings -> Integration** page. \ No newline at end of file diff --git a/manuscript/recipes/minio.md b/manuscript/recipes/minio.md index 00664d1..49780fe 100644 --- a/manuscript/recipes/minio.md +++ b/manuscript/recipes/minio.md @@ -170,14 +170,9 @@ To permanently mount an S3 bucket using goofys, I'd add something like this to / goofys#bucket /mnt/mountpoint fuse _netdev,allow_other,--file-mode=0666 0 0 ``` -## Chef's Notes +## Chef's Notes 📓 1. There are many S3-filesystem-mounting tools available, I just picked Goofys because it's simple. Google is your friend :) 2. Some applications (_like [NextCloud](/recipes/nextcloud/)_) can natively mount S3 buckets 3. Some backup tools (_like [Duplicity](/recipes/duplicity/)_) can backup directly to S3 buckets -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 diff --git a/manuscript/recipes/mqtt.md b/manuscript/recipes/mqtt.md index d0fb44b..342647d 100644 --- a/manuscript/recipes/mqtt.md +++ b/manuscript/recipes/mqtt.md @@ -204,10 +204,4 @@ mqtt-65f4d96945-bjj44 1/1 Running 0 5m To actually **use** your new MQTT broker, you'll need to connect to any one of your nodes (```kubectl get nodes -o wide```) on port 30883 (_the nodeport service we created earlier_). More info on that, and a loadbalancer design, to follow shortly :) -## Chef's Notes - -### Tip your waiter (support me) 👏 - -Did you receive excellent service? Want to make your waiter happy? (_..and support development of current and future recipes!_) See the [support](/support/) page for (_free or paid)_ ways to say thank you! 👏 - -### Your comments? 💬 +## Chef's Notes 📓 \ No newline at end of file diff --git a/manuscript/recipes/munin.md b/manuscript/recipes/munin.md index 630160a..aec1292 100644 --- a/manuscript/recipes/munin.md +++ b/manuscript/recipes/munin.md @@ -134,12 +134,6 @@ Launch the Munin stack by running ```docker stack deploy munin -c