How I build Meteor apps
28 Mar 2016

Policies

Publications and subscriptions

I disagree with the official advice to put the subscription as close to use as possible. Most of the time, I put all subscriptions in the global namespace. This works perfectly for me most of the time, with a few obvious exceptions (huge and/or rapidly changing collections). Those ones get special effort to ensure that things remain performant – remember – premature optimisation is still the root of all evil. Global subscriptions save so much development effort and are almost always the right thing to do.

I view publications more like ‘file permissions’ than ’send this data to the client’. That is, the client can see anything that is published at any time. It’s the server’s job to make sure that that is a sensible (appropriate and safe) subset of the data, and all that the client has to worry about is how best to present it. Remember that from a security point of view, you can’t effectively control data once it’s on the client.

Security

I almost always disable client-side updates and inserts on collections, preferring to use server-side Methods (with paranoid checking) wherever possible. The development overhead of doing this is minimal.

Overly permissive publications and subscriptions are by far the most common security issue. Check that your client-side caches are cleared when the user logs out. Manually query the client-side collections to ensure that only the exact data the client requires is actually present – it’s easy to mess up the publication side and overpublish.

Packages are a huge security risk. They’re not well audited at this stage and Meteor is small enough that many useful packages only have a small number of users.

Packages sometimes publish data automatically. It’s rare that this is mentioned in the documentation. You need to check that any publications fit with your access control model and (again) do not publish any more than is necessary.

Often, you’ll need to build an admin interface. Every user will receive a copy of this, and you need to think about whether it’s a risk. I usually leave admin interfaces in the same application. Occasionally it’s worth building admin code in a separate application pointing to the same MongoDB instance. This will create overheads for development. There are packages to automate this but I haven’t evaluated any yet.

The official Meteor Security Guide is excellent and worth reading carefully.

Package updates

Package updates and Meteor updates will cause breaking changes. You will need to retest everything.

So far, there is no mechanism to tell you which updates are security-related and which are merely bug/feature fixes. I hope that this is remedied soon. Individual package authors pay practically no attention to security; you’re on your own there.

Schemas

I don’t bother. Most data models are simple enough that it’s not necessary.

Error tracking

I install Raven/Sentry on every app that I deploy. It’s almost no effort and it will show you amazing debug information if anything goes wrong at runtime.

Google Analytics

There’s probably something better. This is fine for now.

Standard stuff

Deployments

I deploy small apps to Docker instances with a shared Mongo instance on a cheap 1GB VPS (BinaryLane, because they provide great performance at a great price and are in Sydney). This fits about a dozen low-traffic apps. Anything larger gets migrated to its own instance – usually to Amazon or DigitalOcean where it can programmatically scale.

Standard packages

raix:handlebar-helpers

Iron Router. I haven’t taken the time to learn Flow Router or decide if it’s going to be an improvement.

Semantic-UI. I’m no designer, but with Semantic-UI, nobody can tell the difference. I used to use Bootstrap but find Semantic much easier and prettier.

I use Blaze simply because I haven’t learned React or Angular yet. I should probably learn React at some point.

Structure

I put this last as it’s almost entirely personal preference and completely unimportant.

app/
    client/
        subscriptions.js
        templates and JS go here
    lib/
        collections.js
        shared JS goes here
    server/
        publications.js
        methods.js
        other server-side JS goes here
    public/
deployment/
    deploy.yaml - Ansible playbook
    hosts - the name of my server
doc/
    documentation in Markdown format
README.md

comments powered by Disqus