diff --git a/nix/sources.json b/nix/sources.json index 55a8c277..f64717c3 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -44,6 +44,18 @@ "rev": "e232c0b64ee2bb8baf87d3e541948f8c40dc2f29", "type": "git" }, + "nixos-19.09": { + "branch": "nixos-19.09", + "description": "Nix Packages collection", + "homepage": "", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "75f4ba05c63be3f147bcc2f7bd4ba1f029cedcb1", + "sha256": "157c64220lf825ll4c0cxsdwg7cxqdx4z559fdp7kpz0g6p8fhhr", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/75f4ba05c63be3f147bcc2f7bd4ba1f029cedcb1.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, "nixos-21.05": { "branch": "nixos-21.05", "description": "Nixpkgs/NixOS branches that track the Nixpkgs/NixOS channels", @@ -62,7 +74,7 @@ "homepage": "", "owner": "nixos", "repo": "nixos-hardware", - "rev": "41775780a0b6b32b3d32dcc32bb9bc6df809062d", + "rev": "417v75780a0b6b32b3d32dcc32bb9bc6df809062d", "sha256": "0121bmdga42zkn4y3wsy71b5lglzn180q7vmxaprqp5lvr27v8ik", "type": "tarball", "url": "https://github.com/nixos/nixos-hardware/archive/41775780a0b6b32b3d32dcc32bb9bc6df809062d.tar.gz", @@ -87,18 +99,6 @@ "url": "https://github.com/NixOS/nixpkgs/archive/87807e64a5ef5206b745a40af118c7be8db73681.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, - "nixos-19.09": { - "branch": "nixos-19.09", - "description": "Nix Packages collection", - "homepage": "", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "75f4ba05c63be3f147bcc2f7bd4ba1f029cedcb1", - "sha256": "157c64220lf825ll4c0cxsdwg7cxqdx4z559fdp7kpz0g6p8fhhr", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/75f4ba05c63be3f147bcc2f7bd4ba1f029cedcb1.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, "obelisk": { "branch": "master", "description": "Obelisk provides an easy way to develop and deploy your Reflex project for web and mobile", diff --git a/nixos/roles/firefox-sync.nix b/nixos/roles/firefox-sync.nix index 19cc8818..19ff4bc4 100644 --- a/nixos/roles/firefox-sync.nix +++ b/nixos/roles/firefox-sync.nix @@ -1,10 +1,210 @@ -{ pkgs, ... }: { +{ config, lib, ... }: + +with lib; + +let + pkgs = import (import ../../nix/sources.nix)."nixos-19.09" { }; + + cfg = config.services.firefox.syncserver; + + defaultDbLocation = "/var/db/firefox-sync-server/firefox-sync-server.db"; + defaultSqlUri = "sqlite:///${defaultDbLocation}"; + + syncServerIni = pkgs.writeText "syncserver.ini" '' + [DEFAULT] + overrides = ${cfg.privateConfig} + + [server:main] + use = egg:gunicorn + 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 = ${boolToString cfg.allowNewUsers} + force_wsgi_environ = true + + [browserid] + backend = tokenserver.verifiers.LocalVerifier + audiences = ${removeSuffix "/" cfg.publicUrl} + ''; + + user = "syncserver"; + group = "syncserver"; +in + +{ disabledModules = [ "services/networking/firefox/sync-server.nix" ]; - imports = [ - "${pkgs.sources."nixos-19.09"}/nixos/modules/services/networking/firefox/sync-server.nix" - ]; - services.firefox = { - enable = true; - allowNewUsers = false; + + meta.maintainers = with lib.maintainers; [ nadrieril ]; + + options = { + services.firefox.syncserver = { + enable = mkOption { + type = types.bool; + default = false; + 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; + description = '' + Whether to allow new-user signups on the server. Only request by + existing accounts will be honored. + ''; + }; + + sqlUri = mkOption { + type = types.str; + default = defaultSqlUri; + 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 = { + + systemd.services.syncserver = { + after = [ "network.target" ]; + description = "Firefox Sync Server"; + wantedBy = [ "multi-user.target" ]; + path = [ + pkgs.coreutils + (pkgs.python.withPackages (ps: [ pkgs.syncserver ps.gunicorn ])) + ]; + + serviceConfig = { + User = user; + Group = group; + PermissionsStartOnly = true; + }; + + preStart = '' + if ! test -e ${cfg.privateConfig}; then + mkdir -p $(dirname ${cfg.privateConfig}) + echo > ${cfg.privateConfig} '[syncserver]' + chmod 600 ${cfg.privateConfig} + echo >> ${cfg.privateConfig} "secret = $(head -c 20 /dev/urandom | sha1sum | tr -d ' -')" + fi + chmod 600 ${cfg.privateConfig} + chmod 755 $(dirname ${cfg.privateConfig}) + chown ${user}:${group} ${cfg.privateConfig} + + '' + optionalString (cfg.sqlUri == defaultSqlUri) '' + if ! test -e $(dirname ${defaultDbLocation}); then + mkdir -m 700 -p $(dirname ${defaultDbLocation}) + chown ${user}:${group} $(dirname ${defaultDbLocation}) + fi + + # Move previous database file if it exists + oldDb="/var/db/firefox-sync-server.db" + if test -f $oldDb; then + mv $oldDb ${defaultDbLocation} + chown ${user}:${group} ${defaultDbLocation} + fi + ''; + + script = '' + gunicorn --paste ${syncServerIni} + ''; + }; + + users.users.${user} = { + inherit group; + isSystemUser = true; + }; + + users.groups.${group} = { }; + + services = { + firefox.syncserver = { + allowNewUsers = false; + listen.address = "[::1]"; + publicUrl = "https://firefox-sync.maralorn.de"; + }; + nginx = { + enable = true; + virtualHosts."firefox-sync.maralorn.de" = { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://[::1]:5000"; + extraConfig = '' + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto https;''; + }; + }; + }; + }; + }; } diff --git a/nixos/roles/monitoring/probes.nix b/nixos/roles/monitoring/probes.nix index a4542bad..950eeb83 100644 --- a/nixos/roles/monitoring/probes.nix +++ b/nixos/roles/monitoring/probes.nix @@ -56,6 +56,7 @@ in "https://ci.maralorn.de" "https://cloud.maralorn.de" "https://element.maralorn.de" + "https://firefox-sync.maralorn.de" "https://fdroid.maralorn.de/index-v1.json" "https://home.maralorn.de" "https://matrix.maralorn.de"