Skip to content

Instantly share code, notes, and snippets.

@kalefranz
Created December 18, 2015 06:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kalefranz/bf85483142fa18323dbf to your computer and use it in GitHub Desktop.
Save kalefranz/bf85483142fa18323dbf to your computer and use it in GitHub Desktop.
Ansible Style Guide

Engineering : Ansible Style Guide and Conventions

Created by Kale Franz, last modified on Oct 08, 2015

For now a space for random thoughts and notes.  TODO: Refactor once things have solidified.


General Ansible Style

Prefer args-based task definitions over string-based.

**Example: WRONG**
- name: create redis symlink
  sudo: yes
  file: src=/usr/conda/bin/redis-server dest=/usr/local/bin/redis-server state=link
**Example: Correct**
- name: create redis symlink
  sudo: yes
  file:
    src: /usr/conda/bin/redis-server
    dest: /usr/local/bin/redis-server
    state: link

Use a name directive for every task.

Use sudo on a task-by-task basis.  Never apply "sudo: yes" to a whole play, role, or include statement.

Never use command or shell tasks when an ansible module exists that provides the desired behavior.  Prefer command over shell.


System Application Directory Structure

Individual directories for the application are created as needed within the FHS.

**Example: WRONG**
/etc/nginx.conf
/etc/nginx.d/
/var/log/nginx.log
/var/run/nginx.pid
**Example: CORRECT**
/etc/nginx/nginx.conf
/etc/nginx/conf.d/
/var/log/nginx/nginx.log
/var/run/nginx/nginx.pid
**Example: WRONG**
/etc/supervisord.conf
/etc/supervisord.d/
**Example: CORRECT**
/etc/supervisord/supervisord.conf
/etc/supervisord/conf.d/

System Application User

A dedicated user is created for each system process. UIDs and GIDs are kept consistent across all environments.  The source of truth for UID and GID information is https://bitbucket.org/23andme/ansible/src/develop/pb/roles/local-user/defaults/main.yml.

The shell for the application user is /sbin/nologin.

Application user write permissions are strictly limited to:

  • /usr/home/$USER/
  • /var/run/$USER/
  • /tmp/

Note that /var/log/$USER/ is neither readable nor writable by the application user.  Instead, the application should simply write log information to stdout and stderr.  Then supervisord will collect and write logs appropriately.

Local User Home Directories

When required, a home directory for a local user can be created at `/usr/home/$USER`.  The `/usr/home/` location is used for local users to reserve `/home` for NFS mounting of LDAP user home directories.

Template Module

The template file in the template directory is named exactly what it will be on the remote (i.e. no .j2 extension). The dest parameter of the template task does not specify the file name–only the src parameter does.

**Example**
- name: create gunicorn config for you app
  template:
    src: gunicorn.py
    dest: /etc/opt/you/

We override the default convention when the destination is a ".d" directory.  Here, the file name in the template directory should indicate which .d directory it'll be dropped into.  The dest parameter then specifies the file name and removes the extraneous information.

**Example**
- name: create nginx config for you app
  template:
    src: nginx-you.conf
    dest: /etc/nginx/conf.d/you.conf

Locale Information

The system time zone is set to America/Los_Angeles.

System Package Management

OS-agnostic package management is preferred to decouple package infrastructure from the variety of base OSes.  We use conda.  A base conda installation can provide any necessary application-specific runtimes (python, ruby, java, node, etc).  Language-native package installers are made available (pip, gem, npm, etc.), but their use has some limitations to be aware of for production environments.  #1 Do not assume production environments have access to the outside internet. A dedicated repo/mirror/etc will need to be provisioned within the production environment.  #2 Do not assume compilers (e.g. gcc, g++) exist.  Language-native installers often invoke a compiler to install a package, and here, prefer building a conda package instead.

Init System

Supervisor is the init system used for all conda-installed and application processes. Like Conda for package management, Supervisor abstracts and unifies process startup and monitoring from any OS-specific system (e.g. SysVinit, systemd, Upstart).

Random

  • Don't count on $PATH or $PWD being set properly. Use full paths where possible.
  • Don't count on defaults being set, being set correctly, or not changing out from underneath you.  Make settings explicit, even if they're indeed default.
  • Prefix ansible variable and environment variable names with the app name that makes the most sense.  Examples:
    • YOU_STATIC_HOST
    • YOU_REDIS_CACHE_URL
    • PRODUCT_DB_REL
  • All keys and other files meant to be immutable should be permissioned 0400 or 0444 as appropriate.
  • If a variable name ends in _URL, the url protocol should be prepended.
    • Example:  https://api.23andme.com
  • If the variable name ends in _HOST, it refers to a full-qualified domain name for a machine, and thus should not include a protocol.
    • Example: api.23andme.com

Tags and Uses

tag use case / description
update attached to tasks necessary to update application code and packages from an old deploy to a new deploy
os_update attached to tasks like `yum update` and `apt-get upgrade` for explicit exclusion of inclusion

Resources and Links

File Hierarchy Standard (FHS): wikipedia3.0 PDF

CentOS Standard Users

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment