at 17.09-beta 6.0 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.firefox.syncserver; 7 8 defaultDbLocation = "/var/db/firefox-sync-server/firefox-sync-server.db"; 9 defaultSqlUri = "sqlite:///${defaultDbLocation}"; 10 11 syncServerIni = pkgs.writeText "syncserver.ini" '' 12 [DEFAULT] 13 overrides = ${cfg.privateConfig} 14 15 [server:main] 16 use = egg:Paste#http 17 host = ${cfg.listen.address} 18 port = ${toString cfg.listen.port} 19 20 [app:main] 21 use = egg:syncserver 22 23 [syncserver] 24 public_url = ${cfg.publicUrl} 25 ${optionalString (cfg.sqlUri != "") "sqluri = ${cfg.sqlUri}"} 26 allow_new_users = ${boolToString cfg.allowNewUsers} 27 28 [browserid] 29 backend = tokenserver.verifiers.LocalVerifier 30 audiences = ${removeSuffix "/" cfg.publicUrl} 31 ''; 32 33in 34 35{ 36 options = { 37 services.firefox.syncserver = { 38 enable = mkOption { 39 type = types.bool; 40 default = false; 41 description = '' 42 Whether to enable a Firefox Sync Server, this give the opportunity to 43 Firefox users to store all synchronized data on their own server. To use this 44 server, Firefox users should visit the <option>about:config</option>, and 45 replicate the following change 46 47 <screen> 48 services.sync.tokenServerURI: http://localhost:5000/token/1.0/sync/1.5 49 </screen> 50 51 where <option>http://localhost:5000/</option> corresponds to the 52 public url of the server. 53 ''; 54 }; 55 56 listen.address = mkOption { 57 type = types.str; 58 default = "127.0.0.1"; 59 example = "0.0.0.0"; 60 description = '' 61 Address on which the sync server listen to. 62 ''; 63 }; 64 65 listen.port = mkOption { 66 type = types.int; 67 default = 5000; 68 description = '' 69 Port on which the sync server listen to. 70 ''; 71 }; 72 73 user = mkOption { 74 type = types.str; 75 default = "syncserver"; 76 description = "User account under which syncserver runs."; 77 }; 78 79 group = mkOption { 80 type = types.str; 81 default = "syncserver"; 82 description = "Group account under which syncserver runs."; 83 }; 84 85 publicUrl = mkOption { 86 type = types.str; 87 default = "http://localhost:5000/"; 88 example = "http://sync.example.com/"; 89 description = '' 90 Public URL with which firefox users can use to access the sync server. 91 ''; 92 }; 93 94 allowNewUsers = mkOption { 95 type = types.bool; 96 default = true; 97 description = '' 98 Whether to allow new-user signups on the server. Only request by 99 existing accounts will be honored. 100 ''; 101 }; 102 103 sqlUri = mkOption { 104 type = types.str; 105 default = defaultSqlUri; 106 example = "postgresql://scott:tiger@localhost/test"; 107 description = '' 108 The location of the database. This URL is composed of 109 <option>dialect[+driver]://user:password@host/dbname[?key=value..]</option>, 110 where <option>dialect</option> is a database name such as 111 <option>mysql</option>, <option>oracle</option>, <option>postgresql</option>, 112 etc., and <option>driver</option> the name of a DBAPI, such as 113 <option>psycopg2</option>, <option>pyodbc</option>, <option>cx_oracle</option>, 114 etc. The <link 115 xlink:href="http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html#database-urls"> 116 SQLAlchemy documentation</link> provides more examples and describe the syntax of 117 the expected URL. 118 ''; 119 }; 120 121 privateConfig = mkOption { 122 type = types.str; 123 default = "/etc/firefox/syncserver-secret.ini"; 124 description = '' 125 The private config file is used to extend the generated config with confidential 126 information, such as the <option>syncserver.sqlUri</option> setting if it contains a 127 password, and the <option>syncserver.secret</option> setting is used by the server to 128 generate cryptographically-signed authentication tokens. 129 130 If this file does not exists, then it is created with a generated 131 <option>syncserver.secret</option> settings. 132 ''; 133 }; 134 }; 135 }; 136 137 config = mkIf cfg.enable { 138 139 systemd.services.syncserver = let 140 syncServerEnv = pkgs.python.withPackages(ps: with ps; [ syncserver pasteScript ]); 141 in { 142 after = [ "network.target" ]; 143 description = "Firefox Sync Server"; 144 wantedBy = [ "multi-user.target" ]; 145 path = [ pkgs.coreutils syncServerEnv ]; 146 147 serviceConfig = { 148 User = cfg.user; 149 Group = cfg.group; 150 PermissionsStartOnly = true; 151 }; 152 153 preStart = '' 154 if ! test -e ${cfg.privateConfig}; then 155 mkdir -m 700 -p $(dirname ${cfg.privateConfig}) 156 echo > ${cfg.privateConfig} '[syncserver]' 157 echo >> ${cfg.privateConfig} "secret = $(head -c 20 /dev/urandom | sha1sum | tr -d ' -')" 158 fi 159 chown ${cfg.user}:${cfg.group} ${cfg.privateConfig} 160 '' + optionalString (cfg.sqlUri == defaultSqlUri) '' 161 if ! test -e $(dirname ${defaultDbLocation}); then 162 mkdir -m 700 -p $(dirname ${defaultDbLocation}) 163 chown ${cfg.user}:${cfg.group} $(dirname ${defaultDbLocation}) 164 fi 165 # Move previous database file if it exists 166 oldDb="/var/db/firefox-sync-server.db" 167 if test -f $oldDb; then 168 mv $oldDb ${defaultDbLocation} 169 chown ${cfg.user}:${cfg.group} ${defaultDbLocation} 170 fi 171 ''; 172 serviceConfig.ExecStart = "${syncServerEnv}/bin/paster serve ${syncServerIni}"; 173 }; 174 175 users.extraUsers = optionalAttrs (cfg.user == "syncserver") 176 (singleton { 177 name = "syncserver"; 178 group = cfg.group; 179 isSystemUser = true; 180 }); 181 182 users.extraGroups = optionalAttrs (cfg.group == "syncserver") 183 (singleton { 184 name = "syncserver"; 185 }); 186 }; 187}