{ config, lib, pkgs, ... }: with lib; let cfg = config.services.firefox.syncserver; syncServerIni = pkgs.writeText "syncserver.ini" '' [DEFAULT] overrides = ${cfg.privateConfig} [server:main] use = egg:Paste#http host = ${cfg.listen.address} port = ${toString cfg.listen.port} [app:main] use = egg:syncserver [syncserver] public_url = ${cfg.publicUrl} ${optionalString (cfg.sqlUri != "") "sqluri = ${cfg.sqlUri}"} allow_new_users = ${if cfg.allowNewUsers then "true" else "false"} [browserid] backend = tokenserver.verifiers.LocalVerifier audiences = ${removeSuffix "/" cfg.publicUrl} ''; in { options = { services.firefox.syncserver = { enable = mkOption { type = types.bool; default = false; example = true; description = '' Whether to enable a Firefox Sync Server, this give the opportunity to Firefox users to store all synchronized data on their own server. To use this server, Firefox users should visit the , and replicate the following change services.sync.tokenServerURI: http://localhost:5000/token/1.0/sync/1.5 where corresponds to the public url of the server. ''; }; listen.address = mkOption { type = types.str; default = "127.0.0.1"; example = "0.0.0.0"; description = '' Address on which the sync server listen to. ''; }; listen.port = mkOption { type = types.int; default = 5000; description = '' Port on which the sync server listen to. ''; }; publicUrl = mkOption { type = types.str; default = "http://localhost:5000/"; example = "http://sync.example.com/"; description = '' Public URL with which firefox users can use to access the sync server. ''; }; allowNewUsers = mkOption { type = types.bool; default = true; example = false; description = '' Whether to allow new-user signups on the server. Only request by existing accounts will be honored. ''; }; sqlUri = mkOption { type = types.str; default = "sqlite:////var/db/firefox-sync-server.db"; example = "postgresql://scott:tiger@localhost/test"; description = '' The location of the database. This URL is composed of , where is a database name such as , , , etc., and the name of a DBAPI, such as , , , etc. The SQLAlchemy documentation provides more examples and describe the syntax of the expected URL. ''; }; privateConfig = mkOption { type = types.str; default = "/etc/firefox/syncserver-secret.ini"; description = '' The private config file is used to extend the generated config with confidential information, such as the setting if it contains a password, and the setting is used by the server to generate cryptographically-signed authentication tokens. If this file does not exists, then it is created with a generated settings. ''; }; }; }; config = mkIf cfg.enable { systemd.services.syncserver = { after = [ "network.target" ]; description = "Firefox Sync Server"; wantedBy = [ "multi-user.target" ]; path = [ pkgs.pythonPackages.pasteScript pkgs.coreutils ]; environment.PYTHONPATH = "${pkgs.pythonPackages.syncserver}/lib/${pkgs.pythonPackages.python.libPrefix}/site-packages"; preStart = '' if ! test -e ${cfg.privateConfig}; then umask u=rwx,g=x,o=x mkdir -p $(dirname ${cfg.privateConfig}) echo > ${cfg.privateConfig} '[syncserver]' echo >> ${cfg.privateConfig} "secret = $(head -c 20 /dev/urandom | sha1sum | tr -d ' -')" fi ''; serviceConfig.ExecStart = "${pkgs.pythonPackages.pasteScript}/bin/paster serve ${syncServerIni}"; }; }; }