I like playing around with different services and linking them together to see what kind of weird concoctions I can piece together, and one of them that I've been playing around with has been Tines. It's an automation platform with a key focus on security, and while there are paid subscriptions, you can do a lot with the free version. However, the Tines Tunnel, which is basically a Cloudflare Tunnel, is locked down behind that subscription barrier. And to get a subscription requires reaching out to Tines for a pricing quote, and it's aimed specifically at companies.
I like the features that Tines offers, and so it got me thinking. What if I could basically build my own tunnel of sorts, all through the power of Home Assistant and automations? Through my Nabu Casa subscription, I can create publicly available webhooks, and Tines can make HTTP requests and also host its own webhooks. By stringing these together, I get similar functionality to a tunnel, with secure, two-way communication between the two. It's not as flexible as a true tunnel, but as you'll see, it does the job.
Note that this is an exercise that sits strictly in the realm of "I'm doing this because I can," and not something that everyone should consider. It's fun, it's interesting, and it's learning new software. Sometimes it's fun to try something new and see what the results are, and this is exactly that.
Picking a project and coming up with a plan
Doing something I can't do with regular Home Assistant
With it established that we can deploy two-way communication, next up was to come up with a project and concoct a plan. I thought of how Home Assistant links up practically everything in my home, so this made coming up with an idea tough. With most things, it's easy to just implement an automation from within Home Assistant, so I needed to think of something unique.
That's when I spotted two interesting actions that Tines has: "Send email" and "Receive email." These do exactly what they sound like; send email sends, well, an email, whereas receive email sets up a random string of numbers and letters to create an email address that you can send requests to. What if I could send commands via email, and then get a response back from Tines with either the requested information or an email confirming that my action was completed? One could argue email is the original API, so putting it to the test sounds like a fun idea.
I ultimately went for two routes as a proof of concept: the first was to interact with my self-hosted LLM and get an email response, and the second was to control my Proxmox containers running in my home lab, allowing me to start, stop, or reboot them remotely. There are security implications with this, but I'll go over them and explain how I dealt with them. We have a plan, though, and implementing it was surprisingly easy.
Interpreting commands sent over email
We don't want to pass just any data to Home Assistant
Email is a bit of a messy protocol with a lot of components that make it possible to trust that a sender is who they actually say they are. For example, if you receive an email from "adam@xda-developers.com", how can you verify it came from me? Faking where an email came from is incredibly easy, and if I have commands that control my home lab, I better be sure that those commands are actually coming from me and not someone faking my email address.
When it comes to email, there are a few technologies that can prove if the sender of an email is actually the sender. Two of these are SPF and DKIM, standing for Sender Policy Framework and DomainKeys Identified Mail. The first is a simple check to ensure that the IP address that sent the email is authorized by the domain to do so. This is already hard to spoof, and would require a man-in-the-middle attack, BGP hijacking, or a poorly implemented SPF policy on the domain name to bypass it.
The next, though, is a lot harder to bypass. DKIM essentially provides a digital signature with every email sent, and this signature can then be compared with the public key associated with the domain. If it matches, the email comes from a legitimate sender and has not been tampered with. By combining the two of these with DMARC, it's hard to get more robust than that without also including a key in your email that only you know that you check for as well. If I planned on using this long term, I'd implement that for sure.
When you send an email to the Tines address that it gives you, these tests are all in the headers. So, we can simply check if "spf=pass", "dkim=pass", and "dmarc=pass" all exist in the "Authentication-Results" object. If they don't, we can create a fail path that will send an email letting me know, and if they do pass, we can continue with the rest of our flow.
The rest of our flow is fairly simple. We first need to extract the commands from the subject and the body of the article, and then we set up a flow that goes to different triggers. Triggers are essentially a series of "if-else" blocks, as we can trigger based on a command and have a series of these together based on the text that we extract.
When it comes to extracting text, Tines makes it pretty easy. You can just pass a string from a declared variable, or you can extract from a JSON object, and there are many more options, too. We'll extract from our "receive_email_action.body" parameter, but there's just one issue: the body of the email looks like this (chevrons have been replaced with regular brackets):
"(div dir=\"ltr\")104(/div)\n"
We want the 104 part, but just getting whatever is inside the div is tough. Thankfully, Tines also supports regex, so we can do the following to get the text inside the div consistently, where the chevrons have been replaced with a C.
Cdiv[^C]*C \s*\w+\s+(.*?) C\/divC
This gives us just the text inside the div and assigns it to a variable. The subject line is easy, and the only regex we need is ".*" Finally, the triggers simply check what the text extracted was, and react accordingly based on whether it was "proxmox start", "proxmox stop", or "proxmox reboot."
This next part can be massively improved by hooking things up to the one HTTP request, but I then make a HTTP request from Tines to my Home Assistant webhook, with the key of the JSON object that's sent being "start", "stop", or "reboot", and the value being the number extracted from the email.
To improve this further and decrease the number of blocks that I'm using, I could dynamically create the key sent in the JSON object based on the command, and keep it all in one HTTP request block in Tines. But what about the Home Assistant side? The commands have to go somewhere, so we'll move on to tying it all together.
8 "hidden" Home Assistant integrations worth setting up
If you're knee-deep in Home Assistant like I am, then check out these more niche integrations that require editing your config to use.
Setting up Home Assistant
It's just one automation
First and foremost, I'm using the Proxmox VE HACS integration, which is an enhanced version of the built-in Proxmox integration. It has a bit of a lengthy set-up, but it results in being able to control all of your VMs and LXCs from Home Assistant.
To start, we create an automation in Home Assistant, which is triggered based on a webhook. This will automatically create the webhook for you. I'm only setting it up for LXCs here, but it would be fairly easy to switch it up and make it so you can control VMs, too. We can use the fact that every sensor created by the integration follows the same format:
button.lxc_(name)_(number)_(start/stop/reboot)
With our integration, we define the following variables:
- action: either start, stop, or reboot
- number: the value in the payload sent from Tines
-
button_entity: loops through all buttons, checking for:
- buttons that start with "button.lxc_"
- buttons that end with "_(action)"
- buttons that have the number in them
- status_sensor: the sensor associated with the service, for confirming if our action worked
With this, we can send a command like "proxmox start 104" over email to Tines, which is extracted, and then it gets sent to our Home Assistant webhook. It's interpreted, the variables are set, and we press the "button_entity" variable.
Finally, we wait for 15 seconds, then poll the sensor. If it returns the expected value, we send a rest_command to our Tines webhook, which fires an email with whether the action was successful or whether it failed, by checking if the expected value matches the actual value.
Automation platforms can unlock new ways to control your home lab
The sky is the limit
Let's be clear: this is an incredibly overengineered "solution" to a problem that doesn't really exist. However, I did it to show how a tool like this can be used to automate control of your home lab. Through Home Assistant as a tunnel of sorts, you can enable two-way communication between your home lab and the cloud-based Tines platform, which can be useful in other ways through tools like the command_line integration to send instructions to other servers or containers within your network.
For those concerned about the security of using a cloud-based tool for automation, Tines puts security first and foremost. Its cloud offering is SOC2 Type 2 compliant, though "compliance" is a whole other topic given that there is no centralized agency to conduct those audits. Rest assured, though, that Tines is built on automation and security. Community edition accounts, which I'm using here, only hold logs for seven days. There are limitations to that, such as long-term automations being limited to a week, but it's also great because it means your data is gone a week later.
Deploying something like this requires extra care towards protecting your data and protecting how your commands are invoked, but the platform is built on providing that kind of functionality to large businesses. Some people prefer to control everything locally, which is completely understandable, and for those that do, a tool like n8n is better suited to your use case.
