Smartskills

  Skill Help


The venerable LMS concept pre-dates the smartphone era and was never architected for cloud-based control. We therefore need to jump through some hoops to make this feasible, but the result is more than worth it ! In a nutshell, we need to create a way for Alexa to tunnel through your firewall to securely reach the LMS server on your local network while also keeping unwanted visitors out.

Amazon's account linking process for the skill is where you provide the external connectivity details for your LMS server. You don't create an account with us and don't link to it as such. Instead, we use the landing page shown during account linking to retrieve your configuration details which are then stored directly in the skill. Simple, and it keeps your data safer. There's also no LMS plugin required.

Our skills work by interfacing with your LMS server's jsonrpc interface, usually on port 9000. That's the same port you use in a web browser to access LMS via e.g. the Material skin. On your local network, you use something like http://192.168.1.10:9000 for this. However, for Alexa we need to specify a cloud-accessible URL for LMS and also to support both SSL encryption and secure authentication, so an extra step is needed — proxying.

We have two suggestions for your proxy but you are free to use others if you have the technical expertise:

  • Use ngrok (section Ⅱ), a combination of a free cloud service and a local helper-program. It's really easy to setup after downloading a standalone executable file which is currently available for Windows, Mac and Linux. No worries if you're on NAS — you can install and run ngrok from a different machine in your network and point it towards your NAS. Otherwise, it can all be done on your LMS machine directly. Either way, it's trivial to configure ngrok and a spare RPi can handle the NAS-proxying no problem.
  •  
  • Roll your own (section Ⅵ) reverse proxy using e.g. apache or nginx and handle it all locally without any cloud service. This is harder to setup than ngrok but you may already have done this anyway if you are a Smart Home enthusiast. You'll need a DDNS domain name, SSL cert from e.g. Letsencrypt, and you'll need to open a port on your router.

Please note that it is not possible to use a VPN or Synology QuickConnect with Alexa skills.

You can optionally link our skills with multiple instances of LMS so that the superset of players from those servers will be accessible from a single Amazon account. Please see section Ⅴ for instructions.

Those using ngrok are highly recommended to read sections Ⅱ–Ⅳ in their entirety.

Visit the ngrok.com website (no affiliation) for an explanation of how it works and what plans are available. The free plan works just fine for our purposes. Observe that while you can use ngrok without prior registration/account-creation, your tunnels will then auto-expire after 8 hours and are therefore not of much use here.


Linux
After downloading the correct version of ngrok for your platform, move the executable file to where the system expects to find it: sudo mv ngrok /usr/local/bin. If ngrok will run on the same machine as LMS, at a command prompt type:

ngrok http -auth "myuser:mypass" 9000 > /dev/null 2>&1 &

Otherwise, if ngrok will run on a different machine in your local network, point it to LMS by prepending the IP address to the port number:

ngrok http -auth "myuser:mypass" 192.168.x.y:9000 > /dev/null 2>&1 &

Don't worry — specifying http as protocol starts both http and https tunnels. Please choose strong values for myuser and mypass and re-use them across all the LMS skills and proxy services.

ngrok will now run in the background due to the & at the end. You might need to disown to keep the ngrok process alive after you close the terminal (depends on your distro). Then, to find the assigned tunnel subdomain, we can query the ngrok web UI at port 4040 for the public_url entry by typing

curl -s http://localhost:4040/api/tunnels | grep -Po https://.+?\.io

The output will look something like https://19279a3a.ngrok.io. That's the server URL we will use in securely linking the skill.

As an alternative to the curl command, you can login to your ngrok online dashboard and see your assigned tunnel under Status and then Tunnels.


Windows/MacOS
On Windows, download ngrok and run the relevant command listed above from a DOS or Powershell prompt, without the > /dev/null 2>&1 & at the end. Instead of using curl to determine the assigned ngrok subdomain, use any browser on the same PC to browse to http://localhost:4040 and you will see the URL under the status tab.

On Mac, download the Mac version and run the relevant command listed above in a terminal. You can use either curl in the terminal or point a browser to http://localhost:4040 to determine the URL.


Browser Test
Because your ngrok tunnel now points to LMS at port 9000, you can test that the tunnel is functional by visiting the assigned URL (e.g. https://19279a3a.ngrok.io) in a browser. The browser will pop a modal dialog box asking you for the myuser and mypass values that you specified for the -auth switch. If you enter those you should see the familiar LMS web portal you normally access from your LAN, with the difference that you're now reaching it externally from the cloud. Note the icon indicating that the connection is secure/encrypted.


Link the skill
In the Alexa app or web-portal (a PC is preferable to smartphone or tablet for this) enable the skill and prepare for account-linking. You will use the assigned ngrok URL in the  field on the account-linking landing page. For example:

  https://f8427de225bf.eu.ngrok.io

Fill in the   and fields using the myuser and mypass values that you specified for the -auth switch. These parameters must be reused for authentication across all your LMS-related tunnels/proxies and our LMS skills if you wish to use autoupdate (section Ⅳ).

Press the button which will run some checks on the details you provided and verify that there is actually an LMS server responding at the destination. If there are no errors, the button changes color and function to become — otherwise you can modify your inputs based on the error message and re-try validation.

Submit, and Amazon should tell you that the skill was successfully linked !


Prevent Orphaning
Although ngrok is now running in the background, a machine reboot will terminate it and you would have to run the command again in a terminal to restart ngrok. The next section Ⅲ describes how you can get it to always run as a daemon when your machine boots.

Also, while the free ngrok plan works fine, it has the disadvantage that your server path URL will change every time you reboot/restart ngrok. As this then orphans the skill from LMS, it means choosing between: (1) redoing account-linking manually after every server-restart; (2) running a simple Python or Perl refresh script on your machine after ngrok starts; (3) using ngrok from a dedicated proxying RPi that you never reboot; or (4) getting a paid ngrok plan which persists your subdomain across reboots. The choice herein is yours — note that instructions for option 2 are provided in section Ⅳ, while option 1 is fine if you are still evaluating the skill

Please first read the introductory section Ⅱ on ngrok before attempting this.

ngrok config
Login to your (free) ngrok account from a browser and under Setup & InstallationConnect your Account copy your authtoken from section 2 (e.g. 4nq9771bPxe8ctg7LKr_2ClH7Y15Zqe4bWLWF9p) but otherwise ignore the instructions there. Next, at a command prompt on your ngrok host machine, type:

ngrok authtoken 4nq9771bPxe8ctg7LKr_2ClH7Y15Zqe4bWLWF9p  ← paste your token here

This will create a file called ngrok.yml in a hidden folder .ngrok2 in your home directory. Edit that file with nano ~/.ngrok2/ngrok.yml so that it looks as follows (note the indentation is required; tabs or spaces are both OK):

authtoken: --YOUR_AUTHTOKEN--
web_addr: 0.0.0.0:4040
region: eu
tunnels:
  mediaservertunnel:
    proto: http
    bind_tls: true
    inspect: false
    addr: 192.168.1.10:9000
    auth: "myuser:mypass"   

Here mediaservertunnel is the alias/name by which we can later refer to the tunnel, while addr is the IP address of the LMS server it proxies to. For auth, you should choose a strong username myuser and password mypass to maximize security.

You can test things by typing ngrok start mediaservertunnel which should launch a live status page in your terminal window if all is well. Kill this again with ctrl-c as it was just a test.


systemd config
Next, we need to create the file needed to run ngrok as a service and configure that to run at system-boot. Type the command sudo nano /etc/systemd/system/ngrok.service and give the file the following content:

[Unit]
  Description=ngrok autostart 
  Wants=network.target 
  After=network.target

[Service]
  Type=simple 
  WorkingDirectory=/tmp
  ExecStartPre=/bin/sleep 5
  ExecStart=/usr/local/bin/ngrok start -config=/home/pi/.ngrok2/ngrok.yml mediaservertunnel
  RestartSec=30
  StandardOutput=syslog
  StandardError=syslog
  SyslogIdentifier=ngrok

[Install]
  WantedBy=multi-user.target

The ExecStart entry as specified means we will autostart the tunnel named mediaservertunnel specified in the ngrok config file located at /home/pi/.ngrok2/ngrok.yml (change to suit your setup). You can autostart all your tunnels by replacing the name by --all or start multiple named tunnels by specifying the names separated by spaces. e.g. primary betatest.

On slow hardware, you may want to increase the ExecStartPre delay value to e.g. 60 or 90 seconds to allow networking to become available. With the service file successfully created, type:

sudo systemctl daemon-reload
sudo systemctl enable ngrok
sudo systemctl start ngrok

If all is well, ngrok is now running as a service. You can check its status using

sudo systemctl status ngrok

Also, from any machine in your local network, you can watch what ngrok is doing by browsing to the IP address of the ngrok host machine on port 4040, e.g. http://192.168.1.1:4040 or http://localhost:4040. The status tab there will show you the ngrok subdomain(s) assigned to your tunnel(s).

Remember, when you reboot or otherwise restart the systemd service while on the free ngrok plan, these subdomains will change and orphan the skill from LMS. That is, unless you have auto-updating set up (see section Ⅳ).

Please first read the introductory section Ⅱ on ngrok before attempting this. You must also have setup ngrok to autostart as a systemd service (as detailed in section Ⅲ).

Note that if you are linking both the LMS-Lite and MediaServer skills for LMS, it's best to do so from the same PC and browser as this will ensure that the same script/key updates both skills. The landing-page makes use of your browser's localStorage feature to effect this.

Pay heed that this process only updates the URL component of the ngrok tunnel and assumes unchanged -auth parameters. If you alter those details for whatever reason then it will be necessary to manually redo account-linking by disabling/re-enabling the skill(s).

The autoupdate procedure pushes your changed tunnel details to the cloud by means of the uuid key (e.g. d84fb223c34002944701a9a70e5e82b65e01cda21b6e8914) that was shown at the account-linking stage after your tunnel(s) were verified.


updater script
Download either the Python or Perl updater script according to your personal preferences, and don't forget to chmod +x the file to make it executable.

For the Python file, you need to edit the variables

 myNgrok = 'http://192.168.1.1:4040/api/tunnels'
 myTunnels = ['mediaservertunnel']
 myUuid = ['d84fb223c34002944701a9a70e5e82b65e01cda21b6e8914']
                        

while with the Perl file, that would be

 $myNgrok = 'http://192.168.1.1:4040/api/tunnels';
 @myTunnels = qw/mediaservertunnel/;
 @myUuid = qw/d84fb223c34002944701a9a70e5e82b65e01cda21b6e8914/;
                        

The array myUuid is for the cryptographic key(s) referenced above. myNgrok should contain the 4040 web address such as http://localhost:4040 of your local tunnel inspection page. The array myTunnels contains the name(s) of the tunnel(s) you specified in your ~/.ngrok2/ngrok.yml file. If you have linked the skill(s) to more than one LMS server, this entry might look like ['primary', 'betatest'] or qw/primary betatest/; reflecting the named tunnels in your config file.


systemd service edit
To ensure this script runs automatically whenever your assigned tunnels change, we need to edit the systemd service file from section Ⅳ: sudo nano /etc/systemd/system/ngrok.service. Under the existing ExecStart entry, we insert a new line as follows:

ExecStartPost=/usr/bin/python3 /home/pi/updater.py or (Perl) ExecStartPost=/usr/bin/perl /home/pi/updater.pl

The example assumes you have put the script file in /home/pi but you can change that if you chose a different location. Now upon start/restart, the service will first run ngrok itself (ExecStart) to establish the new tunnel(s) and then the updater script (ExecStartPost) to update the skill(s).

Please keep your myUuid key secure — it's relatively harmless without your -auth details but don't tempt fate…


key re-use
If you link all your LMS skills from the same PC/browser then the myUuid key returned to you will be the same each time. This means that one Python/Perl script can update all your tunnels with a single key and it just makes life easy. If you fail to do this and a new key is presented when you link a skill, you will have to update your script with the new key. If, however, you have any LMS skills still linked with the old key, you should not just replace the old key by the new one, but you should add it and create a list of keys thus:

myUuid = ['d84fb223c340...', '67f8f78097ac...'] or (Perl) @myUuid = qw/d84fb223c340..., 67f8f78097ac.../;

Alternatively, you could re-link the other skill from the same PC/browser so it gets the new key too and that way you still have only one key in use across your skills.

If you run the Python or Perl script manually from a command prompt you will see OK displayed for each successful update or Fail X if something went wrong. In this case, Fail 2 would mean that the uuid value in question is no longer valid so you can remove it from the list. At no time should your list be longer than the number of LMS skills you currently have linked (MediaServer, LMS-Lite).

If you already use ngrok for other purposes and want to be sure of the correct LMS tunnel association(s) when things change, you can optionally append the [tunnelname] during account linking: e.g.   https://f8427de25.ngrok.io[primary]

When linking your skill(s), it's possible to specify multiple URLs that each point to different LMS instances under your control. These can be at the same physical location (e.g. a primary server with a stable release and a betatest server running a nightly version of LMS) or at different locations such as your home and a holiday chalet. A prerequisite is that the aggregate of player names should not reflect repeats/duplicates among your servers/locations. Also, if you link one skill to more than one LMS server, you must also link the other skill similarly.

ngrok tunnels can be mixed with other forms of proxies as you please. Just remember that it's mandatory to use the same -auth and/or .htpasswd parameters for all your proxy services.


ngrok config edit
Make sure your ngrok tunnels appear jointly or severally in .yml file(s) and are configured to autostart in the associated systemd file(s). If your tunnels all run from one ngrok instance, your .yml file will have multiple tunnels — otherwise you will have a separate .yml file on each ngrok host machine. Multiple tunnels in one config might look as follows:

authtoken: 6hR173iJMYTfypshaexbe...
web_addr: 0.0.0.0:4040
region: eu
tunnels:
  primary:
    proto: http
    bind_tls: true
    inspect: false
    addr: 192.168.1.10:9000
    auth: "myuser:mypass"
  betatest:
    proto: http
    bind_tls: true
    inspect: false
    addr: 192.168.1.22:9000
    auth: "myuser:mypass"  

These tunnels would then be referenced as ['primary', 'betatest'] or qw/primary betatest/; in the auto-updating script from section Ⅳ.


Multi-link the skill
In the Alexa app or web-portal (a PC is preferable to smartphone or tablet for this) enable the skill and prepare for account-linking. Enter the comma-separated URL details in the  field on the account-linking landing page. For example:

  https://joebloggs.myddns.me:9443, https://f8427de225bf.eu.ngrok.io

Note that if your list of URLs contains more than one ngrok URL, you must append the names of the tunnels (as defined in your .yml config file) in square brackets [tunnelname] like this:

  https://f8427de25.ngrok.io[primary], https://29f955b.ngrok.io[betatest]

Fill in the   and fields using the myuser and mypass values that you previously specified in the .yml config file under auth: "myuser:mypass" (values should be the same for each tunnel).

Press the button which will run some checks on the details you provided and verify that there is actually an LMS server responding at each destination. If there are no errors, the button changes color and function to become — otherwise you can modify your inputs based on the URL-specific error message(s) and re-try validation.

Submit, and Amazon should tell you that the skill was successfully linked !

Don't choose this option unless you are computer-savvy — use ngrok instead as detailed earlier. If you do want to do things this way, this is not a step-by-step tutorial but here's your checklist:

  • Get yourself a free dynamic DNS name via e.g. no-ip.com. An example of this would be joebloggs.myddns.me
  • Use Letsencrypt to get and install an SSL certificate for the DNS name you chose above using certbot. This is proven to work with Alexa skills.
  • If you use an SSL cert sourced elsewhere, note that it cannot be expired and it should also be from a provider trusted by Amazon. Not observing this is the primary reason for failures with roll-your-own users !
  • Install apache or nginx on a machine of your choice (does not have to be the same as your LMS machine). Create a reverse proxy from 443 on localhost to port 9000 on your LMS server's IP address (in this example, 192.168.1.10 is the LMS machine). For apache, this could look as follows:
  • 
    # put this in /etc/apache2/sites-available
    <VirtualHost *:443>
      ServerName joebloggs.myddns.me
      SSLEngine on
      Header always set Referrer-Policy "same-origin"
      Header always append X-Frame-Options SAMEORIGIN
      ProxyPass / http://192.168.1.10:9000/ Keepalive=On
      ProxyPassReverse / http://192.168.1.10:9000/
      SSLCertificateFile /etc/letsencrypt/live/joebloggs.myddns.me/cert.pem
      SSLCertificateKeyFile /etc/letsencrypt/live/joebloggs.myddns.me/privkey.pem
      SSLCertificateChainFile /etc/letsencrypt/live/joebloggs.myddns.me/chain.pem
      <Location />
        AuthType Basic
        AuthName "MyProxies"
        AuthUserFile /etc/apache2/.htpasswd
        Require valid-user
      </Location>
      <Directory "/">
        Require all denied
      </Directory>
    </VirtualHost>
                                                
  • Open a port in your router that forwards an external port such as 9443 to internal port 443 on the machine that apache runs on.
  • Set up a username myuser and password mypass in apache's .htpasswd file using the command sudo htpasswd -c /etc/apache2/.htpasswd myuser
  • Issue the command sudo systemctl restart apache2 and now your LMS server is externally accessible from https://joebloggs.myddns.me:9443

Browser Test
You now have a valid internet-accessible URL that points to LMS at port 9000. In a browser, paste this URL and then enter the myuser and mypass values in the authentication modal. You should see the familiar LMS web portal you normally access from your LAN, with the difference that you're now reaching it externally from the cloud. Note the icon indicating that the connection is secure/encrypted.


Link the skill
In the Alexa app or web-portal (a PC is preferable to smartphone or tablet for this) enable the skill and prepare for account-linking. You will use your proxy URL in the  field on the account-linking landing page. For example:

  https://joebloggs.myddns.me:9443

Fill in the   and fields using the myuser and mypass values that you specified in .htpasswd.

Press the button which will run some checks on the details you provided and verify that there is actually an LMS server responding at the destination. If there are no errors, the button changes color and function to become — otherwise you can modify your inputs based on the error message and re-try validation.

Submit, and Amazon should tell you that the skill was successfully linked !


Keep an eye on the validity of your SSL cert as the skill(s) will stop functioning upon an expired cert (e.g. LetsEncrypt certs normally expire after 90 days).