diff --git a/.github/workflows/docker-ghcr.yml b/.github/workflows/docker-ghcr.yml new file mode 100644 index 00000000..c3564903 --- /dev/null +++ b/.github/workflows/docker-ghcr.yml @@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2026 LibreCode contributors +# SPDX-License-Identifier: MIT +name: Docker GHCR + +on: + push: + branches: + - main + tags: + - "v*" + pull_request: + paths: + - ".dockerignore" + - ".github/workflows/docker-ghcr.yml" + - "Cargo.lock" + - "Cargo.toml" + - "Dockerfile" + - "appinfo/info.xml" + - "build.rs" + - "src/**" + workflow_dispatch: + +permissions: + contents: read + packages: write + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + flavor: | + latest=auto + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,prefix=sha- + type=raw,value=edge,enable={{is_default_branch}} + + - name: Log in to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore index ed48a19e..c3888ee5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # SPDX-License-Identifier: AGPL-3.0-or-later target .env +.env.notify_push bin build composer.phar diff --git a/Dockerfile b/Dockerfile index bfb6a03a..e3bfaa84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,4 +26,4 @@ FROM scratch COPY --from=build /notify_push / EXPOSE 7867 -CMD ["/notify_push"] +ENTRYPOINT ["/notify_push"] diff --git a/README.md b/README.md index 26704135..b33db570 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,15 @@ [![REUSE status](https://api.reuse.software/badge/github.com/nextcloud/notify_push)](https://api.reuse.software/info/github.com/nextcloud/notify_push) +Portuguese translation: [README.pt-BR.md](./README.pt-BR.md) + Update notifications for nextcloud clients +## Additional documentation + +- Running the container locally and publishing images to GHCR: + [`docs/docker-ghcr.md`](./docs/docker-ghcr.md) + ## About This app attempts to solve the issue where Nextcloud clients have to periodically check the server if any files have @@ -286,6 +293,63 @@ Once the nginx configuration is edit you can reload nginx using. sudo nginx -s reload ``` +#### nginx-proxy + +If you're using the [`nginx-proxy`](https://github.com/nginx-proxy/nginx-proxy) Docker project, do not add the +`location` block manually to the Nextcloud container. In that setup the `server` block is generated by `nginx-proxy`, +so the simplest approach is to publish `notify_push` on the same host under the `/push/` path. + +Example using the generic domain `cloud.example.com`: + +```yaml +services: + nextcloud: + image: nextcloud:apache + environment: + VIRTUAL_HOST: cloud.example.com + VIRTUAL_PATH: / + networks: + - nginx-proxy + - internal + + notify_push: + image: ghcr.io/nextcloud/notify_push:latest + environment: + PORT: "7867" + VIRTUAL_HOST: cloud.example.com + VIRTUAL_PATH: /push/ + VIRTUAL_DEST: / + VIRTUAL_PORT: "7867" + expose: + - "7867" + networks: + - nginx-proxy + - internal +``` + +Important details: + +- `notify_push` must be attached to the same Docker network as `nginx-proxy` +- use `VIRTUAL_PATH=/push/` with the trailing slash +- use `VIRTUAL_DEST=/` so the `/push/` prefix is stripped before forwarding the request +- with `nginx-proxy`, `expose` is usually enough and you do not need to publish port `7867` on the host + +If you prefer injecting a custom config snippet into `nginx-proxy`, create a file at +`/etc/nginx/vhost.d/cloud.example.com` with the following block: + +```nginx +location ^~ /push/ { + proxy_pass http://notify_push:7867/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} +``` + +Again, both trailing slashes in `/push/` and in `proxy_pass` are required. + #### Apache To use apache as a reverse proxy you first need to enable the proxy modules using @@ -328,6 +392,57 @@ the push server is listening. The app will automatically run some tests to verify that the push server is configured correctly. +### Testing + +After finishing the configuration, test it at several levels: + +1. Configure the push server URL in Nextcloud: + +```bash +occ app:enable notify_push +occ notify_push:setup https://cloud.example.com/push +``` + +2. Run the self-test: + +```bash +occ notify_push:self-test +``` + +3. Verify that the proxy responds correctly: + +```bash +curl -I https://cloud.example.com/push +curl -I https://cloud.example.com/push/ +``` + +Expected behavior: + +- `/push` returns `301` redirecting to `/push/` +- `/push/` does not return `502` or another proxy upstream error + +4. Generate a notification in Nextcloud and watch the `notify_push` logs. For example, keep a browser session open in +Nextcloud and create a notification, a Talk message, or a file change. Then verify that the service logs connections +and events. + +With Docker Compose: + +```bash +docker compose logs -f notify_push +``` + +If you need more detail while testing, temporarily increase the log level: + +```bash +occ notify_push:log debug +``` + +After verification, restore the previous log level: + +```bash +occ notify_push:log --restore +``` + ### Logging By default, the push server only logs warnings, you can temporarily change the log level with an occ command diff --git a/README.pt-BR.md b/README.pt-BR.md new file mode 100644 index 00000000..814875b6 --- /dev/null +++ b/README.pt-BR.md @@ -0,0 +1,506 @@ + + +# Client Push + +[![REUSE status](https://api.reuse.software/badge/github.com/nextcloud/notify_push)](https://api.reuse.software/info/github.com/nextcloud/notify_push) + +Versao em portugues do README. Versao original em ingles: [README.md](./README.md) + +Notificacoes de atualizacao para clientes Nextcloud + +## Documentacao adicional + +- Executar o container localmente e publicar imagens no GHCR: + [`docs/docker-ghcr.md`](./docs/docker-ghcr.md) +- Implantar o servico em um stack Nextcloud Docker existente: + [`deploy/nextcloud/README.md`](./deploy/nextcloud/README.md) + +## Sobre + +Este app tenta resolver o problema de os clientes Nextcloud precisarem verificar periodicamente o servidor para saber +se algum arquivo foi alterado. Para manter a sincronizacao responsiva, os clientes tendem a verificar atualizacoes com +frequencia, o que aumenta a carga no servidor. + +Quando muitos clientes fazem essas verificacoes ao mesmo tempo, uma parte consideravel da carga do servidor pode +consistir apenas nessas checagens. + +Ao fornecer uma forma de o servidor enviar notificacoes de atualizacao para os clientes, a necessidade dessas +checagens pode ser bastante reduzida. + +As notificacoes de atualizacao sao fornecidas em regime de "melhor esforco". Pode haver atualizacoes sem notificacao +e tambem pode haver notificacao sem que uma atualizacao real tenha acontecido. Os clientes ainda devem executar +verificacoes periodicas por conta propria, embora com uma frequencia bem menor. + +## Requisitos + +Este app exige um servidor Redis configurado e o Nextcloud tambem precisa estar configurado para usar esse Redis. + +## Configuracao rapida + +O app inclui um assistente de configuracao que deve orientar a maior parte dos cenarios. + +- Instale o app "Client Push" (`notify_push`) pela App Store +- Execute `occ notify_push:setup` e siga as instrucoes exibidas. + Se o assistente falhar, as instrucoes manuais estao abaixo. + +## Configuracao manual + +A configuracao envolve quatro etapas: + +- Instalar o app `notify_push` pela App Store +- Configurar o servidor push +- Configurar o proxy reverso +- Configurar o app no Nextcloud + +> __Para usuarios do Nextcloud Snap:__ \ +> A equipe do snap publicou uma pagina na wiki explicando como instalar o Client Push no Nextcloud Snap. +> +> Veja [a pagina da wiki](https://github.com/nextcloud-snap/nextcloud-snap/wiki/Configure-HPB-client-push-for-Nextcloud-snap)! + +### Servidor push + +O servidor push deve rodar como daemon em segundo plano. A forma recomendada e configura-lo como servico do sistema no +seu init system. +Se voce nao usa systemd, qualquer sistema de init ou gerenciamento de processos que execute o binario do push server +com as variaveis de ambiente descritas tambem funcionara. + +#### systemd + +Em setups baseados em systemd, crie o arquivo `/etc/systemd/system/notify_push.service` com o conteudo abaixo. + +```ini +[Unit] +After=network.target mariadb.service nginx.service postgresql.service redis.service +Description = Push daemon for Nextcloud clients +Documentation = https://github.com/nextcloud/notify_push + +[Service] +# Altere se esta porta ja estiver em uso +Environment = PORT=7867 +ExecStart = /path/to/push/binary/notify_push /path/to/nextcloud/config/config.php +# exige que o push server tenha sido compilado com a feature systemd (habilitada por padrao) +Type = notify +User = www-data +Restart = always +RestartSec = 60 + +[Install] +WantedBy = multi-user.target +``` + +Se o push server nao tiver sido compilado com a feature opcional de systemd, remova a linha `Type=notify`. + +#### OpenRC + +Em setups baseados em OpenRC, crie o arquivo `/etc/init.d/notify_push` com o conteudo abaixo. + +```sh +#!/sbin/openrc-run + +description="Push daemon for Nextcloud clients" + +output_log=${output_log:-/var/log/$RC_SVCNAME.log} +pidfile=${pidfile:-/run/$RC_SVCNAME.pid} + +command=${command:-/path/to/push/binary/notify_push} +command_user=${command_user:-www-data:www-data} +command_args="--port 7867 /path/to/nextcloud/config/config.php" +command_background=true + +depend() { + need net + use nginx php-fpm8 mariadb postgresql redis +} + +start_pre() { + checkpath --file --owner $command_user $output_log +} +``` + +Ajuste os caminhos, portas e usuario conforme necessario. + +#### Configuracao + +O push server pode ser configurado de duas formas: carregando os dados do `config.php` do Nextcloud ou definindo todas +as opcoes via variaveis de ambiente. + +Reutilizar a configuracao do Nextcloud e o metodo recomendado, porque garante que tudo continue sincronizado. + +Se nao for possivel usar `config.php`, configure o push server com as seguintes variaveis: + +- `DATABASE_URL` URL de conexao com o banco do Nextcloud, por exemplo + `postgres://user:password@db_host/db_name` +- `DATABASE_PREFIX` prefixo das tabelas configurado no Nextcloud, por exemplo `oc_` +- `REDIS_URL` URL de conexao com o Redis, por exemplo `redis://redis_host` +- `NEXTCLOUD_URL` URL da instancia Nextcloud, por exemplo `https://cloud.example.com` + +Voce tambem pode fornecer essas opcoes como argumentos de linha de comando. Consulte `notify_push --help`. + +Se a mesma opcao for definida em varias fontes, os argumentos de linha de comando sobrescrevem os valores das +variaveis de ambiente, que por sua vez sobrescrevem os valores lidos de `config.php`. + +A porta em que o servidor escuta so pode ser configurada por `PORT` ou pelo argumento `--port`, e o padrao e `7867`. +Alternativamente, voce pode fazer o servidor escutar em um socket Unix com `SOCKET_PATH` ou `--socket-path`. + +Observe que o Nextcloud carrega todos os arquivos `*.config.php` no diretorio de configuracao, alem do arquivo +principal. Para reproduzir esse mesmo comportamento, use a opcao `--glob-config`. + +
+Usando uma instancia Redis separada para o push server + + +Opcionalmente, voce pode usar uma instancia Redis separada para a comunicacao entre o servidor Nextcloud e o daemon +push. + +Isso ajuda a deslocar a carga do Redis principal ou a usar um setup mais otimizado para esse uso especifico +(`PUBSUB` em vez de cache). + +Voce pode configurar isso adicionando a opcao `notify_push_redis` no `config.php` do servidor Nextcloud. Ela aceita os +mesmos parametros da configuracao Redis padrao. + +
+ +
+Conectando ao Redis via TLS + + +Voce pode conectar ao Redis via TLS usando `rediss://` como URL do Redis. + +O certificado e a chave do cliente podem ser definidos pelos argumentos `--redis-tls-cert` e `--redis-tls-key` +(ou pelas variaveis `REDIS_TLS_CERT` e `REDIS_TLS_KEY`). +O certificado da autoridade certificadora para validar o certificado do servidor pode ser definido por +`--redis-tls-ca` (ou `REDIS_TLS_CA`). + +Adicionalmente, voce pode desabilitar a validacao do hostname do certificado do servidor com +`--redis-tls-dont-validate-hostname` ou desabilitar toda a validacao de certificados com +`--redis-tls-insecure` (ou com as variaveis `REDIS_TLS_DONT_VALIDATE_HOSTNAME` e `REDIS_TLS_INSECURE`). + +
+ +#### Configuracao TLS + +O push server tambem pode servir trafego via TLS. Isso e pensado principalmente para proteger o trafego entre o push +server e o proxy reverso quando eles estiverem em hosts diferentes. Rodar sem proxy reverso ou load balancer nao e +recomendado. + +O TLS pode ser habilitado com os argumentos `--tls-cert` e `--tls-key` (ou pelas variaveis `TLS_CERT` e `TLS_KEY`). + +#### Iniciando o servico + +Depois que o arquivo do servico systemd estiver configurado corretamente, voce pode inicia-lo com: + +- systemd: `sudo systemctl start notify_push` +- OpenRc: `sudo rc-service notify_push start` + +E habilitar o inicio automatico no boot com: + +- systemd: `sudo systemctl enable notify_push` +- OpenRc: `sudo rc-update add notify_push` + +Sempre que este app receber uma atualizacao, reinicie o servico: + +- systemd: `sudo systemctl restart notify_push` +- OpenRc: `sudo rc-service notify_push restart` + +
+Alternativamente, voce pode automatizar isso via systemctl criando o servico e o path abaixo (clique para expandir) + +Primeiro, crie um servico oneshot para reiniciar o daemon. + +`/etc/systemd/system/notify_push-watcher.service` + +```ini +[Unit] +Description = Restart Push daemon for Nextcloud clients when it receives updates +Documentation = https://github.com/nextcloud/notify_push +Requires = notify_push.service +After = notify_push.service +StartLimitIntervalSec = 10 +StartLimitBurst = 5 + +[Service] +Type = oneshot +ExecStart = /usr/bin/systemctl restart notify_push.service + +[Install] +WantedBy = multi-user.target +``` + +Depois, crie um `path` para acionar o restart sempre que o binario mudar. + +`/etc/systemd/system/notify_push-watcher.path` + +```ini +[Unit] +Description = Restart Push daemon for Nextcloud clients when it receives updates +Documentation = https://github.com/nextcloud/notify_push +PartOf = notify_push-watcher.service + +[Path] +PathModified = /path/to/push/binary/notify_push +Unit = notify_push-watcher.service + +[Install] +WantedBy = multi-user.target +``` + +Ajuste o caminho conforme necessario. + +Por fim, habilite com: + +```bash +sudo systemctl enable notify_push-watcher.path +``` + +
+ +### Proxy reverso + +E **fortemente** recomendado colocar o servico push atras de um proxy reverso. Isso evita expor uma porta adicional na +internet e tambem faz a terminacao TLS para nao enviar credenciais em texto puro. + +Voce provavelmente pode usar o mesmo servidor web que ja atende seu Nextcloud. + +#### Nginx + +Se voce usa nginx, adicione o bloco `location` abaixo ao bloco `server` existente do Nextcloud. + +```nginx +location ^~ /push/ { + proxy_pass http://127.0.0.1:7867/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} +``` + +Observe que as duas barras finais sao obrigatorias. + +Depois de editar a configuracao do nginx, recarregue com: + +```bash +sudo nginx -s reload +``` + +#### nginx-proxy + +Se voce usa o projeto [`nginx-proxy`](https://github.com/nginx-proxy/nginx-proxy) em Docker, nao adicione o bloco +`location` manualmente no container do Nextcloud. Nesse caso, o `server` block e gerado pelo `nginx-proxy`, entao o +jeito mais simples e publicar o `notify_push` no mesmo host e no caminho `/push/`. + +Exemplo usando o dominio generico `cloud.example.com`: + +```yaml +services: + nextcloud: + image: nextcloud:apache + environment: + VIRTUAL_HOST: cloud.example.com + VIRTUAL_PATH: / + networks: + - reverse-proxy + - internal + + notify_push: + image: ghcr.io/nextcloud/notify_push:latest + environment: + PORT: "7867" + VIRTUAL_HOST: cloud.example.com + VIRTUAL_PATH: /push/ + VIRTUAL_DEST: / + VIRTUAL_PORT: "7867" + expose: + - "7867" + networks: + - reverse-proxy + - internal +``` + +Pontos importantes: + +- o `notify_push` precisa estar na mesma rede Docker do `nginx-proxy` +- use `VIRTUAL_PATH=/push/` com barra final +- use `VIRTUAL_DEST=/` para remover o prefixo `/push/` antes de encaminhar a requisicao +- em setups com `nginx-proxy`, normalmente `expose` e suficiente e voce nao precisa publicar a porta `7867` no host + +Se preferir injetar configuracao manualmente no `nginx-proxy`, voce pode criar um arquivo em +`/etc/nginx/vhost.d/cloud.example.com` com o bloco abaixo: + +```nginx +location ^~ /push/ { + proxy_pass http://notify_push:7867/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} +``` + +Observe novamente que as barras finais em `/push/` e no `proxy_pass` sao obrigatorias. + +#### Apache + +Para usar Apache como proxy reverso, primeiro habilite os modulos abaixo: + +```bash +sudo a2enmod proxy +sudo a2enmod proxy_http +sudo a2enmod proxy_wstunnel +``` + +Depois adicione estas linhas ao bloco `` usado pelo servidor Nextcloud. + +```apacheconf +ProxyPass /push/ws ws://127.0.0.1:7867/ws +ProxyPass /push/ http://127.0.0.1:7867/ +ProxyPassReverse /push/ http://127.0.0.1:7867/ +``` + +Em seguida, reinicie o Apache: + +```bash +sudo systemctl restart apache2 +``` + +#### Caddy v2 + +```Caddyfile +handle_path /push/* { + reverse_proxy http://127.0.0.1:7867 +} +``` + +### App do Nextcloud + +Depois que o push server e o proxy reverso estiverem configurados, habilite o app `notify_push` e informe onde o +servidor push esta escutando. + +- habilite o app com `occ app:enable notify_push` +- defina a URL do push server com `occ notify_push:setup https://cloud.example.com/push` + +O app executara alguns testes automaticamente para verificar se a configuracao esta correta. + +### Testes + +Depois de concluir a configuracao, teste nestes niveis: + +1. Configure a URL do push server no Nextcloud: + +```bash +occ app:enable notify_push +occ notify_push:setup https://cloud.example.com/push +``` + +2. Execute o autoteste: + +```bash +occ notify_push:self-test +``` + +3. Verifique se o proxy responde corretamente: + +```bash +curl -I https://cloud.example.com/push +curl -I https://cloud.example.com/push/ +``` + +O comportamento esperado e: + +- `/push` responder com `301` para `/push/` +- `/push/` nao responder com `502` ou outro erro de upstream do proxy + +4. Gere uma notificacao no Nextcloud e acompanhe os logs do `notify_push`. Por exemplo, abra o Nextcloud em um +navegador, mantenha a sessao ativa e crie uma notificacao, uma mensagem no Talk ou uma alteracao de arquivo. Em +seguida, observe se o servico registra conexoes e eventos. + +Em Docker Compose: + +```bash +docker compose logs -f notify_push +``` + +Se precisar de mais detalhes durante o teste, aumente temporariamente o nivel de log: + +```bash +occ notify_push:log debug +``` + +Depois de concluir a verificacao, restaure o nivel anterior: + +```bash +occ notify_push:log --restore +``` + +### Logs + +Por padrao, o push server registra apenas avisos. Voce pode alterar temporariamente o nivel de log com: + +```bash +occ notify_push:log +``` + +Onde `level` pode ser `error`, `warn`, `info`, `debug` ou `trace`. Para restaurar o nivel anterior: + +```bash +occ notify_push:log --restore +``` + +Alternativamente, voce pode definir o nivel de log pela variavel `LOG`. + +### Metricas + +O push server pode expor metricas basicas sobre numero de clientes conectados e trafego, definindo a variavel +`METRICS_PORT`. +Por padrao, o endpoint de metricas escuta em todas as interfaces (`0.0.0.0`). +Tambem e possivel fazer o listener de metricas escutar em um socket Unix local usando `METRICS_SOCKET_PATH`. + +Depois disso, as metricas ficam disponiveis em formato compativel com Prometheus no endpoint `/metrics`, na porta ou +socket configurado. + +Voce tambem pode consultar as metricas manualmente com `occ notify_push:metrics`, mesmo sem configurar +`METRICS_PORT` ou `METRICS_SOCKET_PATH`. + +### Certificados autoassinados + +Se o seu Nextcloud usa certificado autoassinado, voce precisa definir `NEXTCLOUD_URL` para uma URL local nao HTTPS ou +desabilitar a verificacao de certificado com `ALLOW_SELF_SIGNED=true`. + +## Troubleshooting + +Ao encontrar problemas, primeiro confirme que voce esta usando a release mais recente. O problema pode ja ter sido +corrigido ou a versao nova pode trazer diagnosticos adicionais. + +### "push server is not a trusted proxy" + +- Garanta que voce nao adicionou uma lista `trusted_proxies` duplicada no `config.php`. +- Se voce alterou `forwarded_for_headers`, garanta que `HTTP_X_FORWARDED_FOR` esteja incluido. +- Se o hostname do seu Nextcloud resolve para um IP dinamico, tente definir `NEXTCLOUD_URL` com o IP interno do + servidor. + + Alternativamente, editar `/etc/hosts` para apontar o dominio do Nextcloud para o IP interno pode funcionar em alguns + setups. +- Se seu ambiente roda em Docker e os containers estao interligados, normalmente voce pode usar o nome do container do + Nextcloud como hostname em `NEXTCLOUD_URL`. + +## Desenvolvimento + +Para saber como usar o push server no seu proprio app ou cliente, consulte [DEVELOPING.md](./DEVELOPING.md) + +## Cliente de teste + +Para desenvolvimento e testes, existe um cliente de teste que pode ser baixado na +[release atual](https://github.com/nextcloud/notify_push/releases/latest).
+(Clique no `test_client` da sua plataforma para baixar o binario.) + +```bash +test_client https://cloud.example.com username password +``` + +Observe que ele nao suporta autenticacao de dois fatores nem fluxos de login nao padrao. Nesses casos, use uma senha +de app. diff --git a/deploy/nextcloud/README.md b/deploy/nextcloud/README.md new file mode 100644 index 00000000..09efda83 --- /dev/null +++ b/deploy/nextcloud/README.md @@ -0,0 +1,90 @@ + + +# Implantacao em um stack Nextcloud existente + +Estes arquivos reproduzem a configuracao necessaria para executar o `notify_push` +em Docker quando Nextcloud, PostgreSQL, Redis e Nginx ja existem. + +## 1. Configure as conexoes + +Copie o modelo para o diretorio do Compose do Nextcloud: + +```bash +cp env.notify-push.example /caminho/do/nextcloud/.env.notify_push +chmod 0600 /caminho/do/nextcloud/.env.notify_push +``` + +Edite `DATABASE_URL`, `DATABASE_PREFIX`, `REDIS_URL` e `NEXTCLOUD_URL`. +A senha inserida em `DATABASE_URL` deve usar percent-encoding. Para codificar +somente a senha: + +```bash +php -r 'echo rawurlencode($argv[1]), PHP_EOL;' 'SENHA' +``` + +Nao inclua `.env.notify_push` no Git. + +## 2. Confira os nomes das redes + +O overlay usa por padrao as redes Docker `internal`, `postgres` e `redis`. +Quando os nomes forem diferentes, defina no arquivo `.env` principal do stack: + +```dotenv +NEXTCLOUD_NETWORK=nome_da_rede_nextcloud +POSTGRES_NETWORK=nome_da_rede_postgres +REDIS_NETWORK=nome_da_rede_redis +``` + +Os hostnames usados em `DATABASE_URL` e `REDIS_URL` tambem precisam resolver +nessas redes. + +## 3. Adicione a rota ao Nginx + +Copie `nginx.notify-push.conf` para um diretorio incluido dentro do bloco +`server` do Nginx. Em um serviço `web` com includes montados, por exemplo: + +```yaml +services: + web: + volumes: + - ./volumes/nginx/includes:/etc/nginx/conf.d/includes:ro +``` + +```bash +cp nginx.notify-push.conf \ + /caminho/do/nextcloud/volumes/nginx/includes/notify_push.conf +``` + +O Nginx e o `notify_push` precisam compartilhar a rede configurada em +`NEXTCLOUD_NETWORK`. + +## 4. Inicie e valide + +Execute a partir do diretorio do stack Nextcloud, informando o overlay: + +```bash +docker compose \ + -f docker-compose.yml \ + -f docker-compose.override.yml \ + -f /caminho/do/notify_push/deploy/nextcloud/compose.notify-push.yml \ + up -d notify_push + +docker compose exec -T web nginx -t +docker compose exec -T web nginx -s reload +docker compose exec -T app php occ notify_push:setup https://cloud.example.com/push +docker compose exec -T app php occ notify_push:self-test +``` + +O resultado esperado do ultimo comando e: + +```text +✓ redis is configured +✓ push server is receiving redis messages +✓ push server can load mount info from database +✓ push server can connect to the Nextcloud server +✓ push server is a trusted proxy +✓ push server is running the same version as the app +``` diff --git a/deploy/nextcloud/compose.notify-push.yml b/deploy/nextcloud/compose.notify-push.yml new file mode 100644 index 00000000..c49f7337 --- /dev/null +++ b/deploy/nextcloud/compose.notify-push.yml @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2026 LibreCode contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Overlay para uma instalacao Nextcloud que ja possui PostgreSQL, Redis e +# um proxy web nas redes indicadas abaixo. +services: + notify_push: + image: "${NOTIFY_PUSH_IMAGE:-ghcr.io/librecodecoop/notify_push:edge}" + restart: unless-stopped + env_file: + - .env.notify_push + environment: + PORT: "7867" + expose: + - "7867" + networks: + - nextcloud + - postgres + - redis + labels: + - com.centurylinklabs.watchtower.enable=true + deploy: + resources: + limits: + cpus: "2" + memory: 256M + reservations: + cpus: "0.25" + memory: 64M + +networks: + nextcloud: + external: true + name: "${NEXTCLOUD_NETWORK:-internal}" + postgres: + external: true + name: "${POSTGRES_NETWORK:-postgres}" + redis: + external: true + name: "${REDIS_NETWORK:-redis}" diff --git a/deploy/nextcloud/env.notify-push.example b/deploy/nextcloud/env.notify-push.example new file mode 100644 index 00000000..a1083408 --- /dev/null +++ b/deploy/nextcloud/env.notify-push.example @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2026 LibreCode contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Copie para .env.notify_push e aplique chmod 0600. +# A senha precisa estar codificada para uso em URL (percent-encoding). +DATABASE_URL=postgres://nextcloud:URL_ENCODED_PASSWORD@postgres/nextcloud + +# Use uma string vazia quando a instalacao nao possuir prefixo. +DATABASE_PREFIX= + +REDIS_URL=redis://redis:6379/0 +NEXTCLOUD_URL=https://cloud.example.com +LOG=info diff --git a/deploy/nextcloud/nginx.notify-push.conf b/deploy/nextcloud/nginx.notify-push.conf new file mode 100644 index 00000000..307c3218 --- /dev/null +++ b/deploy/nextcloud/nginx.notify-push.conf @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2026 LibreCode contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +location ^~ /push/ { + proxy_pass http://notify_push:7867/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} diff --git a/docker-compose.example.yml b/docker-compose.example.yml new file mode 100644 index 00000000..3d08bc39 --- /dev/null +++ b/docker-compose.example.yml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2026 LibreCode contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +services: + notify_push: + image: ghcr.io/librecodecoop/notify_push:edge + build: + context: . + restart: unless-stopped + ports: + - "${NOTIFY_PUSH_PORT:-7867}:7867" + environment: + PORT: "7867" + NEXTCLOUD_URL: "https://cloud.example.com" + DATABASE_URL: "postgres://nextcloud:change-me@db/nextcloud" + DATABASE_PREFIX: "oc_" + REDIS_URL: "redis://redis:6379/0" + LOG: "info" diff --git a/docs/docker-ghcr.md b/docs/docker-ghcr.md new file mode 100644 index 00000000..983836fc --- /dev/null +++ b/docs/docker-ghcr.md @@ -0,0 +1,108 @@ + + +# Docker and GHCR + +This repository already ships a multi-stage `Dockerfile` that compiles `notify_push` as a static binary and copies it +into a minimal runtime image. + +## Build locally + +```bash +docker build -t notify_push:local . +``` + +## Run locally + +You can run the container in two supported ways. + +### Option 1: Load the Nextcloud `config.php` + +This is the recommended option because `notify_push` reuses the same database and redis configuration already used by +Nextcloud. + +```bash +docker run --rm \ + -p 7867:7867 \ + -e PORT=7867 \ + -v /path/to/nextcloud/config:/config:ro \ + notify_push:local \ + /config/config.php +``` + +### Option 2: Configure everything with environment variables + +```bash +docker run --rm \ + -p 7867:7867 \ + -e PORT=7867 \ + -e NEXTCLOUD_URL=https://cloud.example.com \ + -e DATABASE_URL=postgres://nextcloud:change-me@db/nextcloud \ + -e DATABASE_PREFIX=oc_ \ + -e REDIS_URL=redis://redis:6379/0 \ + -e LOG=info \ + notify_push:local +``` + +## Docker Compose example + +An example service definition is available in [`docker-compose.example.yml`](../docker-compose.example.yml). + +```bash +cp docker-compose.example.yml docker-compose.yml +docker compose up -d --build +docker compose logs -f notify_push +``` + +For an existing Dockerized Nextcloud installation, use the production overlay, +environment template, and Nginx route in +[`deploy/nextcloud/`](../deploy/nextcloud/README.md). That example attaches the +push server to the same Nextcloud, PostgreSQL, and Redis networks and keeps the +database URL outside the Compose file. + +If you prefer using `config.php` in Compose, mount the config directory and add: + +```yaml +command: + - /config/config.php +volumes: + - /path/to/nextcloud/config:/config:ro +``` + +The path configured as `datadirectory` must also exist inside the container at +the same absolute path. For Dockerized Nextcloud installations, environment +variables are usually less error-prone than parsing `config.php`. + +## Reverse proxy and app setup + +After the container is running, configure the reverse proxy exactly as described in the main +[`README.md`](../README.md), then point the app to the public push endpoint: + +```bash +occ notify_push:setup https://cloud.example.com/push +``` + +## Publish manually to GHCR + +Replace `librecodecoop` with your GitHub org or username if needed. + +```bash +docker build -t ghcr.io/librecodecoop/notify_push:dev . +echo "$GHCR_TOKEN" | docker login ghcr.io -u YOUR_GITHUB_USER --password-stdin +docker push ghcr.io/librecodecoop/notify_push:dev +``` + +The token needs `write:packages`. If the package should be pulled by anonymous users, set the package visibility to +public in GitHub after the first push. + +## Automatic publication with GitHub Actions + +The workflow in `.github/workflows/docker-ghcr.yml` does the following: + +- Builds the Docker image on pull requests. +- Publishes `edge` and branch tags to `ghcr.io//` on pushes to `main`. +- Publishes version tags when a Git tag like `v1.2.3` is pushed. + +GitHub's built-in `GITHUB_TOKEN` is enough as long as the workflow has `packages: write`. diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index 1b3e3297..827259ae 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -79,16 +79,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.1", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -127,7 +127,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -135,20 +135,20 @@ "type": "tidelift" } ], - "time": "2024-11-08T17:47:46+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -167,7 +167,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -191,9 +191,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", @@ -634,16 +634,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.22", + "version": "9.6.33", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" + "reference": "fea06253ecc0a32faf787bd31b261f56f351d049" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", - "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fea06253ecc0a32faf787bd31b261f56f351d049", + "reference": "fea06253ecc0a32faf787bd31b261f56f351d049", "shasum": "" }, "require": { @@ -654,7 +654,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -665,11 +665,11 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", + "sebastian/comparator": "^4.0.10", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", + "sebastian/exporter": "^4.0.8", + "sebastian/global-state": "^5.0.8", "sebastian/object-enumerator": "^4.0.4", "sebastian/resource-operations": "^3.0.4", "sebastian/type": "^3.2.1", @@ -717,7 +717,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.33" }, "funding": [ { @@ -728,12 +728,20 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2024-12-05T13:48:26+00:00" + "time": "2026-01-27T05:25:09+00:00" }, { "name": "sebastian/cli-parser", @@ -904,16 +912,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", "shasum": "" }, "require": { @@ -966,15 +974,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2026-01-24T09:22:56+00:00" }, { "name": "sebastian/complexity", @@ -1164,16 +1184,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -1229,28 +1249,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", "shasum": "" }, "require": { @@ -1293,15 +1325,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2025-08-10T07:10:35+00:00" }, { "name": "sebastian/lines-of-code", @@ -1474,16 +1518,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", "shasum": "" }, "require": { @@ -1525,15 +1569,27 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2025-08-10T06:57:39+00:00" }, { "name": "sebastian/resource-operations", @@ -1700,16 +1756,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -1738,7 +1794,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -1746,7 +1802,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" } ], "aliases": [], @@ -1759,5 +1815,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/vendor-bin/psalm/composer.lock b/vendor-bin/psalm/composer.lock index 81815631..8e65a168 100644 --- a/vendor-bin/psalm/composer.lock +++ b/vendor-bin/psalm/composer.lock @@ -1300,16 +1300,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -1322,7 +1322,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -1347,7 +1347,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -1363,7 +1363,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", @@ -1433,16 +1433,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.4.48", + "version": "v5.4.50", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "3f38b8af283b830e1363acd79e5bc3412d055341" + "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3f38b8af283b830e1363acd79e5bc3412d055341", - "reference": "3f38b8af283b830e1363acd79e5bc3412d055341", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1a0706e8b8041046052ea2695eb8aeee04f97609", + "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609", "shasum": "" }, "require": { @@ -1489,7 +1489,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.48" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.50" }, "funding": [ { @@ -1500,12 +1500,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-13T18:58:02+00:00" + "time": "2025-11-03T12:58:48+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1747,19 +1751,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -1807,7 +1812,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -1818,25 +1823,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -1887,7 +1896,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -1898,12 +1907,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/service-contracts", @@ -2253,5 +2266,5 @@ "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" }