Serving Alexa Smart Home skills on your own device or server
For creating Alexa skills, you have to implement an AWS Lambda function that is invoked for every request a user makes to Alexa (that involves your skill) in order to carry out your intended actions and possibly return a response to the user.
Now the usual »Cloud« scenario is that your Smart home devices connect to the Cloud of the manufacturer and are always connected to their servers. The Lambda function would then talk to an internal service of the manufacturer in order to relay your Alexa requests to your devices.
I don’t want that.
If you want to control your Smart Home devices locally but still use Alexa for voice control, you need get the Alexa requests that go to your skills’ Lambda function into your local network – either process in Lambda before triggering actions or just pass them to your own »Alexa service« in your home network that does that for you.
There are multiple ways to achieve that:
- Open your Smart Home controller services up to the internet (with authentication, of course) in your home router. This would probably the easiest solution, but you would have to that for every service you want to control through Alexa. Also you would implement all the control logic in Lambda – which can be annoying to debug sometimes.
- Create a full-scale VPC with a VPN gateway that connects to your home network. Overkill. You would also pay for an EC2 instance that acts merely as a proxy. Now you can forward your requests to your in-home »Alexa service« or process them in Lambda and directly trigger the corresponding actions.
- Pipe all Alexa requests through your home router to an HTTP proxy on, e.g., a Raspberry Pi. This proxy would then authenticate and forward incoming Alexa requests to your local »Alexa service«.
I decided for the last approach.
Setting up nginx on a Raspberry Pi
For the following example I’m using Arch Linux ARM. For other distros, please adapt any paths as needed.
Generate Let’s Encrypt certificates for your proxy
Make sure your router forwards ports 80 and 443 to your Raspberry Pi.
This will generate valid certificates in /etc/letsencrypt
.
We can create a directory in /etc/nginx/certs
to have easier access to them:
Generating a CA and client certificates
Your Lambda function will use a client certificate to authenticate itself against your »Alexa service«.
First we create the CA that signs those certificates:
Then we create a client ceriticate for our Lambda function:
Configure nginx
Add the following to the http
section of your nginx.conf
:
Now start your service on port 4567 on your Raspberry Pi. For example, using a minimal Sinatra app:
main.rb
:
Creating a Lambda function that redirects your Alexa requests
This one is simple. Just create a Lambda function running in the NodeJS environment.
index.js
:
Now add your previously generated aws-lambda.key
and aws-lambda.pem
client key and certificate files to the same folder as index.js
.
There you go. Your requests will start filing into your Alexa service ready for being processed by you.