Creating private maven repository on S3 & using in SBT

A short tutorial on how to use S3 buckets to create a private maven repository. We will also go over using this private repo in sbt.

Setup Maven Repository

Create S3 buckets

We'll need two; one for releases & another for snapshots. So go ahead and create these buckets named so:

  1. snapshots.mvn-repo.[domain.com]
  2. releases.mvn-repo.[domain.com]

Secure S3 buckets

Since we want a private maven repository, we'd want some way to control access to them. Lets use IAM to secure this. This will essentially get us a key/secret which has access to only these two buckets:

  • Log into your IAM Console
  • Create a new user
  • When creating user, keep the option "generate access key for each user" checked and be sure to download/save the Access Key ID and Secret Access Key that AWS generated for you for this user. We'll need this later to allow our build to access the buckets.
  • Edit permissions for that user and Attach User Policy which gives acccess to these two buckets. You can use policy generator or custom policy. Note that we need to give access to each bucket and everything under them. You should end up with a policy like so:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1338341152000",
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
"arn:aws:s3:::releases.mvn-repo.[domain.com]", "arn:aws:s3:::releases.mvn-repo.[domain.com]/*", "arn:aws:s3:::snapshots.mvn-repo.[domain.com]", "arn:aws:s3:::snapshots.mvn-repo.[domain.com]/*"
      ]
    }
  ]
}

Now our maven repository is secured and ready for access by our builds.

Publising with SBT

We'll use plugin sbt-s3-resolver

Create .s3credentials file

We need some way to allow our build to access the buckets we created. The plugin allows different ways to do this but here we'll just use a file called .s3credentials in the root of our project that has Access Key ID and Secret Access Key from above like so:

accessKey = [foo]  
secretKey = [bar]

Update plugins.sbt

Open your plugins.sbt and add these lines (check the latest version number here) :

resolvers += "Era7 maven releases" at "http://releases.era7.com.s3.amazonaws.com"

addSbtPlugin("ohnosequences" % "sbt-s3-resolver" % "0.11.0")

Update build.scala

In your build.scala/build.sbt

  • Add these imports:
import ohnosequences.sbt.SbtS3Resolver._  
import com.amazonaws.services.s3.model.Region  
  • Add S3Resolver.defaults to your build settings. Something like:
  lazy val project = Project (
    "your-project",
    file("."),
    settings = Defaults.defaultSettings
      ++ S3Resolver.defaults)
  • Configure the plugin:
s3region := Region.US_Standard,  
s3credentials := file(".s3credentials"),  
publishMavenStyle := false,  
publishTo := {  
  val prefix = if (isSnapshot.value) "snapshots" else "releases"

  Some(s3resolver.value(s"$prefix s3 bucket", s3(prefix+"mvn-repo.[domain.com]")) withIvyPatterns)
},

publish

sbt publish

Resolve with SBT

Setup Resolvers in build.scala

To use the atifacts uploaded to maven repo, we need to setup resolvers. You'd need to setup plugins.sbt, imports and projects settings as above (of course you can skip publishTo for projects which are just using the artifacts). You'll need to add resolvers as below:

      resolvers ++= {
        val releases: Resolver = s3resolver.value("Releases resolver", s3("releases.mvn-repo.[domain.com]")).withIvyPatterns
        val snapshots: Resolver = s3resolver.value("Snapshots resolver", s3("snapshots.mvn-repo.[domain.com]")).withIvyPatterns
        Seq(releases, snapshots)
      },