Apps: "Nginx", "Nexus RM", "Docker", "Docker Compose", LDAP.
Задача: развернуть сервер репозиториев артефактов "Sonatype Nexus Repository Manager v3 (OSS)", настроив его для хранения docker-образов и nuget-библиотек.
Последовательность дальнейших действий такова:
1. Подготовка системного окружения (отдельная инструкция);
2. Установка системы контейнеризации "Docker" (отдельная инструкция);
3. Установка сопутствующего ПО и подготовка конфигурации;
4. Подготовка конфигурации для фронтального web-сервера "Nginx";
5. Наладка запуска посредством "Docker Compose" и "Systemd";
6. Конфигурирование web-приложения "Nexus Repository Manager v3 (OSS)";
7. Проверка функциональности docker-репозитория;
8. Интеграция с внешним LDAP/AD для аутентификации.
2. Установка системы контейнеризации "Docker" (отдельная инструкция);
3. Установка сопутствующего ПО и подготовка конфигурации;
4. Подготовка конфигурации для фронтального web-сервера "Nginx";
5. Наладка запуска посредством "Docker Compose" и "Systemd";
6. Конфигурирование web-приложения "Nexus Repository Manager v3 (OSS)";
7. Проверка функциональности docker-репозитория;
8. Интеграция с внешним LDAP/AD для аутентификации.
Подготовка несущей файловой структуры для приложения "Nexus".
В контейнере "Nexus" запускается к контексте пользователя с UID:200. В несущей системе "Debian/Ubuntu" этот UID по умолчанию обычно никем не занят, что позволяет удобно создать пользователя, которому очевидно будет выданы права доступа к ресурсам, выделенным для docker-контейнера с "Nexus":
# mkdir -p /var/opt/nexus/data
# mkdir -p /var/opt/nexus/logs
# mkdir -p /var/opt/nexus/logs
# groupadd --system --gid 200 nexus
# useradd --system --home-dir /var/opt/nexus --shell /bin/false --gid nexus --uid 200 nexus
# useradd --system --home-dir /var/opt/nexus --shell /bin/false --gid nexus --uid 200 nexus
# chown -R nexus:nexus /var/opt/nexus
# chmod -R o-rwx /var/opt/nexus
# chmod -R o-rwx /var/opt/nexus
Преконфигурирование "Nexus".
Для начала запустим "Nexus" в режиме развёртывания, даже без включения сети, подав внутрь контейнера указание применить желаемые параметры java-машины, которые будут автоматически сохранены в директории "/var/opt/nexus/data" для использования в последующих, уже рабочих запусках:
# docker run --rm --name nexus-preconfigure -e INSTALL4J_ADD_VM_PARAMS="-Xms2g -Xmx2g -XX:MaxDirectMemorySize=3g" -v /var/opt/nexus/data:/nexus-data sonatype/nexus3
....
Started Sonatype Nexus OSS 3.29.2-02
------------------------------------
Started Sonatype Nexus OSS 3.29.2-02
------------------------------------
# docker top nexus-preconfigure
Достаточно дождаться уведомления об успешном запуске "Nexus" и завершить работу контейнера (Ctrl+C).
Подготовка конфигурации для фронтального web-сервера "Nginx".
Для последующего включения в "Nginx" современного SSL/TLS и HTTPv2 генерируем DH-файл:
# mkdir -p /var/opt/letsencrypt
# openssl dhparam -out /var/opt/letsencrypt/dhparam-2048.pem 2048
# chown -R root:root /var/opt/letsencrypt && chmod -R o-rwx /var/opt/letsencrypt
# openssl dhparam -out /var/opt/letsencrypt/dhparam-2048.pem 2048
# chown -R root:root /var/opt/letsencrypt && chmod -R o-rwx /var/opt/letsencrypt
Создадим в файловой системе несущего сервера структуры для конфигурации "Nginx":
# mkdir -p /var/opt/nginx/etc/conf.d
# mkdir -p /var/opt/nginx/logs
# mkdir -p /var/opt/nginx/logs
Конфигурация принимающего подключения пользователей web-сервера "Nginx" проста и сводится к описанию параметров "проксирования" всех запросов web-сервису, запущенному внутри docker-контейнера:
# vi /var/opt/nginx/etc/conf.d/nexus.example.net.conf
server {
listen 80;
listen [::]:80;
server_name nexus.example.net;
server_tokens off;
location /.well-known/acme-challenge {
root /var/www/letsencrypt;
}
location / {
return 307 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name nexus.example.net;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/nexus.example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nexus.example.net/privkey.pem;
ssl_dhparam /etc/letsencrypt/dhparam-2048.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_buffer_size 8k;
ssl_stapling on;
ssl_stapling_verify on;
proxy_connect_timeout 3s; # (default: 60s)
client_max_body_size 0; # (default: 1m)
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://nexus:8081;
proxy_redirect off;
}
}
server {
listen 5000 ssl http2;
listen [::]:5000 ssl http2;
server_name nexus.example.net;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/nexus.example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nexus.example.net/privkey.pem;
ssl_dhparam /etc/letsencrypt/dhparam-2048.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_buffer_size 8k;
ssl_stapling on;
ssl_stapling_verify on;
proxy_connect_timeout 3s; # (default: 60s)
client_max_body_size 0; # (default: 1m)
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://nexus:5000;
proxy_redirect off;
}
}
listen 80;
listen [::]:80;
server_name nexus.example.net;
server_tokens off;
location /.well-known/acme-challenge {
root /var/www/letsencrypt;
}
location / {
return 307 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name nexus.example.net;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/nexus.example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nexus.example.net/privkey.pem;
ssl_dhparam /etc/letsencrypt/dhparam-2048.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_buffer_size 8k;
ssl_stapling on;
ssl_stapling_verify on;
proxy_connect_timeout 3s; # (default: 60s)
client_max_body_size 0; # (default: 1m)
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://nexus:8081;
proxy_redirect off;
}
}
server {
listen 5000 ssl http2;
listen [::]:5000 ssl http2;
server_name nexus.example.net;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/nexus.example.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nexus.example.net/privkey.pem;
ssl_dhparam /etc/letsencrypt/dhparam-2048.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_buffer_size 8k;
ssl_stapling on;
ssl_stapling_verify on;
proxy_connect_timeout 3s; # (default: 60s)
client_max_body_size 0; # (default: 1m)
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://nexus:5000;
proxy_redirect off;
}
}
По умолчанию "Nginx" внутри docker-контейнера стартует в контексте суперпользователя "root", так что убираем доступ к его конфигурации для всех остальных:
# chown -R root:root /var/opt/nginx
# chmod -R go-rwx /var/opt/nginx
# chmod -R go-rwx /var/opt/nginx
Наладка запуска посредством "Docker Compose".
Создаём директорию для размещения конфигурационных файлов "Docker Compose":
# mkdir -p /usr/local/etc/compose
# cd /usr/local/etc/compose
# cd /usr/local/etc/compose
Воспользуемся для единственного в нашей схеме конфигурационного файла именем "по умолчанию":
# vi ./docker-compose.yml
version: "3"
services:
nginx:
depends_on:
- nexus
container_name: nginx
image: nginx:latest
networks:
nexus:
aliases:
- "nginx"
ports:
- 80:80
- 443:443
- 5000:5000
environment:
TZ: "/etc/timezone"
volumes:
- "/var/opt/nginx/etc/conf.d:/etc/nginx/conf.d:ro"
- "/var/opt/letsencrypt:/etc/letsencrypt:ro"
nexus:
container_name: nexus
image: sonatype/nexus3
networks:
nexus:
aliases:
- "nexus"
environment:
TZ: "/etc/timezone"
working_dir: "/var/opt/nexus"
volumes:
- "/var/opt/nexus/data:/nexus-data:rw"
networks:
nexus:
driver: bridge
internal: false
ipam:
driver: default
config:
- subnet: 100.127.255.0/24
services:
nginx:
depends_on:
- nexus
container_name: nginx
image: nginx:latest
networks:
nexus:
aliases:
- "nginx"
ports:
- 80:80
- 443:443
- 5000:5000
environment:
TZ: "/etc/timezone"
volumes:
- "/var/opt/nginx/etc/conf.d:/etc/nginx/conf.d:ro"
- "/var/opt/letsencrypt:/etc/letsencrypt:ro"
nexus:
container_name: nexus
image: sonatype/nexus3
networks:
nexus:
aliases:
- "nexus"
environment:
TZ: "/etc/timezone"
working_dir: "/var/opt/nexus"
volumes:
- "/var/opt/nexus/data:/nexus-data:rw"
networks:
nexus:
driver: bridge
internal: false
ipam:
driver: default
config:
- subnet: 100.127.255.0/24
Запускаем посредством "Docker Compose" всю пачку контейнеров:
# cd /usr/local/etc/compose
# docker-compose up --remove-orphans --build --force-recreate -d
# docker-compose up --remove-orphans --build --force-recreate -d
Пример точечного запуска определённого контейнера:
# docker-compose up --no-start nexus
# docker-compose start nexus
# docker-compose start nexus
Пример точечной остановки и высвобождения ресурсов определённого контейнера:
# docker-compose stop nexus
# docker-compose rm -f -v nexus
# docker-compose rm -f -v nexus
Останавливаем разом все docker-контейнеры, описанные в конфигурации "Docker Compose":
# docker-compose down
Настройка автозагрузки "Docker Compose" посредством "Systemd".
Создаём файл описания параметров запуска и остановки docker-контейнера посредством "Docker Compose" посредством короткоживущего сервиса "Systemd":
# vi /etc/systemd/system/nexus-docker.service
[Unit]
Description=Nexus Repository Manager in Docker Compose Service
Requires=network.target docker.service containerd.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/usr/local/etc/compose
ExecStartPre=-/bin/bash -c 'chown -R nexus:nexus /var/opt/nexus'
ExecStartPre=/usr/local/bin/docker-compose -f docker-compose.yml down --remove-orphans
ExecStart=/usr/local/bin/docker-compose -f /usr/local/etc/compose/docker-compose.yml up --remove-orphans --build --force-recreate --detach
#
ExecStop=/usr/local/bin/docker-compose -f /usr/local/etc/compose/docker-compose.yml down
[Install]
WantedBy=multi-user.target
Description=Nexus Repository Manager in Docker Compose Service
Requires=network.target docker.service containerd.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/usr/local/etc/compose
ExecStartPre=-/bin/bash -c 'chown -R nexus:nexus /var/opt/nexus'
ExecStartPre=/usr/local/bin/docker-compose -f docker-compose.yml down --remove-orphans
ExecStart=/usr/local/bin/docker-compose -f /usr/local/etc/compose/docker-compose.yml up --remove-orphans --build --force-recreate --detach
#
ExecStop=/usr/local/bin/docker-compose -f /usr/local/etc/compose/docker-compose.yml down
[Install]
WantedBy=multi-user.target
Указываем "Systemd" перечитать и принять новую конфигурацию, а потом явно активируем и запускаем новый сервис:
# systemctl daemon-reload
# systemctl enable nexus-docker.service
# systemctl start nexus-docker
# systemctl enable nexus-docker.service
# systemctl start nexus-docker
Смотрим журнал событий "Systemd" если "что-то пошло не так":
# systemctl status nexus-docker.service
# journalctl -xe
# journalctl -xe
Наладка ротации файлов журнала событий.
Не забываем, что для самодельных сервисов ротация их журналов событий не ведётся, и нужно настраивать это отдельно:
# vi /etc/logrotate.d/docker-opt
/var/opt/*/logs/*.log {
size 30M
missingok
notifempty
rotate 5
compress
delaycompress
copytruncate
su root root
}
size 30M
missingok
notifempty
rotate 5
compress
delaycompress
copytruncate
su root root
}
Проверяем корректность конфигурации, не воздействуя при этом на файлы журналов:
# logrotate -d /etc/logrotate.d/docker-opt
Конфигурирование web-приложения "Nexus Repository Manager v3 (OSS)".
Давно разрабатываемые программные продукты, продающиеся на рынке, радуют - все необходимые настройки делаются через довольно удобный web-интерфейс. Просто заходим на сайт, аутентифицируемся как суперпользователь "admin" (в первый раз, до обязательной смены, пароль достаём из файла "/var/opt/nexus/data/admin.password") и приступаем.
Первым делом я бы отключил напрочь доступ к ресурсам без аутентификации:
Nexus -> Administration -> Security -> Anonymous Access:
Access: off
....
Nexus -> Administration -> Security -> Users -> "anonymous":
Status: Disabled
Access: off
....
Nexus -> Administration -> Security -> Users -> "anonymous":
Status: Disabled
Задаём реальный почтовый адрес локальному суперпользователю, чтобы не пропустить важных уведомлений:
Nexus -> Administration -> Security -> Users -> "admin":
Email: admin@example.net
Email: admin@example.net
Разумеется, связь с почтовым сервером тоже понадобится настроить:
Nexus -> Administration -> System -> Email Server:
Enabled: true
Host: mail.example.net
....
Enabled: true
Host: mail.example.net
....
Создаём репозиторий для nuget-библиотек:
Nexus -> Administration -> Repository -> Repositories -> Create repository:
Recipe: nuget (hosted)
Format: nuget
Name: nuget-app
Recipe: nuget (hosted)
Format: nuget
Name: nuget-app
С репозиторием для docker-образов посложнее будет - понадобится явно выделить свободный TCP-порт для приёма клиентских подключений:
Nexus -> Administration -> Repository -> Repositories -> Create repository:
Recipe: docker (hosted)
Name: docker-nginx
Online: on
HTTP:
Port: 5000
HTTPS: off
Allow anonymous docker pull: off
Recipe: docker (hosted)
Name: docker-nginx
Online: on
HTTP:
Port: 5000
HTTPS: off
Allow anonymous docker pull: off
К разнице в настройках двух репозиториев выше поясню, что протокол взаимодействия с "Docker Registry" при аутентификации осуществляет привязку пользователя только к точке входа в сервер, откидывая URL-path (подкаталоги, имена файлов, ?-запросы и #-якоря), оставляя лишь URL-host и URL-port. Таким образом, технически нельзя на одном доменном имени и TCP-порту поддерживать два и более docker-репозитория - приходится каждому отдельному docker-репозиторию выделять свой TCP-порт.
После того, как репозитории артефактов созданы, подготовим для них описания ролей доступа:
Nexus -> Administration -> Security -> Roles -> Create role:
Role ID: role-docker-nginx-user
Role name: role-docker-nginx-user
Privileges:
nx-repository-view-docker-docker-nginx-add
nx-repository-view-docker-docker-nginx-edit
nx-repository-view-docker-docker-nginx-read
Role ID: role-docker-nginx-user
Role name: role-docker-nginx-user
Privileges:
nx-repository-view-docker-docker-nginx-add
nx-repository-view-docker-docker-nginx-edit
nx-repository-view-docker-docker-nginx-read
В конфигурировании роли для доступа к nuget-репозиториям есть одно отличие от всех остальных, поддерживаемых "Nexus" - потребуется добавить право доступа к функционалу оперирования API-ключами (всех типов - ибо ни для чего более "Nexus" пока создавать токены не умеет):
Nexus -> Administration -> Security -> Roles -> Create role:
Role ID: role-nuget-app-user
Role name: role-nuget-app-user
Privileges:
nx-apikey-all
nx-repository-view-nuget-nuget-app-*
Role ID: role-nuget-app-user
Role name: role-nuget-app-user
Privileges:
nx-apikey-all
nx-repository-view-nuget-nuget-app-*
Довольно очевидно из примеров выше, что можно описать как роль с полным доступом к ресурсу, так и собрать ограниченную, точечно подобрав разрешения.
Теперь переходим к созданию пользователей, которые уже будут работать с созданными репозиториями в соответствии с ролями доступа, которые им будут выделены.
В "Nexus" имеется возможность аутентификации через удалённый LDAP-сервис. Но, к сожалению, у пользователей "Nexus" нет возможности создавать индивидуальные token-ключи для аутентификации при непосредственном обращении к docker-репозиториям. Учитывая то, что логин и пароль подключения к docker-репозиториям открытым текстом сохраняются в профилях большинства docker-клиентов, было бы неразумно для обращения к docker-репозиториям пользоваться учётными записями пользователей из LDAP. Таким образом, несмотря на имеющуюся интеграцию с LDAP, всё же для каждого нового подключения к docker-репозиторию надёжнее создавать отдельного локального пользователя "Nexus":
Nexus -> Administration -> Security -> Users -> Create local user:
ID: username0-nexus
First name: Username0
Last name: Nexus
Email: username0@example.net
Password: ***
Status: Active
Roles -> Granted:
role-docker-nginx-user
role-nuget-app-user
ID: username0-nexus
First name: Username0
Last name: Nexus
Email: username0@example.net
Password: ***
Status: Active
Roles -> Granted:
role-docker-nginx-user
role-nuget-app-user
И, последний штрих - добавляем в перечень работающих подсистем аутентификации обслуживающие специфичные запросы к docker/nuget-репозиториям:
Nexus -> Administration -> Security -> Realms:
Active:
....
Docker Bearer Token Realm
NuGet API-Key Realm
Active:
....
Docker Bearer Token Realm
NuGet API-Key Realm
Проверка функциональности docker-репозитория.
Первым делом осуществляем аутентификацию docker-клиента на целевом сервере "Docker Registry" под управлением "Nexus":
$ docker login -u docker-username0 nexus.example.net:5000
WARNING! Your password will be stored unencrypted in /home/user/.docker/config.json.
Login Succeeded
Login Succeeded
Загружаем из официального docker-репозитория образ для тестирования, например web-сервера "Nginx":
$ docker pull nginx:latest
После загрузки образ можно наблюдать в локальном репозитории:
$ docker images
REPOSITORY TAG IMAGE ID
....
nginx latest f6d0b4767a6c
....
nginx latest f6d0b4767a6c
Помечаем локальный образ как доступный для загрузки в наш репозиторий под управлением "Nexus":
$ docker tag f6d0b4767a6c nexus.example.net:5000/nginx:latest
Теперь в локальном репозитории условно два одинаковых docker-образа с разными адресами хранения (на самом деле docker-образ физически один, но ему присвоено два "тега" с разными адресами):
$ docker images
REPOSITORY TAG IMAGE ID
....
nexus.example.net:5000/nginx latest f6d0b4767a6c
nginx latest f6d0b4767a6c
....
nexus.example.net:5000/nginx latest f6d0b4767a6c
nginx latest f6d0b4767a6c
Теперь отдаём команду выгрузить в целевой docker-репозиторий соответствующий ему docker-образ:
$ docker push nexus.example.net:5000/nginx
Если после этого пройти в web-интерфейс "Nexus", то там можно будет обнаружить сведения о загруженном docker-образе и описание его параметров в виде большого количества иерархически распределённых мета-данных.
Неудобно, что бесплатные версии docker-клиентов не поддерживают простое прямое удаление docker-образов из удалённого репозитория - это приходится делать через "docker API" нелинейной серией HTTP-запросов. Проще всего неподготовленному пользователю удалить ненужный ему образ через web-интерфейс "Nexus", если ему на то выделены полномочия, разумеется.
Как минимум, легко можно удалить docker-образ (вернее один из "тегов" - только после удаления последнего "тега" будет удалён и docker-образ, как таковой) из локального репозитория операционной системы:
$ docker rmi nexus.example.net:5000/nginx
После завершения всех процедур явно закрываем аутентифицированный сеанс с docker-репозиторием, во избежание:
$ docker logout nexus.example.net:5000
Интеграция с внешним LDAP/AD для аутентификации.
Выше я упоминал о нежелательности использования рядовых учётных записей пользователей, обслуживаемых LDAP/AD, для аутентификации при работе с репозиториями артефактов "Nexus" - резко возрастает риск утечки паролей.
Однако для упрощённого добавления новых администраторов web-сервиса "Nexus" вполне можно воспользоваться интеграцией с LDAP-сервисом.
Прежде всего, вероятно, понадобится загрузить публичную часть ключа SSL-сертификата LDAP-сервиса, если таковой "самоподписанный", в хранилище доверенных сертификатов "Nexus" (очень удобно, что это можно сделать через web-интерфейс, минуя обычные для java-приложений приседания с их специфичными "keytool" и "cacerts"):
Nexus -> Administration -> Security -> SSL Certificates:
Load Certificate from Server:
ldaps://ldap.example.net:636
Add certificate to truststore.
Load Certificate from Server:
ldaps://ldap.example.net:636
Add certificate to truststore.
Настройка подключения и правила взаимодействия с LDAP-сервисом в "Nexus" просты и отшлифованы годами эксплуатации:
Nexus -> Administration -> Security -> LDAP -> Create connection:
Connection:
Name: ldap.example.net
LDAP server address: ldaps://ldap.example.net:636
Use the Nexus truststore: true
Search base DN: dc=example,dc=net
Authentication method: Simple Authentication
Username or DN: uid=nexus,ou=Accounts,ou=Services,dc=example,dc=net
Password: ***
Users and Groups:
Configuration template: Generic LDAP Server
User relative DN: ou=People
User subtree: true
Object class: inetOrgPerson
User filter: (&(objectclass=person)(memberOf=cn=nexusadmins,ou=groups,dc=example,dc=net))
User ID attribute: uid
Real name attribute: cn
Email attribute: mail
Password attribute: (blank)
Map LDAP groups as roles: false
Connection:
Name: ldap.example.net
LDAP server address: ldaps://ldap.example.net:636
Use the Nexus truststore: true
Search base DN: dc=example,dc=net
Authentication method: Simple Authentication
Username or DN: uid=nexus,ou=Accounts,ou=Services,dc=example,dc=net
Password: ***
Users and Groups:
Configuration template: Generic LDAP Server
User relative DN: ou=People
User subtree: true
Object class: inetOrgPerson
User filter: (&(objectclass=person)(memberOf=cn=nexusadmins,ou=groups,dc=example,dc=net))
User ID attribute: uid
Real name attribute: cn
Email attribute: mail
Password attribute: (blank)
Map LDAP groups as roles: false
Сразу после настройки интеграции с LDAP-сервисом внутри "Nexus" можно будет добавлять пользователей из LDAP-сервиса и выделять роль полного администратора, например:
Nexus -> Administration -> Security -> Users -> LDAP -> "userName0":
Roles -> Granted:
nx-admin
Roles -> Granted:
nx-admin