You should run the service with an unprivilidged user e.g. joe
Please be careful that non root users can not bind port numbers from 1 to 1024
Firt make sure you some prerequisite modules installed
You can install them using e.g. the cpanm utility
# First install the cpanm itself
curl -L --insecure https://cpanmin.us | perl - App::cpanminus
# The rest modules
cpanm Data::Dumper
cpanm XML::Hash::XS
cpanm JSON::XS
cpanm YAML::XS
cpanm Moo
cpanm Plack
cpanm Plack::Middleware::Deflater
cpanm Starman
cpanm Dancer2
cpanm Dancer2::Plugin::WebService
or for every modules
tar xvzf ....tar.gz
cd ...
perl Makefile.PL
make
make test
make install
Assuming that you will start the application as a non privileged user e.g. joe
Create the user if not exists
getent group joe >/dev/null || groupadd joe
getent passwd joe >/dev/null || useradd -g joe --no-log-init -c "Dancer2-Plugin-WebService user" -s /sbin/nologin joe
lslogins -o USER,GROUP,UID,SHELL joe
Create the application e.g TestService inside e.g. the /opt folder
cd /opt
dancer2 gen --application TestService
Give ownership to joe
mkdir /var/log/TestService
mkdir /usr/local/sessions
chown -R joe:joe /opt/TestService
chown -R joe:joe /var/log/TestService
chown -R joe:joe /usr/local/sessions
chown -R joe:joe /usr/share/perl5/site_perl/Dancer2/Plugin/scripts
chmod u+x /usr/share/perl5/site_perl/Dancer2/Plugin/scripts/LinuxOS/AuthUser.pl
chmod u+x /usr/share/perl5/site_perl/Dancer2/Plugin/scripts/HttpBasic/users.pl
chmod u+x /usr/share/perl5/site_perl/Dancer2/Plugin/scripts/HttpBasic/admins.pl
Use logrotate to housekeeping the log files
vi /etc/logrotate.d/TestService
/var/log/TestService/*.log
{
create 640 joe joe
compress
missingok
notifempty
daily
rotate 7
}
If you want your routes ro provide geop ip information install the GeoIP package
At archlinux pacman -S geoip geoip-database geoip-database-extra
At debian apt-get install geoip-bin
At fedora, redhat yum install geoip
At CentOS 5 rpm -Uvh http://mirrors.kernel.org/fedora-epel/5/i386/epel-release-5-4.noarch.rpm
At CentOS 6 rpm -Uvh http://mirrors.kernel.org/fedora-epel/6/i386/epel-release-6-8.noarch.rpm
yum repolist
yum install geoip
If you want compressed replies
vi /opt/TestService/bin/app.psgi
#!/usr/bin/perl
use FindBin;
use lib "$FindBin::Bin/../lib";
use TestService;
use Plack::Builder;
builder { enable 'Deflater'; TestService->to_app }
Or if you have slow CPU use uncompressed replies
vi /opt/TestService/bin/app.psgi
#!/usr/bin/perl
use FindBin;
use lib "$FindBin::Bin/../lib";
use TestService;
TestService->to_app;
Configure the production enviroment
vi /opt/TestService/environments/production.yml
show_errors : 1
startup_info : 1
warnings : 1
no_server_tokens : 0
log : "core"
logger : "file"
engines :
logger :
File :
log_dir : "/var/log/TestService"
file_name : "activity.log"
Configure your application settings
vi /opt/TestService/config.yml
appname : TestService
environment : production
plugins :
WebService :
Version : 1.0.4
Owner : Joe Lunchbucket, Joe.Lunchbucket@example.com
Session directory : /usr/local/sessions
Session idle timout : 3600
Default format : json
Command sudo : /usr/bin/sudo
Command rm : /usr/bin/rm
Routes :
test1 : public
test2 : public
test3 : private
Allowed hosts:
- 127.*
- 10.*
- 192.168.1.23
- 172.20.*
- 32.??.34.4?
- 4.?.?.??
- ????:????:????:6d00:20c:29ff:*:ffa3
- "*"
User must belong to one or more of the groups:
- power
- storage
- network
Authentication method:
Always allow login for testing:
Command : MODULE_INSTALL_DIR/scripts/AlwaysOk/AlwaysOk.sh
Active : no
Use sudo : no
Linux native users:
Command : MODULE_INSTALL_DIR/scripts/LinuxOS/AuthUser.pl
Active : yes
Use sudo : yes
Basic Apache auth for simple users:
Command : MODULE_INSTALL_DIR/scripts/HttpBasic/users.pl
Active : no
Use sudo : no
Basic Apache auth for admins:
Command : MODULE_INSTALL_DIR/scripts/HttpBasic/admins.pl
Active : no
Use sudo : no
Active directory:
Command : MODULE_INSTALL_DIR/scripts/Active Directory/Active Directory.pl
Active : no
Use sudo : no
LDAP:
Command : MODULE_INSTALL_DIR/scripts/LDAP/LDAP.pl
Active : no
Use sudo : no
Write your real code at /opt/TestService/lib/TestService.pm e.g.
package TestService;
use strict;
use warnings;
use Dancer2;
use Dancer2::Plugin::WebService;
our $VERSION = setting('plugins')->{WebService}->{Version};
any '/test_mirror' => sub { RestReply('DATA_USER_SEND') };
any '/test_get_one_key' => sub { RestReply('k1') };
any '/test_get_data' => sub {
my ($var1, $var2) = get_data_user('k1', 'k2');
RestReply( Total => ($var1 + $var2), Thought => 'Lets add !' )
};
any '/test_new_data' => sub {
my %data =
set_data_user( new1 => 'N1', new2 => 'N2' );
set_data_user( new3 => 'N3', new4 => 'N4' );
del_data_user( 'new1' , 'new4' );
RestReply('DATA_USER_ALL')
};
setting('plugins')->{'WebService'}->{'Routes'}->{'test_session'} = 'private';
any '/test_session' => sub {
my ($v1, $v2) = get_data_user('k1', 'k2');
set_data_session(s1 =>'L1', s2=>'L2', s3=>['L3a', 'L3b']);
del_data_session('s7', 's8');
my @Some = get_data_session('s1', 's2', 's3', 's7');
my %All = get_data_session();
RestReply(k1=>$v1, k2=>$v2, SesData_A => $Some[2], SesData_b=> [ @Some[0..1] ], SesData_all=> { %All } )
};
dance;
If you are using nginx web server to reverse proxy you service
from port 80 or for adding https protection ( port 443 )
Add at your nginx.conf something similar to
...
upstream TestService { server 127.0.0.1:65535 fail_timeout=0; keepalive 1024; }
...
server
{
server_name anotherdimension.mooo.com;
listen 80;
listen 443 ssl;
root /tmp;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; # needed for real client IP pass as server enviroment variable HTTP_X_REAL_IP
location /
{
fastcgi_param REMOTE_ADDR X-Real-IP;
proxy_pass http://TestService;
}
}
It is a good idea tou start your application as Linux service
We bind at port 127.0.0.1 because we usually publish such services with the nginx
vi /usr/lib/systemd/system/testservice.service
[Unit]
Description=Perl Dancer2 restful web service
Documentation=https://metacpan.org/pod/Dancer2
After=network.target
ConditionPathExists=/usr/bin/site_perl/plackup
[Service]
Type=simple
User=joe
Group=joe
ExecStart=/usr/bin/site_perl/plackup --host 127.0.0.1 --port 65535 --server Starman --workers=10 --env production -a /opt/TestService/bin/app.psgi
ExecStop=/bin/kill -s QUIT $MAINPID
WorkingDirectory=/opt/TestService
KillMode=mixed
KillSignal=QUIT
StandardOutput=journal
StandardError=inherit
NoNewPrivileges=true
PrivateTmp=true
LimitNOFILE=infinity
RestartPreventExitStatus=255
Restart=on-failure
RestartSec=60s
NotifyAccess=all
[Install]
WantedBy=multi-user.target
start the service
systemctl enable testservice.service
systemctl cat testservice
systemctl start testservice
systemctl show --property=ActiveState testservice
systemctl status testservice
journalctl -xeu testservice | less
to delete the service
systemctl stop testservice
systemctl disable testservice.service
rm /usr/lib/systemd/system/testservice.service
start the application manual
cd /opt/TestService; sudo -u joe /usr/bin/site_perl/plackup --host 127.0.0.1 --port 65535 --server Starman --workers=10 --env production -a /opt/TestService/bin/app.psgi
or during development
cd /opt/TestService; sudo -u joe /usr/bin/site_perl/plackup --port 65535 -a /opt/TestService/bin/app.psgi --Reload /opt/TestService/lib,/opt/TestService/config.yml,/usr/share/perl5/site_perl/Dancer2/Plugin
cd /opt/TestService; sudo -u joe /usr/bin/site_perl/plackup --port 65535 -a /opt/TestService/bin/app.psgi
or without Plack
sudo -u joe perl /opt/TestService/bin/app.psgi
quick test
netstat -anp | grep :65535
curl -X GET http://localhost:65535/info?to=human