Meteor - Deployment

meteor

http://fightingtheboss.github.io/ - done reading
http://galaxy-guide.meteor.com/deploy-guide.html
https://guide.meteor.com/deployment.html
https://forums.meteor.com/t/how-to-deploy-meteor-app-to-now-sh/28943
https://forums.meteor.com/t/super-simple-and-free-meteor-deployments-using-zeit-now/33214

What are the 3 basic options for deploying a Meteor web application?

  1. Use their free servers, which the Meteor staff have set up
  2. Deploy it to any server that has NodeJS and MongoDB installed. This allows you to deploy your app to any server that you have Terminal access to.
  3. Deploy to Galaxy

What is the purpose of the --settings flag of the 'meteor run' command?

Set optional data for Meteor.settings on the server. Typically when developing I would use meteor run —settings settings.json. This works fine and can view the settings in the browser with Meteor.settings on the console.

Settings. These are in a JSON object set via either the --settings Meteor command-line flag or stringified into the METEOR_SETTINGS environment variable. As for setting environment variables, if you use a 3rd party host, you may have a GUI or CLI to define them. Otherwise, you should have plenty resources including on SO:

In short, it should look like:

METEOR_SETTINGS='{"key":"value"}' node main.js

You can also try the bash cat command to extract the content of a file: $(cat settings.json)

They need to go before the command.

How can we deploy our Meteor web application to the free servers?

Deploying to their free servers is easy. All you must do is type:

meteor deploy yourSitesName.meteor.com

This will provision a free hostname and upload your application to run there. You can also use this option with your own custom domain name, such as "YourSite.com," but then you'll need to modify your site's DNS settings to point to origin.meteor.com.

How can we deploy our Meteor web application to our own servers?

meteor bundle .

This will package all the necessary files that will be required to run. Then, you'll Need to setup your MongoDB database and NodeJS dependencies. The Meteor team have included a README in the package, when you bundle your application. This file will provide exact instructions to get your application up and running.

What are common strategies for implementing sticky sessions?

There are a couple of ways we can implement sticky sessions. We can implement sticky sessions with cookies, hashing source IP information or customized URLs. There are some other ways, but these are the common ones.

Hashing source IP is the easiest to implement, but it does not balance the load properly. We can’t trust the IP information and transparent proxy servers (very commonly used by ISPs) hide the original IP information, which means one server will get many requests and the others won’t.

A customized URL path is a very good option and it is very well supported by SockJS. But for this, we’ll need some custom logic in the load balancer and further configuration on Meteor.

The cookie-based solution is ideal for us, since it can balance the load properly and it is easy to set up.

Why should we use leastconn instead of roundrobin?

It is very important to choose a good load-balancing algorithm. HaProxy comes with a bunch of algorithms. The roundrobin algorithm is recommended in the docs. roundrobin is very good for stateless webapps built with Ruby on Rails or PHP.

However, Meteor is stateful and it has long-lasting connections, so it is better to use the leastconn algorithm. It sends new connections to the server that has the lowest number of connections. This balances the load equally, even if a server goes down and comes back. If we use roundrobin, we’ll have an unbalanced load.

What is Meteor Up?

Meteor Up, often referred to as “mupx” or “mup”, is a third-party open-source tool that can be used to deploy Meteor application to any online server over SSH. It handles some of the essential deployment requirements, but you will still need to do a lot of work to get your load balancing and version updates working smoothly. It’s essentially a way to automate the manual steps of using meteor build and putting that bundle on your server.

You can obtain a server running Ubuntu or Debian from many generic hosting providers and Meteor Up can SSH into your server with the keys you provide in the config. You can also watch this video for a more complete walkthrough on how to do it.

Meteor Up has multiple projects so select what is best for your project:

  1. The mupx branch (best for pre-Meteor 1.4)
  2. The kadirahq/mup fork (best for Meteor 1.4 or higher)

Currently, using Meteor Up with Meteor 1.4 requires kadirahq/mup (still in development) and a special docker image with the correct Node version.

You install meteor-up via npm:

npm install -g mup

Use a terminal to navigate to your Meteor application folder and initialize for mup:

mup init

Now you have two JSON files in your directory:

  1. mup.json: This file is used to define the servers that will be used as deployment targets and to specify what components to install
  2. settings.json: This file is used to define deployment-specific configuration options available in Meteor.settings.

Although you do not have to use settings.json, you must adjust the contents of mup.json to reflect your own server setup. Once you are finish with modifying the mup.json file, you can set up the environment using:

mup setup

This will take care of all the server configurations and installation for you. It will also ensure that all server processes are started upon reboot. It uses 'forever' to restart a node in case it crashes. To deploy our application:

mup deploy

Beside init and deploy, there are also commands for starting and stopping application (start / stop / restart) and a way to access the Node.js logs (logs). When passing the -f option to logs, you can monitor the log file continuously similar to using the 'tail -f' command.

What is Galaxy?

Galaxy includes a number of features that make it the easiest way to deploy Meteor apps, including intelligent routing of clients and coordination of version updates. Galaxy is a pay-as-you-go cloud hosting provider starting at $0.035 per hour. It provides:

  1. Meteor specific container architecture
  2. Unlimited maximum containers
  3. Flexible container options per app1
  4. One-click container scaling
  5. Coordinated version updates
  6. Advanced traffic & load routing
  7. High availability fault tolerance
  8. Full application logging
  9. Full application metrics
  10. SSL support
  11. Wildcard domain management
  12. Auto pre-rendering for SEO

Pricing for containers:

  1. $0.035/hour: 512MB RAM, 0.5 ECU
  2. $0.07/hour: 1GB RAM, 1 ECU
  3. $0.14/hour: 2GB RAM, 2 ECU
  4. $0.28/hour: 4GB RAM, 4 ECU

Galaxy Support helps developers with the deployment and management of their apps on Galaxy. Basic support is available to all Galaxy users, but add-on support plans guarantee a speedy response for your critical apps when you need it most. Galaxy support options:

  1. Basic plan:
    1. 2+ business day response
    2. No critical SLA
  2. Priority:
    • $99 /month (billed annually)
    • $149 /month (billed monthly)
    • 1 business day response
    • No critical SLA
  3. Premium:
    • $399 /month (billed annually)
    • $499 /month (billed monthly)2
    • 1 business day response
    • 1-hour critical SLA (24x7x365 coverage)
  4. Enterprise:
    • $1299 /month (billed annually)2
    • $1499 /month (billed monthly)2
    • 4 business hour response
    • 15 min critical SLA (24x7x365 coverage)

If you deploy to Galaxy, you can use a x.meteorapp.com or x.eu.meteorapp.com domain while you are testing the app. Learn more about Galaxy domains. If you deploy to Galaxy, you can generate a free SSL certificate with a single click (courtesy of Let’s Encrypt!).

How can we move our application from meteor.com to our own infrastructure?

The free hosting provided by Meteor at meteor.com is great for deploying prototypes and toys but if your traffic starts to ramp up, you'll eventually have to move on to your own infrastructure. http://fightingtheboss.github.io/

You'll need to back up the data from the DB on your meteor.com site. Oli Evans made a dead simple bash script to help you called Meteor Dump

Meteor uses MongoHQ and unless you have some special reason to run your own MongoDB server, I highly recommend doing the same. The sandbox account gives you 512MB of storage for free and the prices are reasonable beyond that.

It's super simple to copy your data directly across to your new MongoHQ database once you've created an account.

You'll need to bundle your app either before or during deploy using meteor bundle (or mrt bundle). This creates a node-friendly bundle that you can run with node directly (i.e. node bundle/main.js)

If you create your bundle locally and then upload to your server, you'll have to be careful to rebuild your node dependencies in the server environment, as noted in the Meteor docs in the red text under Running your own infrastructure.

If you add packages using Meteorite locally then you'll want Meteorite on the server as well. This is bound to change pretty soon as Meteor (as of 0.6.0) now handles its own versioning and codifies package management a bit more and Meteorite is soon to change to catch up. http://fightingtheboss.github.io/

Meteor expects certain environment variables are set when the app is started:

  1. MONGO_URL: The URL to your MongoDB instance using the mongodb:// protocol.
  2. ROOT_URL: If you serve your site from a domain other than localhost, you'll need to set this so that URLs within your app point to the right place (Meteor.absoluteUrl depends on this variable being set).
  3. PORT: The port the app server should run on. This will vary depending on your environment and setup.
  4. Other packages may require specific environment variables (e.g. MAIL_URL).

Why should we not use the —production flag to deploy?

—production flag is purely meant to simulate production minification, but does almost nothing else. This still watches source code files, exchanges data with package server and does a lot more than just running the app, leading to unnecessary computing resource wasting and security issues. Please don’t use —production flag to deploy!

How can we use Meteor with a CDN?

It’s not strictly required, but often a good idea to set up a Content Delivery Network (CDN) for your site. A CDN is a network of servers that hosts the static assets of your site (such as JavaScript, CSS, and images) in numerous locations around the world and uses the server closest to your user to provide those files in order to speed up their delivery. For example, if the actual web server for your application is on the east coast of the USA and your user is in Australia, a CDN could host a copy of the JavaScript of the site within Australia or even in the city the user is in. This has huge benefits for the initial loading time of your site.

The basic way to use a CDN is to upload your files to the CDN and change your URLs to point at the CDN (for instance if your Meteor app is at http://myapp.com, changing your image URL from <img src="http://myapp.com/cats.gif"> to <img src="http://mycdn.com/cats.gif">). However, this would be hard to do with Meteor, since the largest file – your Javascript bundle – changes every time you edit your app.

For Meteor, we recommend using a CDN with “origin” support (like CloudFront), which means that instead of uploading your files in advance, the CDN automatically fetches them from your server. You put your files in public/ (in this case public/cats.gif), and when your Australian user asks the CDN for http://mycdn.com/cats.gif, the CDN, behind the scenes, fetches http://myapp.com/cats.gif and then delivers it to the user. While this is slightly slower than getting http://myapp.com/cats.gif directly, it only happens one time, because the CDN saves the file, and all subsequent Australians who ask for the file get it quickly.

To get Meteor to use the CDN for your Javascript and CSS bundles, call WebAppInternals.setBundledJsCssPrefix("http://mycdn.com") on the server. This will also take care of relative image URLs inside your CSS files. If you need to use a dynamic prefix, you can return the prefix from a function passed to WebAppInternals.setBundledJsCssUrlRewriteHook().

For all your files in public/, change their URLs to point at the CDN. You can use a helper like assetUrl.

Before:

<img src="http://myapp.com/cats.gif">

After:

Template.registerHelper("assetUrl", (asset) => {
  return "http://mycdn.com/" + asset
});
<img src="{{assetUrl 'cats.gif'}}">

If you are hosting a webfont as part of your application and serving it via a CDN, you may need to configure the served headers for the font to allow cross-origin resource sharing (as the webfont is now served from a different origin to your site itself). You can do this easily enough in Meteor by adding a handler (you’ll need to ensure your CDN is passing the header through):

import { WebApp } from 'meteor/webapp';

WebApp.rawConnectHandlers.use(function(req, res, next) {
  if (req._parsedUrl.pathname.match(/\.(ttf|ttc|otf|eot|woff|font\.css|css)$/)) {
    res.setHeader('Access-Control-Allow-Origin', /* your hostname, or just '*' */);
  }
  next();
});

And then for example with Cloudfront, you would:

  1. Select your distribution
  2. Behavior tab
  3. Select your app origin
  4. Edit button
  5. Under “Whitelist Headers”, scroll down to select “Origin”
  6. Add button
  7. “Yes, Edit” button

How can we use Galaxy?

  1. Log into galaxy
  2. Click on your app.
  3. Click on settings.
  4. In domains, click add new domain and enter your domain
  5. In the description for the Domains and Encryption section you will see an address that looks something like us-east-1.galaxy-ingress.meteor.com. Copy this down.
  6. On your host, create a new custom resource record Name: *, Type: CNAME, Data: us-east-1.galaxy-ingress.meteor.com (or paste yours if it differs in galaxy).
  7. Create a new custom resource record Name: www, Type: CNAME, Data: us-east-1.galaxy-ingress.meteor.com (or paste yours if it differs in galaxy).

The easiest way to operate your app with confidence is to use Galaxy, the service built by Meteor Development Group specifically to run Meteor apps. Galaxy is a distributed system that runs on Amazon AWS. If you understand what it takes to run Meteor apps correctly and just how Galaxy works, you’ll come to appreciate Galaxy’s value, and that it will save you a lot of time and trouble. Most large Meteor apps run on Galaxy today, and many of them have switched from custom solutions they used prior to Galaxy’s launch.

In order to deploy to Galaxy, you’ll need to sign up for an account, and separately provision a MongoDB database.

Once you’ve done that, it’s easy to deploy to Galaxy. You just need to add some environment variables to your settings file to point it at your MongoDB, and you can deploy with:

DEPLOY_HOSTNAME=us-east-1.galaxy-deploy.meteor.com meteor deploy your-app.com --settings production-settings.json

In order for Galaxy to work with your custom domain (your-app.com in this case), you need to set up your DNS to point at Galaxy. Once you’ve done this, you should be able to reach your site from a browser.

You can also log into the Galaxy UI at https://galaxy.meteor.com. Once there you can manage your applications, monitor the number of connections and resource usage, view logs, and change settings.

Set up SSL on your Galaxy application with the certificate and key for your domain. The key things here are to add the force-ssl package and to use the Galaxy UI to add your SSL certificate.

Once you are setup with Galaxy, deployment is simple (just re-run the meteor deploy command above), and scaling is even easier—simply log into galaxy.meteor.com, and scale instantly from there.

How should we select MongoDB hosting provider?

If you are using Galaxy (or need a production quality, managed MongoDB for one of the other options listed here), it’s usually a good idea to use a MongoDB hosting provider. There are a variety of options out there, but a good choice is mLab. The main things to look for are support for oplog tailing, and a presence in the us-east-1 or eu-west-1 AWS region.

How can we do custom deployment?

If you want to figure out your hosting solution completely from scratch, the Meteor tool has a command meteor build that creates a deployment bundle that contains a plain Node.js application. Any npm dependencies must be installed before issuing the meteor build command to be included in the bundle. You can host this application wherever you like and there are many options in terms of how you set it up and configure it.

It’s important that you build your bundle for the correct architecture. If you are building on your development machine, there’s a good chance you are deploying to a different server architecture. You’ll want to specify the correct architecture with --architecture:

# for example if deploying to a Ubuntu linux server:
npm install --production
meteor build /path/to/build --architecture os.linux.x86_64

This will provide you with a bundled application .tar.gz which you can extract and run without the meteor tool. The environment you choose will need the correct version of Node.js and connectivity to a MongoDB server.

Depending on the version of Meteor you are using, you should install the proper version of node using the appropriate installation process for your platform.

  • Node 4.4.7 for Meteor 1.4.x
  • Node 0.10.43 for Meteor 1.3.x and earlier

You can then run the application by invoking node with a ROOT_URL, and MONGO_URL. These instructions are also available in the README file found in the root of the bundle you built above.

cd my_build_bundle_directory
(cd programs/server && npm install)
MONGO_URL=mongodb://localhost:27017/myapp ROOT_URL=http://my-app.com node main.js
  1. ROOT_URL is the base URL for your Meteor project
  2. MONGO_URL is a Mongo connection string URI supplied by the MongoDB provider.

Unless you have a specific need to roll your own hosting environment, the other options here are definitely easier, and probably make for a better setup than doing everything from scratch. Operating a Meteor app in a way that it works correctly for everyone can be complex, and Galaxy handles a lot of the specifics like routing clients to the right containers and handling coordinated version updates for you.

How can we use Continuous Deployment to deploy to Galaxy?

Continuous deployment refers to the process of deploying an application via a continuous integration tool, usually when some condition is reached (such as a git push to the master branch). You can use CD to deploy to Galaxy, as Nate Strauser explains in a blog post on the subject.

How can we do a rolling deployment using Galaxy?

It’s important to understand what happens during a deployment, especially if your deployment involves changes in data format (and potentially data migrations).

When you are running your app on multiple servers or containers, it’s not a good idea to shut down all of the servers at once and then start them all back up again. This will result in more downtime than necessary, and will cause a huge spike in CPU usage when all of your clients reconnect again at the same time. To alleviate this, Galaxy stops and re-starts containers one by one during deployment. There will be a time period during which some containers are running the old version and some the new version, as users are migrated incrementally to the new version of your app.

If the new version involves different data formats in the database, then you need to be a little more careful about how you step through versions to ensure that all the versions that are running simultaneously can work together.

How can we use the okgrow:analytics package?

It’s common to want to know which pages of your app are most commonly visited, and where users are coming from. Here’s a simple setup that will get you URL tracking using Google Analytics. We’ll be using the okgrow:analytics package.

meteor add okgrow:analytics

Now, we need to configure the package with our Google Analytics key (the package also supports a large variety of other providers, check out the documentation on Atmosphere). Pass it in as part of Meteor settings:

{
  "public": {
    "analyticsSettings": {
      // Add your analytics tracking id's here
      "Google Analytics" : {"trackingId": "Your tracking ID"}
    }
  }
}

The analytics package hooks into Flow Router (see the routing article for more) and records all of the page events for you. You may want to track non-page change related events (for instance publication subscription, or method calls) also. To do so you can use the custom event tracking functionality:

export const updateText = new ValidatedMethod({
  ...
  run({ todoId, newText }) {
    // We use `isClient` here because we only want to track
    // attempted method calls from the client, not server to
    // server method calls
    if (Meteor.isClient) {
      analytics.track('todos.updateText', { todoId, newText });
    }

    // ...
  }
});

To achieve a similar abstraction for subscriptions/publications, you may want to write a simple wrapper for Meteor.subscribe().

How can we understand Kadira?

If you really want to understand the ins and outs of running your Meteor application, you should give Kadira a try. Kadira is a full featured Application Performance Monitoring (APM) solution that’s built from the ground up for Meteor. Kadira operates by taking regular client and server side observations of your application’s performance as it conducts various activities and reporting them back to a master server.

When you visit the Kadira application, you can view current and past behavior of your application over various useful metrics. Kadira’s documentation is extensive and invaluable, but we’ll discuss a few key areas here.

Method and Publication Latency. Rather than monitoring HTTP response times, in a Meteor app it makes far more sense to consider DDP response times. The two actions your client will wait for in terms of DDP are method calls and publication subscriptions. Kadira includes tools to help you discover which of your methods and publications are slow and resource intensive.

kadira-method-latency.png

In the above screenshot you can see the response time breakdown of the various methods commonly called by the Atmosphere application. The median time of 56ms and 99th percentile time of 200ms seems pretty reasonable, and doesn’t seem like too much of a concern

You can also use the “traces” section to discover particular cases of the method call that are particular slow:

kadira-method-trace.png

In the above screenshot we’re looking at a slower example of a method call (which takes 214ms), which, when we drill in further we see is mostly taken up waiting on other actions on the user’s connection (principally waiting on the searches/top and counts publications). So we could consider looking to speed up the initial time of those subscriptions as they are slowing down searches a little in some cases.

What is livequery monitoring?

A key performance characteristic of Meteor is driven by the behavior of livequery, the key technology that allows your publications to push changing data automatically in realtime. In order to achieve this, livequery needs to monitor your MongoDB instance for changes (by tailing the oplog) and decide if a given change is relevant for the given publication.

If the publication is used by a lot of users, or there are a lot of changes to be compared, then these livequery observers can do a lot of work. So it’s immensely useful that Kadira can tell you some statistics about your livequery usage:

kadira-observer-usage.png

In this screenshot we can see that observers are fairly steadily created and destroyed, with a pretty low amount of reuse over time, although in general they don’t survive for all that long. This would be consistent with the fact that we are looking at the package publication of Atmosphere which is started everytime a user visits a particular package’s page. The behavior is more or less what we would expect so we probably wouldn’t be too concerned by this information.

When should we enable SEO for our meteor app?

If your application contains a lot of publicly accessible content, then you probably want it to rank well in Google and other search engines’ indexes. As most webcrawlers do not support client-side rendering (or if they do, have spotty support for websockets), it’s better to render the site on the server and deliver it as HTML in this special case.

To do so, we can use the Prerender.io service, thanks to the dfischer:prerenderio package. It’s a simple as meteor add-ing it, and optionally setting your prerender token if you have a premium prerender account and would like to enable more frequent cache changes.

If you’re using Galaxy to host your meteor apps, you can also take advantage of built-in automatic Prerender.io integration. Simply add mdg:seo to your app and Galaxy will take care of the rest.

Chances are you also want to set <title> tags and other <head> content to make your site appear nicer in search results. The best way to do so is to use the kadira:dochead package. The sensible place to call out to DocHead is from the onCreated callbacks of your page-level components.

How can we debug a deployed application?

In case you need to debug a deployed application, you can also use 'meteor deploy <subdomain> --debug' which will allow you to use the browser-based debugger and keep your breakpoints.

How can we see the list of sites that you're authorized to deploy to?

meteor list-sites

How can we see the logs if our application is hosted on meteor.com?

meteor log <subdomain>

How can we connect to the MongoDB database if our application is hosted on meteor.com?

meteor mongo subdomain

How can we get the MongoDB URL if our application is hosted on meteor.com?

meteor mongo --url subdomain.meteor.com

This URL can be used by any MongoDB client such as Robomongo or passed to mongodump. The URL expires after 1 minute.

What is the purpose of the demeteorizer package?

The demeteorizer package wraps and extends the build command by creating a standard Node.js application. To create a highly portable Node.js bundles with demeteorizer, you first need to install it on your development system. Because it comes in form of a node module, it can be installed via npm:

npm install -g demeteorizer

Once it is installed, go to your application folder and run:

demeteorizer -t myApp.tar.gz

Unlike the build command, demeteorizer creates a build directory by default which is why the -t option is needed to create a tarball. It will also create the .demeteorizer directory. The resulting archive can be uploaded and extracted to the server. Some providers such as Modulus.io will allow you to directly upload the archive via a web interface. Thanks to the presence of the package.json file in the root of the project, all modules will be installed automatically if your provider supports it, or you'll navigate to the root folder of the project on the deployment server and issue the install command:

cd /var/www/myDemeteorizedApp
npm install

What are common environment variables used by Meteor?

  1. PORT: The network port to bind to (default: 3000)
  2. BIND_IP: The IP address to bind to (default: all)
  3. ROOT_URL: The base URL of the application
  4. MONGO_URL: The connection string for MongoDB
  5. MONGO_OPLOG_URL: The connection for MongoDB oplog
  6. MAIL_URL: The SMTP connection string for the mail server (default: STDOUT)
  7. NODE_ENV: Some cloud provider user this, typically set to production

Most cloud provider have a web interface for you to define names and values of environment variables.

In what regards is Meteor deployment different from traditional deployment?

In traditional approach, connections are stateless. It makes no difference which application server respond to any request in a series. With Meteor, each connection maintains state and therefore switching between servers for different requests of the same client will break things because any information regarding the context is lost. Traditional web application use server-side session. Perhaps we can use server-side session in Meteor application as well. However, Meteor also use DDP and WebSocket, which means that if a server is restarted we need to do something on the browser side to re-establish the connection, or the users may experience some problem. It is best to use sticky-load-balancing.

Does Meteor support SSL connection?

No. Although Node.js supports SSL connections, Meteor does not. To provide secure connections, SSL can still be used on the load balancer facing the clients. All traffic between the load balancer and the application server will be unencrypted, which is referred to as SSL offloading.

How can we offload static resources to a proxy server or CDN?

The 'meteor build' command automatically minifies and compiles all CSS and JavaScript files and place them in the folder bundle/programs/web.browser. If NGINX is to serve these files, they must be accessible from the nginx server. If Meteor is deployed to a different server, you can either copy the files to nginx machine or configure a folder share using NFS. If you copy the files, remember that you need to repeat this every time you deploy the application. Because each build command will create new random filenames, there is no need to delete the old files. This allows for smoother transition between deployments.

To configure serving static application files and styles, you must define a new location block in your nginx configuration file:

server {
  ...
  location ~* "^/[a-z0-9]{40}\.(css|js)$" {
    root /home/meteor/app/bundle/programs/web.browser/app;
    access_log off;  // Turn access log off for these files to reduce disk I/O
    expires 30d;
    add_header Pragma public
    add_header Cache-Control "public";
  }
}

The content of the public folder should also be served from nginx. Because the public folder is accessible at the root of your application, you'll use file extension to determine whether a request will be served statically or from Meteor. The configuration is similar to the above block:

server {
  ...
  location ~ \.(jpg|jpeg|png|gif|mp3|ico|pdf) {
    root /home/meteor/app/bundle/programs/web.browser/app;
    access_log off;  // Turn access log off for these files to reduce disk I/O
    expires 30d;
    add_header Pragma public
    add_header Cache-Control "public";
  }
}

The only difference between these 2 blocks is the regular expression in the location line. Perhaps we can combine these block.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License