Nexus 3 OSS یک مدیر مخزن مصنوع منبع باز است که می تواند چندین فرمت مانند تصاویر ظرف، Python PIP، Java jar و بسیاری دیگر را مدیریت کند.

چرا یک مدیر مصنوع در محل وجود دارد؟ دلایل زیادی برای آن وجود دارد:

  • از زیرساخت خصوصی خود استفاده کنید: ممکن است کد اختصاصی داشته باشید که باید از آن محافظت شود.
  • سرعت دانلود مصنوعات سریعتر: اگر به طور مداوم همان مصنوعات را از طریق اینترنت دانلود می کنید، می توانید آنها را در یک مکان مرکزی ذخیره کنید تا با ذخیره کردن آنها برای چندین کاربر خود در چندین سرور، آنها را ذخیره کنید.
  • کنترل کنید چه مصنوعاتی به زنجیره ساخت شما می‌رسند: مکان مصنوع‌ها را متمرکز کنید، مطمئن شوید که برای استفاده تأیید شده‌اند، و همچنین تأیید کنید که حاوی کد مخرب نیستند.
  • جداسازی افرادی که می توانند به مصنوعات شما دسترسی داشته باشند: ممکن است شرایط سخت تری در مورد اینکه چه کسی می تواند به برخی از مصنوعات در سازمان خود دسترسی داشته باشد، داشته باشید.

در این مقاله به شما نشان خواهم داد که چگونه می توانید نسخه OSS Nexus 3 را با استفاده از یک کتاب بازی Ansible دانلود، نصب و پیکربندی کنید.

Nexus 3 روی یک رایانه Orange PI 5 با 8 گیگابایت یا رم اجرا می‌شود، اما این تدارک را می‌توان روی هر دستگاهی با حداقل نیازها انجام داد. بخشی از راه اندازی شامل تنظیم یک پروکسی برای PyPI.org، برای ماشین های فهرست شده در فایل موجودی من است.

آنچه برای اجرای کد از این آموزش نیاز دارید

  1. اتصال به اینترنت برای دانلود کد منبع برای ماژول‌های Ansible playbook، Nexus و PIP
  2. دو یا چند دستگاه لینوکس (من از Debian، Armbian و Fedora IOT استفاده کردم)، با حداقل 8 گیگابایت رم. کلاستر من ترکیبی از Raspberry PI 4 و OrangePI 5 دارد.
  3. کنترلر Ansible روی ماشین فدورا اجرا می شود، اما هر سروری می تواند کنترل کننده باشد. دستورالعمل های نصب Ansible به راحتی قابل پیگیری است.

سازمان کتاب بازی

من وظایف را به گروه تقسیم کردم و کتاب بازی به نظر می رسد این است:

[josevnz@dmaf5 Nexus3OnOrangePI]$ tree -N ansible/
ansible/
├── inventories
│   └── home
│       └── hosts.yaml
├── roles
│   ├── clients
│   │   ├── tasks
│   │   │   └── main.yaml
│   │   └── templates
│   │       └── pip.conf.j2
│   └── nexus
│       ├── files
│       │   └── swagger.json
│       ├── tasks
│       │   ├── download.yaml
│       │   ├── install.yaml
│       │   ├── main.yaml
│       │   ├── post_install.yaml
│       │   ├── pre_install.yaml
│       │   ├── repositories.yaml
│       │   ├── third_party.yaml
│       │   └── user.yaml
│       └── templates
│           ├── logrotate.nexus3.j2
│           ├── nexus3.service.j2
│           ├── nexus.rc.j2
│           └── nexus.vmoptions.j2
├── site.yaml
├── vars
│   ├── clients.yaml
│   └── nexus.yaml
└── vault
    ├── nexus_password.enc
    └── README.md

13 directories, 21 files

حالا کمی توضیح بدهم:

  • دو نقش وجود دارد: «مشتری» و «مشتری». نقش Nexus برای راه اندازی نرم افزار مدیریت مصنوع استفاده می شود، در حالی که نقش مشتری تنظیمات پیپ را در هر دستگاه تنظیم می کند.
  • Vars شامل متغیرهایی است که برای هر نقش استفاده می‌شود و با فایل‌ها از هم جدا می‌شوند تا کاربرد آن‌ها واضح‌تر شود
  • ما رمزهای عبور داریم و آنها را با استفاده از ویژگی Ansible vault مدیریت کردیم.
  • فایل “site.yaml” اجرای نقش را هماهنگ می کند:
- hosts: all
  tags: clients
  vars_files:
    - vars/clients.yaml
  roles:
    - clients
- hosts: nexus_server
  tags: nexus
  become_user: root
  become: true
  vars_files:
    - vars/nexus.yaml
  roles:
    - nexus

حالا بیایید حرکت کنیم تا کیهانی را ببینیم که playbook در آن اجرا خواهد شد.

موجودی میزبان

در مورد من بسیار ساده است – من دو گروه اصلی دارم: “مشتریان” و ماشینی که خود سرور Nexus 3 در آن اجرا می شود:

all:
  children:
    nexus_server:
      hosts:
        orangepi5.home:
    home_lab:
      hosts:
        dmaf5.home:
        raspberrypi.home:
        orangepi5.home:

وظیفه مهم بعدی دانلود و پیکربندی Nexus 3 است.

پیشنهاد می‌کنیم بخوانید:  عملگر Non-Null Assertion در TypeScript

نحوه نصب Nexus 3

فایل main.yaml ترتیب و هدف هر کار نصب را برای نقش Nexus شرح می دهد:

# Tasks listed here are related to the remote Nexus 3 server
# Included tasks are called in order
---
  - include_tasks: third_party.yaml
  - include_tasks: pre_install.yaml
  - include_tasks: download.yaml
  - include_tasks: install.yaml
  - include_tasks: post_install.yaml
  - include_tasks: user.yaml
  - include_tasks: repositories.yaml

بیایید ابتدا ببینیم که من دوست دارم آن را “وظایف اصلی” بنامم:

  1. third_party.yaml: در اینجا OpenJDK8 را نصب می‌کنیم (Nexus 3 به زبان جاوا نوشته شده است) و برای مراقبت از لاگ‌های قدیمی Logrotate می‌کنیم.
  2. pre_install.yaml: موارد زیادی در اینجا اتفاق می‌افتد، مانند ایجاد دایرکتوری‌های مورد نیاز برای Nexus، کاربر اختصاصی غیرمجاز که فرآیند را اجرا می‌کند.
  3. download.yaml: همانطور که از نامش مشخص است، نسخه جدیدی از نرم‌افزار Nexus 3 OSS دریافت می‌کنیم و مطمئن می‌شویم که چک‌سوم مناسبی دارد. ما نمی خواهیم بدافزار را از اینترنت نصب کنیم.

سپس وظایفی می آیند که در “گروه نصب سفارشی” قرار می گیرند:

  1. install.yaml: بسته نرم افزار را باز کنید، واحد systemd را برای راه اندازی خودکار آماده کنید، تنظیمات JVM را برای Nexus تنظیم کنید و پیکربندی logrotate را اجرا کنید.
  2. post_install.yaml: چیزهای هیجان انگیزی در اینجا رخ می دهد – نرم افزار نصب شده است، و ما آن را برای اولین بار اجرا می کنیم. همچنین رمز عبور پیش فرض را با استفاده از REST API تغییر می دهیم تا بتوانیم به مرحله سفارشی سازی برویم.
  3. user.yaml: در اینجا ما آماده می شویم تا به کاربران نهایی خود دسترسی مناسب به خدمات ارائه شده توسط Nexus ارائه دهیم. ما این کار را با استفاده از ترکیبی از REST-API و کد مشتری Ansible انجام می دهیم:
# https://help.sonatype.com/repomanager3/installation-and-upgrades/post-install-checklist
# https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api
---
- name: Enable anonymous user
  tags: anonymous
  ansible.builtin.uri:
    user: ""
    password: ""
    url: "/v1/security/anonymous"
    method: PUT
    body_format: raw
    status_code: [ 200, 202, 204 ]
    headers:
      Content-Type: application/json
    body: |-
      { "enabled" : true, "userId" : "anonymous", "realmName" : "NexusAuthorizingRealm" }
    force_basic_auth: true
    return_content: true
  any_errors_fatal: true
- name: Enable Docker security realm
  tags: docker_realm
  ansible.builtin.uri:
    user: ""
    password: ""
    url: "/v1/security/realms/active"
    method: PUT
    body_format: raw
    status_code: [ 200, 202, 204 ]
    headers:
      Content-Type: application/json
    body: |-
      [ "NexusAuthenticatingRealm", "NexusAuthorizingRealm", "DockerToken" ]
    force_basic_auth: true
    return_content: true
  any_errors_fatal: true

پیروی از منطق آسان است، با استفاده از روش http ‘PUT’ می توانید بگویید که یک عملیات اصلاح است (به این معنی که نقش ها و کاربران موجود از قبل وجود دارند). تشخیص خطا با بازگشت کدهای HTTP توسط Nexus انجام می شود.

گام بعدی این است که پروکسی PyPi محلی خود را آماده کنیم. این یک کار چند مرحله ای است و در ادامه به تفصیل توضیح داده خواهد شد.

نحوه تنظیم پروکسی PyPI در Nexus 3

آخرین فایل در نقش Nexus 3 ‘repositories.yaml’ است. در اینجا مراحل زیر را طی می کنیم:

  1. بررسی کنید که آیا پروکسی قبلاً تنظیم شده است (عملیات GET یا فقط خواندنی)
  2. اگر وجود ندارد، یک مخزن جدید ایجاد کنید (روش POST با بارگیری JSON با جزئیات برای ایجاد مخزن کامل جدید)

توجه داشته باشید که این کتاب راهنما گزینه ای برای به روز رسانی تنظیمات مخزن را ارائه نمی دهد. این کار با REST API امکان پذیر است، اما من آن را به عنوان تمرین به خواننده واگذار می کنم.

وظایف آماده سازی پروکسی PyPi در زیر نشان داده شده است:

# Create proxy for repositories
# https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api
# PyPi: https://pip.pypa.io/en/stable/user_guide/
---
- name: Check if the PyPi proxy exists
  tags: pypi_proxy_exists
  ansible.builtin.uri:
    user: ""
    password: ""
    url: "/v1/repositories/pypi/proxy/python_proxy"
    method: GET
    body_format: raw
    status_code: [ 200, 202, 204, 404 ]
    headers:
      Content-Type: application/json
    force_basic_auth: true
    return_content: true
  any_errors_fatal: true
  register: python_local
- name: Create PyPI proxy
  tags: pypi_proxy_create
  ansible.builtin.uri:
    user: ""
    password: ""
    url: "/v1/repositories/pypi/proxy"
    method: POST
    body_format: raw
    status_code: [ 201 ]
    headers:
      Content-Type: application/json
    body: |-
      {
        "name": "python_proxy",
        "online": true,
        "storage": {
          "blobStoreName": "default",
          "strictContentTypeValidation": true
        },
        "proxy": {
          "remoteUrl": "https://pypi.org/",
          "contentMaxAge": -1,
          "metadataMaxAge": 1440
        },
        "negativeCache": {
          "enabled": true,
          "timeToLive": 1440
        },
        "httpClient": {
          "blocked": false,
          "autoBlock": true,
          "connection": {
            "retries": 0,
            "timeout": 60,
            "enableCircularRedirects": false,
            "enableCookies": true,
            "useTrustStore": false
          }
        }
      }
    force_basic_auth: true
    return_content: true
  any_errors_fatal: true
  when: python_local.status == 404

ما تقریباً آنجا هستیم. اکنون باید به مشتریان PyPi خود بگوییم که باید از Nexus محلی خود استفاده کنیم و نه از سایت مستقیم PyPi برای دریافت کتابخانه های Python خود.

پیشنهاد می‌کنیم بخوانید:  تجزیه URL ها با پایتون

نحوه تنظیم مشتریان

نقش مشتری بسیار ساده‌تر است و فقط مستلزم استقرار یک الگو برای pip.conf با اطلاعات کافی برای جستجو در مخزن جدید ما است:

# Tasks here are meant to be used on our clients user
---
- name: Create installation directory for pip.conf
  tags: pip_basedir
  ansible.builtin.file:
    state: directory
    path: ""
    owner: ""
    group: ""
    mode: "u+rwx,go-rwx"
- name: Copy pip.conf file
  tags: pip_copy
  ansible.builtin.template:
    src: pip.conf.j2
    dest: "/pip.conf"
    owner: ""
    group: ""
    mode: u=rxw,g=r,o=r

فایل به دست آمده در ‘ مستقر می شود~/.config/pip/pip.conf‘ از هر ماشین:

# https://pip.pypa.io/en/stable/topics/configuration/
[global]
timeout = 60
[install]
index = http://orangepi5.home:8081/repository/python_proxy/pypi
index-url = http://orangepi5.home:8081/repository/python_proxy/simple/
trusted-host = orangepi5.home

فایل بالا نمونه ای از نحوه نمایش نسخه نهایی فایل پس از استقرار در کلاستر من را نشان می دهد (نسخه شما با URL حل شده متفاوت خواهد بود).

اکنون زمان آن است که کل کتاب بازی را اجرا کنید و ببینید که چگونه به نظر می رسد.

نحوه اجرای Playbook

برای اجرای playbook، چند آرگومان ارسال می کنیم:

  1. محل موجودی میزبان ما
  2. محل فایل رمز رمزگذاری شده و یک فایل اصلی حاوی رمز عبور اصلی برای باز کردن قفل محتویات فایل محافظت شده
  3. و در نهایت محل فایل playbook اصلی ما
cd ansible
ansible-playbook --inventory  inventories --extra-vars @vault/nexus_password.enc --vault-password-file $HOME/vault/ansible_vault_pass site.yaml

asciicast

نحوه تست پروکسی جدید PyPI

برای آزمایش پراکسی جدید خود، Python Rich را با استفاده از pip و یک محیط مجازی نصب می کنیم.

josevnz@orangepi5:~$ python3 -m venv ~/virtualenv/rich
(rich) josevnz@orangepi5:~$ . ~/virtualenv/rich/bin/activate
(rich) josevnz@orangepi5:~$ pip install rich
Looking in indexes: http://orangepi5.home:8081/repository/python_proxy/simple/
Collecting rich
  Downloading http://orangepi5.home:8081/repository/python_proxy/packages/rich/13.3.4/rich-13.3.4-py3-none-any.whl (238 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 238.7/238.7 KB 14.8 MB/s eta 0:00:00
Collecting pygments<3.0.0,>=2.13.0
  Downloading http://orangepi5.home:8081/repository/python_proxy/packages/pygments/2.15.0/Pygments-2.15.0-py3-none-any.whl (1.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 23.8 MB/s eta 0:00:00
Collecting markdown-it-py<3.0.0,>=2.2.0
  Downloading http://orangepi5.home:8081/repository/python_proxy/packages/markdown-it-py/2.2.0/markdown_it_py-2.2.0-py3-none-any.whl (84 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 84.5/84.5 KB 6.9 MB/s eta 0:00:00
Collecting mdurl~=0.1
  Downloading http://orangepi5.home:8081/repository/python_proxy/packages/mdurl/0.1.2/mdurl-0.1.2-py3-none-any.whl (10.0 kB)
Installing collected packages: pygments, mdurl, markdown-it-py, rich
Successfully installed markdown-it-py-2.2.0 mdurl-0.1.2 pygments-2.15.0 rich-13.3.4

و سپس با دیدن مصنوعات جدید در مخزن جدید می توانیم تأیید کنیم که حافظه پنهان واقعاً استفاده شده است:

آرتیفکت های جدید در مخزن PyPI Python_proxy
مصنوعات PyPi را ببینید

بیایید یک نسخه نمایشی از کلاینت را در عمل ببینیم و چیز دیگری را نصب کند:

asciicast

سفارشی سازی بیشتر با استفاده از REST-API

هر نصب Nexus به شما امکان می دهد یک فایل JSON را دانلود کنید که API پشتیبانی شده توسط سرور را توصیف می کند. به عنوان مثال، در سرور من می توانید یک کپی مانند این را از سرور orangepi5.home من دریافت کنید:

curl --fail --remote-name http://orangepi5.home:8081/service/rest/swagger.json

همچنین، UI به شما اجازه می دهد تا سایر نقاط پایانی REST API را برای سفارشی کردن نصب خود امتحان کنید.

اسناد API Swagger در Nexus 3
تست REST API

نتیجه

توصیه می کنم کمی وقت بگذارید و کتاب Nexus 3 را بخوانید تا با ویژگی هایی که این ابزار می تواند ارائه دهد آشنا شوید.

انجمن نصب کننده های Debian و RPM را آماده کرده است، در صورتی که به این نوع راه اندازی نیاز دارید به جای استفاده از Ansible.

Nexus 3 مقدار زیادی دارد از تنظیمات قابل تنظیم ما اینجا فقط سطح را پوشاندیم. در حین تهیه این مقاله، «مخزن ThoTeam Nexus3-oss» را با یک کتاب بازی بسیار کامل و به‌روز پیدا کردم، اما بسیار پیچیده‌تر از هر چیزی بود که برای آزمایشگاه خانگی‌ام نیاز داشتم.

Archiva یکی دیگر از مدیران مصنوع منبع باز است که از نظر عملکرد محدودتر است اما تنظیم آن نیز ساده تر است.

یک چک لیست پس از نصب با برخی از کارهایی که برای آزمایشگاه خانگی خود نیازی به انجام آنها نداشتم وجود دارد. لطفاً آن را بررسی کنید تا مطمئن شوید تنظیمات شما کامل شده است.