[{"content":"","date":null,"permalink":"/articles/","section":"Articles","summary":"","title":"Articles"},{"content":"","date":null,"permalink":"/tags/homeassistant/","section":"Tags","summary":"","title":"homeassistant"},{"content":"Former IT geek who continues to dabble in bits and pieces from time to time. Hobbyist magician and member of the The Magic Circle. Aviation industry worker talking to aeroplanes (well, pilots) for a living. Former private pilot. Procrastinator.\n","date":null,"permalink":"/","section":"Jonathan Batchelor","summary":"Former IT geek who continues to dabble in bits and pieces from time to time.","title":"Jonathan Batchelor"},{"content":"After following this guide on YouTube from The Home Automation Guy, I thought I’d try and take it one step further and add an alert function using the M5Stack’s LED.\nIn the ESP Home configuration for the Atom, I added the following section to add a control for the LED:\nlight: - platform: neopixelbus type: GRB variant: SK6812 pin: 27 num_leds: 1 id: status_led name: \u0026#34;Status LED\u0026#34; internal: False default_transition_length: 2s effects: - pulse: name: \u0026#34;Slow Pulse\u0026#34; transition_length: 1s update_interval: 3s initial_state: state: False This appears in Home Assistant as a light entity.\nAs the M5Stack Atom Lite is in the bedroom (mounted behind the TV), I didn’t want it lighting up in the night when we’re sleeping. I added a Helper Schedule defining awake hours - schedule.awake_hours.\nThen I added an automation to Home Assistant using the automation builder. It produced the following YAML for me:\nalias: Water Swiss Cheese Plant description: \u0026#34;\u0026#34; triggers: - trigger: state entity_id: - plant.swiss_cheese_plant from: null to: null id: swiss_cheese_plant_state_change - trigger: state entity_id: - schedule.awake_hours from: null to: null conditions: [] actions: - if: - condition: state entity_id: schedule.awake_hours state: \u0026#34;on\u0026#34; then: - if: - condition: state entity_id: plant.swiss_cheese_plant state: problem then: - action: light.turn_on metadata: {} data: rgb_color: - 255 - 0 - 0 effect: Slow Pulse target: entity_id: light.m5stackatom_status_led else: - if: - condition: state entity_id: plant.swiss_cheese_plant state: ok - condition: trigger id: - swiss_cheese_plant_state_change then: - action: light.turn_on metadata: {} data: rgb_color: - 0 - 255 - 0 effect: None target: entity_id: light.m5stackatom_status_led - delay: hours: 0 minutes: 1 seconds: 0 milliseconds: 0 - action: light.turn_off metadata: {} data: {} target: entity_id: light.m5stackatom_status_led else: - action: light.turn_off metadata: {} data: {} target: entity_id: light.m5stackatom_status_led else: - action: light.turn_off metadata: {} data: {} target: entity_id: light.m5stackatom_status_led mode: single This will be triggered either by the plant state changing or by the awake hours schedule changing.\nIf it is within the awake hours (schedule.awake_hours is on) then it checks to see if the plant is in a problem state and if so turns on the led with a red slow pulse effect. If the plant isn’t in a problem state then it checks to see if the plant triggered the automation and if so sets the led to green for one minute then turns it off. If the plant is in an ok state and didn’t trigger the automation (i.e. the schedule did) then the led is turned off.\nFinally if the automation is triggered but it’s outside the schedule time (or the schedule changes to off) then the led is turned off.\n","date":"1 May 2025","permalink":"/articles/plant_monitor_alert_with_ha_and_m5stack_atom_lite/","section":"Articles","summary":"After following this guide on YouTube from The Home Automation Guy, I thought I’d try and take it one step further and add an alert function using the M5Stack’s LED.","title":"Plant monitor alert with Home Assistant and M5Stack Atom Lite"},{"content":"","date":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags"},{"content":"I\u0026rsquo;d previously used Authelia to have SSO on my Traefik setup so was looking for something similar to this on Caddy. This led me to caddy-security and the associated https://authp.github.io, however nothing was very clear as to where to go with this. Fortunately I found this blog post which went a long way to explaining things!\nInstall # Rather than messing about with any downloads, initially I simply swapped out the image: line in my docker-compose.yml:\n# image: caddy:2 image: \u0026#34;ghcr.io/authp/authp:v1.0.1\u0026#34; I realise that this is possibly risky in that it uses caddy:latest, so doesn\u0026rsquo;t pin a specific version of Caddy. Copying the Dockerfile from https://github.com/authp/authp/blob/main/Dockerfile and updating for your requirements could be a better option and one that I will investigate at a later date. Running docker compose up -d --build caddy pulled and built a new image, which I verified had the extra modules:\n$ docker compose exec -w /etc/caddy caddy caddy list-modules [...] dns.providers.cloudflare http.authentication.providers.authorizer http.handlers.authenticator http.handlers.trace security security.secrets.aws_secrets_manager Non-standard modules: 6 I checked at this point that everything was still working.\nConfiguration # Trying to keep things simple I wanted to just secure some sites for just me using a local user database. To start with I didn\u0026rsquo;t want any external authentications, signups or service listings, but these are all possible.\nI started with adding the following to the global section of my Caddyfile, just underneath the email setting (shown here for completeness):\n{ email example@example.com order authenticate before respond order authorize before reverse_proxy security { local identity store localdb { realm local path /etc/caddy/auth/local/users.json } authentication portal auth { enable identity store localdb cookie domain example.com cookie lifetime 86400 # 24 hours in seconds transform user { match origin local action add roll authp/user } } authorization policy user_policy { set auth url https://auth.example.com allow rolls authp/user } } } (Update example.com to your domain)\nI reloaded caddy to check things were still working and to generate the local identity store and secrets:\n$ docker compose exec -w /etc/caddy caddy caddy reload Everything looked good and was still working.\n$ sudo tree caddy caddy ├── auth │ └── local │ └── users.json └── Caddyfile I then updated the users.json to change the default user to my details and change the password hash appropriately.1\nFinally I added the auth endpoint and a test site to the Caddyfile:\nauth.example.com { authenticate with myportal } test.example.com { authorize with users_policy root * /sites/test.example.com file_server } Et volia! Navigating to my test site requires now requires me to log in via my SSO portal. 🎉\nChanging Passwords # I never worked this out in Authelia, but with one extra line in the transform user section, a link is added for logged in users at your portal site to change their settings including their password:\nui link \u0026#34;Portal Settings\u0026#34; /settings icon \u0026#34;las la-cog\u0026#34; Multi Factor Authentication (MFA) # When I was running Authelia, I set up MFA using TOTP in my password manager, fortunately this is quite easy to add to Caddy!\nAfter adding the Settings link as above, add a further line to the transform user section:\nrequire mfa Reload Caddy and use the Settings page on the portal to add your MFA app. Thats it!\nFinal thoughts # Now that I\u0026rsquo;ve got past the first barrier of the authp docs where the Getting Started section was a bit sparse, it seems pretty easy to get this working. Hopefully this write up will help others make this work!\nPlease go to this post on Mastodon to add any comments or suggestions!\nI used the info from the authp site here: https://authp.github.io/docs/authenticate/local/password-management With the bcrypt-cli binary ending up at ~/go/bin/bcrypt-cli after using the go install command.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2 March 2023","permalink":"/articles/adding_sso_to_caddy/","section":"Articles","summary":"I\u0026rsquo;d previously used Authelia to have SSO on my Traefik setup so was looking for something similar to this on Caddy.","title":"Adding Single Sign On (SSO) to Caddy"},{"content":"","date":null,"permalink":"/tags/caddy/","section":"Tags","summary":"","title":"caddy"},{"content":"","date":null,"permalink":"/tags/docker/","section":"Tags","summary":"","title":"docker"},{"content":"","date":null,"permalink":"/tags/letsencrypt/","section":"Tags","summary":"","title":"letsencrypt"},{"content":"","date":null,"permalink":"/tags/mfa/","section":"Tags","summary":"","title":"mfa"},{"content":"","date":null,"permalink":"/tags/security/","section":"Tags","summary":"","title":"security"},{"content":"","date":null,"permalink":"/tags/selfhosting/","section":"Tags","summary":"","title":"selfhosting"},{"content":"","date":null,"permalink":"/tags/sso/","section":"Tags","summary":"","title":"sso"},{"content":"After re-building my VPS because things were a bit messy, I decided to move away from the rather complicated Traefik setup that I had before and move over to Caddy. This took a little while to get my head around, but ultimately is much simpler!\nDocker compose # I\u0026rsquo;m running Caddy within a docker compose environment using a pretty basic setup in a docker-compose.yml file:\nversion: \u0026#34;3.7\u0026#34; networks: default: name: caddy-proxy volumes: caddy_data: external: true caddy_config services: caddy: image: caddy:2.6.4 container_name: caddy restart: unless-stopped ports: - \u0026#34;80:80\u0026#34; - \u0026#34;443:443\u0026#34; - \u0026#34;443:443/udp\u0026#34; volumes: - $PWD/caddy:/etc/caddy - $PWD/sites:/sites - caddy_data:/data - caddy_config:/config Caddyfile # My Caddyfile sits in the caddy subdirectory and is really very simple:\n{ email: example@example.com } www.example.com { redir https://example.com{uri} } example.com { root * /sites/example.com file_server } Here I\u0026rsquo;m removing the www with a redirect, then I\u0026rsquo;m serving files from a directory under the mounted /sites directory which was mounted into the caddy container by docker. I can then just copy over my public folder from hugo to serve up this site. Caddy handles all the letsencrypt certificates and things without any messing about!\nMore services # With this setup it\u0026rsquo;s pretty simple to add more services and use Caddy as proxy, for example FreshRSS:\nAddition to the services section of docker-compose.yml:\nfreshrss: image: freshrss/freshrss:latest container_name: freshrss restart: unless-stopped logging: options: max-size: 10m volumes: - $PWD/freshrss/data:/var/www/FreshRSS/data - $PWD/freshrss/extensions:/var/www/FreshRSS/extensions environment: - TZ=Europe/London - CRON_MIN=\u0026#39;2,32\u0026#39; and the Caddyfile addition:\nfreshrss.example.com { reverse_proxy freshrss:80 } Comments # Please go to this post on Mastodon to add any comments or suggestions!\n","date":"20 February 2023","permalink":"/articles/selfhosting_with_caddy_and_docker/","section":"Articles","summary":"After re-building my VPS because things were a bit messy, I decided to move away from the rather complicated Traefik setup that I had before and move over to Caddy.","title":"Self-hosting with Caddy and Docker"},{"content":"","date":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories"}]