To create the scripts in install-consul, we had to find a way to write and package the scripts that satisfied a
number of requirements. This document captures the requirements, the options we considered, and an explanation of
which option we picked and why.
The requirements
We need to write and package the scripts in this Module in a way that satisfies the following requirements:
Packages. There needs to be a way to fetch these scripts from a canonical location (e.g. GitHub repo, package
manager repository) at a specific version number (e.g. v0.0.3 of install-consul), much like a package manager.
We don't want people copy/pasting these scripts into their local repos, or it'll make upgrades and maintenance
difficult.
Cross-platform. The packaging system should work on most major Linux distributions. It should also work on OS X,
as that's what many people use for development.
Handles dependencies. These scripts rely on certain dependencies being installed on the system, such as curl,
wget, jq, aws, and so on. We need a way to automatically manage and install these dependencies that works
across all major Linux distributions.
Simple package manager installation: We don't want a package manager that takes a dozen steps to install.
Simple client usage. The scripts in this Module are fairly simple, so it shouldn't take a dozen steps to
install one. Ideally, we can use a one-liner such as apt install -y install-consul, except it should work on all
major Linux distributions.
Simple publish usage. We need a fast and reliable way to publish new versions of the scripts. Ideally, we'd avoid
having to publish each update to multiple package repos (apt, yum, etc), especially if that requires any sort of
manual approval (e.g. a PR for each new version).
Testable in dev mode. We must be able to do local, iterative development on the example code in the
examples folder. That means there is a way to "package" these scripts so that, in dev mode, they are
downloaded from the local file system, rather than some package repo such as apt or yum.
Mature: We want to use a solution that is mature, battle-tested, and has an active community around it.
Publish usage: Complicated. Nix has its own expression
language, which I found fairly confusing. The docs are
so-so. Creating new packages and pushing new versions seems to require a pull
request.
Dev mode: Complicated. Not clear how to use it in dev mode.
Maturity: Moderate. It's been around a while and there is a community around it, but it's buggy and confusing to
use.
Verdict: It's confusing to use, slow (every install downloads the universe), buggy on OS X, and it's not clear how
to use it in dev mode.
Description: Package apps as super-powered tar files.
Dependency Management. Yes. Supports both native installers (e.g. apt) and tpkg itself.
Install process: Difficult. Requires Ruby and Ruby Gems to be installed first, so every Packer template would
have to install Ruby and Gem (e.g. sudo apt install ruby), which some people won't want on their production
servers, and then install tpkg: sudo gem install tpkg.
Client usage: Simple. tpkg --install PACKAGE.
Publish usage: Simple. tpkg --make PATH. That produces a file you can upload to your own package
server, which can be any web server that hosts the file and a special
metadata file. Might be able to use GitHub releases or S3 for this.
Dev mode: Simple. The tpkg --make PATH command makes the package available for local install.
Maturity: Poor. Might be a dead project. The GitHub repo has almost no followers.
Only a couple commits in the last few years.
Verdict: Dependency on Ruby and the lack of community activity is a no-go.
Description: A way to install "apps" on all major Linux distributions. It seems like it's designed for standalone apps and
binaries rather than scripting. Packages, called "snaps", are completely isolated from each other and the host OS
(using cgroups?) and can define interfaces, slots, plugs, etc to communicate with each other (a bit like "type
safety").
Dependency Management: No. Or at least, I can't find it.
Install process: Simple. sudo apt install snapd.
Client usage: Simple. sudo snap install PACKAGE.
Publish usage: Complicated. You have to sign up for an account in the Ubuntu
Store, install a separate app (sudo apt install snapcraft), login
(snapcraft login), configure channels (stable, beta, etc); after that, it's an easy snapcraft push command
for each new version.
Dev mode: Simple. snapcraft supports it.
Maturity: Moderate. Community seems fairly active, as this is a project maintained by Canonical.
Verdict: It only works on Linux, so hard to do development.
curl | bash
Description: Upload our scripts to Git, release them with version numbers, and pipe curl into bash to run them.
Dependency Management: No.
Install process: Simple. Nothing to install! Well, perhaps curl, but that's as simple as it gets.
Client usage: Simple. curl -Ls https://raw.githubusercontent.com/foo/bar/v0.0.3/install-consul | bash /dev/stdin.
Unfortunately, without any checksum or signature verification, this is a mild security risk if the GitHub repo
gets hijacked. Moreover, this only works for individual files. If the script has dependencies, those have to
be downloaded separately.
Publish usage: Simple. Just create a new GitHub release.
Dev mode: Simple. Just change the URL to a local file path.
Maturity: Strong. No need for a community, as we're just using curl!
Verdict: This only works well for a single file. Of course, that file could download other files, but to do that,
the file has to know what version it is, what to use to download, where to download to, etc.
Description: A slightly more structured version of piping curl into bash. You specify a GitHub repo, a path, and a version
number and the installer checks out the repo at the specified version, and runs an install.sh script in the
specified path.
Dependency Management: No. It's up to the install.sh script to figure out the details.
Install process: Simple. curl -Ls https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version v0.0.14.
Note, this is subject to the same security risks as piping curl into bash. Since there is just one installer
and we don't update it often, we could publish it into apt, yum, etc repos to avoid this problem.
Client usage: Simple. gruntwork-install --module-name 'PATH' --repo 'https://github.com/foo/bar' --tag v0.0.3.
Does not currently do checksum or signature verification, but that could be added.
Publish usage: Simple. Just create a new GitHub release. Works with private GitHub repos too.
Dev mode: Simple. Just specify a local file path.
Maturity: Poor. The community is tiny, though this project is actively maintained by Gruntwork.
Verdict: A bit too specific to Gruntwork's use case.
Install process: Simple. Packer can do it automatically for Chef
Solo and you can do it manually for Ansible:
sudo apt install -y ansible.
Client usage: Complicated. You first have to download the Chef Recipe or Ansible Playbook from the Module
repo (e.g. using a shell-local provisioner with curl) and then you can use the downloaded recipe or playbook
with the built-in Packer commands (e.g. chef-solo
Provisioner and ansible-local
Provisioner).
Publish usage: Simple. Just create a new GitHub release.
Dev mode: Simple. Just use local file paths for the recipes and playbooks.
Maturity: Strong. All these cfg mgmt tools have massive communities.
Verdict: Requires installing the tools on each server and learning a new set of tools, which feels like overkill
for a few simple scripts.
Git
Description: Run git clone with the --branch parameter (which can be set to a tag) to check out a specific version of the
code.
Dependency Management: No.
Install process: Simple. Just install Git, if it's not installed already.
Client usage: Simple. Once you've run git clone, all the code you need is on disk, and you just execute it.
Publish usage: Simple. Just create a new GitHub release.
Dev mode: Simple. Just use your local checkout.
Maturity: Strong. It's Git, so the community is massive.
Verdict: The biggest missing feature is dependency management, but it's a perfect fit in every other way, so
this is our choice.
Questions? Ask away.
We're here to talk about our services, answer any questions, give advice, or just to chat.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"06f140f324996ecec28b18d6e52142789006ab89"}]},{"name":".gitignore","path":".gitignore","sha":"c749affedc4dee4e84093bef93f6ba0ebdaaf306"},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"81355c81b991ffeeb1224a07bfb86f0fa592b6cd"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"4be01a6334d39aa5bf6abe6baae701f5e2a8c5ac"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","sha":"bdfb309d7ff6bb05ffc1ea9453604805c022d13b"},{"name":"LICENSE","path":"LICENSE","sha":"7a4a3ea2424c09fbe48d455aed1eaa94d9124835"},{"name":"NOTICE","path":"NOTICE","sha":"2655cb5943994ab8de6faec5e5afc28ce4ec10c7"},{"name":"README.md","path":"README.md","sha":"d2cbf5451f176c46b432261675b3afc5b03ee8a7"},{"name":"_ci","children":[{"name":"publish-amis-in-new-account.md","path":"_ci/publish-amis-in-new-account.md","sha":"5b5daa55c3e36c1c4739471be92ccb53995f9783"},{"name":"publish-amis.sh","path":"_ci/publish-amis.sh","sha":"a2554844ab0693d24edd3f0439073458070350fc"}]},{"name":"_docs","children":[{"name":"architecture.png","path":"_docs/architecture.png","sha":"539fece6e8a9fd7a56245e2b63e6640a1e0591ef"},{"name":"consul-ui-screenshot.png","path":"_docs/consul-ui-screenshot.png","sha":"622c7e70d3ab805b1bb8e27e474ff8243d4bc994"},{"name":"package-managers.md","path":"_docs/package-managers.md","sha":"f382b6997245e03adba61c02346519a70ee016d4","toggled":true}],"toggled":true},{"name":"examples","children":[{"name":"README.md","path":"examples/README.md","sha":"8eca7399ca356c90a307206147362bc35588179c"},{"name":"consul-ami","children":[{"name":"README.md","path":"examples/consul-ami/README.md","sha":"da69b57110946044c33581e84436940e31e5d159"},{"name":"consul.json","path":"examples/consul-ami/consul.json","sha":"88c2af9e8e4c313f512af2f72a184871250021d0"}]},{"name":"consul-examples-helper","children":[{"name":"README.md","path":"examples/consul-examples-helper/README.md","sha":"296f6878fd49edb27d6a6b62fa4119b6a407ba26"},{"name":"consul-examples-helper.sh","path":"examples/consul-examples-helper/consul-examples-helper.sh","sha":"cb356cf348574378bbecbf49b3d6bf0339606cbe"}]},{"name":"example-with-custom-asg-role","children":[{"name":"README.md","path":"examples/example-with-custom-asg-role/README.md","sha":"fa1fbb9d7416fa96f13afb6b82664bbe1638ea3f"},{"name":"main.tf","path":"examples/example-with-custom-asg-role/main.tf","sha":"c0fcf7631ff6b439363f80c3709691bf9c9d4383"},{"name":"outputs.tf","path":"examples/example-with-custom-asg-role/outputs.tf","sha":"493b36c2b62ad81a4d1d4eb62e268442206eeded"},{"name":"user-data-client.sh","path":"examples/example-with-custom-asg-role/user-data-client.sh","sha":"fd0158b0287de6bf2a6956718c7aa802076fe489"},{"name":"user-data-server.sh","path":"examples/example-with-custom-asg-role/user-data-server.sh","sha":"c78ebc05584513fa04f44d44ef2b9d17c98e2ea6"},{"name":"variables.tf","path":"examples/example-with-custom-asg-role/variables.tf","sha":"387fac5d0223a2466e0f671d055f8255058b3050"}]},{"name":"example-with-encryption","children":[{"name":"README.md","path":"examples/example-with-encryption/README.md","sha":"0f2de7374cf63ee0b18cae4b960b85ec88403866"},{"name":"main.tf","path":"examples/example-with-encryption/main.tf","sha":"bfc7f675ab5ba84c20001d715dec5ab224826e9f"},{"name":"outputs.tf","path":"examples/example-with-encryption/outputs.tf","sha":"493b36c2b62ad81a4d1d4eb62e268442206eeded"},{"name":"packer","children":[{"name":"README.md","path":"examples/example-with-encryption/packer/README.md","sha":"b7b8ca11120c5f69565dab81eeeed659223538e9"},{"name":"ca.crt.pem","path":"examples/example-with-encryption/packer/ca.crt.pem","sha":"c41779f19be6d742d10be51d80c29aa5d41a660c"},{"name":"consul-with-certs.json","path":"examples/example-with-encryption/packer/consul-with-certs.json","sha":"9942398f7b76dc1589394efb1348d9a727389a7a"},{"name":"consul.crt.pem","path":"examples/example-with-encryption/packer/consul.crt.pem","sha":"4a4ea11b89006f41fe2cb8b707d62463bb739184"},{"name":"consul.key.pem","path":"examples/example-with-encryption/packer/consul.key.pem","sha":"b7de428c63382b087007a236602797cc0a0a45f5"}]},{"name":"user-data-client.sh","path":"examples/example-with-encryption/user-data-client.sh","sha":"2ab3735d96777ce9324bc55f7be29c338ef0c1bb"},{"name":"user-data-server.sh","path":"examples/example-with-encryption/user-data-server.sh","sha":"5e97fc02da696b348ee26a2c1803bf7e3e018c79"},{"name":"variables.tf","path":"examples/example-with-encryption/variables.tf","sha":"9187e8892ddb952fd8adf217071d310d1c644967"}]},{"name":"root-example","children":[{"name":"README.md","path":"examples/root-example/README.md","sha":"6c562cb22c28cc5e35b5a21a94b66d6af9101081"},{"name":"user-data-client.sh","path":"examples/root-example/user-data-client.sh","sha":"fd0158b0287de6bf2a6956718c7aa802076fe489"},{"name":"user-data-server.sh","path":"examples/root-example/user-data-server.sh","sha":"c78ebc05584513fa04f44d44ef2b9d17c98e2ea6"}]}]},{"name":"main.tf","path":"main.tf","sha":"19daa7655b66775c23378dcb4382e92f05f86a34"},{"name":"modules","children":[{"name":"README.md","path":"modules/README.md","sha":"8eca7399ca356c90a307206147362bc35588179c"},{"name":"consul-client-security-group-rules","children":[{"name":"README.md","path":"modules/consul-client-security-group-rules/README.md","sha":"777b679a73df3d5c96fb584176e91449c3a72615"},{"name":"main.tf","path":"modules/consul-client-security-group-rules/main.tf","sha":"6ae3118188ae5c7806cc2ac88cc5a1ac3e50edd1"},{"name":"variables.tf","path":"modules/consul-client-security-group-rules/variables.tf","sha":"c9c25d00fdc683748570ba5e2ee718c9af8e6697"}]},{"name":"consul-cluster","children":[{"name":"README.md","path":"modules/consul-cluster/README.md","sha":"b9a3c55973ef27b0022f5eda05840f7cc65cea03"},{"name":"main.tf","path":"modules/consul-cluster/main.tf","sha":"721f6fc0c5bf9efed37d582c767b772893424a7f"},{"name":"outputs.tf","path":"modules/consul-cluster/outputs.tf","sha":"a980d658e1be410a013a7e7febcc38a49899ffdc"},{"name":"variables.tf","path":"modules/consul-cluster/variables.tf","sha":"6830617eb65853e5c8e9a6ce27f6bb49a546aa34"}]},{"name":"consul-iam-policies","children":[{"name":"README.md","path":"modules/consul-iam-policies/README.md","sha":"7725295fbdbf3d2fe881796e63074e3215854f5f"},{"name":"main.tf","path":"modules/consul-iam-policies/main.tf","sha":"803883bcb9ce412710c9e7d59873bf734c2067c2"},{"name":"variables.tf","path":"modules/consul-iam-policies/variables.tf","sha":"1bda7959f19ea4ab20108ec9fb8802036bfd22fd"}]},{"name":"consul-security-group-rules","children":[{"name":"README.md","path":"modules/consul-security-group-rules/README.md","sha":"315155181f5b42ff0fc6f16b86eaa930811366fe"},{"name":"main.tf","path":"modules/consul-security-group-rules/main.tf","sha":"c9081bfa75ebc080a68346fd104dcea22f0a89be"},{"name":"variables.tf","path":"modules/consul-security-group-rules/variables.tf","sha":"90e1bec3a64824c9416088e46cae9d7ffcc45638"}]},{"name":"install-consul","children":[{"name":"README.md","path":"modules/install-consul/README.md","sha":"26c636fc061fc894c41c792d28428f0266056e86"},{"name":"install-consul","path":"modules/install-consul/install-consul","sha":"f33c659cbb0dc5ab7d5846e7ece811481d42792e"}]},{"name":"install-dnsmasq","children":[{"name":"README.md","path":"modules/install-dnsmasq/README.md","sha":"dbfcd308061679992e9afc3c11264b8140cfe04c"},{"name":"install-dnsmasq","path":"modules/install-dnsmasq/install-dnsmasq","sha":"6ff5256cf38477fe3693c93056a37b96fcb37b16"}]},{"name":"run-consul","children":[{"name":"README.md","path":"modules/run-consul/README.md","sha":"b5e8ec01a3de18d23095cfdf943e4243a74a32d3"},{"name":"run-consul","path":"modules/run-consul/run-consul","sha":"ffb5dece503f333949b73553e27039cc7caa1f99"}]},{"name":"setup-systemd-resolved","children":[{"name":"README.md","path":"modules/setup-systemd-resolved/README.md","sha":"c71225757127230251fa0774fe608eac9102ea09"},{"name":"setup-systemd-resolved","path":"modules/setup-systemd-resolved/setup-systemd-resolved","sha":"28670839d4c362281407b394303b6ab6162d7ebf"}]}]},{"name":"outputs.tf","path":"outputs.tf","sha":"493b36c2b62ad81a4d1d4eb62e268442206eeded"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"874818e6da7a9c0c9338edde0c27fa3f8a3b3d05"},{"name":"aws_helpers.go","path":"test/aws_helpers.go","sha":"a340f3a3779fb5efd7c9410f3e72734f9ad4a324"},{"name":"consul_cluster_test.go","path":"test/consul_cluster_test.go","sha":"b44bd7d665b26d7d672f3c557b5eaa3a8fd59df2"},{"name":"consul_cluster_with_custom_asg_role_test.go","path":"test/consul_cluster_with_custom_asg_role_test.go","sha":"9ae0ef139943ab35a8d419e6dac36a3a63a3851e"},{"name":"consul_cluster_with_encryption_test.go","path":"test/consul_cluster_with_encryption_test.go","sha":"7d5b18e14addba8ea16423bcf7efae7019bad66b"},{"name":"consul_enterprise_test.go","path":"test/consul_enterprise_test.go","sha":"8ef7e432973510e89f3dc5207856e1211c208b1f"},{"name":"consul_helpers.go","path":"test/consul_helpers.go","sha":"153811288dee25b13c3e15b73d740e18dadfe8db"},{"name":"go.mod","path":"test/go.mod","sha":"6a500c12e474d5afd9a4a6a958895cca0ba80281"},{"name":"go.sum","path":"test/go.sum","sha":"061b1735dfb194fc921bb33058c4ae93af1c3fe8"},{"name":"terratest_helpers.go","path":"test/terratest_helpers.go","sha":"7376d9065d4958533286b82c0a00f86c4f173fce"}]},{"name":"variables.tf","path":"variables.tf","sha":"6e69029d26449d2d967bf43875c681cbcb901200"}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"package-managers\">Package Managers</h1><div class=\"preview__body--border\"></div><p>To create the scripts in <code>install-consul</code>, we had to find a way to write and package the scripts that satisfied a\nnumber of requirements. This document captures the requirements, the options we considered, and an explanation of\nwhich option we picked and why.</p>\n<h2 class=\"preview__body--subtitle\" id=\"the-requirements\">The requirements</h2>\n<p>We need to write and package the scripts in this Module in a way that satisfies the following requirements:</p>\n<ul>\n<li>\n<p><strong>Packages</strong>. There needs to be a way to fetch these scripts from a canonical location (e.g. GitHub repo, package\nmanager repository) at a specific version number (e.g. <code>v0.0.3</code> of <code>install-consul</code>), much like a package manager.\nWe don't want people copy/pasting these scripts into their local repos, or it'll make upgrades and maintenance\ndifficult.</p>\n</li>\n<li>\n<p><strong>Cross-platform</strong>. The packaging system should work on most major Linux distributions. It should also work on OS X,\nas that's what many people use for development.</p>\n</li>\n<li>\n<p><strong>Handles dependencies</strong>. These scripts rely on certain dependencies being installed on the system, such as <code>curl</code>,\n<code>wget</code>, <code>jq</code>, <code>aws</code>, and so on. We need a way to automatically manage and install these dependencies that works\nacross all major Linux distributions.</p>\n</li>\n<li>\n<p><strong>Simple package manager installation</strong>: We don't want a package manager that takes a dozen steps to install.</p>\n</li>\n<li>\n<p><strong>Simple client usage</strong>. The scripts in this Module are fairly simple, so it shouldn't take a dozen steps to\ninstall one. Ideally, we can use a one-liner such as <code>apt install -y install-consul</code>, except it should work on all\nmajor Linux distributions.</p>\n</li>\n<li>\n<p><strong>Simple publish usage</strong>. We need a fast and reliable way to publish new versions of the scripts. Ideally, we'd avoid\nhaving to publish each update to multiple package repos (apt, yum, etc), especially if that requires any sort of\nmanual approval (e.g. a PR for each new version).</p>\n</li>\n<li>\n<p><strong>Testable in dev mode</strong>. We must be able to do local, iterative development on the example code in the\n<a href=\"/repos/v0.7.4/terraform-aws-consul/examples\" class=\"preview__body--description--blue\">examples</a> folder. That means there is a way to "package" these scripts so that, in dev mode, they are\ndownloaded from the local file system, rather than some package repo such as apt or yum.</p>\n</li>\n<li>\n<p><strong>Mature</strong>: We want to use a solution that is mature, battle-tested, and has an active community around it.</p>\n</li>\n</ul>\n<h2 class=\"preview__body--subtitle\" id=\"the-options\">The options</h2>\n<p>Here are the options we've looked at.</p>\n<h3 class=\"preview__body--subtitle\" id=\"nix-https-nixos-org-nix\"><a href=\"https://nixos.org/nix/\" class=\"preview__body--description--blue\" target=\"_blank\">Nix</a></h3>\n<ul>\n<li><strong>Description</strong>: Purely functional package manager, so dependency versioning, rollback, etc works very cleanly.</li>\n<li><strong>Dependency Management</strong>: Yes.</li>\n<li><strong>Install process</strong>: Simple. <code>bash <(curl https://nixos.org/nix/install)</code>.</li>\n<li><strong>Client usage</strong>: Simple. <code>nix-env --install PACKAGE</code>.</li>\n<li><strong>Publish usage</strong>: Complicated. Nix has its own <a href=\"https://nixos.org/nix/manual/#sec-expression-syntax\" class=\"preview__body--description--blue\" target=\"_blank\">expression\nlanguage</a>, which I found fairly confusing. The docs are\nso-so. Creating new packages and pushing new versions seems to require <a href=\"https://nixos.org/wiki/Create_and_debug_nix_packages\" class=\"preview__body--description--blue\" target=\"_blank\">a pull\nrequest</a>.</li>\n<li><strong>Dev mode</strong>: Complicated. Not clear how to use it in dev mode.</li>\n<li><strong>Maturity</strong>: Moderate. It's been around a while and there is a community around it, but it's buggy and confusing to\nuse.</li>\n</ul>\n<p><strong>Verdict</strong>: It's confusing to use, slow (every install downloads the universe), buggy on OS X, and it's not clear how\nto use it in dev mode.</p>\n<h3 class=\"preview__body--subtitle\" id=\"tpkg-http-tpkg-github-io\"><a href=\"http://tpkg.github.io/\" class=\"preview__body--description--blue\" target=\"_blank\">tpkg</a></h3>\n<ul>\n<li><strong>Description</strong>: Package apps as super-powered tar files.</li>\n<li><strong>Dependency Management</strong>. Yes. Supports both native installers (e.g. apt) and tpkg itself.</li>\n<li><strong>Install process</strong>: Difficult. Requires Ruby and Ruby Gems to be installed first, so every Packer template would\nhave to install Ruby and Gem (e.g. <code>sudo apt install ruby</code>), which some people won't want on their production\nservers, and then install <code>tpkg</code>: <code>sudo gem install tpkg</code>.</li>\n<li><strong>Client usage</strong>: Simple. <code>tpkg --install PACKAGE</code>.</li>\n<li><strong>Publish usage</strong>: Simple. <code>tpkg --make PATH</code>. That produces a file you can upload to your own <a href=\"http://tpkg.github.io/package_server.html\" class=\"preview__body--description--blue\" target=\"_blank\">package\nserver</a>, which can be any web server that hosts the file and a special\nmetadata file. Might be able to use GitHub releases or S3 for this.</li>\n<li><strong>Dev mode</strong>: Simple. The <code>tpkg --make PATH</code> command makes the package available for local install.</li>\n<li><strong>Maturity</strong>: Poor. Might be a dead project. The <a href=\"https://github.com/tpkg\" class=\"preview__body--description--blue\" target=\"_blank\">GitHub repo</a> has almost no followers.\nOnly a couple commits in the last few years.</li>\n</ul>\n<p><strong>Verdict</strong>: Dependency on Ruby and the lack of community activity is a no-go.</p>\n<h3 class=\"preview__body--subtitle\" id=\"snap-https-snapcraft-io\"><a href=\"https://snapcraft.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Snap</a></h3>\n<ul>\n<li><strong>Description</strong>: A way to install "apps" on all major Linux distributions. It seems like it's designed for standalone apps and\nbinaries rather than scripting. Packages, called "snaps", are completely isolated from each other and the host OS\n(using cgroups?) and can define interfaces, slots, plugs, etc to communicate with each other (a bit like "type\nsafety").</li>\n<li><strong>Dependency Management</strong>: No. Or at least, I can't find it.</li>\n<li><strong>Install process</strong>: Simple. <code>sudo apt install snapd</code>.</li>\n<li><strong>Client usage</strong>: Simple. <code>sudo snap install PACKAGE</code>.</li>\n<li><strong>Publish usage</strong>: Complicated. You have to sign up for an account in the <a href=\"https://myapps.developer.ubuntu.com/\" class=\"preview__body--description--blue\" target=\"_blank\">Ubuntu\nStore</a>, install a separate app (<code>sudo apt install snapcraft</code>), login\n(<code>snapcraft login</code>), configure channels (stable, beta, etc); after that, it's an easy <code>snapcraft push</code> command\nfor each new version.</li>\n<li><strong>Dev mode</strong>: Simple. <code>snapcraft</code> supports it.</li>\n<li><strong>Maturity</strong>: Moderate. Community seems fairly active, as this is a project maintained by Canonical.</li>\n</ul>\n<p><strong>Verdict</strong>: It only works on Linux, so hard to do development.</p>\n<h3 class=\"preview__body--subtitle\" id=\"curl-bash\"><code>curl | bash</code></h3>\n<ul>\n<li><strong>Description</strong>: Upload our scripts to Git, release them with version numbers, and pipe <code>curl</code> into <code>bash</code> to run them.</li>\n<li><strong>Dependency Management</strong>: No.</li>\n<li><strong>Install process</strong>: Simple. Nothing to install! Well, perhaps <code>curl</code>, but that's as simple as it gets.</li>\n<li><strong>Client usage</strong>: Simple. <code>curl -Ls https://raw.githubusercontent.com/foo/bar/v0.0.3/install-consul | bash /dev/stdin</code>.\nUnfortunately, without any checksum or signature verification, this is a mild security risk if the GitHub repo\ngets hijacked. Moreover, this only works for individual files. If the script has dependencies, those have to\nbe downloaded separately.</li>\n<li><strong>Publish usage</strong>: Simple. Just create a new GitHub release.</li>\n<li><strong>Dev mode</strong>: Simple. Just change the URL to a local file path.</li>\n<li><strong>Maturity</strong>: Strong. No need for a community, as we're just using <code>curl</code>!</li>\n</ul>\n<p><strong>Verdict</strong>: This only works well for a single file. Of course, that file could download other files, but to do that,\nthe file has to know what version it is, what to use to download, where to download to, etc.</p>\n<h3 class=\"preview__body--subtitle\" id=\"gruntwork-installer-https-github-com-gruntwork-io-gruntwork-installer\"><a href=\"/repos/gruntwork-installer\" class=\"preview__body--description--blue\">Gruntwork Installer</a></h3>\n<ul>\n<li><strong>Description</strong>: A slightly more structured version of piping <code>curl</code> into <code>bash</code>. You specify a GitHub repo, a path, and a version\nnumber and the installer checks out the repo at the specified version, and runs an <code>install.sh</code> script in the\nspecified path.</li>\n<li><strong>Dependency Management</strong>: No. It's up to the <code>install.sh</code> script to figure out the details.</li>\n<li><strong>Install process</strong>: Simple. <code>curl -Ls https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version v0.0.14</code>.\nNote, this is subject to the same security risks as piping <code>curl</code> into <code>bash</code>. Since there is just one installer\nand we don't update it often, we <em>could</em> publish it into apt, yum, etc repos to avoid this problem.</li>\n<li><strong>Client usage</strong>: Simple. <code>gruntwork-install --module-name 'PATH' --repo 'https://github.com/foo/bar' --tag v0.0.3</code>.\nDoes not currently do checksum or signature verification, but that could be added.</li>\n<li><strong>Publish usage</strong>: Simple. Just create a new GitHub release. Works with private GitHub repos too.</li>\n<li><strong>Dev mode</strong>: Simple. Just specify a local file path.</li>\n<li><strong>Maturity</strong>: Poor. The community is tiny, though this project is actively maintained by Gruntwork.</li>\n</ul>\n<p><strong>Verdict</strong>: A bit too specific to Gruntwork's use case.</p>\n<h3 class=\"preview__body--subtitle\" id=\"fpm-https-github-com-jordansissel-fpm\"><a href=\"https://github.com/jordansissel/fpm\" class=\"preview__body--description--blue\" target=\"_blank\">fpm</a></h3>\n<ul>\n<li><strong>Description</strong>: A script that makes it easy to package your code as native packages (e.g. <code>.deb</code>, <code>.rpm</code>).</li>\n<li><strong>Dependency Management</strong>: Yes.</li>\n<li><strong>Install process</strong>: Simple. No install process, as you use your standard OS package managers (i.e. <code>apt</code>, <code>yum</code>).</li>\n<li><strong>Client usage</strong>: Simple. <code>sudo apt install -y PACKAGE</code>.</li>\n<li><strong>Publish usage</strong>: Complicated. You have to package and publish to all major Linux package repos.</li>\n<li><strong>Dev mode</strong>: Complicated. Not clear how you use it in dev mode.</li>\n<li><strong>Maturity</strong>: Strong. Big community, active project.</li>\n</ul>\n<p><strong>Verdict</strong>: Requires publishing to multiple repos for every release, which is complicated.</p>\n<h3 class=\"preview__body--subtitle\" id=\"configuration-management-tools-e-g-ansible-https-www-ansible-com-chef-https-www-chef-io\">Configuration management tools (e.g. <a href=\"https://www.ansible.com/\" class=\"preview__body--description--blue\" target=\"_blank\">Ansible</a>, <a href=\"https://www.chef.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Chef</a>)</h3>\n<ul>\n<li><strong>Description</strong>: Tools built for managing server configuration.</li>\n<li><strong>Dependency Management</strong>: Yes. Most cfg mgmt tools have ways of leveraging the built-in package managers\n(e.g. <a href=\"https://docs.chef.io/resource_package.html\" class=\"preview__body--description--blue\" target=\"_blank\">package command in Chef</a> and <a href=\"http://docs.ansible.com/ansible/package_module.html\" class=\"preview__body--description--blue\" target=\"_blank\">package command in\nAnsible</a>).</li>\n<li><strong>Install process</strong>: Simple. Packer can do it automatically for <a href=\"https://www.packer.io/docs/provisioners/chef-solo.html\" class=\"preview__body--description--blue\" target=\"_blank\">Chef\nSolo</a> and you can do it manually for Ansible:\n<code>sudo apt install -y ansible</code>.</li>\n<li><strong>Client usage</strong>: Complicated. You first have to download the Chef Recipe or Ansible Playbook from the Module\nrepo (e.g. using a <code>shell-local</code> provisioner with <code>curl</code>) and then you can use the downloaded recipe or playbook\nwith the built-in Packer commands (e.g. <a href=\"https://www.packer.io/docs/provisioners/chef-solo.html\" class=\"preview__body--description--blue\" target=\"_blank\">chef-solo\nProvisioner</a> and <a href=\"https://www.packer.io/docs/provisioners/ansible-local.html\" class=\"preview__body--description--blue\" target=\"_blank\">ansible-local\nProvisioner</a>).</li>\n<li><strong>Publish usage</strong>: Simple. Just create a new GitHub release.</li>\n<li><strong>Dev mode</strong>: Simple. Just use local file paths for the recipes and playbooks.</li>\n<li><strong>Maturity</strong>: Strong. All these cfg mgmt tools have massive communities.</li>\n</ul>\n<p><strong>Verdict</strong>: Requires installing the tools on each server and learning a new set of tools, which feels like overkill\nfor a few simple scripts.</p>\n<h3 class=\"preview__body--subtitle\" id=\"git\">Git</h3>\n<ul>\n<li><strong>Description</strong>: Run <code>git clone</code> with the <code>--branch</code> parameter (which can be set to a tag) to check out a specific version of the\ncode.</li>\n<li><strong>Dependency Management</strong>: No.</li>\n<li><strong>Install process</strong>: Simple. Just install Git, if it's not installed already.</li>\n<li><strong>Client usage</strong>: Simple. Once you've run <code>git clone</code>, all the code you need is on disk, and you just execute it.</li>\n<li><strong>Publish usage</strong>: Simple. Just create a new GitHub release.</li>\n<li><strong>Dev mode</strong>: Simple. Just use your local checkout.</li>\n<li><strong>Maturity</strong>: Strong. It's Git, so the community is massive.</li>\n</ul>\n<p><strong>Verdict</strong>: The biggest missing feature is dependency management, but it's a perfect fit in every other way, so\nthis is our choice.</p>\n","repoName":"terraform-aws-consul","repoRef":"v0.11.0","serviceDescriptor":{"serviceName":"HashiCorp Consul","serviceRepoName":"terraform-aws-consul","serviceRepoOrg":"hashicorp","cloudProviders":["aws"],"description":"Deploy a Consul cluster. Supports automatic bootstrapping, DNS, Consul UI, and auto healing.","imageUrl":"consul.png","licenseType":"open-source","technologies":["Terraform","Bash"],"compliance":[],"tags":[""]},"serviceCategoryName":"Service Mesh","fileName":"package-managers.md","filePath":"/_docs/package-managers.md","title":"Repo Browser: HashiCorp Consul","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}