okvpn/packeton

为供应商的私有 PHP 包仓库

安装: 114

依赖: 0

建议者: 0

安全: 0

星标: 397

关注者: 4

分支: 63

开放问题: 29

类型:项目

v2.6.0 2024-09-15 12:58 UTC

README

Run Tests PHP Version Require Hits-of-Code Docker pulls License

Fork 自 Packagist。作为 Private Packagist for vendors 的开源替代品,基于 SatisPackagist

完整文档 docs.packeton.org

功能

  • 兼容 Composer API v2,基于 Symfony 6。
  • 支持 GitHub、Gitea、Bitbucket 和 GitLab 或自定义格式的更新 webhook。
  • 客户用户和 ACL 组,以及通过供应商和版本限制访问。
  • Composer 代理和镜像。
  • 通用的 Packeton webhooks
  • 允许在客户许可证过期后冻结新版本的更新。
  • 包的 zip 文件和下载镜像,从您的服务器上下载。
  • 凭据和身份验证 http-basic 配置或 ssh 密钥。
  • 支持单体仓库,如 symfony/symfony
  • 拉取请求 composer.lock 变更审查。
  • OAuth2 GitHub、Bitbucket、GitLab/Gitea 和其他集成。
  • 安全监控。
  • 多子仓库。

这个分支有什么变化?

  • 禁用匿名访问、注册、垃圾邮件/反垃圾邮件,添加 ACL 权限。
  • 支持 MySQL、PostgreSQL 或 SQLite。
  • 移除了 HWIOBundle、Algolia、GoogleAnalytics 和其他未使用依赖项以及其他指标收集器。

目录表

演示

查看我们的 管理演示。用户名/密码(admin/123456)

Demo

使用 Docker 安装和运行

您可以使用 packeton/packeton 镜像或 GitHub 容器注册表的 ghcr.io/vtsykun/packeton:latest 镜像

docker run -d --name packeton \
    --mount type=volume,src=packeton-data,dst=/data \
    -p 8080:80 \
    packeton/packeton:latest

容器运行后,您可以通过命令 packagist:user:manager 创建管理员用户

docker exec -it packeton bin/console packagist:user:manager admin --password=123456 --admin

或者使用 docker-compose 构建、运行 docker 容器

  • docker-compose.yml 单个容器示例,这里容器运行 supervisor 以启动其他任务:nginx、redis、php-fpm、cron、worker。然而,它并不遵循 docker 最佳实践,即每个服务必须在一个容器中。但使用起来非常简单,遵循了 KISS 原则

  • docker-compose-split.yml - 多个容器,其中每个容器一个服务

docker-compose build

docker-compose up -d # Run with single supervisor container 
docker-compose up -f docker-compose-split.yml -d # Or split 

Docker 环境变量

  • APP_SECRET - 必须是静态的,用于在数据库中加密 SSH 密钥。值自动生成,请参阅数据卷中的 .env
  • APP_COMPOSER_HOME - composer 主目录,默认 /data/composer
  • DATABASE_URL - 数据库 DSN,默认 sqlite:////data/app.db. 例如 postgres "postgresql://app:pass@127.0.0.1:5432/app?serverVersion=14&charset=utf8"
  • PACKAGIST_DIST_PATH - 默认 /data/zipball,存储压缩版本的路径
  • REDIS_URL - Redis 数据库,默认 redis://#
  • PACKAGIST_DIST_HOST - 主机名,(自动) 默认使用请求中的当前主机头。
  • TRUSTED_PROXIES - 反向代理的 IPs。参见 Symfony 文档
  • TRUSTED_HOSTS - 信任的主机,如果已启用公共访问且你的 nginx 配置使用 server_name,则需要设置。否则,可能存在因每个主机生成大量缓存而导致 DDoS 攻击的风险。
  • PUBLIC_ACCESS - 允许匿名用户访问读取包元数据,默认:false
  • MAILER_DSN - 重置密码的邮件发送者,默认禁用
  • MAILER_FROM - 邮件发送者

安装

需求

  • PHP 8.1+
  • Redis 用于某些功能(收藏、下载统计、工作队列)。
  • git/svn/hg 取决于你想要支持的仓库。
  • Supervisor 运行后台工作进程
  • (可选) MySQL 或 PostgreSQL 作为主数据存储,默认 SQLite
  1. 克隆仓库
  2. 安装依赖项:composer install
  3. 创建 .env.local 并将需要的环境变量复制到其中,参见 Docker 环境变量部分
  4. 运行 bin/console doctrine:schema:update --force --complete 来设置数据库
  5. 通过控制台创建管理员用户。
php bin/console packagist:user:manager username --email=admin@example.com --password=123456 --admin 
  1. (可选) 如果你更改了配置文件,那么你需要清除缓存 rm -rf var/cache/*php bin/console cache:clear

  2. 启用 cron tabs 和后台作业。启用 crontab crontab -e -u www-data 或使用 Docker 友好的内置 cron 需求运行器。

* * * * * /var/www/packagist/bin/console okvpn:cron >> /dev/null

示例,作为后台进程运行 cron 而不使用 crontab。可以与 supervisor 一起使用。

bin/console okvpn:cron --demand

设置 Supervisor 以运行工作进程。

sudo apt -y --no-install-recommends install supervisor

创建一个新的 Supervisor 配置文件。

sudo vim /etc/supervisor/conf.d/packagist.conf

将以下行添加到文件中。

[program:packagist-workers]
environment =
        HOME=/var/www/
command=/var/www/packagist/bin/console packagist:run-workers --env=prod --no-debug
directory=/var/www/packagist/
process_name=%(program_name)s_%(process_num)02d
numprocs=1
autostart=true
autorestart=true
startsecs=0
redirect_stderr=true
priority=1
user=www-data
  1. 重要 确保 web-server、cron 和 supervisor 在同一用户下运行,该用户应有一个 ssh 密钥,该密钥提供对 git/svn/hg 仓库的读取(克隆)访问。如果你在 www-data 下运行应用程序,你可以将你的 ssh 密钥添加到 /var/www/.ssh/

你现在应该能够访问该站点,创建用户等。

  1. 创建一个 VirtualHost,DocumentRoot 指向 public/

SSH 密钥访问和 composer oauth 令牌。

Packagist 使用 Composer 全局配置和全局 ssh-key 来获取对您的仓库的读取访问,因此 supervisor 工作进程 packagist:run-workers 和 web-server 必须在具有 ssh 密钥或 composer 配置以提供对您的 git/svn/hg 仓库的读取(克隆)访问的用户下运行。例如,如果您的应用程序在 www-data 下运行并且具有主目录 /var/www,则目录结构必须如下所示。

    └── /var/www/
        └── .ssh/ # ssh keys directory
            ├── config
            ├── id_rsa # main ssh key
            ├── private_key_2 # additional ssh key
            └── private_key_3

示例 ssh 配置,用于多个 SSH 密钥和不同的 github 账户/仓库,请参阅 此处 了解详细信息

# .ssh/config - example

Host github-oroinc
	HostName github.com
	User git
	IdentityFile /var/www/.ssh/private_key_2
	IdentitiesOnly yes

Host github-org2
	HostName github.com
	User git
	IdentityFile /var/www/.ssh/private_key_3
	IdentitiesOnly yes

如果你遇到错误 此私钥无效,则是因为在管理员面板中插入 ssh 时,ssh 密钥是用较新的 OpenSSH 生成的。新密钥可以使用 ssh-keygen 工具转换为旧的 PEM 格式。ssh-keygen -p -m PEM -f ~/.ssh/id_rsa

你可以在 composer 主目录的 auth.json 中添加 GitHub/GitLab 访问令牌(默认 APP_COMPOSER_HOME="%kernel.project_dir%/var/.composer")或使用 UI 凭证,请参阅 此处

{
    "github-oauth": {
        "github.com": "xxxxxxxxxxxxx"
    }
}

允许连接到 http

你可以在 composer 主目录中创建 config.json(参见 APP_COMPOSER_HOME 环境变量)或在 UI 凭证表单中添加此选项。

{
    "secure-http": false
}

不要使用 GitHub Api。

默认情况下,我们禁用了GitHub API的使用,以强制使用ssh密钥或通过https克隆仓库,就像使用其他任何git仓库一样。您可以使用环境选项 GITHUB_NO_API 再次启用它,请参阅此处

配置

为了添加配置,请将任何名称的文件添加到文件夹 config/packages/* 中。配置将按照优先级合并默认值,按文件名排序。

Docker安装的配置位于 /data/config.yaml。您还可以使用docker volume将配置直接添加到路径 config/packages/ldap.yaml

...
        volumes:
            - .docker:/data
            - ${PWD}/ldap.yaml:/var/www/packagist/config/packages/ldap.yaml

/var/www/packagist/ 是Docker安装的默认根目录。

配置的完整示例。

packeton:
    github_no_api: '%env(bool:GITHUB_NO_API)%' # default true
    rss_max_items: 30
    archive: true

    # default false
    anonymous_access: '%env(bool:PUBLIC_ACCESS)%'

    anonymous_archive_access: '%env(bool:PUBLIC_ACCESS)%' # default false

    archive_options:
        format: zip
        basedir: '%env(resolve:PACKAGIST_DIST_PATH)%'
        endpoint: '%env(PACKAGIST_DIST_HOST)%' # default auto detect by host headers 
        include_archive_checksum: false
        prebuild_zipball: false # If true - will be created .zip package for each release (and uploaded to S3/storage). Default - build dynamically, only if requested

    # disable by default 
    jwt_authentication:
        algo: EdDSA
        private_key: '%kernel.project_dir%/var/jwt/eddsa-key.pem'
        public_key: '%kernel.project_dir%/var/jwt/eddsa-public.pem'
        passphrase: ~

    # See mirrors section
    mirrors: ~
    
    metadata:
        format: auto # Default, see about metadata.
        info_cmd_message: ~ # Bash logo, example - \u001b[37;44m#StandWith\u001b[30;43mUkraine\u001b[0m
    
    artifacts:
        # Allow uploading archives
        support_types: ['gz', 'tar', 'tgz', 'zip']
        #Allowed paths for artifact composer repo type
        allowed_paths:
            - '/data/hdd1/composer'
        # Default path to storage/(local cache for S3) of uploaded artifacts
        artifact_storage: '%composer_home_dir%/artifact_storage'

    web_protection: 
        ## Multi host protection, disable web-ui if host !== app.example.com and ips != 127.0.0.1, 10.9.1.0/24
        ## But the repo metadata will be available for all hosts and ips.
        repo_hosts: ['*', '!app.example.com'] 
        allow_ips: '127.0.0.1, 10.9.1.0/24'

元数据格式。

Packeton支持Composer 1和2的元数据。出于性能原因,对于Composer 1,根据用户代理头部使用元数据:如果ua != 1,则使用 providers-lazy-url;如果ua == 1,则使用 provider-includes

其中 UA 1 - Composer User-Agent = 1. UA 2 - Composer User-Agent = 2。

更新 webhook

您可以使用GitLab、Gitea、GitHub和Bitbucket项目的post-receive钩子来确保每次您推送代码时,您的包都保持最新。更简单的方法是使用组webhooks,以防止手动为每个仓库添加。

Bitbucket Webhooks

要启用Bitbucket web hook,请转到您的BitBucket仓库,打开设置并从菜单中选择“Webhooks”。添加一个新的钩子。您必须输入包含您的用户名和API令牌的Packagist端点。将URL输入为 https://<app>/api/bitbucket?token=user:token。保存您的更改并完成。

GitLab Service

要启用GitLab服务集成,请转到您的GitLab仓库,从菜单中选择设置 > 集成。在项目服务列表中搜索Packagist。勾选“Active”框,输入您的 packeton.org 用户名和API令牌。保存您的更改并完成。

GitLab Group Hooks

组webhooks将应用于组中的所有项目,并允许同步所有项目。要启用组GitLab webhook,您必须拥有付费计划。转到您的GitLab Group > 设置 > Webhooks。将URL输入为 https://<app>/api/update-package?token=user:token

GitHub Webhooks

要启用GitHub webhook,请转到您的GitHub仓库。点击“设置”按钮,点击“Webhooks”。添加一个新的钩子。将URL输入为 https://<app>/api/github?token=user:token

手动或其他钩子设置

如果您不使用Bitbucket或GitHub,则有一个通用的端点,您可以从git post-receive钩子或类似的操作中手动调用。您必须向 https://example.org/api/update-package?token=user:api_token 发送POST请求,请求体如下所示

{
  "repository": {
    "url": "PACKAGIST_PACKAGE_URL"
  }
}

默认情况下,这将与Gitea一起工作。

您还可以在路径参数中使用包名,请参阅ApiController

https://example.org/api/update-package/acme/packet1?token=<token>

例如,您可以使用curl这样做

curl -XPOST -H 'content-type:application/json' 'https://example.org/api/update-package?token=user:api_token' -d' {"repository":{"url":"PACKAGIST_PACKAGE_URL"}}'

您可以使用包名而不是使用repo URL。您必须发送一个请求体为POST请求。

{
  "composer": {
    "package_name": "okvpn/test"
  }
}
{
  "composer": {
    "package_name": ["okvpn/test", "okvpn/pack2"]
  }
}

自定义webhook格式转换器

您可以创建一个代理中间件来将JSON有效负载转换为适用的内部格式。首先,您需要创建一个新的Rest端点以接受外部请求。

转到 设置 > Webhooks 并点击 添加webhook。填写表格

  • url - https://<app>/api/update-package?token=user:token
  • 更多选项 > 名称限制 - #your-unique-name#(必须是一个有效的正则表达式)
  • 触发 > 通过对 https://APP_URL/api/webhook-invoke/{name} 的HTTP请求 - 选择复选框
  • 有效负载 - 使用twig表达式编写一个脚本,以将外部请求转换为上一个示例中的POST请求。

例如,如果输入请求有一个格式,twig有效负载可能如下所示

{
   "repository":{
      "slug":"vtsykun-packeton",
      "id":11,
      "name":"vtsykun-packeton",
      "scmId":"git",
      "state":"AVAILABLE",
      "links": {
          "clone": [
              {"href": "https://github.com/vtsykun/packeton.git"}
          ]
      }
   }
}
{% set repository = request.repository.links.clone[0].href %}
{% if repository is null %}
    {{ interrupt('Request does not contains repository link') }}
{% endif %}

{% set response = {
    'repository': {'url': repository },
    'packeton': {'regex': '{^(?:ssh://git@|https?://|git://|git@)?(?P<host>[a-z0-9.-]+)(?::[0-9]+/|[:/])(scm/)?(?P<path>[\\w.-]+(?:/[\\w.-]+?)+)(?:\\.git|/)?$}i'} 
} %}

{{ response|json_encode }}

有关详细信息,请参阅twig表达式语法。

点击“保存按钮”

现在,如果您调用URL https://APP_URL/api/webhook-invoke/your-unique-name?token=<user>:<token>,请求将被转发到 https://APP_URL/api/update-package?token=user:token,并根据您的规则转换POST负载。

使用和认证

默认情况下,管理员用户可以访问所有仓库,可以提交包、创建用户、查看统计信息。客户用户只能查看相关的包和自己的个人资料,以及如何使用API令牌的说明。

为了认证Composer对仓库的访问,需要在全局auth.json文件中添加凭据,例如

composer config --global --auth http-basic.example.org <user> <token>

API令牌可以在您的个人资料中找到。

在您的composer.json文件中配置此私有仓库。

{
  "repositories": [{
      "type": "composer",
      "url": "https://packeton.company.com"
  }],
  "require": {
    "company/name1": "1.0.*",
    ....
  }
}

创建管理员和维护者用户。

应用程序角色

  • ROLE_USER - 最小访问级别,这些用户只能读取所选包的元数据。
  • ROLE_FULL_CUSTOMER - 可以读取所有包的元数据。
  • ROLE_MAINTAINER - 可以提交新的包并读取所有元数据。
  • ROLE_ADMIN - 可以创建新的客户用户、管理webhook和凭据。

您可以通过控制台使用fos user bundle命令创建用户,然后将其提升为管理员或维护者。

php bin/console packagist:user:manager username --email=admin@example.com --password=123456 --admin # create admin user
php bin/console packagist:user:manager user1 --add-role=ROLE_MAINTAINER # Add ROLE_MAINTAINER to user user1

许可协议

MIT