Aller au contenu principal

Nexus le gestionnaire d'artefacts

· 16 minutes de lecture
Stéphane ROBERT
Consultant DevOps

S'il est bien un outil qui est indispensable dans une démarche Devops c'est bien le gestionnaire de dépôts. C'est dans cet outil qu'on va stocker les artefacts, les paquets et les métadonnées produites par les pipelines CI/CD.

J'ai fait le choix d'installer Nexus dans mon Home Lab Devops pour les raisons suivantes :

  • Nexus offre dans sa version opensource la gestion de toute une série de repositories en natif dont : APT, Yum, Docker, Maven, Pypi, Nuget, npm, R, RubyGems, Go, Helm, Composer*, Cpan*, ... et RAW.
  • C'est un très bon exercice pour se former à Ansible, Terraform, Vagrant

Ma démarche pour l'automatisation de l'installation de Nexus

Mes ressources étant limitées, j'ai commencé par développer le playbook Ansible sur une machine virtuelle créé avec Vagrant. Une fois le playbook fonctionnel, je l'ai transposé dans une VM instanciée avec du Terraform sur une de mes machines de mon Homelab.

Les objectifs que je me suis fixés et les contraintes imposées :

  • Pouvoir faire les upgrades facilement
  • Ne pas utiliser de Bdd externes (pas assez de ressources)
  • Ajouter de la persistance sur les données via un simple partage Nfs. Avant j'utilisais un cluster glusterfs sur 3 Raspberry Pi. Je rebasculerais dessus dans les prochaines semaines après l'avoir reconstruit.
  • Pas d'installation via Docker.

Pour écrire le playbook Ansible, j'ai tout simplement transposé la procédure d'installation disponible sur le site de la documentation de Nexus.

Ecriture du Vagrantfile

Maintenant je peux dire que je suis à l'aise avec Vagrant. Donc voici la configuration que j'ai utilisée :

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "almalinux/8"
  config.vm.synced_folder '.', '/vagrant', disabled: true
  config.vm.provider "libvirt" do |hv|
    hv.cpus = "2"
    hv.memory = "3072"
  end
  config.vm.define "nexus" do |nexus|
    nexus.vm.network "forwarded_port", guest: 443, host: 8443
    nexus.vm.network :private_network, ip: "192.168.3.10"
    nexus.vm.hostname = "nexus"
    nexus.vm.provision "ansible" do |a|
      a.verbose = "v"
      a.playbook = "deploy_nexus.yml"
    end
  end
end

Comme vous pouvez le voir j'utilise un VM avec 2 CPU et 3 Go de RAM. C'est le minimum requis. Je ne partage que le port 443, car c'est nginx qui portera la partie SSL et se chargera de faire le lien vers les différents types de repository. J'ai utilisé une box AlmaLinux dans sa version 8.

Mise en place du serveur NFS

Pour stocker les données persistantes j'ai fait le choix d'utiliser des montages NFS. Sur mon PC de travail et sur un de mes serveurs du Home Lab j'ai installé le serveur NFS, accompagné du service statd (pour la gestion du remote locking).

sudo apt update
sudo apt install nfs-kernel-server
sudo systemctl enable rpc-statd.service --now
sudo systemctl enable nfs-server.service --now

sudo mkdir /home/data
sudo chown nobody:nogroup /home/data
echo "/home/data        *(rw,insecure,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -ra
exportfs


/home/data
                <world>

Comme je n'ai pas créé de FS dédié, je le crée sur le FS /home qui a le plus de place à disposition. Je n'ai pas non plus mis de restriction sur la plage d'IP qui peut y accéder (vous pouvez le faire.)

Ecriture du playbook

Je me suis forcé de surtout pas reprendre de l'existant et de l'écrire à la volée avec les objectifs que je me suis fixé.

---
- hosts: all
  gather_facts: true
  become: true
  vars:
    ## Nexus
    nexus_version: 3.38.0-01
    force_install: false
    nexus_version_running: 1.0
    nexus_package: "nexus-{{ nexus_version }}-unix.tar.gz"
    nexus_installation_dir: /opt/sonatype
    nexus_data_dir: /data/nexus
    nexus_os_group: nexus
    nexus_os_user: nexus
    nexus_tmp_dir: '/tmp/nexus'
    nexus_default_port: 8081
    nexus_default_context_path: '/'
    nexus_timezone: Europe/Paris
    nexus_os_max_filedescriptors: 65536
    nfs_path : 192.168.1.101:/data
    memory: 1536
    # nfs_path: 192.168.122.1:/home/vagrant/Projets/nexus/data

    ## Nginx
    nginx_version: 1.18
    nginx_fqdn: artefacts.robert.local
    cert_file: "{{ nginx_fqdn }}+4.pem"
    cert_key: "{{ nginx_fqdn }}+4-key.pem"

  tasks:
    - name: "Check nexus-latest link stat in {{ nexus_installation_dir }}"
      ansible.builtin.stat:
        path: "{{ nexus_installation_dir }}/nexus"
      register: running_version
    - name: Register current running version if any
      ansible.builtin.set_fact:
        nexus_version_running: >-
          {{
            running_version.stat.lnk_target
            | regex_replace('^.*nexus-(\d*\.\d*\.\d*-\d*)', '\1')
          }}
      when:
        - running_version.stat.exists | default(false)
        - running_version.stat.islnk | default(false)
    - name: create group nexus
      ansible.builtin.group:
        name: "{{ nexus_os_group }}"
        state: present
    - name: create user nexus
      ansible.builtin.user:
        name: "{{ nexus_os_user }}"
        groups: "{{ nexus_os_group }}"
        append: yes
    - name: create /data mount
      ansible.builtin.file:
        path: /data
        state: directory
        mode: 0755
    - name: mount nfs /data
      ansible.posix.mount:
        src: "{{ nfs_path }}"
        path: /data
        # opts: vers=4,udp
        state: mounted
        fstype: nfs
    - name: Create Nexus directory
      ansible.builtin.file:
        path: "{{ item }}"
        state: "directory"
        owner: "{{ nexus_os_user }}"
        group: "{{ nexus_os_group }}"
        mode: 0755
      with_items:
      - "{{ nexus_tmp_dir }}"
      - "{{ nexus_installation_dir }}"
      - "{{ nexus_data_dir }}"
      - "{{ nexus_data_dir }}/log"
      - "{{ nexus_data_dir }}/tmp"
    - name: get list of services
      ansible.builtin.service_facts:
    - name: Stop nexus service
      ansible.builtin.service:
        name: nexus
        enabled: true
        state: stopped
      when: (nexus_version != nexus_version_running or force_install) and "nexus.service" in ansible_facts.services
    - name: Delete lock file
      ansible.builtin.file:
        path: /data/nexus/lock
        state: absent
      when: nexus_version != nexus_version_running or force_install
    - name: install packages
      ansible.builtin.package:
        state: present
        name:
          - glibc-common
          - glibc-langpack-en
          - glibc-langpack-fr
          - java
          - rsync
          - tar
          - unzip
          - epel-release
          - python3-libsemanage
          - policycoreutils-python-utils
    - name: set as default locale
      ansible.builtin.command: localectl set-locale LANG=en_US.UTF-8
    - name: Get path to default settings
      ansible.builtin.set_fact:
        nexus_default_settings_file: "{{ nexus_installation_dir }}/nexus/etc/nexus-default.properties"
    - name: install nexus
      become_user: nexus
      ansible.builtin.unarchive:
        src: "http://download.sonatype.com/nexus/3/{{ nexus_package }}"
        dest: "{{ nexus_installation_dir }}"
        remote_src: yes
        owner: nexus
      when: nexus_version != nexus_version_running or force_install
    - name: Update symlink nexus
      ansible.builtin.file:
        path: "{{ nexus_installation_dir }}/nexus"
        src: "{{ nexus_installation_dir }}/nexus-{{ nexus_version }}"
        owner: "{{ nexus_os_user }}"
        group: "{{ nexus_os_group }}"
        state: link
      register: nexus_latest_version
      when: nexus_version != nexus_version_running or force_install
    - name: Setup Nexus tmp directory
      ansible.builtin.lineinfile:
        dest: "{{ nexus_installation_dir }}/nexus/bin/nexus.vmoptions"
        regexp: "^-Djava.io.tmpdir=.*"
        line: "-Djava.io.tmpdir={{ nexus_tmp_dir }}"
      when: nexus_version != nexus_version_running or force_install
    - name: Setup Nexus data directory
      ansible.builtin.lineinfile:
        dest: "{{ nexus_installation_dir }}/nexus/bin/nexus.vmoptions"
        regexp: "^-Dkaraf.data=.*"
        line: "-Dkaraf.data={{ nexus_data_dir }}"
      when: nexus_version != nexus_version_running or force_install
    - name: Setup JVM logfile directory
      ansible.builtin.lineinfile:
        dest: "{{ nexus_installation_dir }}/nexus/bin/nexus.vmoptions"
        regexp: "^-XX:LogFile=.*"
        line: "-XX:LogFile={{ nexus_data_dir }}/log/jvm.log"
      when: nexus_version != nexus_version_running or force_install
    - name: Setup Nexus default timezone
      ansible.builtin.lineinfile:
        dest: "{{ nexus_installation_dir }}/nexus/bin/nexus.vmoptions"
        regexp: "^-Duser.timezone=.*"
        line: "-Duser.timezone={{ nexus_timezone }}"
      when: nexus_version != nexus_version_running or force_install
    - name: Set nexus user
      ansible.builtin.lineinfile:
        dest: "{{ nexus_installation_dir }}/nexus/bin/nexus.rc"
        regexp: ".*run_as_user=.*"
        line: "run_as_user=\"{{ nexus_os_user }}\""
      when: nexus_version != nexus_version_running or force_install
    - name: Set nexus port
      ansible.builtin.lineinfile:
        dest: "{{ nexus_default_settings_file }}"
        regexp: "^application-port=.*"
        line: "application-port={{ nexus_default_port }}"
      when: nexus_version != nexus_version_running or force_install
    - name: Set nexus context path
      ansible.builtin.lineinfile:
        dest: "{{ nexus_default_settings_file }}"
        regexp: "^nexus-context-path=.*"
        line: "nexus-context-path={{ nexus_default_context_path }}"
      when: nexus_version != nexus_version_running or force_install
    - name: Configure Memory Usage
      ansible.builtin.lineinfile:
        dest: /opt/sonatype/nexus/bin/nexus.vmoptions
        regexp: "^-{{ item }}.*"
        line: "-{{ item }}{{ memory }}"
      with_items:
        - "Xms"
        - "Xmx"
        - "XX:MaxDirectMemorySize="
      tags: memory
    - name: Create systemd service configuration
      ansible.builtin.template:
        src: "nexus.service"
        dest: "/etc/systemd/system"
        mode: 0755
      when: nexus_version != nexus_version_running or force_install
    - name: Reload systemd service configuration
      ansible.builtin.service:
        name: nexus
        enabled: true
        state: restarted
        daemon_reload: yes
      when: nexus_version != nexus_version_running or force_install
    - name: Install tools for debug
      ansible.builtin.package:
        name:
          - htop
          - net-tools
        state: present
# Deploy Nginx
    - name: install nginx
      ansible.builtin.dnf:
        name: '@nginx:{{ nginx_version }}'
        state: present
    - name: copy nginx config
      ansible.builtin.copy:
        src: files/nginx.conf
        dest: /etc/nginx
        mode: 0644
    - name: template nginx configuration
      ansible.builtin.template:
        src: artefacts.conf
        dest: /etc/nginx/conf.d/artefacts.conf
        mode: 0640
      notify: reload_nginx
    - name: copy certificate
      ansible.builtin.copy:
        src: "files/{{ item }}"
        dest: "/etc/ssl/{{ item }}"
        mode: 0640
      with_items:
        - "{{ cert_file }}"
        - "{{ cert_key }}"
      notify: reload_nginx
    - name: set sebool httpd can network connect to on
      ansible.posix.seboolean:
        name: httpd_can_network_connect
        state: yes
        persistent: yes
    - name: enable & start nginx
      ansible.builtin.service:
        name: nginx
        enabled: yes
        state: started
  handlers:
    - name: reload_nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded

L'installation est faite dans le dossier /opt/sonatype en y déposant le contenu du tar.gz téléchargé. Ensuite un lien est créé vers la version désirée. Si la version n'existe pas, on arrête Nexus et on fait l'installation, dans le cas contraire, on bypass pour ne faire que la partie configuration.

Si l'installation s'est mal passée vous pouvez la relancer en mettant force_install à true. Ne pas oublier de le remettre à false par la suite.

La gestion de la version se fait avec la variable nexus_version. Les versions disponibles.

Ensuite on procède à l'installation de nginx dont les certificats ont été générés avec mkcert.

La configuration de Nginx se fait via l'utilisation d'un template Ansible :

server_tokens off;

  server {
    listen  80;
    server_name {{ nginx_fqdn }};
    return 301 https://$server_name$request_uri;
  }
  server {
    listen *:443 ssl http2;
    server_name {{ nginx_fqdn }};

    # allow large uploads of files for docker
    client_max_body_size 2G;

    ssl_certificate /etc/{{ cert_file }};
    ssl_certificate_key /etc/{{ cert_key }};
    ssl_verify_client off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    add_header Strict-Transport-Security "max-age=63072000; allways;";

    location /v2/ {
      proxy_pass http://127.0.0.1:8082;
      proxy_set_header Host $host:$server_port;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto "https";
    }

    location / {
      # Use IPv4 upstream address instead of DNS name to avoid attempts by nginx to use IPv6 DNS lookup
      proxy_pass http://127.0.0.1:8081;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto "https";
    }
  }

Il y a redirections dont une qui permet de définir l'accès à une registry docker. Nous verrons comment la créer plus tard.

Test de la VM avec vagrant

Vous pouvez télécharger le code en clonant le repository que je vous ai mis à disposition :

git clone

N'oubliez pas de changer les variables du fqdn, des certificats et du montage nfs.

Pour lancer la création de la VM :

vagrant up --no-destroy-on-error --provision

Dans la phase de développement, je vous conseille d'ajouter l'option --no-destroy-on-error qui permet de garder la vm même si le playbook plante. Pour le relancer l'option --provision permet de spécifier qu'il ne faut que refaire la partie provisioning.

Ensuite, il suffit de se rendre sur l'url https://192.168.3.10 dans votre navigateur. Si vous le faites depuis visual code, vous pouvez ajouter le port 192.168.3.10:443 et dans le navigateur https://localhost.

Pour se connecter la première fois, il faut récupérer le mot de passe que Nexus a généré. Le user est admin :

cat /data/nexus/admin.password

Nexus vous demandera de le changer de suite ! Activer l'accès en mode anonymous.

Installation sur une machine du home Lab avec Terraform

Maintenant que cela fonctionne je l'installe sur une des machines Ubuntu du Home Lab. Pour cela je crée le partage NFS comme ci-dessus.

[Maj] La configuration automatique des machines du home lab est décrite ici

Installation de libvirt

Il faut installer et configurer libvirt pour qu'il utilise le pont réseau monté sur la carte ethernet. Cela permet d'exposer les VM sur le même réseau que la machine hôte et donc bénéficier du serveur dhcp (ma box).

sudo apt install libvirt-daemon-system libvirt-clients libvirt-dev qemu-kvm cockpit

J'installe cockpit pour faciliter la configuration. En effet, la création du pont réseau se fait en deux clics.

Pour y accéder https://ip-de-votre-machine:9090.

Création du pont réseau

Une fois identifié, il suffit de se rendre dans la partie réseau et de cliquer sur [Ajouter un Pont]. Donnez-lui un nom, br0 par exemple et cliquer sur le nom de la carte réseau à associer (eth0, enp1s0, ...). [Appliquez]

On configure ensuite libvirt pour qu'il utilise ce pont. Sur la machine hôte créer un fichier se nommant bridged-network.xml et y mettre ce contenu :

<network>
    <name>bridged-network</name>
    <forward mode="bridge" />
    <bridge name="br0" />
</network>

(attention mettre le nom du pont que vous avez créé précédement !

Et on applique :

sudo virsh net-define bridged-network.xml
sudo virsh net-start bridged-network
sudo virsh net-autostart bridged-network

Création du code Terraform

Je vous fournis le code que j'ai utilisé :

terraform {
  required_providers {
    libvirt = {
      source = "dmacvicar/libvirt"
    }
  }
}

// instance the provider
provider "libvirt" {
  // uri = "qemu:///system"
  uri = "qemu+ssh://root@devbox/system"
}

// variables that can be overriden
variable "hostname" { default = "artefacts" }
variable "domain" { default = "robert.local" }
variable "ip_type" { default = "dhcp" } # dhcp is other valid type
variable "memoryMB" { default = 1024*3 }
variable "cpu" { default = 3 }

// fetch the latest ubuntu release image from their mirrors
resource "libvirt_volume" "os_image" {
  name = "${var.hostname}-os_image"
  pool = "default"
  source = "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2"
  format = "qcow2"
}

// Use CloudInit ISO to add ssh-key to the instance
resource "libvirt_cloudinit_disk" "commoninit" {
          name = "${var.hostname}-commoninit.iso"
          pool = "default"
          user_data      = data.template_cloudinit_config.config.rendered
          network_config = data.template_file.network_config.rendered
}

data "template_file" "user_data" {
  template = file("${path.module}/cloud_init.cfg")
  vars = {
    hostname = var.hostname
    fqdn = "${var.hostname}.${var.domain}"
    public_key = file("~/.ssh/id_ed25519.pub")
  }
}

data "template_cloudinit_config" "config" {
  gzip = false
  base64_encode = false
  part {
    filename = "init.cfg"
    content_type = "text/cloud-config"
    content = "${data.template_file.user_data.rendered}"
  }
}

data "template_file" "network_config" {
  template = file("${path.module}/network_config_${var.ip_type}.cfg")
}

// Create the machine
resource "libvirt_domain" "domain-ubuntu" {
  # domain name in libvirt, not hostname
  name = "${var.hostname}"
  memory = var.memoryMB
  vcpu = var.cpu

  disk {
      volume_id = libvirt_volume.os_image.id
  }
  network_interface {
      network_name = "bridged-network"
      mac = "52:54:00:36:14:e9"
  }

  cloudinit = libvirt_cloudinit_disk.commoninit.id

  # IMPORTANT
  # Ubuntu can hang is a isa-serial is not present at boot time.
  # If you find your CPU 100% and never is available this is why
  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }

  graphics {
    type = "spice"
    listen_type = "address"
    autoport = "true"
  }
}

terraform {
  required_version = ">= 0.12"
}


output "ips" {
  #value = libvirt_domain.domain-ubuntu
  #value = libvirt_domain.domain-ubuntu.*.network_interface
  # show IP, run 'terraform refresh' if not populated
  value = libvirt_domain.domain-ubuntu.*.network_interface
}

Il faut modifier :

  • la variable domain (au début du script)
  • dans network_interface changer de mac addresse si besoin. Je la fixe pour que l'ip utilise un bail statique sur ma box Orange.

Ce code fait appel à du cloud-init pour configurer la VM.

#cloud-config
# https://cloudinit.readthedocs.io/en/latest/topics/modules.html
timezone: Europe/Paris

fqdn: artefacts.robert.local
manage_etc_hosts: true
resize_rootfs: true

users:
  - name: admuser
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: users, wheel
    home: /home/admuser
    shell: /bin/bash
    lock_passwd: false
    ssh-authorized-keys:
      - ${public_key}

# only cert auth via ssh (console access can still login)
## debug - ssh_pwauth: true
disable_root: false
ssh_pwauth: true
chpasswd:
  list: |
    root:passwd
    admuser:123456
  expire: false
growpart:
  mode: auto
  devices: ['/']
packages:
  - qemu-guest-agent
write_files:
  - path: /etc/sysctl.d/10-disable-ipv6.conf
    permissions: 0644
    owner: root
    content: |
      net.ipv6.conf.all.disable_ipv6 = 1
      net.ipv6.conf.default.disable_ipv6 = 1
# every boot
bootcmd:
    - [ sh, -c, 'echo $(date) | sudo tee -a /root/bootcmd.log' ]
# run once for setup

runcmd:
  - sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
  - systemctl restart sshd
  - sysctl --load /etc/sysctl.d/10-disable-ipv6.conf
  - localectl set-keymap fr
  - localectl set-locale LANG=fr_FR.UTF8
  - domainname robert.local

Modifier le nom de domain !!

Et pour la partie réseau :

version: 2
ethernets:
  eth0:
    dhcp4: true
    nameservers:
      addresses: [192.168.1.1]
      search: [robert.local]

Modifier le nom de domain et la gateway !!

Démarrage de la VM

Maintenant que tout est prêt allez on démarre le tout :

terraform init
terraform apply -auto-approve

Allez dans cockpit et dans machine virtuelle cliquez sur artefacts.

Ouvrez la console série et entrez root, passwd pour vous connecter.

cloud-init status
status: done

C'est bon elle est configurée !

On peut lancer le playbook Ansible.

ansible-playbook -i inventory deploy_nexus.yml

Ça va mouliner un certain temps. Tout dépend des ressources de votre machine hôte. Moi, c'est un Atom x5-Z8350 et il faut pas moins de 10 minutes avant que Nexus soit opérationel. J'ai commandé un miniforums UM250 : RYZEN 5 PRO 2500U + 16Go de RAM + 256 Gb de SSD upgradable.Y a eu une belle promo sur Amazon.fr à 390€.

Dans la fenêtre console il suffit de taper la commande suivante pour vérifier que nexus est démarré :

ss -tl
LISTEN 0      128          0.0.0.0:sunrpc      0.0.0.0:*
LISTEN 0      128          0.0.0.0:ssh         0.0.0.0:*
LISTEN 0      128             [::]:sunrpc         [::]:*
LISTEN 0      128             [::]:ssh            [::]:*

Si le port 8081 apparaît, c'est que Nexus a démarré. Vous pouvez aussi vérifier les logs dans /data/nexus/log/nexus.log.

sudo tail -f /data/nexus/log/nexus.log
....
2022-02-21 15:41:32,390+0100 INFO  [jetty-main-1]  *SYSTEM org.sonatype.nexus.bootstrap.jetty.JettyServer -
-------------------------------------------------

Started Sonatype Nexus OSS 3.37.3-02

-------------------------------------------------

Enfin !

Ouvrez votre navigateur sur l'adresse que vous avez défini : https://artefacts.robert.local

Configuration d'une registry Docker

Pour stocker vos images de container, vous pouvez activer le plugin docker de Nexus. Identifiez-vous avec le compte admin. Et cliquez en haut à gauche sur la roue dentée, puis [repository], puis [create repositories]. Choissisez docker (hosted) et renseignez les paramêtres comme dans l'image ci-dessous:

Dans la partie finissez par [Create repository].

Test de la registry docker

On va tester le stockage d'image. On va faire simple :

Sur votre poste de travail, taguer une image avec le nom de domaine de votre nexus :

docker pull alpine:3.15.0
docker tag alpine:3.15 artefacts.robert.local/alpine:3.15.0
docker login -u admin artefacts.robert.local
Password:
WARNING! Your password will be stored unencrypted in /home/vagrant/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

docker push artefacts.robert.local/alpine:3.15
The push refers to repository [artefacts.robert.local/alpine]
8d3ac3489996: Pushed

Un petit tour dans nexus. [Browse] [test] ->

On a une registry docker sécurisée ! C'est pas merveilleux ?

Si Nexus ne démarre pas

Connectez-vous avec le compte nexus :

sudo su - nexus

On va lancer la commande de démarrage manuellement :

sh -x /opt/sonatype/nexus/bin/nexus start

Si vous ne voyez pas d'erreur recopier la dernière commande affichée. Et lancer là :

java.lang.NumberFormatException

J'ai eu ce problème qui était dû à l'absence du service rpc.statd sur la machine hébergeant le partage NFS. Il suffit donc de l'installer et de le démarrer (voir au début du billet).

Pas assez de ressources.

Par défaut la jvm Nexus est configurée avec les paramètres -Xms2703m, -Xmx2703m et -XX:MaxDirectMemorySize=2703m. Vous pouvez essayer de les réduire à 1536 ça devrait démarrer. Ca se passe dans le fichier /opt/sonatype/nexus/bin/nexus.vmoptions

Attention à chaque nouvelle installation il faudra le refaire, à moins que vous l'ajoutiez dans le playbook ansible (le temps que je le fasse).

Plus loin

Le code source de l'ensemble est disponible sur gitlab

Il y a encore un peu de travail pour rendre le playbook tip-top au petits oignons. Mais je vous laisse jouer avec pour apprendre :

  • gérer la configuration mémoire avec des lineinfile. Je vous déconseille le template car les fichiers de configuration nexus
  • ....