Firefox Bookmark Syncing
Posted on Thu 26 April 2018 in linux
As you may already have heard, the bookmark syncing service Xmarks is shutting down on 1st of May 2018. This is really a pity since the service supported multiple operating system platforms as well as different browsers via corresponding extensions, plus there was not any costs involved.
After checking different (fee-based) alternatives, I examined again the built-in syncing services that are included in today's browsers: However, since I do not want to store my private data at Google -- for reasons --, I checked the syncing service that is provided by the new Firefox Quantum. Although, Mozilla seems to be slightly less evil than Google, I still had a bad feeling about storing my bookmarks at their server, so I did some further research. After a while, I stumbled over the SyncServer, which is basically the backend of the syncing service used in Firefox. I decided to setup a custom syncing backend that can be used with Firefox. The bad news about this approach is that there is no Debian package available and Mozilla's documentation leaves room for improvement, so expect a path of trial and tribulation ;-)
Before discussing the installation of the private bookmark syncing service, a short warning: though, the syncing server itself can be installed on your private server, the general user authentication, that is required to use the syncing service, is another matter. In fact there seems to be ways to install also a custom authentication server, but this is even less documented, so I will skip this part and simply rely on Mozilla's service for authentication, which is some sort of compromise, but okay with me.
Installation of Mozilla's SyncServer
There are a couple of steps necessary to install the syncing service: First, some packages from the Debian repositories must be installed to be able to obtain the server's source code and to build it.
apt-get install python-dev git-core python-virtualenv g++
Then, the source code can be cloned from the corresponding github repository to
the /opt
directory and be built:
cd /opt
git clone https://github.com/mozilla-services/syncserver
cd syncserver
make build
A separate system user is created that should own the service in the following:
useradd -s /usr/sbin/nologin -r -M syncserver
chown syncserver:www-data -R /opt/syncserver
chmod 750 -R /opt/syncserver
To check the successful installation of the syncing server do:
make test
Configuration
The main idea of the configuration is to run the syncing server via the provided gunicorn server and prefix it with an nginx server to obtain a better stability and performance. In the end, the nginx server will provide the syncing service on port 8080, using https to secure the connection.
The main configuration of the syncing server is done via the
/opt/syncserver/syncserver.ini
file. Adapt the configuration, for example,
as follows:
[server:main]
use = egg:gunicorn
host = 127.0.0.1
port = 8081
workers = 2
timeout = 60
Also set the public_url
to https://sync.example.com:8080/
and
sqluri
to sqlite:////opt/syncserver/syncserver.db
. It is also
recommended to set a unique secret
to secure the server. At least on first
start, also the allow_new_users
variable must be set to true
,
otherwise it will not be possible to setup a new account on the server.
For a short test of the new configuration, the server can be simply launched as follows:
make serve
Systemd
Since the syncing server should run automatically a systemd
service is configured.
Create the /etc/systemd/system/syncserver.service
file with the following
content:
[Unit]
Description=syncserver daemon
Requires=gunicorn.socket
After=network.target
[Service]
PIDFile=/run/gunicorn/pid
User=syncserver
Group=www-data
RuntimeDirectory=gunicorn
WorkingDirectory=/opt/syncserver
ExecStart=/opt/syncserver/local/bin/gunicorn --pid /run/gunicorn/pid \
--bind unix:/run/gunicorn/socket --paste syncserver.ini
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
The service will run using the previously created user.
Additionally, prepare the corresponding socket file
/etc/systemd/system/gunicorn.socket
:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn/socket
[Install]
WantedBy=sockets.target
Besides, an allowance for the creation of the corresponding run directory must
be created in /etc/tmpfiles.d/gunicorn.conf
, containing:
d /run/gunicorn 0755 syncserver www-data -
Ensure that gunicorn
subdirectory is existing:
mkdir /run/gunicorn
chown syncserver:www-data -R /run/gunicorn
chmod 750 -R /run/gunicorn
Finally, the new systemd gunicorn socket can be enabled and started:
systemctl enable gunicorn.socket
systemctl start gunicorn.socket
Gunicorn itself should automatically start after requesting the socket:
curl --unix-socket /run/gunicorn/socket http
Nginx
To delegate the gunicorn-based syncing server to the outside world nginx is used, which simply can be installed from the Debian repositories:
apt install nginx
Then, create a nginx configuration file
/etc/nginx/sites-available/syncserver
with the following content:
server {
listen 8080 ssl;
server_name sync.example.com;
# use letsencrypt to get ssl certificates
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_read_timeout 120;
proxy_connect_timeout 10;
proxy_pass http://unix:/run/gunicorn/socket;
}
}
The nginx configuration passes the gunicorn socket to the external port 8080. The configuration uses a free Let's Encrypt SSL certificate to protect the communication via https.
Link the created syncing server nginx page to the corresponding directory to enable the site (and disable the default page, if desired).
ln -s /etc/nginx/sites-available/syncserver /etc/nginx/sites-enabled/syncserver
# rm /etc/nginx/sites-enabled/default
Enable and start the nginx server:
systemctl enable nginx
systemctl start nginx
The syncing server should now be running and can be tested by simply accessing the corresponding webpage:
curl https://sync.example.com:8080/token/1.0/sync/1.5
Configure Firefox
Finally, the Firefox configuration can be adapted to use the private syncing
server. To this end, open the configuration page via about:config
and
search for tokenserver
. Change the value of
identity.sync.tokenserver.uri
to
https://sync.example.com:8080/token/1.0/sync/1.5
. That's basically it!
Now, you can click the upper right main menu and select Sign in to Sync. As stated above, in the current configuration you need to have a Mozilla account for authentication i.e. if you do not have such account yet, create it now on Firefox Account. After the confirmation of the account you can log in using the chosen credentials and start the syncing process. Et voilĂ -- your bookmarks should be synced to your private syncing server.
Debugging
When the the syncing is not working as expected, you can access the Firefox logs
via about:sync-log
. Happy debugging ;-)
Some Last Words
Do not forget to set allow_new_users
to false
, if you do not want to
store other people's bookmarks. Additionally, do not forget to adapt your
firewall to allow access to the used port.