Rails application usura Ansible servo usque ad explicandam profecta est

Non ita pridem opus mihi erat aliquot fabularum Ansiblerum libros scribere, ut servo praepararem ad applicationem cancellorum explicandam. Et, mirum, simplicem gradatim manualem non inveni. Librum alterius fabulae imitari nolui sine intellegentia quae fiebat, et in fine legi documentum habui, me omnia colligendo. Fortasse aliquem adiuvare possum hunc processum ope huius articuli accelerare.

In primis intellegendum est quod ansible te praebet opportuno instrumento ad praefinitum actionum album in remoto servo(s) per SSH perficiendum. Hic magicae non est, plugin instituere non potes ac nulla media instruere applicationis tui cum schoenis, vigilantia et aliis nullam e cista. Ut ad librum fabularum scribas, debes scire quid facere velis et quomodo facere. Ideo non sum contentus libris fabularum GitHub paratis, vel articulis similibus: "Image et currendi, operabitur."

Quid ergo opus est?

Ut iam dixi, ad fabularum scribendarum rationem debes scire quid vis facere et facere. Decernamus quid opus sit. Ad applicationes cancellos pluribus fasciculis systematis egebimus: nginx, postgresql (redis, etc). Praeterea certa versio rubicunda indigemus. Optimum est instituere per rbenv (rvm, asdf...). Haec omnia ut usor radicis currens semper est idea mala, sic debes creare user separatum et eius iura configurare. Post haec, necesse est ut codicem nostrum ministro inseras, configas pro nginx, postgres, etc et omnia haec officia incipias.

Quam ob rem in actuum ordo talis est.

  1. Login ut radix
  2. install ratio packages
  3. creare novum user, configurare iura, ssh key
  4. configurare systema fasciculi (nginx etc) et currunt
  5. Usorem in database creo (potes database statim creare)
  6. Login ut novus user
  7. Install rbenv et ruby
  8. Installing bundler
  9. Uploading per applicationem codice
  10. Deductis Leopardus servo

Ultimi etiam gradus fieri possunt utendo capistrano, saltem e archa quod codicem imitari potest in directoria emissio, commutare emissionem cum symlink in bene instruere, effinge configs ex directorio communi, sileo puma, etc. Haec omnia fieri possunt utens Ansible, sed cur?

File structure

Ansible habet stricte file structure pro omnibus tuis documentis, ita optimum est omnia in directorio separato servare. Porro, utrum in cancellis ipsa applicatione, an separatim, non tanti momenti erit. Files condere potes in reposito separato git. Personaliter, commodissimum inveni directorium ansible in /config directorio cancellorum applicationis et omnia in uno repositorio recondere.

Simplex Playbook

Playbook tabella est yml quae, syntaxi speciali adhibita, describit quid Ansible facere debeat et quomodo. Faciamus primum playbook qui nihil agit;

---
- name: Simple playbook
  hosts: all

Hic simpliciter dicimus fabulas nostras nuncupari Simple Playbook et quod in omnibus exercitiis contenta exequantur. Servare possumus in nomine / ansible presul cum nomine playbook.yml et conantur currere;

ansible-playbook ./playbook.yml

PLAY [Simple Playbook] ************************************************************************************************************************************
skipping: no hosts matched

Ansible dicit se nescire aliquas virtutes quae omni indice aequant. Enumerari debent in speciali inventarium file.

Faciamus illud in directorio anibili eodem:

123.123.123.123

Hoc modo exprimimus solum exercitum (specialiter exercitum nostrum VPS ad probandum vel localem exercitum subcriptio) eamque sub nomine servamus. inventory.
Potes experiri currens ansible cum tabella inventario:

ansible-playbook ./playbook.yml -i inventory
PLAY [Simple Playbook] ************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************

PLAY RECAP ************************************************************************************************************************************

Si accessum ad certum exercitum ssh habes, tunc possibilis erit notitias coniungere et colligere de systemate remoto. (Default NEGOTIUM [Gathering Facts]) post quam dabit brevem relationem de executione (Play RECAP).

Defalta nexus usoris utitur sub quo initium in systematis es. Verisimile non erit in exercitu. In fasciculo playbook, exprimere possis utentem ad coniungere utentem directivum remoti_usoris. Etiam, informationes de systemate remoto saepe tibi supervacaneum esse potest ac ne tempus terere conferenda sit. Hoc negotium etiam debilitari potest;

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

Experiri currendo playbook iterum ac fac nexum laborat. (Si radicem usoris denotas, tunc etiam opus est ut facti sint: directivum verum ut iura elevata obtineat. Sicut scriptum in documentis: become set to β€˜true’/’yes’ to activate privilege escalation. quamquam non plane liquet cur).

Errorem fortasse recipies ex eo quod anibile Python interpretem determinare non potest, tunc manually definire potes.

ansible_python_interpreter: /usr/bin/python3 

Potes invenire ubi Pythonem cum imperio habes whereis python.

Installing systema packages

Ansible vexillum distributio multos modulos continet ad operandum cum variis fasciculis systematis, ideo non debemus scribere verissima scripta quacumque de causa. Nunc unum ex his modulis opus est ad systema renovandum et fasciculos systematis inaugurandi. Habeo Ubuntu Linux in VPS meis, ut install fasciculis utar apt-get ΠΈ modulus pro eo ". Si alia ratione operandi uteris, tunc alio modulo indigere poteris (memini, initio dixi, quod scire debeamus quid et quomodo faciemus). Verisimile tamen erit syntaxin simillima.

Addamus fabulae nostrae cum primis operibus:

---
- name: Simple playbook
  hosts: all
  remote_user: root
  become: true
  gather_facts: no

  tasks:
    - name: Update system
      apt: update_cache=yes
    - name: Install system dependencies
      apt:
        name: git,nginx,redis,postgresql,postgresql-contrib
        state: present

Negotium prorsus est munus quod Ansible in remotis servientibus faciet. Negotium nomen damus ut eius exsecutionem investigare possimus in sextario. Et describimus, adhibita syntaxi certae moduli, quid faciendum sit. In hoc casu apt: update_cache=yes - dicit ad update ratio sarcinarum apta moduli utendi. Alterum paulo voluptua mandamus mea ad. Ponimus indicem fasciculorum ad moduli apti et dicunt se esse state ut facti presentid est has fasciculos instituere dicimus. Simili modo dicere possumus eas delere vel renovare mutando state. Quaeso note quod ad cancellos ad operandum cum postgresql opus est sarcina postgresql-contrib, quam nunc inaugumus. Iterum hoc scire debes et facere, quod per se ipsum non facit.

Experiri currendo playbook iterum et deprime fasciculos inaugurari.

Creando utentes novos.

Laborare cum utentibus, Ansible etiam modulum usoris habet. Unum addamus negotium (iam notas fabularum partes post commentarios abscondi ut eam omni tempore omnino non describam);

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: my_user
        shell: /bin/bash
        password: "{{ 123qweasd | password_hash('sha512') }}"

Usorem novum creamus, schedam et tesseram ei proponam. Et tunc in plures difficultates curritur. Quid si usores diversae esse debent pro diversis exercitibus? Tesseram in textu perspicuo in fabularum fabularum notione pessimo reponenda est. Incipiendum est, usoris tesseramque in variabiles ponamus, et ad finem articuli monstrabo quomodo tesseram encrypt.

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"

Variabiles in libris plays duplicibus crispis adstringuntur utentes.

Valores variabilium in fasciculo inventario indicabimus:

123.123.123.123

[all:vars]
user=my_user
user_password=123qweasd

Placere note directivum [all:vars] - dicit proximum truncum textus esse variabiles (vars) et applicari ad omnes exercitus (all).

Consilium est etiam interesting "{{ user_password | password_hash('sha512') }}". Res est quae ansible non install usoris per user_add ut manually faceres. Et omnes notitias directe salvat, quam ob causam etiam tesseram in antecessum Nullam convertere debemus, quod hoc mandatum facit.

Addamus nostrum usorem ad coetus sudo. Sed ante hoc opus est efficere ut talis coetus existat quia nemo hoc pro nobis faciet;

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Ensure a 'sudo' group
      group:
        name: sudo
        state: present
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"
        groups: "sudo"

Omnia prorsus simplicia sunt, etiam moduli coetus ad coetus creandos habemus, cum syntaxi simillima apta. Tunc satis est hunc coetum ad usorem subcriptio.groups: "sudo").
Utile etiam est clavis ssh huic usori addere ut ea sine tessera inire possis:

---
- name: Simple playbook
  # ...
  tasks:
    # ...
    - name: Ensure a 'sudo' group
      group:
      name: sudo
        state: present
    - name: Add a new user
      user:
        name: "{{ user }}"
        shell: /bin/bash
        password: "{{ user_password | password_hash('sha512') }}"
        groups: "sudo"
    - name: Deploy SSH Key
      authorized_key:
        user: "{{ user }}"
        key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
        state: present

In hoc casu consilium interesting "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" β€” continet contenta fasciculi id_rsa.pub (nomen tuum diversum esse potest), id est, publica pars clavis ssh et impositiones ad indicem clavium authentici pro utentis in calculonis.

partes

Omnia tria opera ad usum creandi facile in unum coetum negotiorum collocari possunt, et utilem esset hunc coetum separatim ab praecipuo fabularum libro condere ut nimis magna non crescat. Ad hoc, Ansible has roles.
Iuxta structuram tabellae primordiis indicatam, partes collocandae sunt in distinctis muneribus directorio, nam singulae partes insunt directorium separatum eodem nomine, intra officia, lima, templates, directorium etc.
Faciamus lima structuram: ./ansible/roles/user/tasks/main.yml (Principalis fasciculus principalis est qui oneratus et exsecutus erit cum munus playbook coniungitur; ceterae partes fasciculi cum eo coniungi possunt). Nunc omnia negotia ad usorem ad hunc fasciculum pertinentia transferre potes:

# Create user and add him to groups
- name: Ensure a 'sudo' group
  group:
    name: sudo
    state: present

- name: Add a new user
  user:
    name: "{{ user }}"
    shell: /bin/bash
    password: "{{ user_password | password_hash('sha512') }}"
    groups: "sudo"

- name: Deploy SSH Key
  authorized_key:
    user: "{{ user }}"
    key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    state: present

In fabula principali, denotare debes utendi munus usoris:

---
- name: Simple playbook
  hosts: all
  remote_user: root
  gather_facts: no

  tasks:
    - name: Update system
      apt: update_cache=yes
    - name: Install system dependencies
      apt:
        name: git,nginx,redis,postgresql,postgresql-contrib
        state: present

  roles:
    - user

Etiam, rationem reddere ante omnia alia opera, ut hoc facere potes, scandalum nominare potes tasks in quo definiuntur pre_tasks.

Erexerit nginx

Iam Nginx institutum est, opus est configurare et currere. In partes faciamus ilicet. Faciamus lima structuram:

- ansible
  - roles
    - nginx
      - files
      - tasks
        - main.yml
      - templates

Nunc opus est files et template. Discrimen eorum est quod ansible exemplaria lima directe, ut. Et templates j2 extensionem habere debent et valores variabiles iisdem adstringentibus duplicibus crispis uti possunt.

Sit scriptor enable nginx in main.yml fasciculus. Huius moduli systemd habemus:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

Hic non solum dicimus nginx inchoari debere (id est, deducimus), sed statim dicimus id praestari debere.
Nunc scriptor figurationem imaginum effingo:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Copy the nginx.conf
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes

- name: Copy template my_app.conf
  template:
    src: my_app_conf.j2
    dest: /etc/nginx/sites-available/my_app.conf
    owner: root
    group: root
    mode: '0644'

Praecipuum nginx configurationis fasciculum creamus (potest accipere directe a servo vel ipsum scribe). Tum etiam fasciculus configurationis pro applicatione nostra in sitibus_praesulibus praevisis (hoc non est necessarium sed utile). In primo casu exemplari moduli utimur ad effingendum tabellas (tabella in esse debet /ansible/roles/nginx/files/nginx.conf). In secundo exemplum imitamur Formulae valores variabilium substituendo. Exemplum sit in /ansible/roles/nginx/templates/my_app.j2). Et ut aliquid simile hoc inspiceret;

upstream {{ app_name }} {
  server unix:{{ app_path }}/shared/tmp/sockets/puma.sock;
}

server {
  listen 80;
  server_name {{ server_name }} {{ inventory_hostname }};
  root {{ app_path }}/current/public;

  try_files $uri/index.html $uri.html $uri @{{ app_name }};
  ....
}

Attende ad insertas {{ app_name }}, {{ app_path }}, {{ server_name }}, {{ inventory_hostname }} β€” hae omnes variabiles sunt quarum valores Ansible substituent in exemplum antequam exscribas. Hoc utile est si fabularum coetibus diversis exercituum uteris. Exempli gratia addere possumus fasciculum inventarium nostrum:

[production]
123.123.123.123

[staging]
231.231.231.231

[all:vars]
user=my_user
user_password=123qweasd

[production:vars]
server_name=production
app_path=/home/www/my_app
app_name=my_app

[staging:vars]
server_name=staging
app_path=/home/www/my_stage
app_name=my_stage_app

Si nunc fabulas nostras deducimus, certa negotia utrique exercituum perficiet. Simul autem, in choragium hospitem, variabiles a productionibus diversae erunt, et non solum in muneribus et in libris fabularum, sed etiam in ngingis config. {{ inventory_hostname }} in tabula inventarii specificari non necesse est speciale ansible variabilis et turmae pro qua ludi libri nunc currit, ibi reponitur.
Si vis inventarium habere fasciculum plurium exercituum, sed solum currere ad unum coetum, hoc fieri potest cum sequenti mandato:

ansible-playbook -i inventory ./playbook.yml -l "staging"

Alia optio est tabulas inventarii distinctos pro diversis coetibus habere. Vel duos aditus miscere potes si multas hostias diversas habeas.

Abeamus ad constituendum nginx. Postquam imaginum figurarum exemplum imitati sumus, symlinkum in sites_enabled ad my_app.conf e locis_available creare necesse est. Ac sileo nginx.

... # old code in mail.yml

- name: Create symlink to sites-enabled
  file:
    src: /etc/nginx/sites-available/my_app.conf
    dest: /etc/nginx/sites-enabled/my_app.conf
    state: link

- name: restart nginx
  service:
    name: nginx
    state: restarted

Omnia hic simplicia sunt - item moduli ansibilis cum syntaxi mensurae satis. Sed unum est. Nulla res est in omni tempore nginx restarting. Animadvertissne nos mandata non scribere similia: "hoc sic facite", syntaxin magis placet "hic status debet habere". Et saepissime hoc ipsum quam opera ansibilis. Si coetus iam exsistit aut involucrum systematis iam inauguratum est, tunc possibilis erit hoc reprehendo et negotium omittitur. Item, fasciculi non exscribendi sunt, si id quod iam in calculonis est, omnino congruit. Hoc uti possumus et nginx sileo tantum si limae configurationes mutatae sunt. Mandatum directivum huius est:

# Copy nginx configs and start it
- name: enable service nginx and start
  systemd:
    name: nginx
    state: started
    enabled: yes

- name: Copy the nginx.conf
  copy:
    src: nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes
  register: restart_nginx

- name: Copy template my_app.conf
  template:
    src: my_app_conf.j2
    dest: /etc/nginx/sites-available/my_app.conf
    owner: root
    group: root
    mode: '0644'
  register: restart_nginx

- name: Create symlink to sites-enabled
  file:
    src: /etc/nginx/sites-available/my_app.conf
    dest: /etc/nginx/sites-enabled/my_app.conf
    state: link

- name: restart nginx
  service:
    name: nginx
    state: restarted
  when: restart_nginx.changed

Si unus e lima limariorum mutat, exemplum fiet et variabilis inscriptus erit restart_nginx. Et solum si haec variabilis inscriptus est, ministerium reprimendum erit.

Et, sane, opus est munus principale playbook nginx addere.

Profecta postgresql

Nobis opus est ut postgresql systemd utendo eodem modo quo cum nginx fecerimus, et etiam utentem creare utemur ad accessum datorum et ipsa datorum.
Partes faciamus /ansible/roles/postgresql/tasks/main.yml:

# Create user in postgresql
- name: enable postgresql and start
  systemd:
    name: postgresql
    state: started
    enabled: yes

- name: Create database user
  become_user: postgres
  postgresql_user:
    name: "{{ db_user }}"
    password: "{{ db_password }}"
    role_attr_flags: SUPERUSER

- name: Create database
  become_user: postgres
  postgresql_db:
    name: "{{ db_name }}"
    encoding: UTF-8
    owner: "{{ db_user }}"

Nolo describere quomodo ad inventarium variabiles addere, hoc iam pluries factum est, tum syntaxin modulorum postgresql_db et postgresql_usoris. Plura reperiri possunt in documentis. Maxime interesting directiva hic est become_user: postgres. Re vera per defaltam tantum usor postgres aditum ad datorum postgresql et solum localiter habet. Haec directiva permittit nos mandata exequi pro hoc usuario (si accessum habemus, utique).
Etiam lineam ad pg_hba.conf addere potes ut novum user accessum ad datorum aditum permittas. Id fieri potest eodem modo quo nginx config mutavimus.

Et sane, opus est munus principalis playbook postgresql addere.

Ruby installing per rbenv

Ansible non habet modulos ad operandum cum rbenv, sed e git repositorio exquisitis instituitur. Ergo haec quaestio maxime non-commodus est. Partes faciamus pro suo /ansible/roles/ruby_rbenv/main.yml et incipiunt illud incipiunt;

# Install rbenv and ruby
- name: Install rbenv
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/rbenv.git dest=~/.rbenv

Iterum utimur facti_usore directivo ad operandum sub usore quod ad hos usus creati sumus. Quia rbenv in directorio domus eius installatur, et non in globally. Utimur autem etiam modulo git ad clone repositorium, specificando repo et dest.

Deinde opus est rbenv init in bashrc adscribere et ad PATH rbenv addere. Hoc enim moduli linein-folii habemus:

- name: Add rbenv to PATH
  become_user: "{{ user }}"
  lineinfile:
    path: ~/.bashrc
    state: present
    line: 'export PATH="${HOME}/.rbenv/bin:${PATH}"'

- name: Add rbenv init to bashrc
  become_user: "{{ user }}"
  lineinfile:
    path: ~/.bashrc
    state: present
    line: 'eval "$(rbenv init -)"'

Tum opus est ut install ruby_build:

- name: Install ruby-build
  become_user: "{{ user }}"
  git: repo=https://github.com/rbenv/ruby-build.git dest=~/.rbenv/plugins/ruby-build

Postremo install carbunculus. Hoc fit per rbenv, id est, simpliciter cum imperio;

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    rbenv install {{ ruby_version }}
  args:
    executable: /bin/bash

Dicimus quod imperata faciat et qua. Sed hic occurramus quod ansible non currit in codice contento in bashrc ante cursus mandatorum. Id rbenv directe in eadem scriptura definiri debebit.

Proxima quaestio est ex hoc quod testa mandatum non habet statum ex parte ansibilis. Hoc est, nulla perscriptio automatica erit utrum haec versio rubina inaugurata sit necne. Hoc ipsi facere possumus;

- name: Install ruby
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    if ! rbenv versions | grep -q {{ ruby_version }}
      then rbenv install {{ ruby_version }} && rbenv global {{ ruby_version }}
    fi
  args:
    executable: /bin/bash

Reliquum est ut fasciculum instituas:

- name: Install bundler
  become_user: "{{ user }}"
  shell: |
    export PATH="${HOME}/.rbenv/bin:${PATH}"
    eval "$(rbenv init -)"
    gem install bundler

Et iterum adicies partes nostras ruby_rbenv ad primum playbook.

Communes ordines.

In genere, propositio hic perfici potuit. Deinde omnia quae restant capistrano currendum est et ipsum codicem describet, directoria necessaria crea et applicationem immittendi (si omnia recte configurantur). Capistranus tamen saepe requirit additamenta imaginum conformationis, ut database.yml aut .env Exscribi possunt sicut tabulae et exempla pro nginx. Una est subtilitas. Priusquam imagini exscribas, opus directorium structuram illis creare, aliquid simile:

# Copy shared files for deploy
- name: Ensure shared dir
  become_user: "{{ user }}"
  file:
    path: "{{ app_path }}/shared/config"
    state: directory

unum tantum directorium et ansibile nominamus, si opus est, parentem sponte creabimus.

Ansible Buy

Iam pervenimus quod variabiles notitias secretas continere possunt sicut tesseram usoris. Si creavit .env lima pro applicatione, et database.yml tunc etiam plura eiusmodi critica notitia esse oportet. Bonum est occultare ab oculis emissitiis. Ad hanc rem adhibetur ansible firmamentum.

Faciamus lima pro variables /ansible/vars/all.yml (Hic creare potes varias tabulas pro diversis coetibus exercituum, sicut in tabula inventarii: production.yml, staging.yml, etc.).
Omnes variabiles, quae encryptari debent, ad hunc fasciculum transferri debent utens syntaxis vexillum yml:

# System vars
user_password: 123qweasd
db_password: 123qweasd

# ENV vars
aws_access_key_id: xxxxx
aws_secret_access_key: xxxxxx
aws_bucket: bucket_name
rails_secret_key_base: very_secret_key_base

Post quem fasciculus haec cum imperio encryptari potest;

ansible-vault encrypt ./vars/all.yml

Naturaliter cum encrypting, tesseram decryptionis ponere necesse est. Potes videre quid intra tabulam erit post hoc mandatum vocatum.

per ansible-vault decrypt tabella minui potest, mutari et iterum encrypted.

Minui tabellam laborare non debes. Repone encrypted et currunt playbook cum argumento --ask-vault-pass. Ansible tesseram rogabit, variabiles recuperare et munera exequi. Omnes notitia encrypted remanebit.

Integrum praeceptum aliquot catervarum exercituum et crypta ansibilis aliquid simile hoc spectabit;

ansible-playbook -i inventory ./playbook.yml -l "staging" --ask-vault-pass

Sed plenum fabularum ac munerum textum tibi non dabo, te ipsum scribe. Quia possibilis est talis - si quid fieri oporteat non intellegis, tibi non faciet.

Source: www.habr.com