Check for new Dropbox folders on Linux

For a customer, I created a service on a remote server that processes files delivered via Dropbox. Problem is Dropbox on Linux will sync all the folders in its root folder, unless it’s excluded. You can exclude all folders except the one you’re interested in, but as soon as you add a folder to your Dropbox, it will appear on your Linux server.

This script will warn you if a new folder appears. It doesn’t exclude automatically new folders, but this feature could be added if you’re brave enough.

#!/usr/bin/perl
# When using Dropbox on Linux, the complete dropbox folder is 
# sync'ed by default, which can use precious disk space if 
# we only need some folders.
# Because we cant choose which folders will be sync'ed on
# Linux, we can only exclude folders we don't want. So this script
# reports when a new folder is added to the Dropbox top folder.
# A nice feature would be to be able to only allow some folders.
# Note: since we can't exclude files, they are not reported.
# Dont add a large file to the root of Dropbox, you can't exclude it from syncing.

# if this script finds folders not in the allowed list, it sends
# an email and a notification, in case the mail is flagged as spam.

# I choose not to exclude new folders directly in this script,
# in case something breaks. This script is run on a server used by
# a customer as a WebService endpoint, so better be safe.

# To exclude a folder from syncing, use the dropbox-cli script available at
# https://www.dropbox.com/download?dl=packages/dropbox.py
# then do
# ./dropbox.py exclude add "Folder to exclude"
#
# Coriolis Stephan Burlot, Apr 11, 2018

use strict;
use Data::Dumper;
use MIME::Lite;
use WebService::Prowl;

## the path to the Dropbox folder
my $dropbox_folder = '/home/stephan/Dropbox/';

## email settings
my $email_address = 'EMAIL_ADDRESS';

## I use Prowl (prowlapp.com) to send notifications to my phone.
## prowl settings
my $prowl_api_key = 'PROWL_API_KEY';

## Allowed folders
# famous last words:
# customer: "the folder is named TEST_Service, we'll change the
# name when we go in production."
my @allowed_folders = qw/TEST_Service/;

#################################
## sends a email with the message passed as parameter
sub send_email($) {
  my $content = shift @_;
  
  my $msg = MIME::Lite->new(
    From  => $email_address,
    To    => $email_address,
    Subject => 'Dropbox Bot',
    Data  => $content
  );
  $msg->send;
}

#################################
## sends a notification via Prowl
sub send_notification($$$) {
  my ($app, $event, $message) = @_;
  if ($event eq "") {
    $event = ' ';
  }
  
  # grab your API key from prowlapp.com
  my $ws = WebService::Prowl->new(apikey => $prowl_api_key);
  $ws->verify || die $ws->error();
  $ws->add(application => "$app",
       event     => "$event",
       description => "$message",
       url     => "");

}

#################################
## MAIN
#################################

# I dont use smartmatch, ie
# if ($file ~~ @allowed_folders)
# so I create a hash for simple matching.
my %allowed = map { $_ => 1 } @allowed_folders;

chdir $dropbox_folder;
if (opendir(my $dh, $dropbox_folder)) {
  my @folders = grep !/^\./, readdir($dh);
  closedir $dh;
  
  # array of bad folders
  my @bad = map { -f $_ || exists $allowed{$_} ? (): $_ } @folders;
  if (scalar(@bad) != 0) {
    print "New folders: " . join(", ", @bad) . "\n";
    send_notification('Linode_Small', 'Dropbox Bot', "There are new folders in Dropbox: you should exclude them.");
    send_email("Hello,\n\nI found these new folders in Dropbox:\n\n" . join("\n", @bad) . "\n\nThey should be excluded.\n");
  }
} else {
  send_notification('Linode_SMALL', 'Dropbox Bot', "I cant open Dropbox folder. Is it still there?");
  send_email("Hello,\n\nI can't opendir $dropbox_folder\n\nIs Dropbox still here?");
  die "Can't opendir $dropbox_folder: $!\n";
}

Enjoy.

Configuring Nginx for HTTPS access

If you manage nginx servers and get the error: SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET in Firefox or ERR_SSL_PROTOCOL_ERROR in Chrome when connecting to your website:

Error when connecting via Firefox
Error when connecting via Firefox

 

Error when connecting via Chrome
Error when connecting via Chrome

Make sure your config has the following:

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

To be sure, add these params to your http{} blocks, in nginx.conf.

I had these settings in all my virtual servers configuration file for https sites and it worked, but as soon as I added 1 certificate, I had this error. Adding the ssl_session settings to nginx.conf solved this.

curl* will report:

curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received.

* Not all versions of curl will report this: on MacOS 10.13.3, curl v7.54.0 doesnt report an error. On Ubuntu 16.04, curl v7.47.0 reports this error.

source

Apache htaccess file for .ipa files

To allow my customers to download my iOS apps signed with AdHoc or Entreprise certificates, I use this htaccess file:

<FilesMatch "\.(ipa|plist)$">
 FileETag None
 <ifModule mod_headers.c>
 Header unset ETag
 Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
 Header set Pragma "no-cache"
 Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
 </ifModule>
</FilesMatch>

AddType application/octet-stream .ipa
<Files *.ipa>
 Header set Content-Disposition attachment
</Files>

The “Caches” directives are not mandatory, but large customers are usually behind a reverse proxy and I want to avoid side effects, if possible.

So far, so good.

Nouvelles Prestations

Au cours de mes projets, je créé et j’administre des serveurs web pour fournir des contenus aux applications mobiles iOS (iPhone, iPad). Parallèlement à mon activité de développeur freelance, je gère également les serveurs d’une cinquantaine de site de PME et d’indépendants pour une société de web design partenaire.

J’ai décidé d’officialiser cette activité d’administrateur de sites et j’ai créé la structure Service Web qui permet aux clients qui produisent du contenu avec une grande facilité – sur WordPress notamment – mais qui sont complètement perdus avec les notions de DNS, de boîtes IMAP, de mise à jour ou de backup, de se concentrer sur leur activité sans avoir à se préoccuper des détails techniques. Ces services ne sont jamais inclus dans les offres d’hébergement, car ils requièrent un minimum d’implication dans la structure d’un site web.

Ma solide expérience d’administrateur web me permet aujourd’hui de créer cette nouvelle structure qui propose de fournir ces prestations professionnelles en terme d’hébergement et de maintenance sous la forme d’offres « clés en mains » accessibles à tous: Service Web

Using WordPress Jetpack with Nginx and Varnish

I need to manage a few WordPress sites and I wanted to add the Jetpack plugin so I can manage all sites from a WordPress.com account. After having installed the Jetpack plugin, trying to manage my site from WordPress.com fails with this error:
Screen Shot 2015-07-03 at 23.25.44

Watching the Varnish log, I tried the same call made by WordPress.com with curl. The endpoint /xmlrpc.php is called via POST, and curl gave me another hint:

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
 <fault>
 <value>
 <struct>
 <member>
 <name>faultCode</name>
 <value><int>-32700</int></value>
 </member>
 <member>
 <name>faultString</name>
 <value><string>parse error. not well formed</string></value>
 </member>
 </struct>
 </value>
 </fault>
</methodResponse>

The error -32700 is not really useful, but a search on DuckDuckGo gave me the solution:

Add this line to the beginning of the wp_config.php file of your site:

$_SERVER['SERVER_PORT'] = 80;

And voila, it works.

Almost everybody seems to agree on Varnish being the problem, but the solutions given did not work for me. Just in case, the solutions mentioned were to tell Varnish to ignore the calls to /xmlrpc.php.