Github & Travis CI submodule trigger build for main project

Good day.

I was participating in project Pupil and one of the task was to trigger build of main project from push event of submodule. In order to do that you need to do simple POST request to travis api but Github doesn’t allow to add custom headers thus request cannot be authenticated. So workaround is rather simple.

1. Create .travis.yml in submodule:

- master
- linux
sudo: false
- "/bin/bash ./scripts/"

2. Create wrapper script around curl request (./scripts/


curl -s -X POST -H "Content-Type: application/json" \
-H "Accept: application/json" -H "Travis-API-Version: 3" \
-H "Authorization: token ${TRAVIS_TOKEN}" \
-d '{"request":{"branch":"master"}}' \

Note: %2F is /

3. Add TRAVIS_TOKEN to environment variables of Travis CI.
More information can be found at this page: Triggering builds through the API

4. If you are using git submodules then during build stage you need to add following command to script section of main project:
git submodule foreach git pull origin master

That’s it. Simple workaround. I hope I didn’t miss anything important. 😉

Elance Пользовательское соглашение

Бобрый день.

Я наверно не единственный человек который искал перевод Elance User Agreement.

Запрашивает его Банк в случае если открываешь ИП и хочешь честно платить налоги.
Перевод любительский но мой банк принял без проблем. Без лишних слов представляю.

Пользовательское соглашение-140916
Пользовательское соглашение-150217

Версия указывает на актуальность перевода. Более старая для истории. Я не поленился и перевел измениния которые вступают в силу с 17 февраля 2015г.

С уважением,

Выражаю огромную благодарность Соколовой Марине за помощь в переводе. 🙂

fpm pecl / pear to deb or rpm

Sometimes it happens. You need to convert pecl / pear package to deb or rpm.

This is What you need: fpm. This tool will solve your problem.

But if you try to do something like that:

# fpm -s pear -t deb mypearpackage

It will obviously fail. And actually it’s not a feature of fpm but rather very old bug of pear: pear bug #18666
If you read entire bug you will find workaround/patch. I will save your time and give a link on it: diff

Once you patch those two files: PEAR/Builder.php and PEAR/Command/Install.php fpm will actually works.

But you would face another issue. Since pear doesn’t know anything about php.ini it will suggest to manually add extension to php.ini.
You can simplify your life by splitting fpm into two subcommands.
First one will convert pear package to directory:

# fpm -s pear -t dir mypearpackage

And after you will manually add conf.d file (note: php –ini) to mypearpackage.dir/ you can pack it to rpm or deb as usual:

# fpm -s dir -C mypearpackage.dir/ -t deb -n mypearpackage ./

note: pecl is actually wrapper around pear. So pecl packages also can be converted by fpm using ether “–pear-channel” argument or by specifying channel in package name like that:

# fpm -s pear -t dir

I hope I didn’t miss anything important. 😉

CentOS SSH disable SCP and SFTP for some users

Sometimes one need to create a special SSH accounts that do only one thing: starts a program or a shell script. In that case one might need to prevent possibility to download or upload files to server. Due to my research it was not so trivial task as it might be looking.

Lets start with a description of how SCP and SFTP works.

SFTP works as subprocess of shell. So basically when user logs in via sftp client shell starts subprocess which in case of CentOS is /usr/libexec/openssh/sftp-server(One can find that info in /etc/ssh/sshd_config).

Meanwhile SCP talks directly with a shell. So it actually needs /bin/bash set as user shell.

Commonly described solution such as:

Match Group nosft
Subsystem   sftp  /bin/false

actually doesn’t work on CentOS(At least version 6). Maybe because SSHD is too old or something like that. If one tries to restart SSHD with above code in the config file he will get following error:

# service sshd restart
Stopping sshd:                                             [  OK  ]
Starting sshd: /etc/ssh/sshd_config line 141: Directive 'Subsystem' is not allowed within a Match block

I’ve found small trick how to solve this problem.

First thing is to disable SFTP. Since it’s using another process withing shell let’s find it and deny it. For that I’m going to use small shell script that is wrapper around /bin/bash. So one needs to set following script as login shell of user account:


# disable sftp
if [ "$2" == "/usr/libexec/openssh/sftp-server" ]; then
    exit 1


What it does? It’s actually looking for second argument of the starting command and if it matches sftp-server it exits with status code 1. And when user tries to initiate SFTP session it immediately drops a session.

But in case of SCP client will think a little longer but it will login and allow download and upload files. What to do? Since SCP talks directly to the shell we need to get rid of shell. Replace last scring (/bin/bash) in above script with a program that you want user to interact (example: telnet to another device) and SCP will fail to connect due to timeout since it cannot talk directly to shell.

I hope I didn’t miss anything important. 😉

Mikrotik DHCP to DNS hostnames

When I previously worked with DNSMASQ such thing was handled automatically. DHCP client sends his hostname and DHCP server then server add’s this hostname to DNS allowing clients to access host by hostname. There were some issues with static names but this is different story. In common it worked good. It was a surprise for me that Mikrotik doesn’t support such feature out of box.

After some time of reading wiki and googling I’ve came with my own solution.

My script is using ttl and domain name to distinguish between static and dynamic clients.

:local zone "localdomain"
:local timetolive "00:05:00"
:local hostname
:local ip
:local dnsip
:local dhcpip
:local dnsnode
:local dhcpnode

/ip dns static;
:foreach i in=[find where name ~ (".*\\.".$zone) and ttl ~ $timetolive] do={
  :set hostname [ get $i name ];
  :set hostname [ :pick $hostname 0 ( [ :len $hostname ] - ( [ :len $zone ] + 1 ) ) ];
  /ip dhcp-server lease;
  :set dhcpnode [ find where host-name=$hostname ];
  :if ( [ :len $dhcpnode ] > 0) do={
    :log debug ("Lease for ".$hostname." still exists. Not deleting.");
  } else={
    :log info ("Lease expired for ".$hostname.", deleting DNS entry.");
    /ip dns static remove $i;

/ip dhcp-server lease;
:foreach i in=[find] do={
  :set hostname ""
  :local mac
  :set dhcpip [ get $i address ];
  :set mac [ get $i mac-address ];
  :if ( [ :len $hostname ] = 0) do={
    :set hostname [ get $i host-name ];
  :if ( [ :len $hostname ] > 0) do={
    :set hostname ( $hostname . "." . $zone );
    /ip dns static;
    :set dnsnode [ find where name=$hostname ];
    :if ( [ :len $dnsnode ] > 0 ) do={
# it exists. Is its IP the same
      :set dnsip [ get $dnsnode address ];
      :if ( $dnsip = $dhcpip ) do={
        :log debug ("DNS entry for " . $hostname . " does not need updating.");
      } else={
        :log info ("Replacing DNS entry for " . $hostname);
        /ip dns static remove $dnsnode;
        /ip dns static add name=$hostname address=$dhcpip ttl=$timetolive;
    } else={
# it doesnt exist. Add it
      :log info ("Adding new DNS entry for " . $hostname);
      /ip dns static add name=$hostname address=$dhcpip ttl=$timetolive;

One needs to put this script to Mikrotik router and schedule execution each 5 minutes.

/system scheduler
add interval=5m name=dhcp-dns-run on-event=dhcp-dns start-time=00:00:00

Another thing that needs to be mentioned it that DHCP server on your Mikrotik needs to provide clients with domain name. Something like this:

/ip dhcp-server network
add address= comment="default configuration" dns-server= domain=localdomain gateway= netmask=24

I hope I didn’t miss anything important. 😉

Thoughts that don't belong to wiki…