Saturday, August 17, 2013

Archiva Repository Manager for Grails

Recently deployed Apache Archiva as a Maven repository manager, for use by our Grails projects (primarily as a local cache for remote artifacts). The default configuration for Archiva does this almost completely out-of-the-box — just needed a little extra configuration for Grails plugins. Here are the steps I took to install Archiva on Ubuntu 12.04 and configure our Grails projects to use it:

Install Archiva

There isn't yet an Ubuntu apt package for Archiva, so you have to download and install it manually. It's pretty straightforward, though:

# download archiva 1.3.6
wget http://download.nextag.com/apache/archiva/1.3.6/binaries/apache-archiva-1.3.6-bin.tar.gz

# extract and move to /opt/archiva
tar xf apache-archiva-1.3.6-bin.tar.gz
sudo mv apache-archiva-1.3.6 /opt/.
sudo ln -s /opt/apache-archiva-1.3.6 /opt/archiva

# delete wrapper-linux-x86-32 files (if you're using 64-bit linux -- otherwise keep them!)
sudo rm /opt/archiva/bin/wrapper-linux-x86-32
sudo rm /opt/archiva/lib/libwrapper-linux-x86-32.so

# create archiva working dir with the default conf files
sudo mkdir /srv/archiva
sudo cp -r /opt/archiva/conf /srv/archiva/.
sudo mkdir /srv/archiva/data
sudo mkdir /srv/archiva/logs

# add daemon user
sudo useradd -r archiva
sudo chown -R archiva:archiva /srv/archiva

# create daemon script
echo '#!/bin/sh -e
#
# /etc/init.d/archiva daemon control script
#
### BEGIN INIT INFO
# Provides:          archiva
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Should-Start:      $named
# Should-Stop:       $named
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start Archiva
# Description:       Start/Stop Aparche Archiva at /opt/archiva.
### END INIT INFO

export ARCHIVA_BASE=/srv/archiva
export RUN_AS_USER=archiva

/opt/archiva/bin/archiva $@
' | sudo tee /etc/init.d/archiva
sudo update-rc.d archiva defaults 80 20

The above script will install Archiva 1.3.6 at /opt/archiva, create a working dir for it at /srv/archiva, create a new, unprivileged archiva user, and create an /etc/init.d/archiva script to run Archiva as a daemon. You can now start Archiva with the command sudo service archiva start, and it automatically will start whenever the machine boots.

Before I started it, however, I also configured Archiva to use a MySQL DB as its data store, since MySQL was already running on the same box (Archiva uses Apache Derby by default). To do so, I first created a database for Archiva and a database for Apache Redback (which Archiva uses for its user store):

echo "create archiva mysql db as root..."
mysql -uroot -p - e'
    CREATE DATABASE archiva DEFAULT CHARACTER SET ascii;
    GRANT ALL ON archiva.* TO "archiva" IDENTIFIED BY "secret-archiva-password";

    CREATE DATABASE redback DEFAULT CHARACTER SET ascii;
    GRANT ALL ON redback.* TO "redback" IDENTIFIED BY "secret-redback-password";
'

And configured Archiva to use MySQL by altering its /srv/archiva/conf/jetty.xml configuration file to use MySQL settings in place of Derby:

  <!-- Archiva Database -->

  <New id="archiva" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/archiva</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">archiva</Set>
        <Set name="user">archiva</Set>
        <Set name="password">archiva-secret-password</Set>
      </New>
    </Arg>
  </New>

  <New id="archivaShutdown" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/archivaShutdown</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">archiva</Set>
        <Set name="user">archiva</Set>
        <Set name="password">archiva-secret-password</Set>
      </New>
    </Arg>
  </New>

  <!-- Users / Security Database -->

  <New id="users" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/users</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">redback</Set>
        <Set name="user">redback</Set>
        <Set name="password">redback-secret-password</Set>
      </New>
    </Arg>
  </New>

  <New id="usersShutdown" class="org.mortbay.jetty.plus.naming.Resource">
    <Arg>jdbc/usersShutdown</Arg>
    <Arg>
      <New class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
        <Set name="serverName">localhost</Set>
        <Set name="databaseName">redback</Set>
        <Set name="user">redback</Set>
        <Set name="password">redback-secret-password</Set>
      </New>
    </Arg>
  </New>

And finally, linked the MySQL java driver into Archiva's lib directory:

sudo ln -s /usr/share/java/mysql.jar /opt/archiva/lib/.

Proxy Archiva Thru Apache

Archiva runs on port 8080 by default. To avoid conflicts with other services, I changed it to port 6161:

sudo perl -pli -e 's/(name="jetty.port" default=")\d+/\16161/' /srv/archiva/conf/jetty.xml

(Restart Archiva after making this change, if you've already started it.) Then I added an Apache (web server) virtual host for it at /etc/apache2/sites-available/archiva, to proxy it from port 80 (running on a server with a DNS entry of archiva.example.com):

echo '
<VirtualHost *:80>
    ServerName archiva.example.com

    ProxyPreserveHost On
    RewriteEngine On

    # redirect / to /archiva
    RewriteRule ^/$ /archiva [L,R=301]

    # forward all archiva requests to archiva servlet
    RewriteRule (.*) http://localhost:6161$1 [P]
</VirtualHost>
' | sudo tee /etc/apache2/sites-available/archiva

sudo a2enmod proxy proxy_http rewrite
sudo a2ensite archiva
sudo service apache2 restart

Now you should be able to access Archiva simply by navigating to http://archiva.example.com/ (which will redirect to http://archiva.example.com/archiva). The first time you access it, you'll be prompted to create a new admin user. Do that so you can configure a few more things.

Add Proxy Connector for Grails Plugins

Once Archiva is up and running, and you've logged in as admin, navigate to the "Administration" > "Repositories" section of Archiva by using the leftnav. Click the "Add" link on the right side of the "Remote Repositories" section of the page, and enter the following settings:

Identifier: grails-plugins
Name: Grails Plugins
URL: http://repo.grails.org/grails/plugins/
Username:
Password:
Timeout in seconds: 60
Type: Maven 2.x Repository

Click the "Add Repository" button to save the new remote repo. Then navigate to the "Administration" > "Proxy Connectors" section using the leftnav. Click the "Add" link at the top-right of the page, and enter the following settings:

Network Proxy: (direct connection)
Managed Repository: internal
Remote Repository: grails-plugins
Return error when: always
Cache failures: yes
Releases: once
On remote error: stop
Checksum: fix
Snapshots: hourly

Click the "Save Proxy Connector" button to save the new proxy connector. The Archiva server should now be acting as a proxy for the Grails Plugins repo. It already comes configured as a proxy for the Maven Central repo, so you should be ready to use it with Grails.

Update BuildConfig.groovy

You can now comment out all the other default repos in the repositories section of the conf/BuildConfig.groovy files of your various Grails projects, and add a repo entry for your new Archiva server:

    repositories {
        mavenRepo 'http://archiva.example.com/archiva/repository/internal/'

        //grailsPlugins()
        //grailsHome()
        //grailsCentral()
        //mavenCentral()
        //mavenLocal()
        //...
    }

After updating your BuildConfig.groovy file, test out your changes by deleting your ivy2 cache folder (~/.ivy2/cache), and running a clean grails build (which will re-download all the dependencies for the Grails project through your new Archiva server).

1 comment: