Code Monkey home page Code Monkey logo

welder's Introduction

๐Ÿ‘จโ€๐Ÿญ Welder

Welder allows you to set up a Linux server with plain shell scripts.

I wrote it out of frustration with Ansible. Ansible is an amazing and powerful tool, but for my needs it's just too much. 90% of the time all I need is:

ssh -t [email protected] "$(< ./my-setup-script.sh)"
# or:
ssh -t [email protected] "$(cat ./my-setup-script.sh)"

In most basic terms, that's what welder does.

But there's some more.

Features

Welder allows you to:

  • execute local shell scripts on the server via ssh
  • organize your scripts into a logical set of reusable modules
  • set up a server with a single command (welder run <playbook>)
  • run one-off shell scripts (welder run-script <[email protected]> <path/to/script.sh>)
  • use liquid templates for configuration (optional)
  • enter sudo password just once per playbook

See welder-contrib for some example modules.

Directory structure

An example directory structure:

โ”œโ”€โ”€ modules
โ”‚ย ย  โ”œโ”€โ”€ nginx
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ files
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ nginx.conf
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ setup.sh
โ”‚ย ย  โ”œโ”€โ”€ rails
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ files
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ nginx
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ site.conf.liquid
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ systemd
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚   โ”œโ”€โ”€ puma.service.liquid
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”‚   โ””โ”€โ”€ sidekiq.service.liquid
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ rbenv-vars.liquid
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ setup.sh
โ”‚ย ย  โ”œโ”€โ”€ system
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ files
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ 10periodic
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ 50unattended-upgrades
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ setup.sh
โ”œโ”€โ”€ config.yml
โ”œโ”€โ”€ vault.yml
โ”œโ”€โ”€ vault.yml.gpg
โ””โ”€โ”€ my-site.yml

Example playbook:

ssh_url: [email protected]
ssh_port: 22  # Optional (default: 22)

shared_path: ../shared # optional

# List of modules to execute
modules:
  - system
  - firewall
  - rbenv
  - nginx
  - rails

Templates

Welder uses liquid for templates. It's mostly compatible with ansible's *.j2 files:

# modules/rails/files/nginx-site.conf.liquid
upstream thumbor {
  {% for port in thumbor_instances %}
      server 127.0.0.1:{{ port }};
  {% endfor %}
}

server {
    listen 80;

    server_name {{ thumbor_host }};
    include snippets/ssl-{{ app_domain }}.conf;

    location / {
        proxy_pass http://thumbor;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

config.yml

The config.yml file will be used to provide variables for your *.liquid templates:

# example config.yml
app_name: example
app_domain: example.com

ruby_version: "2.4.0"
ruby_deploy_user: "deploy"
rails_env: production

app_dir: "/var/www/example"
letsencrypt_web_dir: "/var/www/letsencrypt"

thumbor_host: images.example.com
thumbor_instances:
  - 8000
  - 8001
  - 8002
  - 8003

During the compilation phase, config.yml is turned into a bash-compatible format and uploaded to the server:

# compiled config-variables file
cfg_app_name='example'
cfg_app_domain='example.com'
cfg_ruby_version='2.4.0'
cfg_ruby_deploy_user='deploy'
cfg_rails_env='production'
cfg_app_dir='/var/www/example'
cfg_thumbor_host='images.example.com'
cfg_thumbor_instances=(8000 8001 8002 8003)

You can then source it in your setup scripts:

# modules/example/setup.sh
source setup/config-variables

echo $cfg_app_name
echo $cfg_app_dir
# (notice the $cfg_ prefix)

NOTE: In order for this to work reliably, config.yml has to be fairly flat and simple - nested hashes are not supported.

Shared Modules

If you want to avoid duplicating modules across different projects, you can specify shared_path in your playbook YML file:

ssh_url: [email protected]

shared_path: ../shared

modules:
  - system
  - firewall

In the example above, ../shared directory should contain modules directory.

Security Notes

Don't store any sensitive information (passwords etc.) in config.yml. If you want to keep passwords in git, create a vault.yml file, add it to .gitignore and store the encrypted version in revision control:

# encrypt & decrypt vault.yml using your gpg key
gpg --encrypt --recipient 'John Doe' vault.yml
gpg --decrypt --output vault.yml vault.yml.gpg

# encrypt & decrypt using a passphrase (no private/public key needed)
gpg --symmetric --cipher-algo aes256 vault.yml
gpg --decrypt --output vault.yml --cipher-algo aes256 vault.yml.gpg

For more information on how to set up GPG/PGP, see this excellent tutorial.

Think of this as just another level of security for your private git repos. You probably don't want to store the encrypted vault in a public repo.

sudo

Because sudo password is passed as an argument to the expect script, it will be visible in the process list on your local computer. This could be an issue if you're using a shared machine to run setup scripts.

Example setup script

# modules/nginx/setup.sh

set -xeu # 'u' will give you warnings on unbound config variables

[[ -f setup/config-variables ]] && source setup/config-variables

sudo add-apt-repository -y ppa:nginx/stable
sudo apt-get update && sudo apt-get install -y nginx

sudo service nginx start

sudo cp setup/modules/nginx/files/nginx.conf /etc/nginx/nginx.conf

# Disable default site
if [ -f /etc/nginx/sites-enabled/default ]; then
  sudo rm /etc/nginx/sites-enabled/default
fi

sudo service nginx restart

Usage

welder run my-site # runs the playbook defined in my-site.yaml

The run script will compile templates and configs, upload them to the server (to /home/username/setup) and then it will ask you for the sudo password. After that, it will execute all *.sh scripts from the modules listed in the playbook file.

Additional commands:

welder compile <playbook>  # compiles templates and uploads them to the server
welder cleanup <playbook>  # remove compiled files from the server

If you want to run a single *.sh script on the server, you can use this:

welder run-script <[email protected]> <path/to/script.sh>

NOTE: the run-script command does not compile templates. It merely wraps ssh -t [email protected] "$(< ./path/to/script.sh)". If you want access to templates and config, run welder compile <playbook> first and welder cleanup <playbook> when you're done.

Installation

  1. Install dependencies

    Welder requires expect, rsync and ruby. Ruby is used mainly as a convenient way to parse YAML configuration files.

    Optionally, if you'd like to use the templating feature, you need to install liquid gem:

    $ gem install liquid
  2. Check out this repository into /opt/welder (or whatever location you prefer):

    # git clone https://github.com/pch/welder.git /opt/welder
  3. Add a symbolic link to the welder front-end in your $PATH:

    # ln -sf /opt/welder/bin/welder /usr/local/bin/welder

Caveats

Since welder allows you to run anything on the server, you should use it with caution. It won't protect you from screw-ups, like rm -rf "/$undefined_variable".

Use at your own risk.

Known Issues / Limitations

  • YAML config doesn't support nested values
  • Ruby dependency should be optional

welder's People

Contributors

pch avatar v1shwa avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.