For now a space for random thoughts and notes. TODO: Refactor once things have solidified.
Prefer args-based task definitions over string-based.
- name: create redis symlink sudo: yes file: src=/usr/conda/bin/redis-server dest=/usr/local/bin/redis-server state=link
- 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
.
Individual directories for the application are created as needed within the FHS.
/etc/nginx.conf /etc/nginx.d/ /var/log/nginx.log /var/run/nginx.pid
/etc/nginx/nginx.conf /etc/nginx/conf.d/ /var/log/nginx/nginx.log /var/run/nginx/nginx.pid
/etc/supervisord.conf /etc/supervisord.d/
/etc/supervisord/supervisord.conf /etc/supervisord/conf.d/
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.
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.
- 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.
- name: create nginx config for you app template: src: nginx-you.conf dest: /etc/nginx/conf.d/you.conf
The system time zone is set to America/Los_Angeles
.
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.
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).
- 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
or0444
as appropriate. - If a variable name ends in
_URL
, the url protocol should be prepended.- Example:
https://api.23andme.com
- Example:
- 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
- Example:
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 |