okvpn / packeton
为供应商的私有 PHP 包仓库
Requires
- php: >=8.1
- ext-redis: *
- babdev/pagerfanta-bundle: ^4.4
- cebe/markdown: ^1.1
- composer/composer: ^2.6
- doctrine/common: ^3
- doctrine/dbal: ^3.7
- doctrine/doctrine-bundle: ^2.9
- doctrine/orm: ^2.15
- ezyang/htmlpurifier: ^4.16 || dev-master
- firebase/php-jwt: ^6.5
- friendsofphp/proxy-manager-lts: ^1.0
- knplabs/knp-menu-bundle: ^3.2
- laminas/laminas-feed: ^2.20
- league/flysystem-async-aws-s3: ^3.15
- league/flysystem-bundle: ^3.1
- nelmio/cors-bundle: ^2.2
- nelmio/security-bundle: ^3.0
- okvpn/cron-bundle: ^1.1
- okvpn/expression-language: ^1.0
- oro/doctrine-extensions: ^2.0
- pagerfanta/core: ^4.2
- pagerfanta/doctrine-orm-adapter: ^4.2
- pagerfanta/twig: ^4.2
- snc/redis-bundle: ^4.4
- symfony/asset: ^6.4 || ^7.0
- symfony/console: ^6.4 || ^7.0
- symfony/debug-bundle: ^6.4 || ^7.0
- symfony/dotenv: ^6.4 || ^7.0
- symfony/expression-language: ^6.4 || ^7.0
- symfony/flex: ^2
- symfony/form: ^6.4 || ^7.0
- symfony/framework-bundle: ^6.4 || ^7.0
- symfony/http-client: ^6.4 || ^7.0
- symfony/ldap: ^6.4 || ^7.0
- symfony/lock: ^6.4 || ^7.0
- symfony/mailer: ^6.4 || ^7.0
- symfony/mime: ^6.4 || ^7.0
- symfony/monolog-bundle: ^3.8
- symfony/process: ^6.4 || ^7.0
- symfony/property-access: ^6.4 || ^7.0
- symfony/property-info: ^6.4 || ^7.0
- symfony/runtime: ^6.4 || ^7.0
- symfony/security-bundle: ^6.4 || ^7.0
- symfony/serializer: ^6.4 || ^7.0
- symfony/translation: ^6.4 || ^7.0
- symfony/twig-bundle: ^6.4 || ^7.0
- symfony/validator: ^6.4 || ^7.0
- symfony/var-exporter: ^6.4 || ^7.0
- symfony/web-link: ^6.4 || ^7.0
- symfony/yaml: ^6.4 || ^7.0
- twig/extra-bundle: ^3.4
- twig/string-extra: ^3.4
- twig/twig: ^3.0
Requires (Dev)
- phpunit/phpunit: ^10.0
- symfony/browser-kit: ^6.4 || ^7.0
- symfony/css-selector: ^6.4 || ^7.0
- symfony/maker-bundle: ^1
- symfony/stopwatch: ^6.4 || ^7.0
- symfony/web-profiler-bundle: ^6.4 || ^7.0
Conflicts
This package is auto-updated.
Last update: 2024-09-17 21:56:39 UTC
README
Fork 自 Packagist。作为 Private Packagist for vendors 的开源替代品,基于 Satis 和 Packagist。
完整文档 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 和其他未使用依赖项以及其他指标收集器。
目录表
- 作为 Docker 容器运行
- 演示
- 从代码安装
- 使用反向代理
- 出站 webhook
- SSH 密钥访问
- 配置
- LDAP 认证
- 从 Packagist.com 导入
- OAuth2 GitHub、GitLab 集成
- 更新 webhook
- 镜像 Composer 仓库
- S3 存储提供商
- 安全监控
- 比较 Private Packagist 与 Packeton
- 用法
演示
查看我们的 管理演示。用户名/密码(admin/123456)
使用 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/composerDATABASE_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
- 克隆仓库
- 安装依赖项:
composer install
- 创建 .env.local 并将需要的环境变量复制到其中,参见 Docker 环境变量部分
- 运行
bin/console doctrine:schema:update --force --complete
来设置数据库 - 通过控制台创建管理员用户。
php bin/console packagist:user:manager username --email=admin@example.com --password=123456 --admin
-
(可选) 如果你更改了配置文件,那么你需要清除缓存
rm -rf var/cache/*
或php bin/console cache:clear
-
启用 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
- 重要 确保 web-server、cron 和 supervisor 在同一用户下运行,该用户应有一个 ssh 密钥,该密钥提供对 git/svn/hg 仓库的读取(克隆)访问。如果你在
www-data
下运行应用程序,你可以将你的 ssh 密钥添加到 /var/www/.ssh/
你现在应该能够访问该站点,创建用户等。
- 创建一个 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