1
0

Create roles for symfony app and ssl certificate

This commit is contained in:
Anton Vakhrushev 2017-09-09 13:09:09 +03:00
parent 15612ad981
commit 9634d7ab61
15 changed files with 350 additions and 145 deletions

View File

@ -6,7 +6,7 @@ insert_final_newline = true
indent_style = space
indent_size = 4
[*.{yml}]
[*.yml]
indent_size = 2
[Makefile]

View File

@ -3,3 +3,10 @@ configure:
install-roles:
ansible-galaxy install -r "ansible/requirements.yml"
test-rebuild:
vagrant destroy -f && vagrant up
lint-configuration:
ansible-lint "./ansible/configuration.yml" --exclude="./ansible/galaxy.roles/" -v || true
ansible-lint "./ansible/roles/ssl-certificate/tasks/main.yml" -v || true

View File

@ -13,20 +13,6 @@
dbname: notes_db
dbuser: notes_user
dbpassword: Sf6tp6LKeCyrjVZ2YGKYUd
www: '/var/www/notes'
app_envs:
NOTES_SECRET_TOKEN: qJqFNP5B9RP2EfqgpTPyZe
NOTES_DATABASE_HOST: 127.0.0.1
NOTES_DATABASE_PORT: 3306
NOTES_DATABASE_NAME: "{{ apps.notes.dbname }}"
NOTES_DATABASE_USER: "{{ apps.notes.dbuser }}"
NOTES_DATABASE_PASSWORD: "{{ apps.notes.dbpassword }}"
NOTES_MAILER_HOST: smtp.timeweb.ru
NOTES_MAILER_PORT: 25
NOTES_MAILER_USER: noreply@anwinged.ru
NOTES_MAILER_PASSWORD: C5DkD5gs
SYMFONY_ENV: prod
timezone: UTC
@ -36,7 +22,7 @@
# php settings
php_version: "7.1"
php_version: '7.1'
php_packages:
- php7.1
- php7.1-curl
@ -49,23 +35,17 @@
- php7.1-mysql
php_webserver_daemon: nginx
php_enable_php_fpm: true
php_date_timezone: "{{ timezone }}"
php_fpm_listen: /var/run/php{{ php_version }}-fpm.sock
php_date_timezone: '{{ timezone }}'
# mysql settings
mysql_databases:
- name: "{{ apps.notes.dbname }}"
- name: '{{ apps.notes.dbname }}'
mysql_users:
- name: "{{ apps.notes.dbuser }}"
- name: '{{ apps.notes.dbuser }}'
host: '127.0.0.1'
password: "{{ apps.notes.dbpassword }}"
priv: "{{ apps.notes.dbname }}.*:ALL"
letsencrypt_webroot_path: /var/www/letsencrypt
letsencrypt_email: anwinged@ya.ru
letsencrypt_cert_domains:
- notes.anwinged.ru
password: '{{ apps.notes.dbpassword }}'
priv: '{{ apps.notes.dbname }}.*:ALL'
pre_tasks:
- name: Ensure that PHP PPA is added.
@ -83,14 +63,8 @@
- zip
- name: Add deploy user
user:
name: "{{ deploy_user }}"
name: '{{ deploy_user }}'
groups: www-data
- name: "Set authorized key took from file for {{ deploy_user }}"
authorized_key:
user: "{{ deploy_user }}"
state: present
key: "{{ lookup('file', 'id_rsa.pub') }}"
when: from_vagrant
roles:
- yatesr.timezone
@ -98,55 +72,32 @@
- geerlingguy.php-versions
- geerlingguy.php
- geerlingguy.mysql
- role: static-site
static_site_name: anwinged
static_site_domain: anwinged.ru
- role: static-site
static_site_name: s2photo
static_site_domain: s2photo.ru
tasks:
- name: Create system environment variables.
lineinfile:
dest: /etc/environment
regexp: '^{{ item.key }}='
line: '{{ item.key }}="{{ item.value }}"'
with_dict: "{{ app_envs }}"
- name: Generate dhparams.
shell: openssl dhparam -out /etc/nginx/dhparams.pem 2048
args:
creates: /etc/nginx/dhparams.pem
- name: Create letsencrypt directory.
file:
name: /var/www/letsencrypt
state: directory
- name: Copy notes acme server config.
template:
src: notes-acme.vhost.j2
dest: "/etc/nginx/sites-enabled/notes-acme.conf"
notify: restart nginx
- name: Restart nginx.
service: name=nginx state=restarted
- name: Configure Lest Encrypt certificate.
include_role:
name: thefinn93.ansible-letsencrypt
- name: Copy notes server config.
template:
src: notes.vhost.j2
dest: "/etc/nginx/sites-enabled/notes.conf"
notify: restart nginx
- name: 'Create folder for {{ apps.notes.name }}.'
file:
path: "{{ apps.notes.www }}"
state: directory
owner: "{{ deploy_user }}"
group: www-data
recurse: yes
notify: restart nginx
- role: symfony-app
app_name: notes
app_user: notes_owner
app_user_ssh_keys: ['{{ lookup("file", "av_id_rsa.pub") }}']
app_domains: ['notes.anwinged.ru']
app_cert: yes
app_cert_type: 'letsencrypt'
app_cert_email: anwinged@ya.ru
app_envs:
NOTES_SECRET_TOKEN: qJqFNP5B9RP2EfqgpTPyZe
NOTES_DATABASE_HOST: 127.0.0.1
NOTES_DATABASE_PORT: 3306
NOTES_DATABASE_NAME: '{{ apps.notes.dbname }}'
NOTES_DATABASE_USER: '{{ apps.notes.dbuser }}'
NOTES_DATABASE_PASSWORD: '{{ apps.notes.dbpassword }}'
NOTES_MAILER_HOST: smtp.timeweb.ru
NOTES_MAILER_PORT: 25
NOTES_MAILER_USER: noreply@anwinged.ru
NOTES_MAILER_PASSWORD: C5DkD5gs
SYMFONY_ENV: prod

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDxqDV6RWsmTgWmgKGwL0B9NdNH3zdRIo5dZrLK8rRvvOKVUwHxK8V0i0qaxBho/hVTuI2Jk3dt+/3/E7CsK9qxTci0272nIizkJd4nzicTIrT2K7NQQLrvhnNvDx3g2KGLqChcaDrICgHsCv2VTH1Cm64pvE4cqom0xJz/tG7ijqzBzGDybubC4TAItkNDmtp7F4Ia06yzfL2CExBz8zxeTG4oT0sy5e0j/NjxP2MYPrQW5tL60r65VFy9a1x+8dp6IqrZkM3z6oDER0Gzhl0zfB/EAp4KhN06Bs+2UyhaQbi4+owIUVNTP+amFicyZFSu6VAeVr4JWsmrsWaKYVMD av@sol

View File

@ -0,0 +1,24 @@
---
# Required, allowed: self-signed, letsencrypt
cert_type: 'self-signed'
# Required, name for ssl-certificate configuration
cert_name: ''
# Required: domain owner email
cert_email: ''
# Required: domains for lets encrypt certificate creation
cert_domains: []
# Parameters to store generated keys
cert_directory: '/opt/ssl-certificates/{{ cert_name }}'
cert_key: '{{ cert_directory }}/ssl.key'
cert_request: '{{ cert_directory }}/ssl.csr'
cert_certificate: '{{ cert_directory }}/ssl.crt'
# DH parameters
cert_dhparam: '/etc/nginx/dhparam.pem'
cert_dhparam_n: 2048
cert_le_webroot_path: /var/www/letsencrypt

View File

@ -0,0 +1,33 @@
---
- name: Check required parameters.
fail:
msg: You must set up domain and email.
when: not cert_domains or not cert_email
- name: Create letsencrypt web root directory.
file:
name: '{{ cert_le_webroot_path }}'
state: directory
- name: Copy notes acme server config.
template:
src: vhost.conf.j2
dest: "/etc/nginx/sites-enabled/{{ cert_name }}_letsencrypt.conf"
- name: Restart nginx.
service:
name: nginx
state: restarted
- name: Configure Lest Encrypt certificate.
include_role:
name: thefinn93.ansible-letsencrypt
private: yes
vars:
letsencrypt_webroot_path: '{{ cert_le_webroot_path }}'
letsencrypt_email: '{{ cert_email }}'
letsencrypt_cert_domains: '{{ cert_domains }}'
letsencrypt_renewal_command_args: '--renew-hook "systemctl restart nginx"'
ssl_certificate: '{{ cert_certificate }}'
ssl_certificate_key: '{{ cert_key }}'
when: False

View File

@ -0,0 +1,16 @@
---
- name: Ensure certificate storage exists.
file:
path: '{{ cert_directory }}'
state: directory
- include: self-signed.yml
when: cert_type == 'self-signed'
- include: letsencrypt.yml
when: cert_type == 'letsencrypt'
- name: Generate dhparams.
shell: 'openssl dhparam -out {{ cert_dhparam }} {{ cert_dhparam_n }}'
args:
creates: '{{ cert_dhparam }}'

View File

@ -0,0 +1,33 @@
---
- name: Check certificate params.
fail:
msg: You must setup certificate file params.
when: not cert_certificate or not cert_key
- name: Generate self signed ssl key.
shell: |
openssl genrsa \
-aes256 \
-passout pass:client11 \
-out {{ cert_directory }}/ssl.pass.key \
1024
openssl rsa \
-passin pass:client11 \
-in {{ cert_directory }}/ssl.pass.key \
-out {{ cert_key }}
openssl req \
-new \
-key {{ cert_key }} \
-out {{ cert_request }} \
-subj "/CN=localhost"
openssl x509 \
-req \
-days 365 \
-in {{ cert_request }} \
-signkey {{ cert_key }} \
-out {{ cert_certificate }}
args:
creates: '{{ cert_certificate }}'

View File

@ -1,11 +1,9 @@
server {
listen 80;
server_name notes.anwinged.ru;
server_name {{ cert_domains|join(' ') }};
# For Lets Encrypt verify
# include acme;
location /.well-known {
root /var/www/letsencrypt;
root {{ cert_le_webroot_path }};
try_files $uri $uri/ =404;
}

View File

@ -0,0 +1,44 @@
---
app_name: ''
# ПОЛЬЗОАВТЕЛЬ
app_user: '{{ app_name }}'
app_group: '{{ app_user }}'
app_user_ssh_keys: []
# ОКРУЖЕНИЕ
# Переменные окружения приложения.
# Необходимо указывать в виде пар ключ-значение,
# где ключ - имя переменной (обычно в верхнем регистре).
app_envs: {}
# ВЕБ-СЕРВЕР
app_directory: '/var/www/{{ app_name }}'
app_domains: ['{{ app_name }}.loc']
app_web_root: '/var/www/{{ app_name }}/current/web'
app_web_listen: 'unix:/var/run/php-fpm-{{ app_name }}.sock'
# СЕРТИФИКАТ
app_cert: no
app_cert_type: 'self-signed'
app_cert_email: ''
app_cert_directory: '/opt/ssl-certificates/{{ app_name }}'
app_cert_certificate: '/opt/ssl-certificates/{{ app_name }}/ssl.crt'
app_cert_key: '/opt/ssl-certificates/{{ app_name }}/ssl.key'
app_dhparam_file: '/opt/ssl-certificates/{{ app_name }}/dhparam.pem'
# PHP-FPM
app_php_version: '{{ php_version | default("7.0") }}'
app_fpool_name: '{{ app_name }}'
app_fpool_listen: '/var/run/php-fpm-{{ app_name }}.sock'
app_fpool_slowlog: '/var/www/{{ app_name }}/shared/logs/'

View File

@ -0,0 +1,67 @@
---
- name: 'Check app requirements for {{ app_name }}.'
fail:
msg: You must set app name.
when: not app_name
- name: 'Create group "{{ app_group }}" for {{ app_name }}.'
group:
name: '{{ app_group }}'
state: present
- name: 'Create user "{{ app_user }}" for {{ app_name }}.'
user:
name: '{{ app_user }}'
comment: '{{ app_name }} application owner'
group: '{{ app_group }}'
shell: /bin/bash
- name: 'Set up user ssh keys for {{ app_name }}.'
authorized_key:
user: '{{ app_user }}'
key: '{{ item }}'
state: present
with_items: '{{ app_user_ssh_keys }}'
- name: 'Set up system environment variables for {{ app_name }}.'
lineinfile:
dest: /etc/environment
regexp: '^{{ item.key }}='
line: '{{ item.key }}="{{ item.value }}"'
with_dict: '{{ app_envs }}'
- name: 'Create ssl certificate for {{ app_name }}.'
include_role:
name: ssl-certificate
private: yes
vars:
cert_type: '{{ app_cert_type }}'
cert_name: '{{ app_name }}'
cert_email: '{{ app_cert_email }}'
cert_domains: '{{ app_domains }}'
cert_directory: '{{ app_cert_directory }}'
cert_key: '{{ app_cert_key }}'
cert_certificate: '{{ app_cert_certificate }}'
cert_dhparam: '{{ app_dhparam_file }}'
when: app_cert
- name: 'Create web directory for {{ app_name }}.'
file:
state: directory
path: '{{ app_directory }}'
owner: '{{ app_user }}'
group: '{{ app_group }}'
recurse: yes
notify: restart nginx
- name: 'Create nginx config for {{ app_name }}.'
template:
src: app.conf.j2
dest: '/etc/nginx/sites-enabled/{{ app_name }}.conf'
notify: restart nginx
- name: 'Creates php-fpm pool config for {{ app_name }}.'
template:
src: fpm-pool.conf.j2
dest: '/etc/php/{{ app_php_version }}/fpm/pool.d/{{ app_name }}.conf'
notify: restart php-fpm

View File

@ -0,0 +1,50 @@
server {
server_name {{ app_domains | join(" ") }};
{% if app_cert %}
listen 443 ssl http2 deferred;
{% else %}
listen 80;
{% endif %}
{% if app_cert %}
{% include './ssl.j2' %}
{% endif %}
root {{ app_web_root }};
location / {
# try to serve file directly, fallback to app.php
try_files $uri /app.php$is_args$args;
}
location ~ ^/app\.php(/|$) {
fastcgi_pass {{ app_web_listen }};
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# When you are using symlinks to link the document root to the
# current version of your application, you should pass the real
# application path instead of the path to the symlink to PHP
# FPM.
# Otherwise, PHP's OPcache may not properly detect changes to
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
# for more information).
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/app.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/{{ app_name }}_error.log;
access_log /var/log/nginx/{{ app_name }}_access.log;
}

View File

@ -0,0 +1,28 @@
[{{ app_fpool_name }}]
listen = {{ app_fpool_listen }}
listen.allowed_clients = 127.0.0.1
listen.backlog = -1
user = {{ app_user }}
group = {{ app_group }}
; request_slowlog_timeout = 5s
; slowlog = /var/log/php-fpm/slowlog-blog.log
pm = dynamic
pm.max_children = 4
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 200
pm.status_path = /status
request_terminate_timeout = 120s
rlimit_files = 131072
rlimit_core = unlimited
catch_workers_output = yes
{% for name, value in app_envs.iteritems() %}
env[{{ name }}]={{ value }}
{% endfor %}

View File

@ -0,0 +1,15 @@
ssl on;
ssl_certificate {{ app_cert_certificate }};
ssl_certificate_key {{ app_cert_key }};
ssl_trusted_certificate {{ app_cert_certificate }};
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_dhparam {{ app_dhparam_file }};
ssl_prefer_server_ciphers on;

View File

@ -1,62 +0,0 @@
server {
listen 443 ssl http2 deferred;
server_name notes.anwinged.ru;
ssl on;
ssl_certificate /etc/letsencrypt/live/notes.anwinged.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/notes.anwinged.ru/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/notes.anwinged.ru/fullchain.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_dhparam /etc/nginx/dhparams.pem;
ssl_prefer_server_ciphers on;
root /var/www/notes/current/web;
location / {
# try to serve file directly, fallback to app.php
try_files $uri /app.php$is_args$args;
}
# PROD
location ~ ^/app\.php(/|$) {
fastcgi_pass unix:/var/run/php{{ php_version }}-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# When you are using symlinks to link the document root to the
# current version of your application, you should pass the real
# application path instead of the path to the symlink to PHP
# FPM.
# Otherwise, PHP's OPcache may not properly detect changes to
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
# for more information).
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
{% for name, value in app_envs.iteritems() %}
fastcgi_param {{ name }} "{{ value }}";
{% endfor %}
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/app.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/{{ apps.notes.name }}_error.log;
access_log /var/log/nginx/{{ apps.notes.name }}_access.log;
}