by

How To Install Firefox Sync Server 1.5 on Ubuntu.

With Firefox 29, Mozilla introduced a new version of their sync protocol. While new things are (usually) nice, Firefox 29 and later versions of the browser is not compatible with the old versions of the sync protocol. The renders the Sync Server you installed following the guide I wrote useless. It’s time to install the new version of the Firefox Sync Server on your Ubuntu box.

This guide is based on Mozilla’s own installation and configuration instructions, with a few tweaks. My version of the guide will focus on installing the Sync Server behind Apache 2.2, simply because that’s my setup. If you need to know how to use Apache 2.4 or Nginx, please refer to Mozilla’s instructions.

A major change from the old version of the sync protocol is that the new one requires that you use Firefox Accounts for user authentication. With last year’s NSA and PRISM scandal in mind, this is a bad thing, because the authentication for your sync server now goes through a third party. The good news is that you can also run your own installation of a Firefox Accounts server, but this is not covered by this guide. I might eventually get around to write a guide for that as well, but if you’re in a hurry to run your own Firefox Accounts server and can’t wait for that to happen, you can follow Mozilla’s own installation and configuration instructions for the Firefox Accounts Server.

With all that in mind, let’s get started.

Building, configuring and running

The first thing you do is to install a few prerequisites. There’s a chance you might already have one or more of these installed, but the following command will make sure you have everything you need.

$ sudo apt-get install python-dev git-core python-virtualenv

Next, we pull the latest version of the sync server source code from Mozilla’s git repository on github and build it.

$ cd /opt
$ sudo git clone https://github.com/mozilla-services/syncserver
$ cd syncserver
$ sudo make build

The “make” command will download a few dependencies and build the server. This might all take a while, depending on the speed of your internet connection and how powerful your CPU is. When the build is complete, we can move on to configuring the sync server, which we’ll do by making changes to the syncserver.ini file. Open the file in your preferred text editor and make the following changes:

The public_url parameter is the client-visible URL for the service. So if your server is installed at a server using the IP address 192.168.1.222, you have to set the following value:

[syncserver]
public_url = http://192.168.1.222:5000/

By default the server will use an in-memory database for storage, meaning that any sync data will be lost on server restart. You will almost certainly want to configure a more permanent database, which can be done with the “sqluri” setting. The sync server can also use a MySQL database, but configuring setting up everything to get that to work is not covered by this guide.

[syncserver]
sqluri = sqlite:////opt/syncserver/syncserver.db

The server uses a “secret” to generate cryptographically-signed authentication tokens. Save the configuration file and exit your text editor and run the following command to generate a unique secret:

$ head -c 20 /dev/urandom | sha1sum

The result should be a long string of alphanumeric characters. Copy-paste the string into the secret parameter in the syncserver.ini file (your value will be different from the one in the example below):

[syncserver]
secret = db8a203aed5fe3e4594d4b75990acb76242efd35

We can now finally start the server. Exit the text editor and run the following command:

$ sudo local/bin/pserve syncserver.ini

The server is now running and will run until you tell it to stop by pressing CTRL+C.

Configuring Firefox

At the time of writing (Firefox 30), there’s no convenient way to configure Firefox to use a private sync server. You have to open a new window or tab in the browser and enter about:config in the address bar. Search for the services.sync.tokenServerURI in the available settings and change the value to the address of your server with a path of “token/1.0/sync/1.5”.

For instance, with the settings we used above for the server, the complete value will be “http://192.168.1.222:5000/token/1.0/sync/1.5”.

Hopefully, Mozilla will change the way a custom sync server is configured in future versions of Firefox. Next, go to Settings -> “Sign in to Sync”. When signed in, Firefox should finally sync everything with your own sync server. As soon as Firefox starts syncing, you should see log messages appear in your console window. If nothing happens, you can enter about:sync-log in a browser or tab window’s address bar to check if there’s anything in Firefox’ client side sync logs.

If you want to sync Firefox on your Android phone with your personal sync server, you’re almost all out of luck. Right now, there’s no way to configure the Android version of Firefox to use another sync server than Mozilla’s own unless you compile the browser from source. Further details and updates may be found in Bug 1003877.

Running behind Apache 2.2

So now you have the Firefox Sync Server 1.5 up and running and Firefox is synchronizing with it successfully. But there are a few issues with the current configuration we need to address:

  • The communication channel is not encrypted, making it easy for a man in the middle to eavesdrop on you.
  • The server does not start automatically when you boot Ubuntu.
  • As it is started now, the server will stop when you log out.

All of these issue can be solved by running the sync server behind a web server and Mozilla has provided the necessary building block for us to do so. I’m assuming that you have Apache 2.2, mod_wsgi and mod_ssl installed and properly configured already. If you don’t and have no idea how to do that, there are plenty of other guides on the internet that can help you. Another assumption I make is that your sync server will be available on a valid domain, for instance example.com.

First, we need to create a file called syncserver in the directory /etc/apache2/sites-available. Then copy-paste the following into the file. Replace “example.com” with the hostname you will be using.

<Directory /opt/syncserver>
  Order deny,allow
  Allow from all
</Directory>
 
<VirtualHost *:443>
  ServerName example.com
  DocumentRoot /opt/syncserver
 
  SSLEngine on
  SSLCertificateFile /etc/apache2/example.com.crt
  SSLCertificateKeyFile /etc/apache2/exampe.com.key
 
  WSGIProcessGroup sync
  WSGIDaemonProcess sync user=ffsync group=ffsync processes=2 threads=25 python-path=/opt/syncserver/local/lib/python2.7/site-packages/
  WSGIPassAuthorization On
  WSGIScriptAlias / /opt/syncserver/syncserver.wsgi
  CustomLog /var/log/apache2/example.com-access.log combined
  ErrorLog  /var/log/apache2/example.com-error.log
</VirtualHost>

Next, we’ll create the necessary certificate files. Once again, replace “example.com” with whatever domain name you will be using. You can use the default values on all the prompts openssl gives you.

$ sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/apache2/example.com.key -out /etc/apache2/example.com.crt

Then we have to change the value of the public_url parameter in the syncserver.ini file so it matches the new sync server address and protocol, which is HTTPS now, not HTTP.

[syncserver]
public_url = https://example.com/

Next, we create a local user to run the sync server and make sure the user has the rights to access the correct files.

$ sudo useradd -d /opt/syncserver/ -l -r -U ffsync
$ sudo chown -R ffsync:ffsync /opt/syncserver/

The final step on the server is to activate the new Apache configuration and restart everything to make sure Apache is able to actually start the sync server.

$ sudo a2ensite syncserver
$ sudo service apache2 restart

Configuring Firefox (again)

On the client side we now need to configure Firefox to accept our self signed certificate. This should have been as easy as to add a security exception, but I can’t for the life of me get it to work. I did find a workaround, however.

In Firefox, go to Options -> Advanced -> Certificates -> View Certificates. In the new windows, select the Servers tab, then click Add Exceptions. Enter the URL of your sync server and click Get Certificate. Make sure that the “Permanently store exception” checkbox is checked and click Confirm Exception. Next, click the Authorities tab, select your certificate in the list and click Edit trust. In the window that opens, check “This certificate can identify websites”, click OK and you’re all done.

Next, we have to disconnect from the previous sync server URL. Go to Options -> select the Sync tab and click Disconnect and then Continue. Then, we have to update the value of the services.sync.tokenServerURI parameter in about:config that we set earlier so that the new address is being used. In this example, the complete value will be “https://example.com/token/1.0/sync/1.5”.

Now open a new browser tab and go to https://example.com/token/1.0/sync/1.5. If you get a sec_error_ca_cert_invalid error you have to edit yet another value in about:config. Find security.use_mozillapkix_verification and set the value to false. If you don’t get an error, there is no need to change this value. This is at least an issue in Firefox 31, where the certificate verification changed, but might change again in later versions of Firefox.

The last step on the client side is to reconnect to the sync server. Just do it in the same way as you did earlier.

So there you have it. Your own Firefox Sync Server 1.5 running behind Apache over an SSL connection. Setting everything up is a major pain in the ass, wasn’t it? Firefox doesn’t exactly make it easy. I hope Mozilla starts to take privacy even more seriously in the future and make the process more stream lined.

Write a Comment

Comment

15 Comments

  1. Great tutorial, thank you for all the work!
    One question: with what value do I have to replace the example.com in the apache config?
    The true hostname of the system? One of the domains connected to the IP of the server?
    Thanks in advance!

    • In my case I’ve just used a subdomain, for instead ffsync.example.com. Make sure you use this in every configuration file where example.com is used in this guide and you should be good to go.

      It’s possible you can use an IP address as well, but I’m not sure how that is configured in the Apache configuration.

  2. Hi and thank you for your nice tutorial.
    I’m having problems with this configuration (Firefox Sync Server behind an Apache 2.4 through HTTPS).
    So the Access itself works, but the client browsers always return to the “Connect to Sync again”. The Apache2-Error-Log tells the following:
    [:error] [pid 11272] INFO:requests.packages.urllib3.connectionpool:Resetting dropped connection: verifier.accounts.firefox.com
    [:error] [pid 11272] INFO:mozsvc.metrics:{“tokenserver.backend.get_user”: 0.0008149147033691406, “code”: 401, “request_time”: 1.2031610012054443, “remoteAddressChain”: [“x.x.x.x”], “agent”: “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0”, “tokenserver.assertion.verify”: 1.201512098312378, “token.assertion.verify_success”: 1, “path”: “https://my.domain.name/token/1.0/sync/1.5”, “method”: “GET”}

    If you have an idea for me, would be nice :)
    Thanks and Regards,
    D0C

  3. Hello,

    I’m using LinuxMint 17.1 and while I do the “make build” command, I’m getting errors. I have no clue where to start looking, because I am pretty much a Linux beginner.

    Here’s is my terminal output:

    phebert@NAS-Linux /opt/syncserver $ sudo make build
    virtualenv –python=`which python2 python | head -n 1` –no-site-packages ./local
    Running virtualenv with interpreter /usr/bin/python2
    New python executable in ./local/bin/python2
    Also creating executable in ./local/bin/python
    Installing setuptools, pip…done.
    CFLAGS=”-Wno-error -Wno-error=format-security” ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future ./local/bin/pip install -r requirements.txt
    Downloading/unpacking https://github.com/mozilla-services/mozservices/archive/e00e1b68130423ad98d0f6185655bde650443da8.zip (from -r requirements.txt (line 9))
    Downloading e00e1b68130423ad98d0f6185655bde650443da8.zip (unknown size): 53kB downloaded
    Running setup.py (path:/tmp/pip-MO1l9z-build/setup.py) egg_info for package from https://github.com/mozilla-services/mozservices/archive/e00e1b68130423ad98d0f6185655bde650443da8.zip

    Downloading/unpacking https://github.com/mozilla-services/tokenserver/archive/d7e513e8a4f5c588b70d685a8df1d2e508c341c0.zip (from -r requirements.txt (line 10))
    Downloading d7e513e8a4f5c588b70d685a8df1d2e508c341c0.zip (unknown size): 322kB downloaded
    Running setup.py (path:/tmp/pip-5tGKaK-build/setup.py) egg_info for package from https://github.com/mozilla-services/tokenserver/archive/d7e513e8a4f5c588b70d685a8df1d2e508c341c0.zip

    warning: no files found matching ‘*.spec’
    warning: no files found matching ‘*.json’ under directory ‘tokenserver’
    Downloading/unpacking http://github.com/mozilla-services/server-syncstorage/archive/1.5.5.zip (from -r requirements.txt (line 11))
    Downloading 1.5.5.zip (unknown size): 110kB downloaded
    Running setup.py (path:/tmp/pip-AhM1kf-build/setup.py) egg_info for package from http://github.com/mozilla-services/server-syncstorage/archive/1.5.5.zip

    Downloading/unpacking cornice==0.16.2 (from -r requirements.txt (line 1))
    Downloading cornice-0.16.2.tar.gz (45kB): 45kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/cornice/setup.py) egg_info for package cornice
    /usr/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: ‘paster_plugins’
    warnings.warn(msg)

    Downloading/unpacking gunicorn==19.1.1 (from -r requirements.txt (line 2))
    Downloading gunicorn-19.1.1-py2.py3-none-any.whl (104kB): 104kB downloaded
    Downloading/unpacking pyramid==1.5 (from -r requirements.txt (line 3))
    Downloading pyramid-1.5.tar.gz (2.4MB): 2.4MB downloaded
    Running setup.py (path:/opt/syncserver/local/build/pyramid/setup.py) egg_info for package pyramid

    Downloading/unpacking requests==2.2.1 (from -r requirements.txt (line 4))
    Downloading requests-2.2.1-py2.py3-none-any.whl (625kB): 625kB downloaded
    Downloading/unpacking simplejson==3.4 (from -r requirements.txt (line 5))
    Downloading simplejson-3.4.0.tar.gz (68kB): 68kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/simplejson/setup.py) egg_info for package simplejson

    Downloading/unpacking SQLAlchemy==0.9.4 (from -r requirements.txt (line 6))
    Downloading SQLAlchemy-0.9.4.tar.gz (4.5MB): 4.5MB downloaded
    Running setup.py (path:/opt/syncserver/local/build/SQLAlchemy/setup.py) egg_info for package SQLAlchemy

    warning: no files found matching ‘*.jpg’ under directory ‘doc’
    warning: no files found matching ‘distribute_setup.py’
    warning: no files found matching ‘sa2to3.py’
    warning: no files found matching ‘ez_setup.py’
    no previously-included directories found matching ‘doc/build/output’
    Downloading/unpacking unittest2==0.5.1 (from -r requirements.txt (line 7))
    Downloading unittest2-0.5.1.tar.gz (62kB): 62kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/unittest2/setup.py) egg_info for package unittest2

    Downloading/unpacking zope.component==4.2.1 (from -r requirements.txt (line 8))
    Downloading zope.component-4.2.1.tar.gz (462kB): 462kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/zope.component/setup.py) egg_info for package zope.component

    warning: no previously-included files matching ‘*.dll’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyc’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyo’ found anywhere in distribution
    warning: no previously-included files matching ‘*.so’ found anywhere in distribution
    Downloading/unpacking configparser==3.3.0r2 (from -r requirements.txt (line 14))
    Downloading configparser-3.3.0r2.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/configparser/setup.py) egg_info for package configparser

    Downloading/unpacking konfig (from mozsvc==0.8->-r requirements.txt (line 9))
    Downloading konfig-0.9.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/konfig/setup.py) egg_info for package konfig

    Downloading/unpacking PyBrowserID (from tokenserver==1.2.7->-r requirements.txt (line 10))
    Downloading PyBrowserID-0.9.2.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/PyBrowserID/setup.py) egg_info for package PyBrowserID

    Downloading/unpacking testfixtures (from tokenserver==1.2.7->-r requirements.txt (line 10))
    Downloading testfixtures-4.1.1.tar.gz (81kB): 81kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/testfixtures/setup.py) egg_info for package testfixtures

    Downloading/unpacking pyramid-hawkauth (from SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading pyramid_hawkauth-0.1.0.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/pyramid-hawkauth/setup.py) egg_info for package pyramid-hawkauth

    Downloading/unpacking PyMySQL (from SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading PyMySQL-0.6.3-py2.py3-none-any.whl (63kB): 63kB downloaded
    Downloading/unpacking pymysql-sa (from SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading pymysql_sa-1.0.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/pymysql-sa/setup.py) egg_info for package pymysql-sa

    Downloading/unpacking umemcache (from SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading umemcache-1.6.3.zip
    Running setup.py (path:/opt/syncserver/local/build/umemcache/setup.py) egg_info for package umemcache

    Downloading/unpacking wsgiproxy (from SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading WSGIProxy-0.2.2.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/wsgiproxy/setup.py) egg_info for package wsgiproxy

    Downloading/unpacking webtest (from SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading WebTest-2.0.17.zip (88kB): 88kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/webtest/setup.py) egg_info for package webtest

    no previously-included directories found matching ‘docs/_build’
    warning: no previously-included files matching ‘*.pyc’ found anywhere in distribution
    warning: no previously-included files matching ‘__pycache__’ found anywhere in distribution
    Requirement already satisfied (use –upgrade to upgrade): setuptools in ./local/lib/python2.7/site-packages (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading/unpacking WebOb>=1.3.1 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading WebOb-1.4.tar.gz (633kB): 633kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/WebOb/setup.py) egg_info for package WebOb

    no previously-included directories found matching ‘*.pyc’
    no previously-included directories found matching ‘*.pyo’
    Downloading/unpacking repoze.lru>=0.4 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading repoze.lru-0.6.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/repoze.lru/setup.py) egg_info for package repoze.lru

    Downloading/unpacking zope.interface>=3.8.0 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading zope.interface-4.1.2.tar.gz (919kB): 919kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/zope.interface/setup.py) egg_info for package zope.interface

    warning: no previously-included files matching ‘*.dll’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyc’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyo’ found anywhere in distribution
    warning: no previously-included files matching ‘*.so’ found anywhere in distribution
    Downloading/unpacking zope.deprecation>=3.5.0 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading zope.deprecation-4.1.1.tar.gz (146kB): 146kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/zope.deprecation/setup.py) egg_info for package zope.deprecation

    warning: no previously-included files matching ‘*.dll’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyc’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyo’ found anywhere in distribution
    warning: no previously-included files matching ‘*.so’ found anywhere in distribution
    Downloading/unpacking venusian>=1.0a3 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading venusian-1.0.tar.gz (45kB): 45kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/venusian/setup.py) egg_info for package venusian

    Downloading/unpacking translationstring>=0.4 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading translationstring-1.3-py2.py3-none-any.whl
    Downloading/unpacking PasteDeploy>=1.5.0 (from pyramid==1.5->-r requirements.txt (line 3))
    Downloading PasteDeploy-1.5.2-py2.py3-none-any.whl
    Downloading/unpacking zope.event (from zope.component==4.2.1->-r requirements.txt (line 8))
    Downloading zope.event-4.0.3.tar.gz (390kB): 390kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/zope.event/setup.py) egg_info for package zope.event

    warning: no previously-included files matching ‘*.dll’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyc’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyo’ found anywhere in distribution
    warning: no previously-included files matching ‘*.so’ found anywhere in distribution
    Requirement already satisfied (use –upgrade to upgrade): argparse in /usr/lib/python2.7 (from konfig->mozsvc==0.8->-r requirements.txt (line 9))
    Downloading/unpacking hawkauthlib>=0.1 (from pyramid-hawkauth->SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading hawkauthlib-0.1.1.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/hawkauthlib/setup.py) egg_info for package hawkauthlib

    Downloading/unpacking tokenlib (from pyramid-hawkauth->SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading tokenlib-0.3.1.tar.gz
    Running setup.py (path:/opt/syncserver/local/build/tokenlib/setup.py) egg_info for package tokenlib

    Downloading/unpacking Paste (from wsgiproxy->SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading Paste-1.7.5.1.tar.gz (523kB): 523kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/Paste/setup.py) egg_info for package Paste

    warning: no previously-included files matching ‘*’ found under directory ‘docs/_build/_sources’
    Downloading/unpacking six (from webtest->SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading six-1.9.0-py2.py3-none-any.whl
    Downloading/unpacking waitress>=0.8.5 (from webtest->SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading waitress-0.8.9.tar.gz (121kB): 121kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/waitress/setup.py) egg_info for package waitress

    Downloading/unpacking beautifulsoup4 (from webtest->SyncStorage==1.5.5->-r requirements.txt (line 11))
    Downloading beautifulsoup4-4.3.2.tar.gz (143kB): 143kB downloaded
    Running setup.py (path:/opt/syncserver/local/build/beautifulsoup4/setup.py) egg_info for package beautifulsoup4

    Installing collected packages: cornice, gunicorn, pyramid, requests, simplejson, SQLAlchemy, unittest2, zope.component, configparser, konfig, mozsvc, PyBrowserID, testfixtures, tokenserver, pyramid-hawkauth, PyMySQL, pymysql-sa, umemcache, wsgiproxy, webtest, SyncStorage, WebOb, repoze.lru, zope.interface, zope.deprecation, venusian, translationstring, PasteDeploy, zope.event, hawkauthlib, tokenlib, Paste, six, waitress, beautifulsoup4
    Running setup.py install for cornice
    /usr/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: ‘paster_plugins’
    warnings.warn(msg)

    Compiling /opt/syncserver/local/build/gunicorn/gunicorn/workers/_gaiohttp.py …
    File “/opt/syncserver/local/build/gunicorn/gunicorn/workers/_gaiohttp.py”, line 64
    yield from self.wsgi.close()
    ^
    SyntaxError: invalid syntax

    Running setup.py install for pyramid

    Installing ptweens script to /opt/syncserver/local/bin
    Installing pdistreport script to /opt/syncserver/local/bin
    Installing proutes script to /opt/syncserver/local/bin
    Installing pshell script to /opt/syncserver/local/bin
    Installing prequest script to /opt/syncserver/local/bin
    Installing pviews script to /opt/syncserver/local/bin
    Installing pcreate script to /opt/syncserver/local/bin
    Installing pserve script to /opt/syncserver/local/bin
    Running setup.py install for simplejson
    building ‘simplejson._speedups’ extension
    x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wno-error -Wno-error=format-security -fPIC -I/usr/include/python2.7 -c simplejson/_speedups.c -o build/temp.linux-x86_64-2.7/simplejson/_speedups.o
    x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector –param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-error -Wno-error=format-security build/temp.linux-x86_64-2.7/simplejson/_speedups.o -o build/lib.linux-x86_64-2.7/simplejson/_speedups.so

    Running setup.py install for SQLAlchemy
    building ‘sqlalchemy.cprocessors’ extension
    x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wno-error -Wno-error=format-security -fPIC -I/usr/include/python2.7 -c lib/sqlalchemy/cextension/processors.c -o build/temp.linux-x86_64-2.7/lib/sqlalchemy/cextension/processors.o
    x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector –param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-error -Wno-error=format-security build/temp.linux-x86_64-2.7/lib/sqlalchemy/cextension/processors.o -o build/lib.linux-x86_64-2.7/sqlalchemy/cprocessors.so
    building ‘sqlalchemy.cresultproxy’ extension
    x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wno-error -Wno-error=format-security -fPIC -I/usr/include/python2.7 -c lib/sqlalchemy/cextension/resultproxy.c -o build/temp.linux-x86_64-2.7/lib/sqlalchemy/cextension/resultproxy.o
    x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector –param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-error -Wno-error=format-security build/temp.linux-x86_64-2.7/lib/sqlalchemy/cextension/resultproxy.o -o build/lib.linux-x86_64-2.7/sqlalchemy/cresultproxy.so
    building ‘sqlalchemy.cutils’ extension
    x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wno-error -Wno-error=format-security -fPIC -I/usr/include/python2.7 -c lib/sqlalchemy/cextension/utils.c -o build/temp.linux-x86_64-2.7/lib/sqlalchemy/cextension/utils.o
    x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector –param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wno-error -Wno-error=format-security build/temp.linux-x86_64-2.7/lib/sqlalchemy/cextension/utils.o -o build/lib.linux-x86_64-2.7/sqlalchemy/cutils.so

    warning: no files found matching ‘*.jpg’ under directory ‘doc’
    warning: no files found matching ‘distribute_setup.py’
    warning: no files found matching ‘sa2to3.py’
    warning: no files found matching ‘ez_setup.py’
    no previously-included directories found matching ‘doc/build/output’
    Running setup.py install for unittest2
    changing mode of build/scripts-2.7/unit2.py from 644 to 755
    changing mode of build/scripts-2.7/unit2 from 644 to 755

    changing mode of /opt/syncserver/local/bin/unit2 to 755
    changing mode of /opt/syncserver/local/bin/unit2.py to 755
    Installing unit2 script to /opt/syncserver/local/bin
    Installing unit2-2.7 script to /opt/syncserver/local/bin
    Running setup.py install for zope.component

    warning: no previously-included files matching ‘*.dll’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyc’ found anywhere in distribution
    warning: no previously-included files matching ‘*.pyo’ found anywhere in distribution
    warning: no previously-included files matching ‘*.so’ found anywhere in distribution
    Skipping installation of /opt/syncserver/local/lib/python2.7/site-packages/zope/__init__.py (namespace package)
    Installing /opt/syncserver/local/lib/python2.7/site-packages/zope.component-4.2.1-py2.7-nspkg.pth
    Running setup.py install for configparser
    deleting configparser.egg-info/requires.txt

    Running setup.py install for konfig

    Running setup.py install for mozsvc

    Running setup.py install for PyBrowserID

    Running setup.py install for testfixtures

    Running setup.py install for tokenserver

    warning: no files found matching ‘*.spec’
    warning: no files found matching ‘*.json’ under directory ‘tokenserver’
    Running setup.py install for pyramid-hawkauth

    Running setup.py install for pymysql-sa

    Running setup.py install for umemcache
    building ‘umemcache’ extension
    x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wno-error -Wno-error=format-security -fPIC -DWIN32_LEAN_AND_MEAN -I./lib/ -I/usr/include/python2.7 -c ./python/umemcache.cpp -o build/temp.linux-x86_64-2.7/./python/umemcache.o
    x86_64-linux-gnu-gcc: error trying to exec ‘cc1plus’: execvp: No such file or directory
    error: command ‘x86_64-linux-gnu-gcc’ failed with exit status 1
    Complete output from command /opt/syncserver/local/bin/python2 -c “import setuptools, tokenize;__file__=’/opt/syncserver/local/build/umemcache/setup.py’;exec(compile(getattr(tokenize, ‘open’, open)(__file__).read().replace(‘\r\n’, ‘\n’), __file__, ‘exec’))” install –record /tmp/pip-G7oVND-record/install-record.txt –single-version-externally-managed –compile –install-headers /opt/syncserver/local/include/site/python2.7:
    running install

    running build

    running build_ext

    building ‘umemcache’ extension

    creating build

    creating build/temp.linux-x86_64-2.7

    creating build/temp.linux-x86_64-2.7/python

    creating build/temp.linux-x86_64-2.7/lib

    x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -Wno-error -Wno-error=format-security -fPIC -DWIN32_LEAN_AND_MEAN -I./lib/ -I/usr/include/python2.7 -c ./python/umemcache.cpp -o build/temp.linux-x86_64-2.7/./python/umemcache.o

    x86_64-linux-gnu-gcc: error trying to exec ‘cc1plus’: execvp: No such file or directory

    error: command ‘x86_64-linux-gnu-gcc’ failed with exit status 1

    —————————————-
    Cleaning up…
    Command /opt/syncserver/local/bin/python2 -c “import setuptools, tokenize;__file__=’/opt/syncserver/local/build/umemcache/setup.py’;exec(compile(getattr(tokenize, ‘open’, open)(__file__).read().replace(‘\r\n’, ‘\n’), __file__, ‘exec’))” install –record /tmp/pip-G7oVND-record/install-record.txt –single-version-externally-managed –compile –install-headers /opt/syncserver/local/include/site/python2.7 failed with error code 1 in /opt/syncserver/local/build/umemcache
    Storing debug log for failure in /home/phebert/.pip/pip.log
    make: *** [local/COMPLETE] Error 1

    This is chinese to me, there’s so much errors that I have no clue where to start. I have installed the python-dev git-core python-virtualenv softwares like stated in your article.

    Any help would be very much appreciated.
    Thanks,
    Phil

  4. hello, I followed your guide, but I have some trouble. If I try to access https://mysync-site.com/1.0/sync/1.5 get an error 403 and reading the logs I get this:
    “[Sun April 12 13:18:42 2015] [crit] [client *.*.*.*] (13) Permission denied: /opt/syncserver/.htaccess pcfg_openfile: unable to check htaccess file, Ensure it is readable”
    I can not understand what the problem is, you can help me?

    bye!

    • It sounds like the user running the server does not have access to the .htaccess file. Try to run the following command:

      sudo chmod 744 /opt/syncserver/.htaccess

      Note that this will make the file readable to all users. If the .htaccess file contains anything that should not be readable by all users, you should start the server with a specific user that has access to the file.

      • Thanks for the reply,
        I tried changing permissions but nothing is changed. I tried changing owner of /opt/syncserver from ffsync to www-data and now if I go to my-syncserver.url.ext I get “it work!” but nothingelse.
        I don’t understand why you create new user for ffsync, this user not have permission for apache server.

        p.s. sorry for my bad english!!

        • Apache’s job is simply to provide security by enabling you to connect using HTTPS instead of HTTP. It does not run the Firefox Sync Server, it routes all incoming requests to it. What happens if you connect directly to the Firefox Sync Server and not through Apache?

          • ok, thank you, I understand how it works. I added www-data user to the ffsync group, otherwise apache can not read the contents of / opt / SyncServer. In this way it all works. If www-data is not in the ffsync group get a 403 error.
            If I connecty my browser directly to the Firefox sync server all works fine.
            bye

  5. Hello,

    Thanks for this Howto. When I try to access the syncserver I have an 403 Error. The log say this:

    tail -f syncserver-error.log
    [Thu Feb 23 19:05:34.012629 2017] [authz_core:error] [pid 8539] [client 109.42.3.21:34869] AH01630: client denied by server configuration: /opt/syncserver/syncserver.wsgi