image_stream_server
is a ROS node that wraps a python Flask web server. It is designed to offer a very simple web interface for the different ROS projects. The following sections described the different steps to perform to setup up the web server. The first two sections might differ depending on your ISP (Internet Service Provider) but aren't necessary if you want to keep your web server within you local network. However, if you want to access that server from the world wide web you will need them.
The following sections are divided in two parts. The first one detail the setup of the web server and the second one describe the ROS node associated to the server followed by an example using the webcam
node.
Most of ISPs use an ip to represent several routers. Each of them has a virtual ip, that is used to route the traffic that this specific to that router. I'm using Free
(a french ISP) and in your customer account you can enable this option and restart your router. You can find this option from the MAFREEBOX > Demander une IP fixe V4 Full Stack
. Now you router has a unique ip that is reachable on the world wide web even if it restarts its IP will remain unchanged.
Some internet provider offer a DNS service that can be used for your web application. A DNS (Domain Name Service) resolves your router ip to a specific name. Free
provides this option and you can choose a name for your server (if it is not already in use). Go into the MAFREEBOX > Personnaliser mon reverse DNS
then at the bottom of the page, enter a name for your server in the field Reverse DNS personnalisé
. For instance my server name is xxxxxx.hd.freebox.fr
.
Nginx server is another web server. Compared to Flask
, Nginx
is production oriented server. However, Flask
is very practical for prototyping and hobbies. Using Nginx
as a reverse proxy allow to dedicate the SSL security to Nginx
while keeping the content under the hood of Flask
server. Below is a small diagram that explain what's happening when you try to reach the server:
You can easily install Nginx
using sudo apt-get install nginx
. Once this is done, you should configure Nginx
to act as a proxy.
This will be describe in section 5.
LetsEncrypt is a nonprofit certificate authority. You can ask for a certificate using their utility program certbot
. Its installation is very simple sudo apt-get install certbot
.
To ask a certificate you can use the following command line:
sudo letsencrypt certonly --dry-run --manual --email [email protected] -d xxxxxxx.hd.free.fr
It will prompt you a message asking to your server to reply a specific hash when a specific URL is queried by LetsEncrypt
. By doing so, LetsEncrypt
so they ensure you are the owner of the server. For doing this we will modify our Flash
application to answer that hash.
Once this is done, you should have a certificate, and a private key in the /etc/letsencrypt/live/your-dns-name
directory.
NOTE: This operation can also be performed at the Nginx
level.
The modification looks like:
@auth.route('/.well-known/acme-challenge/<challenge>')
def letsencrypt_check(challenge):
challenge_response = {
"SyVlwQEXFZDlHUzT28Ko6azone2j2hRuROOT5jlDDk0":"SyVlwQEXFZDlHUzT28Ko6azone2j2hRuROOT5jlDDk0.CsnZA_XCWM39H5F1SjCSbq5yGPswgizWR5WLnn6aoUQ",
}
return Response(challenge_response[challenge], mimetype='text/plain')
The certificate is usually valid for a period of 90 days but it can be easily renewed.
Now, we'll indicate Nginx
to listen on the 443
port (https) and to redirect all 80
port traffic to the 443
port to be sure that the connection to your server will be secure using the https
protocol. Furthermore we will give him the path to certificate file and private key to use to encrypt the connection.
You can create a Nginx
configuration file in /etc/nginx/conf.d
directory and link that file into the /etc/nginx/site-enabled
and /etc/nginx/site-available
directories.
The configuration file typically look like this:
server {
listen 443 ssl;
server_name your-dns-name www.your-dns-name;
ssl_certificate /etc/letsencrypt/live/your-dns-name/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/your-dns-name/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5000/;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name your-dns-name www.your-dns-name;
location / {
return 301 https://$host$request_uri;
}
}
As you can see the incoming traffic of the Nginx
server is redirected toward the loopback address on wich my server is running.
Your server is now ready to receive incoming connections.
The last step is to open the 443
(https) port for TCP
traffic on your router and redirect the traffic to the machine that host your server in your local network. These redirections can be defined using the web interface of your router mafreebox.freebox.fr
for my ISP for instance. The machine that host my server is my raspberry pi. In Paramètre de la freebox > Gestion des ports
I added two rules, that redirect all incoming traffic of port 80
and 443
to my raspberry pi ip. The image below shows the rule I added:
Once enable, you should be able to reach your server from the world wide web.
The ROS node offers the possibility to configure the server port and the image topic. The implementation handle an incoming topic image and display it in the web application. sensor_msgs/Image
and sensor_msgs/CompressedImage
topics are handled (sensor_msgs/CompressedImage
are recommended as they offer a better frame rate for streaming). Below is an example of the image_stream_server
node in action with the webcam
node.