I have an idea to make an application, this time I want to try to run it on a local Raspberry machine. Also take my time to explore Home Assistant with several smart devices around.
simple structure for the system
Raspberry Pi OS using Debian, to check CPU arch using: lscpu
. After some installation and services running on the machine, I need to expose or visit these pages outside of my local router network. I remembered my team used ngrok
before for development and test a local progress. Unfortunately there is a confirm page and the CLI tool isn’t friendly from my point, so I end up with Cloudflare tunnel service. And it would be easier for me as all domain DNS setup by the service.
Install cloudflared
CLI tool:
wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
sudo chmod +x ./cloudflared
./cloudfalred -v
Create a tunnel (I use terminal
for the name):
./cloudflared tunnel create [name]
Create a config file nvim ~/.cloudflared/config.yml
with content:
tunnel: 823626d1-xxxx-49c5-9d09-b34c86266409 #from tunnel id created
credentials-file: /home/duongital/.cloudflared/823626d1-xxxx-49c5-9d09-b34c86266409.json
ingress:
- hostname: http.caybaobap.com
service: http://localhost:80
- hostname: pi.caybaobap.com
service: ssh://localhost:22
- service: http_status:404
I just care about port 80 and 22, for all HTTP website and SSH from anywhere. HTTP can be public but SSH should be protected using One Trust Application, we do that later.
Then we need to config DNS for the domain by adding CNAME (or directly edit on Cloudflare Dashboard):
./cloudflared tunnel route dns 823626d1-xxxx-49c5-9d09-b34c86266409 http.caybaobap.com
./cloudflared tunnel route dns 823626d1-xxxx-49c5-9d09-b34c86266409 pi.caybaobap.com
check on dashboard to have CNAME or not
Test the tunnel by running ./cloudflared tunnel run [name]
, the we can visit the domain to see if http response correctly.
Now we can install the service to systemd
to restart the service on every time the machine is rebooted (out of electric ⚡️):
# change root file
sudo nvim /etc/systemd/system/cloudflared.service
[Unit]
Description=cloudflared
After=network.target
[Service]
TimeoutStartSec=0
Type=notify
ExecStart=/home/duongital/Cloudflare/cloudflared-linux-arm --no-autoupdate --config /home/duongital/.cloudflared/config.yml tunnel run
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Now we can start or stop the service by using sudo systemctl restart cloudflared.service
. Note that we can’t use alias ~/
in systemd config file and restart the service also following *.servce
.
After that, the world can access our Raspberry machine, we need to handle or route requests by this is just a simple config to demonstrate:
server {
listen 80;
server_name 127.0.0.1;
location /pocketbase/ {
proxy_pass http://localhost:8090;
}
location /portainer/ {
proxy_pass http://localhost:9443;
}
location /homeassistant/ {
proxy_pass http://localhost:8123;
}
}
Protect SSH on port 22 by using Application:
- Option 1: you aren’t with a dev machine and trying to SSH via a browser and get security code from configured email.
This the beta
feature to render on browser we can connect to Raspberry Pi anywhere (even mobile).
create an application to protect ssh
keep all default settings but remember to enable Browser rendering
So now every time we visit pi.caybaobap.com, it will verify if you are the person in Policy and send 6 digits to the email.
- Option 2: you are with a dev machine
Change SSH configuration file and install cloudflared
on local machine by following this tutorial. This will run a proxy command cloudflared
client and connect to remote machine via ssh
command.
# vim ~/.ssh/config
Host pi.example.com
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
Now we can ssh to the machine by ssh [email protected]
, it opens a browser to verify for first time.
Demo
Grafana Monitoring
Home Assistant on iPad (the data is served from Raspberry Pi 4)
Lessons learn:
While using proxy_pass
for Home Assistant, I always get an error 400 Bad Request from a different network connection. It’s fine from local router network and also with PocketBase or Portainer, then I checked around the Internet and see that HA Container not exposed the port directly and there should be trusted IPs added to configuration.yml
. I just though the reason from Cloudflared proxy or NGINX but it did’t, we should check log files and see the root cause:
# NGINX
/var/log/nginx/error.log debug # add debug to see more details
# Cloudflared
./cloudflared-linux-arm tunnel --loglevel debug run 823626d1-xxxx-49c5-9d09-b34c86266409
Future ideas:
- Expose PostgreSQL service, maybe: sql.caybaobap.com
- Mount an micro SSD 1T to save or upload files (UI web to view Gallery)