• Stars
    star
    167
  • Rank 226,635 (Top 5 %)
  • Language
    JavaScript
  • Created almost 10 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Command-line tool to manage nginx-powered proxies for node apps. Static file delivery, load balancing, HTTPS, all that jazz with a clean interface.

CircleCI

mechanic

Purpose

nginx is a popular reverse proxy server among node developers. It's common to set up one or more node apps listening on high-numbered ports and use nginx virtual hosting and reverse proxy features to pass traffic to node. nginx can also serve static files better than node can, and it has battle-tested round-robin load balancing features.

We've boiled down our favorite configuration recipes for nginx to a simple utility that takes care of spinning up and shutting down proxies for new node sites on a server. It can also handle load balancing, canonical redirects, direct delivery of static files and https configuration. It takes the place of manually editing nginx configuration files.

Install

Step One: install nginx on your Linux server.

Under Ubuntu Linux that would be:

apt-get install nginx

Make sure Apache isn't in the way, already listening on port 80. Remove it really, really thoroughly. Or reconfigure it for an alternate port, like 9898, and set it up as a fallback as described below.

Step Two:

npm install -g mechanic

NOTE: mechanic will reconfigure nginx after each command given to it. A strong effort is made not to mess up other uses of nginx. Mechanic's nginx configuration output is written to /etc/nginx/conf.d/mechanic.conf, where both Debian-flavored and Red Hat-flavored Linux will load it. No other nginx configuration files are touched. You can change the folder where mechanic.conf is written, see below.

Step Three:

Go nuts.

Let's add a single proxy that talks to one node process, which is listening on port 3000 on the same server (localhost):

All commands must be run as root.

Adding a site

mechanic add mysite --host=mysite.com --backends=3000

Replace mysite with a good "shortname" for your siteβ€” letters and numbers and underscores only, no leading digits.

mechanic will reconfigure and restart nginx as you go along and remember everything you've asked it to include.

Aliases: alternate hostnames

Next we decide we want some aliases: other hostnames that deliver the same content. It's common to do this in the pre-launch period. With the update command we can add new options to a site without starting from scratch:

mechanic update mysite --aliases=www.mysite.com,mysite.temporary.com

Canonicalization: redirecting to the "real name"

In production, it's better to redirect traffic so that everyone sees the same domain. Let's start redirecting from our aliases rather than keeping them in the address bar:

mechanic update mysite --canonical=true

Setting a default site

We've realized this site should be the default site for the entire server. If a request arrives with a hostname that doesn't match any --host or --aliases list, it should always go to this site, redirecting first if the site is canonical. We can do that with default:

mechanic update mysite --default=true

Warning: If your server came with a default website already configured, like the server block that appears in /etc/nginx/nginx.conf in CentOS 7, you will need to comment that out to use this feature. mechanic does not mess with the rest of your nginx settings, that is up to you.

Fast static file delivery

Let's score a big performance win by serving our static files directly with nginx. This is simple: if a file matching the URL exists, nginx will serve it directly. Otherwise the request is still sent to node. All we have to do is tell nginx where our static files live.

mechanic update mysite --static=/opt/stagecoach/apps/mysite/current/public

Browsers will cache the static files for up to 7 days. That's a good thing, but if you use this feature make sure any dynamically generated files have new filenames on each new deployment.

Serving index.html for bare directories

When using --static, you can optionally enable serving index.html automatically when a URL matches a directory name by using the --autoindex option.

mechanic update mysite --autoindex

As with all boolean options you can change your mind later:

mechanic update mysite --autoindex=false

In a typical proxy configuration, this makes it possible to use an index.html file as a cached static version of a resource with a "pretty URL" like /people that would normally hit your back end server.

Static websites

Although static websites will never be a primary use case for mechanic, you can set up a perfectly reasonable static webserver like this:

mechanic add mysite --host=mysite.com --static=/var/www/html/mysite --autoindex

The backends option is no longer mandatory when --static is present.

If you have more elaborate use cases that don't involve a reverse proxy, you should really create a separate nginx configuration file for that site.

Load balancing

Traffic is surging, so we've set up four node processes to take advantage of four cores. They are listening on ports 3000, 3001, 3002 and 3003. Let's tell nginx to distribute traffic to all of them:

mechanic update mysite --backends=3000,3001,3002,3003

Across two servers

This time we want to load-balance between two separate back-end servers, each of which is listening on two ports:

mechanic update mysite --backends=192.168.1.2:3000,192.168.1.2:3001,192.168.1.3:3000,192.168.1.3:3001

You can use hostnames too.

Secure backends

If you're proxying to a remote server, it's a good idea to enable HTTPS there too, so your connection is secure end-to-end. If you use the https-upstream option, nginx will make requests to your backends using SSL.

mechanic update mysite --https-upstream

Note that this can introduce a significant performance overhead, as nginx will need to validate certificates and encrypt the connection with the backend.

Backends for certain URL paths only

You can configure a backend exclusively for with a certain path prefix:

mechanic update mysite --backends=3000,3001:/ci-server

This is also supported for backends not running on the same computer:

mechanic update mysite --backends=192.168.1.2:3000,192.168.1.2:4000/ci-server

The prefix is included in the URL passed through to the backend.

If such a backend is present, matching requests are sent only to it. You may have more than one for the same path, in which case they are load balanced by nginx in the usual way.

This feature is useful when microservices share a single hostname.

Secure sites

Now we've added ecommerce and we need a secure site:

mechanic update mysite --https=true

Now nginx will serve the site with https (as well as http) and look for mysite.cer and mysite.key in the folder /etc/nginx/certs.

See the nginx docs on how to handle intermediate certificates.

Redirecting to the secure site

Next we decide we want the site to be secure all the time, redirecting any traffic that arrives at the insecure site:

mechanic update mysite --https=true --redirect-to-https=true

Redirecting to another site

We can also redirect all traffic to a different site. To redirect 100% of the traffic to one specific URL, use --redirect:

mechanic update mysite --redirect=https://example.com

To instead append the rest of the original URL to a redirected domain, use --redirect-full:

mechanic update mysite --redirect-full=https://example.com

Setting --redirect clears --redirect-full, and vice versa.

Enabling HTTP/2

We can enable HTTP/2 by setting http2 to true:

mechanic set true

Disabling HTTP/2

We can disable HTTP/2 by setting http2 to an empty string:

mechanic set ''

Permanent and Temporary Redirects

All redirects are temporary by default. To make redirects permanent (301), use --permanent=true. To go back to a temporary (302) redirect, use --permanent=false.

mechanic update mysite --permanent=true

Shutting off HTTPS

Now we've decided we don't want ecommerce anymore. Let's shut that off:

mechanic update mysite --https=false

Removing a site

Now let's remove the site completely:

mechanic remove mysite

Disabling options

You can disable any previously set option, such as static, by setting it to false or the empty string.

Falling back to Apache

If you also want to serve some content with Apache on the same server, first configure Apache to listen on port 9898 instead of 80, then set up a default site for mechanic that forwards traffic there:

mechanic add apache --host=dummy --backends=9898 --default=true

We still need a host setting even for a default site (TODO: remove this requirement).

Apache doesn't have to be your default. You could also use --host and set up individual sites to be forwarded to Apache.

Global options

There are a few global options you might want to change. Here's how. The values shown are the defaults.

conf: nginx configuration file location

mechanic set conf /etc/nginx/conf.d

This is the folder where the mechanic.conf nginx configuration file will be created. Note that both Red Hat and Debian-flavored Linux load everything in this folder by default.

restart: nginx restart command

mechanic set restart "nginx -s reload"

The command to restart nginx.

Don't forget the quotes if spaces are present. That's just how the shell works, but it bears repeating.

logs: webserver log file folder

mechanic set logs /var/log/nginx

If this isn't where you want your nginx access and error log files for each site, change the setting.

bind: bind address

mechanic set bind "*"

By default, mechanic tells nginx to accept traffic on all IP addresses assigned to the server. (* means "everything.") If this isn't what you want, set a specific ip address with bind.

_If you reset this setting to _ make sure you quote it, so the shell doesn't give you a list of filenames.*

Enabling websockets

By default, nginx does not proxy websockets. You can enable this by passing the --websockets flag:

mechanic update mysite --websockets

This enables websockets proxying per the nginx documentation by setting the HTTP version for the proxy to 1.1 and setting the Upgrade header.

As with other boolean flags you can turn this off again with --websockets=false.

template: custom nginx template file

mechanic set template /etc/mechanic/custom.conf

You don't have to use our nginx configuration template.

Take a look at the file template.conf in the nginx npm module. It's just a nunjucks template that builds an nginx configuration based on your mechanic settings.

You can copy that template anywhere you like, make your own modifications, then use mechanic set template to tell mechanic where to find it.

Lazy overrides

If you don't want to customize our template, check out the convenience override files that mechanic creates for you:

/etc/nginx/mechanic-overrides/myshortname/top
/etc/nginx/mechanic-overrides/myshortname/server
/etc/nginx/mechanic-overrides/myshortname/location
/etc/nginx/mechanic-overrides/myshortname/proxy

top is loaded before any of mechanic's directives for that site. Use it when nothing else fits.

server is included inside the server block for the site, just before the location block, when redirect-to-https is not in effect. It is a good place to change a setting like access_log.

location is included inside the location block, and is a good place to add something like CORS headers for static font files. It is also a good place to change the client_max_body_size directive.

proxy is loaded inside the proxy server configuration and is ideal if you need to override mechanic's proxy settings.

These files start out empty; you can add whatever you like.

Of course, if this isn't enough flexibility for your needs, you can create a custom template.

Refreshing your nginx configuration

Maybe you updated mechanic with npm update -g mechanic and you want our latest configuration. Maybe you edited your custom template. Either way, you want to rebuild your nginx configuration without changing any settings:

mechanic refresh

Resetting to the defaults

To completely reset mechanic, throwing away everything it knows:

mechanic reset

Warning: like it says, this will completely reset your configuration and forget everything you've done. Don't do that unless you really want to.

Listing your configuration settings

mechanic list

This gives you back commands sufficient to set them up the same way again. Great for copying to another server. Here's some sample output:

mechanic set restart "/usr/sbin/nginx -s reload"
mechanic add test --host=test.com --aliases=www.test.com --canonical=true --https=true
mechanic add test2 --host=test2.com --aliases=www.test2.com,test2-prelaunch.mycompany.com

If you want to wipe the configuration on another server before applying these commands there, use mechanic reset.

Custom nginx templates

You don't have to use our nginx configuration template.

Take a look at the file template.conf in the nginx npm module. It's just a nunjucks template that builds an nginx configuration based on your mechanic settings.

Custom nginx path

If you use brew (a package manager for mac) to install nginx, nginx install path will be /usr/local/etc/nginx. Mechanic default nginx path is /etc/nginx. You can change default nginx path below:

mechanic set restart 'brew services restart nginx'
mechanic set conf '/usr/local/etc/nginx/conf.d'
mechanic set overrides /usr/local/etc/nginx/mechanic-overrides
mechanic set logs /usr/local/var/log/nginx

Storing the database in a different place

It's stored in /var/lib/misc/mechanic.json. That's one hundred percent correct according to the filesystem hierarchy standard, adhered to by all major Linux distributions and many other flavors of Unix. But if you absolutely insist, you can use the --data option to specify another location. You'll have to do it every time you run mechanic, though. That's why we only use this option for unit tests.

If necessary mechanic will create /var/lib/misc.

Credits

mechanic was created to facilitate our work at P'unk Avenue. We use it to host sites powered by ApostropheCMS.

More Repositories

1

apostrophe

A full-featured, open-source content management framework built with Node.js that empowers organizations by combining in-context editing and headless architecture in a full-stack JS environment.
JavaScript
4,318
star
2

sanitize-html

Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis. Built on htmlparser2 for speed and tolerance
JavaScript
3,413
star
3

stagecoach

Painlessly deploy node.js applications to your staging and production servers. Use a standard VPS or dedicated server to host both Node and traditional Apache-based websites. Pairs nicely with nginx and mechanic.
Shell
303
star
4

random-words

Generate one or more common English words. Intended for use as sample text, for example generating random blog posts for testing
JavaScript
222
star
5

apostrophe-sandbox

This sandbox site is the basis for our live demo. For your own projects, you can use apostrophe-boilerplate as a more streamlined, cleaner point of departure via the apostrophe-cli tool.
Less
112
star
6

apostrophe-headless

Add REST APIs to your Apostrophe "pieces," powering your React/Vue/etc. apps with a headless CMS.
JavaScript
97
star
7

express-cache-on-demand

express-cache-on-demand
JavaScript
80
star
8

prettiest

Improbably easy data storage and locking for command line scripts. Pairs well with shelljs and a nice chianti.
JavaScript
77
star
9

oembetter

A modern oembed client. Allows you to register filters to improve or supply oembed support for sites that don't normally have it. You can also supply a whitelist of services you trust to prevent XSS attacks.
JavaScript
50
star
10

uploadfs

Store files in a web-accessible location. Includes S3, Azure, and local filesystem-based backends. Can also scale and autorotate image files. Additional storage and image-processing backends are easy to create.
JavaScript
50
star
11

sluggo

High-speed, unicode-aware, browser-friendly slug generator
JavaScript
47
star
12

split-html

Split HTML into two valid fragments wherever a certain selector is matched. Works on the server side.
JavaScript
36
star
13

apostrophe-workflow

Provides approval-based workflow and localization capabilities for projects that need them. An optional component of the Apostrophe CMS.
JavaScript
36
star
14

apostrophe-open-museum

Learn about ApostropheCMS via this boilerplate site built for an imaginary art museum.
HTML
34
star
15

apostrophe-documentation

Documentation for the ApostroheCMS open-souce ecosystem
Shell
25
star
16

apostrophe-blog

Blogging for the Apostrophe 2 content management system for Node.
JavaScript
22
star
17

moog

Moog provides powerful module subclassing.
JavaScript
18
star
18

absolution

Accepts HTML and a base URL, and returns HTML with absolute URLs. Great for generating valid RSS feed entries.
JavaScript
15
star
19

apostrophe-boilerplate

Shell
14
star
20

apostrophe-seo

SEO for ApostropheCMS
JavaScript
14
star
21

apostrophe-cli

DEPRECATED. Use `@apostrophecms/cli` as the active ApostropheCMS CLI tool.
JavaScript
14
star
22

apostrophe-samples

An Apostrophe website that demonstrates various techniques and will be linked to in documentation, stackoverflow answers, etc. Check it out to learn where that code is supposed to go!
JavaScript
13
star
23

apostrophe-passport

Allows users to log into Apostrophe CMS sites via Google, Gitlab, etc. Works with most passport strategy modules.
JavaScript
13
star
24

apostrophe-palette

An in-context interface for modifying the the visual appearance of an ApostropheCMS site.
JavaScript
12
star
25

apostrophe-events

JavaScript
10
star
26

apostrophe-forms

Allow your users to build custom forms on the fly on your Apostrophe site
JavaScript
9
star
27

apostrophe-guides

Build guides for your ApostropheCMS website
JavaScript
9
star
28

apostrophe-monitor

Monitors and restarts an Apostrophe app when your code, templates, etc. change. Like nodemon but much faster because it takes advantage of how Apostrophe works.
JavaScript
8
star
29

apostrophe-tiptap-rich-text-widgets

Wrapper allowing the use of the tiptap vue-based rich-text editor for Apostrophe 2.x. In 3.x it will be standard equipment.
JavaScript
6
star
30

apostrophe-signup

Lets the public sign up for accounts on a website powered by apostrophecms.
JavaScript
6
star
31

apostrophe-enterprise-testbed

A testbed for browser-based functional testing of apostrophe, apostrophe-workflow, and similar modules found in enterprise settings.
JavaScript
6
star
32

apostrophe-lean-frontend

An alternative frontend javascript environment for ApostropheCMS, with no vendor libraries (no jQuery, no lodash, etc). Just enough glue to let you write widget players, plus some players for standard widgets which you can opt into... otherwise it doesn't push them at all.
JavaScript
6
star
33

apostrophe-places

0.6 implementation of apostrophe-map
JavaScript
5
star
34

a3-boilerplate

Simple, minimal starting point for new Apostrophe 3 projects
Shell
5
star
35

apostrophe-site-map

Generates a site map of your Apostrophe site, for SEO and content strategy purposes.
JavaScript
5
star
36

broadband

Given a MongoDB query cursor, process the results in parallel, up to the specified limit.
JavaScript
5
star
37

launder

A sanitizer module for the people. Built for Apostrophe.
JavaScript
4
star
38

linode-dns-tools

Power tools for the linode DNS API. Import a zone file, globally replace an IP address, etc.
JavaScript
4
star
39

count-outside-pull-requests

Count pull requests to your github repositories from outside your team.
JavaScript
4
star
40

max-mem

Measure maximum memory usage of a command
JavaScript
4
star
41

boring

A minimalist command line option parser.
JavaScript
4
star
42

time-limited-regular-expressions

Evaluates regular expressions with a time limit to mitigate DOS attacks based on catastrophic backtracking.
JavaScript
3
star
43

apostrophe-optimizer

Optimizes the performance of the Apostrophe CMS by prefetching related content to eliminate extra MongoDB queries.
JavaScript
3
star
44

piece-type-importer

JavaScript
3
star
45

apostrophe-open-graph

Open Graph for ApostropheCMS
JavaScript
3
star
46

apostrophe-elasticsearch

All text searches within Apostrophe are powered by Elasticsearch when this module is active.
JavaScript
3
star
47

sync-content

Back up and restore Apostrophe sites via the admin bar. Also useful for moving content between environments.
JavaScript
3
star
48

apostrophe-profiler

Debug tools for the Apostrophe CMS
JavaScript
3
star
49

apostrophe-link-widgets

ApostropheCMS link widgets
JavaScript
3
star
50

moog-require

Leverage npm's "require" with the "moog" module subclassing tool
JavaScript
3
star
51

apostrophe-personas

Specialize the content of each page of an Apostrophe site based on the user's primary affiliation (employee versus employer, truck vs. car, etc.)
JavaScript
3
star
52

apostrophe-selective-permissions

Create specialized permissions for users of your ApostropheCMS site, such as an "seo" permission that allows editing only certain fields of certain pieces and pages.
JavaScript
2
star
53

security-headers

This module sends the modern HTTP security headers that are expected by various security scanners.
JavaScript
2
star
54

apostrophe-favicons

Generates and links a set of favicons from an image in the media library
JavaScript
2
star
55

cache-on-demand

"On demand" caching that kicks in only when requests arrive simultaneously.
JavaScript
2
star
56

a3-docs

Apostrophe 3.x documentation.
Shell
2
star
57

a3-demo

A test project for ApostropheCMS 3.x
JavaScript
2
star
58

apostrophe-secure-attachments

Limit direct URL access to uploaded attachments, such as PDFs, to those who have appropriate permissions.
JavaScript
2
star
59

apostrophe-pieces-orderings-bundle

Manually sort your pieces, then put that handpicked order into effect for pieces-pages, widgets and even the manage view.
JavaScript
2
star
60

apostrophe-redirects

Allows admins to create redirects within an Apostrophe site
JavaScript
2
star
61

heic-to-jpeg-middleware

Middleware to convert HEIC/HEIF files from iOS 11 devices like the iPhone to JPEG format, with no other modifications to your code that expects JPEG
JavaScript
2
star
62

apostrophe-atom

Atom snippets for working with Apostrophe projects.
2
star
63

form

JavaScript
2
star
64

apostrophe-nightwatch-tools

Nightwatch custom commands useful for testing ApostropheCMS sites.
JavaScript
2
star
65

stylelint-config-apostrophe

An stylelint configuration for Apostrophe.
JavaScript
2
star
66

apostrophe-override-options

Override Apostrophe's getOption method based on the current page type, page settings, etc.
JavaScript
2
star
67

apostrophe-address-widgets

ApostropheCMS address widgets
JavaScript
2
star
68

apostrophe-pieces-submit-widgets

Submit user generated content to Apostrophe CMS
JavaScript
2
star
69

apostrophe-pieces-import

Adds features to apostrophe-pieces allowing easy import of content via CSV, Excel, etc.
JavaScript
2
star
70

apostrophe-storybook

This repository is deprecated. The UI library is now included in ApostropheCMS core, in the 3.0 branch.
Vue
2
star
71

apostrophe-review-and-deploy

Require an approval process for the entire site, or one locale, then push the site's content from "pre-production" to production on another host
JavaScript
2
star
72

apostrophe-gulp-starter

A demo configuration incorporating Gulp.js with ApostropheCMS
Shell
2
star
73

content-upgrader

Tools to upgrade your site's content from previous versions of Apostrophe. See also code-upgrader.
JavaScript
2
star
74

apostrophe-rich-text-permalinks

Create permalinks to Apostrophe content inside the rich text editor. Your permalinks will stay fresh if the content moves.
JavaScript
2
star
75

apostrophe-i18n-static

Add editable pieces for translation through i18n to an Apostrophe project
JavaScript
2
star
76

apostrophe-svg-sprites

apostrophe-images for SVGs in external sprite maps!
JavaScript
2
star
77

redirect

Manage site redirects for Apostrophe 3.
JavaScript
1
star
78

sitemap

The Apostrophe Sitemap module generates XML sitemaps for websites powered by Apostrophe 3.
JavaScript
1
star
79

apostrophe-twitter-widgets

Twitter for Apostrophe 2
JavaScript
1
star
80

apostrophe-pubmed

Piece subclass with an enhanced editor modal for easily syncing single PubMed docs to new piece instances
JavaScript
1
star
81

apostrophe-maintenance-mode

Put your Apostrophe site in maintenance mode, preventing access until you turn it on again
JavaScript
1
star
82

gatsby-source-apostrophe

Gatsby source plugin for ApostropheCMS
JavaScript
1
star
83

apostrophe-saml

Single sign-on for the Apostrophe CMS via SAML or Shibboleth
JavaScript
1
star
84

apostrophe-pieces-export

JavaScript
1
star
85

apostrophe-styleguide

Boilerplate styleguide to drop into your projects
HTML
1
star
86

kafka

Kafka support for A3
JavaScript
1
star
87

apostrophe-docs-popularity

Track and sort the popularity of pieces and pages on an Apostrophe site according to metrics of your choice: social network votes, views, votes, etc.
JavaScript
1
star
88

apostrophe-db-mongo-3-driver

Extends ApostropheCMS to use the 3.x version of the MongoDB native driver, for better compatibility with MongoDB 3.6, 4.0, etc.
JavaScript
1
star
89

code-upgrader

Very pre-alpha tool for converting apostrophe modules from 2.x format to newer format using esprima and escodegen.
JavaScript
1
star
90

blog

An A3 bundle for managing and browsing blog articles
JavaScript
1
star
91

asset-es5

For those who still require IE11 support for the frontend build.
JavaScript
1
star
92

apostrophe-login-recaptcha

Attempt to prove users are human before allowing local login to apostrophe
JavaScript
1
star
93

apostrophe-query-cache

Simple mongodb query caching solution for Apostrophe sites that become database-bound.
JavaScript
1
star
94

apostrophe-caches-redis

Replaces Apostrophe's MongoDB-based caching mechanism with Redis.
JavaScript
1
star
95

login-totp

JavaScript
1
star
96

seo

Add and manage SEO meta fields to all documents in Apostrophe 3.
JavaScript
1
star
97

csv-to-zone-file

Converts CSV to a zonefile just good enough to import into Amazon Route 53
JavaScript
1
star
98

eslint-config-apostrophe

An eslint configuration for the apostrophe core modules.
JavaScript
1
star
99

apostrophe-area-structure

A modal window that displays a visualization of your page's area structure
JavaScript
1
star
100

apostrophe-external-notifications

Send notifications via Slack and other systems when various events occur in ApostropheCMS
JavaScript
1
star