-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
weblate: init at 5.6.2, add module #325541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
569192c
python3Packages.phply: init at 1.2.6
erictapen a41a550
python3Packages.aeidon: init at 1.15
erictapen a3645d0
python3Packages.translate-toolkit: init at 3.13.2
erictapen 2a6c991
python3Packages.ahocorasick-rs: init at 0.22.0
erictapen e5af89b
python3Packages.celery: add redis as optional dependency
erictapen 0f9dcc2
python3Packages.django-crispy-bootstrap3: init at 2024.1
erictapen e59da34
python3Packages.pyicumessageformat: init at 1.0.0
erictapen c30fa9a
python3Packages.siphashc: init at 2.4.1
erictapen 77c26ec
python3Packages.weblate-language-data: init at 2024.5
erictapen 92e0b2c
python3Packages.weblate-schemas: init at 2024.1
erictapen 1bcf166
python3Packages.translation-finder: init at 2.16
erictapen bdc0e7d
weblate: init at 5.6.2
erictapen d96e777
nixos/weblate: init module and test
erictapen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,388 @@ | ||
| { | ||
| config, | ||
| lib, | ||
| pkgs, | ||
| ... | ||
| }: | ||
|
|
||
| let | ||
| cfg = config.services.weblate; | ||
|
|
||
| dataDir = "/var/lib/weblate"; | ||
| settingsDir = "${dataDir}/settings"; | ||
|
|
||
| finalPackage = cfg.package.overridePythonAttrs (old: { | ||
| # We only support the PostgreSQL backend in this module | ||
| dependencies = old.dependencies ++ cfg.package.optional-dependencies.postgres; | ||
| # Use a settings module in dataDir, to avoid having to rebuild the package | ||
| # when user changes settings. | ||
| makeWrapperArgs = (old.makeWrapperArgs or [ ]) ++ [ | ||
| "--set PYTHONPATH \"${settingsDir}\"" | ||
| "--set DJANGO_SETTINGS_MODULE \"settings\"" | ||
| ]; | ||
| }); | ||
| inherit (finalPackage) python; | ||
|
|
||
| pythonEnv = python.buildEnv.override { | ||
| extraLibs = with python.pkgs; [ | ||
| (toPythonModule finalPackage) | ||
| celery | ||
| ]; | ||
| }; | ||
|
|
||
| # This extends and overrides the weblate/settings_example.py code found in upstream. | ||
| weblateConfig = | ||
| '' | ||
| # This was autogenerated by the NixOS module. | ||
|
|
||
| SITE_TITLE = "Weblate" | ||
| SITE_DOMAIN = "${cfg.localDomain}" | ||
| # TLS terminates at the reverse proxy, but this setting controls how links to weblate are generated. | ||
| ENABLE_HTTPS = True | ||
| SESSION_COOKIE_SECURE = ENABLE_HTTPS | ||
| DATA_DIR = "${dataDir}" | ||
| CACHE_DIR = f"{DATA_DIR}/cache" | ||
| STATIC_ROOT = "${finalPackage.static}/static" | ||
| MEDIA_ROOT = "/var/lib/weblate/media" | ||
| COMPRESS_ROOT = "${finalPackage.static}/compressor-cache" | ||
| DEBUG = False | ||
|
|
||
| DATABASES = { | ||
| "default": { | ||
| "ENGINE": "django.db.backends.postgresql", | ||
| "HOST": "/run/postgresql", | ||
| "NAME": "weblate", | ||
| "USER": "weblate", | ||
| } | ||
| } | ||
|
|
||
| with open("${cfg.djangoSecretKeyFile}") as f: | ||
| SECRET_KEY = f.read().rstrip("\n") | ||
|
|
||
| CACHES = { | ||
| "default": { | ||
| "BACKEND": "django_redis.cache.RedisCache", | ||
| "LOCATION": "unix://${config.services.redis.servers.weblate.unixSocket}", | ||
| "OPTIONS": { | ||
| "CLIENT_CLASS": "django_redis.client.DefaultClient", | ||
erictapen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "PASSWORD": None, | ||
| "CONNECTION_POOL_KWARGS": {}, | ||
| }, | ||
| "KEY_PREFIX": "weblate", | ||
| "TIMEOUT": 3600, | ||
| }, | ||
| "avatar": { | ||
| "BACKEND": "django.core.cache.backends.filebased.FileBasedCache", | ||
| "LOCATION": "/var/lib/weblate/avatar-cache", | ||
| "TIMEOUT": 86400, | ||
| "OPTIONS": {"MAX_ENTRIES": 1000}, | ||
| } | ||
| } | ||
|
|
||
|
|
||
| CELERY_TASK_ALWAYS_EAGER = False | ||
| CELERY_BROKER_URL = "redis+socket://${config.services.redis.servers.weblate.unixSocket}" | ||
| CELERY_RESULT_BACKEND = CELERY_BROKER_URL | ||
|
|
||
| VCS_BACKENDS = ("weblate.vcs.git.GitRepository",) | ||
|
|
||
| '' | ||
| + lib.optionalString cfg.smtp.enable '' | ||
| ADMINS = (("Weblate Admin", "${cfg.smtp.user}"),) | ||
|
|
||
| EMAIL_HOST = "${cfg.smtp.host}" | ||
| EMAIL_USE_TLS = True | ||
| EMAIL_HOST_USER = "${cfg.smtp.user}" | ||
| SERVER_EMAIL = "${cfg.smtp.user}" | ||
| DEFAULT_FROM_EMAIL = "${cfg.smtp.user}" | ||
| EMAIL_PORT = 587 | ||
| with open("${cfg.smtp.passwordFile}") as f: | ||
| EMAIL_HOST_PASSWORD = f.read().rstrip("\n") | ||
|
|
||
| '' | ||
| + cfg.extraConfig; | ||
| settings_py = | ||
| pkgs.runCommand "weblate_settings.py" | ||
| { | ||
| inherit weblateConfig; | ||
| passAsFile = [ "weblateConfig" ]; | ||
| } | ||
| '' | ||
| mkdir -p $out | ||
| cat \ | ||
| ${finalPackage}/${python.sitePackages}/weblate/settings_example.py \ | ||
| $weblateConfigPath \ | ||
| > $out/settings.py | ||
| ''; | ||
|
|
||
| environment = { | ||
| PYTHONPATH = "${settingsDir}:${pythonEnv}/${python.sitePackages}/"; | ||
| DJANGO_SETTINGS_MODULE = "settings"; | ||
| # We run Weblate through gunicorn, so we can't utilise the env var set in the wrapper. | ||
| inherit (finalPackage) GI_TYPELIB_PATH; | ||
erictapen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }; | ||
|
|
||
| weblatePath = with pkgs; [ | ||
| gitSVN | ||
|
|
||
| #optional | ||
| git-review | ||
| tesseract | ||
| licensee | ||
| mercurial | ||
| ]; | ||
| in | ||
| { | ||
|
|
||
| options = { | ||
| services.weblate = { | ||
| enable = lib.mkEnableOption "Weblate service"; | ||
|
|
||
| package = lib.mkPackageOption pkgs "weblate" { }; | ||
|
|
||
| localDomain = lib.mkOption { | ||
| description = "The domain name serving your Weblate instance."; | ||
| example = "weblate.example.org"; | ||
| type = lib.types.str; | ||
| }; | ||
|
|
||
| djangoSecretKeyFile = lib.mkOption { | ||
| description = '' | ||
| Location of the Django secret key. | ||
|
|
||
| This should be a path pointing to a file with secure permissions (not /nix/store). | ||
|
|
||
| Can be generated with `weblate-generate-secret-key` which is available as the `weblate` user. | ||
| ''; | ||
| type = lib.types.path; | ||
| }; | ||
|
|
||
| extraConfig = lib.mkOption { | ||
| type = lib.types.lines; | ||
| default = ""; | ||
| description = '' | ||
| Text to append to `settings.py` Weblate configuration file. | ||
| ''; | ||
| }; | ||
|
|
||
| smtp = { | ||
| enable = lib.mkEnableOption "Weblate SMTP support"; | ||
| user = lib.mkOption { | ||
| description = "SMTP login name."; | ||
| example = "weblate@example.org"; | ||
| type = lib.types.str; | ||
| }; | ||
|
|
||
| host = lib.mkOption { | ||
| description = "SMTP host used when sending emails to users."; | ||
| type = lib.types.str; | ||
| example = "127.0.0.1"; | ||
| }; | ||
|
|
||
| passwordFile = lib.mkOption { | ||
| description = '' | ||
| Location of a file containing the SMTP password. | ||
|
|
||
| This should be a path pointing to a file with secure permissions (not /nix/store). | ||
| ''; | ||
| type = lib.types.path; | ||
| }; | ||
| }; | ||
|
|
||
| }; | ||
| }; | ||
|
|
||
| config = lib.mkIf cfg.enable { | ||
|
|
||
| systemd.tmpfiles.rules = [ "L+ ${settingsDir} - - - - ${settings_py}" ]; | ||
|
|
||
| services.nginx = { | ||
| enable = true; | ||
| virtualHosts."${cfg.localDomain}" = { | ||
|
|
||
| forceSSL = true; | ||
| enableACME = true; | ||
|
|
||
| locations = { | ||
| "= /favicon.ico".alias = "${finalPackage}/${python.sitePackages}/weblate/static/favicon.ico"; | ||
| "/static/".alias = "${finalPackage.static}/static/"; | ||
| "/static/CACHE/".alias = "${finalPackage.static}/compressor-cache/CACHE/"; | ||
| "/media/".alias = "/var/lib/weblate/media/"; | ||
| "/".proxyPass = "http://unix:///run/weblate.socket"; | ||
| }; | ||
|
|
||
| }; | ||
| }; | ||
|
|
||
| systemd.services.weblate-postgresql-setup = { | ||
| description = "Weblate PostgreSQL setup"; | ||
| after = [ "postgresql.service" ]; | ||
| serviceConfig = { | ||
| Type = "oneshot"; | ||
| User = "postgres"; | ||
| Group = "postgres"; | ||
| ExecStart = '' | ||
| ${config.services.postgresql.package}/bin/psql weblate -c "CREATE EXTENSION IF NOT EXISTS pg_trgm" | ||
| ''; | ||
| }; | ||
| }; | ||
|
|
||
| systemd.services.weblate-migrate = { | ||
| description = "Weblate migration"; | ||
| after = [ "weblate-postgresql-setup.service" ]; | ||
| requires = [ "weblate-postgresql-setup.service" ]; | ||
| # We want this to be active on boot, not just on socket activation | ||
| wantedBy = [ "multi-user.target" ]; | ||
| inherit environment; | ||
| path = weblatePath; | ||
| serviceConfig = { | ||
| Type = "oneshot"; | ||
| StateDirectory = "weblate"; | ||
| User = "weblate"; | ||
| Group = "weblate"; | ||
| ExecStart = "${finalPackage}/bin/weblate migrate --noinput"; | ||
| }; | ||
| }; | ||
|
|
||
| systemd.services.weblate-celery = { | ||
| description = "Weblate Celery"; | ||
| after = [ | ||
| "network.target" | ||
| "redis.service" | ||
| "postgresql.service" | ||
| ]; | ||
| # We want this to be active on boot, not just on socket activation | ||
| wantedBy = [ "multi-user.target" ]; | ||
| environment = environment // { | ||
| CELERY_WORKER_RUNNING = "1"; | ||
| }; | ||
| path = weblatePath; | ||
| # Recommendations from: | ||
| # https://github.com/WeblateOrg/weblate/blob/main/weblate/examples/celery-weblate.service | ||
| serviceConfig = | ||
| let | ||
| # We have to push %n through systemd's replacement, therefore %%n. | ||
| pidFile = "/run/celery/weblate-%%n.pid"; | ||
| nodes = "celery notify memory backup translate"; | ||
| cmd = verb: '' | ||
| ${pythonEnv}/bin/celery multi ${verb} \ | ||
| ${nodes} \ | ||
| -A "weblate.utils" \ | ||
| --pidfile=${pidFile} \ | ||
| --logfile=/var/log/celery/weblate-%%n%%I.log \ | ||
| --loglevel=DEBUG \ | ||
| --beat:celery \ | ||
| --queues:celery=celery \ | ||
| --prefetch-multiplier:celery=4 \ | ||
| --queues:notify=notify \ | ||
| --prefetch-multiplier:notify=10 \ | ||
| --queues:memory=memory \ | ||
| --prefetch-multiplier:memory=10 \ | ||
| --queues:translate=translate \ | ||
| --prefetch-multiplier:translate=4 \ | ||
| --concurrency:backup=1 \ | ||
| --queues:backup=backup \ | ||
| --prefetch-multiplier:backup=2 | ||
| ''; | ||
| in | ||
| { | ||
| Type = "forking"; | ||
| User = "weblate"; | ||
| Group = "weblate"; | ||
| WorkingDirectory = "${finalPackage}/${python.sitePackages}/weblate/"; | ||
| RuntimeDirectory = "celery"; | ||
| RuntimeDirectoryPreserve = "restart"; | ||
| LogsDirectory = "celery"; | ||
| ExecStart = cmd "start"; | ||
| ExecReload = cmd "restart"; | ||
| ExecStop = '' | ||
| ${pythonEnv}/bin/celery multi stopwait \ | ||
| ${nodes} \ | ||
| --pidfile=${pidFile} | ||
| ''; | ||
| Restart = "always"; | ||
| }; | ||
| }; | ||
|
|
||
| systemd.services.weblate = { | ||
| description = "Weblate Gunicorn app"; | ||
| after = [ | ||
| "network.target" | ||
| "weblate-migrate.service" | ||
| "weblate-celery.service" | ||
| ]; | ||
| requires = [ | ||
| "weblate-migrate.service" | ||
| "weblate-celery.service" | ||
| "weblate.socket" | ||
| ]; | ||
| inherit environment; | ||
| path = weblatePath; | ||
| serviceConfig = { | ||
| Type = "notify"; | ||
| NotifyAccess = "all"; | ||
| ExecStart = | ||
| let | ||
| gunicorn = python.pkgs.gunicorn.overridePythonAttrs (old: { | ||
| # Allows Gunicorn to set a meaningful process name | ||
| dependencies = (old.dependencies or [ ]) ++ old.optional-dependencies.setproctitle; | ||
| }); | ||
| in | ||
| '' | ||
| ${gunicorn}/bin/gunicorn \ | ||
| --name=weblate \ | ||
| --bind='unix:///run/weblate.socket' \ | ||
| weblate.wsgi | ||
| ''; | ||
| ExecReload = "kill -s HUP $MAINPID"; | ||
| KillMode = "mixed"; | ||
| PrivateTmp = true; | ||
| WorkingDirectory = dataDir; | ||
| StateDirectory = "weblate"; | ||
| RuntimeDirectory = "weblate"; | ||
| User = "weblate"; | ||
| Group = "weblate"; | ||
| }; | ||
| }; | ||
|
|
||
| systemd.sockets.weblate = { | ||
| before = [ "nginx.service" ]; | ||
| wantedBy = [ "sockets.target" ]; | ||
| socketConfig = { | ||
| ListenStream = "/run/weblate.socket"; | ||
| SocketUser = "weblate"; | ||
| SocketGroup = "weblate"; | ||
| SocketMode = "770"; | ||
| }; | ||
| }; | ||
|
|
||
| services.redis.servers.weblate = { | ||
| enable = true; | ||
| user = "weblate"; | ||
| unixSocket = "/run/redis-weblate/redis.sock"; | ||
| unixSocketPerm = 770; | ||
| }; | ||
|
|
||
| services.postgresql = { | ||
| enable = true; | ||
| ensureUsers = [ | ||
| { | ||
| name = "weblate"; | ||
| ensureDBOwnership = true; | ||
| } | ||
| ]; | ||
| ensureDatabases = [ "weblate" ]; | ||
| }; | ||
|
|
||
| users.users.weblate = { | ||
| isSystemUser = true; | ||
| group = "weblate"; | ||
| packages = [ finalPackage ] ++ weblatePath; | ||
| }; | ||
|
|
||
| users.groups.weblate.members = [ config.services.nginx.user ]; | ||
| }; | ||
|
|
||
| meta.maintainers = with lib.maintainers; [ erictapen ]; | ||
|
|
||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.