organize patches + add gemma4 patch
All checks were successful
Build and Deploy / deploy (push) Successful in 2m41s

This commit is contained in:
2026-04-07 20:57:54 -04:00
parent 645a532ed7
commit 98310f2582
5 changed files with 93 additions and 2 deletions

View File

@@ -0,0 +1,379 @@
From ab57092a60123e361cf0de1c1a314a9888c45219 Mon Sep 17 00:00:00 2001
From: Simon Gardling <titaniumtown@proton.me>
Date: Sat, 21 Mar 2026 09:24:39 -0400
Subject: [PATCH] temp
---
.../services/networking/firefox-syncserver.md | 23 +++
.../networking/firefox-syncserver.nix | 140 ++++++++++++++----
pkgs/by-name/sy/syncstorage-rs/package.nix | 49 ++++--
3 files changed, 174 insertions(+), 38 deletions(-)
diff --git a/nixos/modules/services/networking/firefox-syncserver.md b/nixos/modules/services/networking/firefox-syncserver.md
index 991e97f799d6..3bc45cfa5640 100644
--- a/nixos/modules/services/networking/firefox-syncserver.md
+++ b/nixos/modules/services/networking/firefox-syncserver.md
@@ -32,6 +32,29 @@ This configuration should never be used in production. It is not encrypted and
stores its secrets in a world-readable location.
:::
+## Database backends {#module-services-firefox-syncserver-database}
+
+The sync server supports MySQL/MariaDB (the default) and PostgreSQL as database
+backends. Set `database.type` to choose the backend:
+
+```nix
+{
+ services.firefox-syncserver = {
+ enable = true;
+ database.type = "postgresql";
+ secrets = "/run/secrets/firefox-syncserver";
+ singleNode = {
+ enable = true;
+ hostname = "localhost";
+ url = "http://localhost:5000";
+ };
+ };
+}
+```
+
+When `database.createLocally` is `true` (the default), the module will
+automatically enable and configure the corresponding database service.
+
## More detailed setup {#module-services-firefox-syncserver-configuration}
The `firefox-syncserver` service provides a number of options to make setting up
diff --git a/nixos/modules/services/networking/firefox-syncserver.nix b/nixos/modules/services/networking/firefox-syncserver.nix
index 6a50e49fc096..70a56314e323 100644
--- a/nixos/modules/services/networking/firefox-syncserver.nix
+++ b/nixos/modules/services/networking/firefox-syncserver.nix
@@ -13,7 +13,21 @@ let
defaultUser = "firefox-syncserver";
dbIsLocal = cfg.database.host == "localhost";
- dbURL = "mysql://${cfg.database.user}@${cfg.database.host}/${cfg.database.name}${lib.optionalString dbIsLocal "?socket=/run/mysqld/mysqld.sock"}";
+ dbIsMySQL = cfg.database.type == "mysql";
+ dbIsPostgreSQL = cfg.database.type == "postgresql";
+
+ dbURL =
+ if dbIsMySQL then
+ "mysql://${cfg.database.user}@${cfg.database.host}/${cfg.database.name}${lib.optionalString dbIsLocal "?socket=/run/mysqld/mysqld.sock"}"
+ else
+ "postgres://${cfg.database.user}@${cfg.database.host}/${cfg.database.name}${lib.optionalString dbIsLocal "?host=/run/postgresql"}";
+
+ # postgresql.target waits for postgresql-setup.service (which runs
+ # ensureDatabases / ensureUsers) to complete, avoiding race conditions
+ # where the syncserver starts before its database and role exist.
+ dbService = if dbIsMySQL then "mysql.service" else "postgresql.target";
+
+ syncserver = cfg.package.override { dbBackend = cfg.database.type; };
format = pkgs.formats.toml { };
settings = {
@@ -22,7 +36,7 @@ let
database_url = dbURL;
};
tokenserver = {
- node_type = "mysql";
+ node_type = if dbIsMySQL then "mysql" else "postgres";
database_url = dbURL;
fxa_email_domain = "api.accounts.firefox.com";
fxa_oauth_server_url = "https://oauth.accounts.firefox.com/v1";
@@ -41,7 +55,8 @@ let
};
};
configFile = format.generate "syncstorage.toml" (lib.recursiveUpdate settings cfg.settings);
- setupScript = pkgs.writeShellScript "firefox-syncserver-setup" ''
+
+ mysqlSetupScript = pkgs.writeShellScript "firefox-syncserver-setup" ''
set -euo pipefail
shopt -s inherit_errexit
@@ -79,6 +94,47 @@ let
echo "Single-node setup failed"
exit 1
'';
+
+ postgresqlSetupScript = pkgs.writeShellScript "firefox-syncserver-setup" ''
+ set -euo pipefail
+ shopt -s inherit_errexit
+
+ schema_configured() {
+ psql -d ${cfg.database.name} -tAc "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'services')" | grep -q t
+ }
+
+ update_config() {
+ psql -d ${cfg.database.name} <<'EOF'
+ BEGIN;
+
+ INSERT INTO services (id, service, pattern)
+ VALUES (1, 'sync-1.5', '{node}/1.5/{uid}')
+ ON CONFLICT (id) DO UPDATE SET service = 'sync-1.5', pattern = '{node}/1.5/{uid}';
+ INSERT INTO nodes (id, service, node, available, current_load,
+ capacity, downed, backoff)
+ VALUES (1, 1, '${cfg.singleNode.url}', ${toString cfg.singleNode.capacity},
+ 0, ${toString cfg.singleNode.capacity}, 0, 0)
+ ON CONFLICT (id) DO UPDATE SET node = '${cfg.singleNode.url}', capacity = ${toString cfg.singleNode.capacity};
+
+ COMMIT;
+ EOF
+ }
+
+
+ for (( try = 0; try < 60; try++ )); do
+ if ! schema_configured; then
+ sleep 2
+ else
+ update_config
+ exit 0
+ fi
+ done
+
+ echo "Single-node setup failed"
+ exit 1
+ '';
+
+ setupScript = if dbIsMySQL then mysqlSetupScript else postgresqlSetupScript;
in
{
@@ -88,25 +144,26 @@ in
the Firefox Sync storage service.
Out of the box this will not be very useful unless you also configure at least
- one service and one nodes by inserting them into the mysql database manually, e.g.
- by running
-
- ```
- INSERT INTO `services` (`id`, `service`, `pattern`) VALUES ('1', 'sync-1.5', '{node}/1.5/{uid}');
- INSERT INTO `nodes` (`id`, `service`, `node`, `available`, `current_load`,
- `capacity`, `downed`, `backoff`)
- VALUES ('1', '1', 'https://mydomain.tld', '1', '0', '10', '0', '0');
- ```
+ one service and one nodes by inserting them into the database manually, e.g.
+ by running the equivalent SQL for your database backend.
{option}`${opt.singleNode.enable}` does this automatically when enabled
'';
package = lib.mkPackageOption pkgs "syncstorage-rs" { };
+ database.type = lib.mkOption {
+ type = lib.types.enum [
+ "mysql"
+ "postgresql"
+ ];
+ default = "mysql";
+ description = ''
+ Which database backend to use for storage.
+ '';
+ };
+
database.name = lib.mkOption {
- # the mysql module does not allow `-quoting without resorting to shell
- # escaping, so we restrict db names for forward compaitiblity should this
- # behavior ever change.
type = lib.types.strMatching "[a-z_][a-z0-9_]*";
default = defaultDatabase;
description = ''
@@ -117,9 +174,15 @@ in
database.user = lib.mkOption {
type = lib.types.str;
- default = defaultUser;
+ default = if dbIsPostgreSQL then defaultDatabase else defaultUser;
+ defaultText = lib.literalExpression ''
+ if database.type == "postgresql" then "${defaultDatabase}" else "${defaultUser}"
+ '';
description = ''
- Username for database connections.
+ Username for database connections. When using PostgreSQL with
+ `createLocally`, this defaults to the database name so that
+ `ensureDBOwnership` works (it requires user and database names
+ to match).
'';
};
@@ -137,7 +200,8 @@ in
default = true;
description = ''
Whether to create database and user on the local machine if they do not exist.
- This includes enabling unix domain socket authentication for the configured user.
+ This includes enabling the configured database service and setting up
+ authentication for the configured user.
'';
};
@@ -237,7 +301,7 @@ in
};
config = lib.mkIf cfg.enable {
- services.mysql = lib.mkIf cfg.database.createLocally {
+ services.mysql = lib.mkIf (cfg.database.createLocally && dbIsMySQL) {
enable = true;
ensureDatabases = [ cfg.database.name ];
ensureUsers = [
@@ -250,16 +314,27 @@ in
];
};
+ services.postgresql = lib.mkIf (cfg.database.createLocally && dbIsPostgreSQL) {
+ enable = true;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ {
+ name = cfg.database.user;
+ ensureDBOwnership = true;
+ }
+ ];
+ };
+
systemd.services.firefox-syncserver = {
wantedBy = [ "multi-user.target" ];
- requires = lib.mkIf dbIsLocal [ "mysql.service" ];
- after = lib.mkIf dbIsLocal [ "mysql.service" ];
+ requires = lib.mkIf dbIsLocal [ dbService ];
+ after = lib.mkIf dbIsLocal [ dbService ];
restartTriggers = lib.optional cfg.singleNode.enable setupScript;
environment.RUST_LOG = cfg.logLevel;
serviceConfig = {
- User = defaultUser;
- Group = defaultUser;
- ExecStart = "${cfg.package}/bin/syncserver --config ${configFile}";
+ User = cfg.database.user;
+ Group = cfg.database.user;
+ ExecStart = "${syncserver}/bin/syncserver --config ${configFile}";
EnvironmentFile = lib.mkIf (cfg.secrets != null) "${cfg.secrets}";
# hardening
@@ -303,10 +378,19 @@ in
systemd.services.firefox-syncserver-setup = lib.mkIf cfg.singleNode.enable {
wantedBy = [ "firefox-syncserver.service" ];
- requires = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal "mysql.service";
- after = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal "mysql.service";
- path = [ config.services.mysql.package ];
- serviceConfig.ExecStart = [ "${setupScript}" ];
+ requires = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal dbService;
+ after = [ "firefox-syncserver.service" ] ++ lib.optional dbIsLocal dbService;
+ path =
+ if dbIsMySQL then [ config.services.mysql.package ] else [ config.services.postgresql.package ];
+ serviceConfig = {
+ ExecStart = [ "${setupScript}" ];
+ }
+ // lib.optionalAttrs dbIsPostgreSQL {
+ # PostgreSQL peer authentication requires the system user to match the
+ # database user. Run as the superuser so we can access all databases.
+ User = "postgres";
+ Group = "postgres";
+ };
};
services.nginx.virtualHosts = lib.mkIf cfg.singleNode.enableNginx {
diff --git a/pkgs/by-name/sy/syncstorage-rs/package.nix b/pkgs/by-name/sy/syncstorage-rs/package.nix
index 39b2b53ab03c..944ed72525af 100644
--- a/pkgs/by-name/sy/syncstorage-rs/package.nix
+++ b/pkgs/by-name/sy/syncstorage-rs/package.nix
@@ -1,14 +1,18 @@
{
fetchFromGitHub,
+ fetchurl,
rustPlatform,
pkg-config,
python3,
cmake,
libmysqlclient,
+ libpq,
+ openssl,
makeBinaryWrapper,
lib,
nix-update-script,
nixosTests,
+ dbBackend ? "mysql",
}:
let
@@ -19,17 +23,23 @@ let
p.tokenlib
p.cryptography
]);
+ # utoipa-swagger-ui downloads Swagger UI assets at build time.
+ # Prefetch the archive for sandboxed builds.
+ swaggerUi = fetchurl {
+ url = "https://github.com/swagger-api/swagger-ui/archive/refs/tags/v5.17.14.zip";
+ hash = "sha256-SBJE0IEgl7Efuu73n3HZQrFxYX+cn5UU5jrL4T5xzNw=";
+ };
in
-rustPlatform.buildRustPackage rec {
+rustPlatform.buildRustPackage (finalAttrs: {
pname = "syncstorage-rs";
- version = "0.21.1-unstable-2026-01-26";
+ version = "0.21.1-unstable-2026-02-24";
src = fetchFromGitHub {
owner = "mozilla-services";
repo = "syncstorage-rs";
- rev = "11659d98f9c69948a0aab353437ce2036c388711";
- hash = "sha256-G37QvxTNh/C3gmKG0UYHI6QBr0F+KLGRNI/Sx33uOsc=";
+ rev = "50a739b58dc9ec81995f86e71d992aa14ccc450e";
+ hash = "sha256-idq0RGdwoV6GVuq36IVVVCFbyMTe8i/EpVWE59D/dhM=";
};
nativeBuildInputs = [
@@ -39,16 +49,35 @@ rustPlatform.buildRustPackage rec {
python3
];
- buildInputs = [
- libmysqlclient
- ];
+ buildInputs =
+ lib.optional (dbBackend == "mysql") libmysqlclient
+ ++ lib.optionals (dbBackend == "postgresql") [
+ libpq
+ openssl
+ ];
+
+ buildNoDefaultFeatures = true;
+ # The syncserver "postgres" feature only enables syncstorage-db/postgres.
+ # tokenserver-db/postgres must be enabled separately so the tokenserver
+ # can also connect to PostgreSQL (it dispatches on the URL scheme at runtime).
+ buildFeatures =
+ let
+ cargoFeature = if dbBackend == "postgresql" then "postgres" else dbBackend;
+ in
+ [
+ cargoFeature
+ "tokenserver-db/${cargoFeature}"
+ "py_verifier"
+ ];
+
+ SWAGGER_UI_DOWNLOAD_URL = "file://${swaggerUi}";
preFixup = ''
wrapProgram $out/bin/syncserver \
--prefix PATH : ${lib.makeBinPath [ pyFxADeps ]}
'';
- cargoHash = "sha256-9Dcf5mDyK/XjsKTlCPXTHoBkIq+FFPDg1zfK24Y9nHQ=";
+ cargoHash = "sha256-80EztkSX+SnmqsRWIXbChUB8AeV1Tp9WXoWNbDY8rUE=";
# almost all tests need a DB to test against
doCheck = false;
@@ -60,10 +89,10 @@ rustPlatform.buildRustPackage rec {
meta = {
description = "Mozilla Sync Storage built with Rust";
homepage = "https://github.com/mozilla-services/syncstorage-rs";
- changelog = "https://github.com/mozilla-services/syncstorage-rs/releases/tag/${version}";
+ changelog = "https://github.com/mozilla-services/syncstorage-rs/releases/tag/${finalAttrs.version}";
license = lib.licenses.mpl20;
maintainers = [ ];
platforms = lib.platforms.linux;
mainProgram = "syncserver";
};
-}
+})
--
2.53.0