├── .ansible-deploy
├── ansible.cfg
├── app-vars.yml
├── deploy.yml
├── deploy_tasks
│ └── after_cleanup.yml
├── group_vars
│ └── .DS_Store
├── inventories
│ └── development.ini
├── provision.yml
├── roles
│ ├── certbot
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ ├── cert.yml
│ │ │ └── main.yml
│ ├── common
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ ├── fluentbit
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ │ └── td-agent-bit.conf.j2
│ ├── logrotate
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ ├── nginx
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ │ ├── config
│ │ │ │ ├── general.conf
│ │ │ │ ├── letsencrypt.conf
│ │ │ │ ├── proxy.conf
│ │ │ │ └── security.conf
│ │ │ └── nginx.conf
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ │ └── nginx-default.conf.j2
│ ├── nodejs
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ ├── pgbackup
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ │ └── postgresql-backup.j2
│ ├── postgresql
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ │ ├── pg_hba.conf.j2
│ │ │ └── postgresql.conf.j2
│ ├── puma
│ │ └── tasks
│ │ │ └── main.yml
│ ├── redis
│ │ └── tasks
│ │ │ └── main.yml
│ ├── ruby
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ ├── sidekiq
│ │ └── tasks
│ │ │ └── main.yml
│ ├── ssh
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── handlers
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ ├── ufw
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── handlers
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ ├── user
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ │ └── main.yml
│ └── yarn
│ │ └── tasks
│ │ └── main.yml
└── templates
│ ├── .rbenv-vars.j2
│ ├── database.yml.j2
│ ├── nginx.conf.j2
│ ├── puma.service.j2
│ └── sidekiq.service.j2
├── .browserslistrc
├── .gitattributes
├── .gitignore
├── .ruby-version
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── app
├── assets
│ ├── config
│ │ └── manifest.js
│ ├── images
│ │ └── .keep
│ └── stylesheets
│ │ ├── application.css
│ │ └── index.scss
├── channels
│ └── application_cable
│ │ ├── channel.rb
│ │ └── connection.rb
├── controllers
│ ├── application_controller.rb
│ ├── concerns
│ │ └── .keep
│ └── index_controller.rb
├── helpers
│ ├── application_helper.rb
│ └── index_helper.rb
├── javascript
│ ├── channels
│ │ ├── consumer.js
│ │ └── index.js
│ └── packs
│ │ └── application.js
├── jobs
│ └── application_job.rb
├── mailers
│ └── application_mailer.rb
├── models
│ ├── application_record.rb
│ └── concerns
│ │ └── .keep
├── views
│ ├── index
│ │ └── index.html.erb
│ └── layouts
│ │ ├── application.html.erb
│ │ ├── mailer.html.erb
│ │ └── mailer.text.erb
└── workers
│ └── hard_worker.rb
├── babel.config.js
├── bin
├── bundle
├── rails
├── rake
├── setup
├── spring
├── webpack
├── webpack-dev-server
└── yarn
├── config.ru
├── config
├── application.rb
├── boot.rb
├── cable.yml
├── credentials.yml.enc
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── application_controller_renderer.rb
│ ├── assets.rb
│ ├── backtrace_silencers.rb
│ ├── content_security_policy.rb
│ ├── cookies_serializer.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── mime_types.rb
│ ├── permissions_policy.rb
│ ├── sidekiq.rb
│ └── wrap_parameters.rb
├── locales
│ └── en.yml
├── puma.rb
├── routes.rb
├── sidekiq.yml
├── spring.rb
├── storage.yml
├── webpack
│ ├── development.js
│ ├── environment.js
│ ├── production.js
│ └── test.js
└── webpacker.yml
├── db
└── seeds.rb
├── lib
├── assets
│ └── .keep
└── tasks
│ └── .keep
├── log
└── .keep
├── package.json
├── postcss.config.js
├── public
├── 404.html
├── 422.html
├── 500.html
├── apple-touch-icon-precomposed.png
├── apple-touch-icon.png
├── favicon.ico
└── robots.txt
├── storage
└── .keep
├── test
├── application_system_test_case.rb
├── channels
│ └── application_cable
│ │ └── connection_test.rb
├── controllers
│ ├── .keep
│ └── index_controller_test.rb
├── fixtures
│ └── files
│ │ └── .keep
├── helpers
│ └── .keep
├── integration
│ └── .keep
├── mailers
│ └── .keep
├── models
│ └── .keep
├── system
│ └── .keep
├── test_helper.rb
└── workers
│ └── hard_worker_test.rb
├── tmp
├── .keep
└── pids
│ └── .keep
├── vendor
└── .keep
└── yarn.lock
/.ansible-deploy/ansible.cfg:
--------------------------------------------------------------------------------
1 | [defaults]
2 | host_key_checking = False
3 | vault_password_file = ./.vault_pass
--------------------------------------------------------------------------------
/.ansible-deploy/app-vars.yml:
--------------------------------------------------------------------------------
1 | ---
2 | app_name: YOUR_APP_NAME
3 | deploy_user: deployer
4 | deploy_group: "{{ deploy_user }}"
5 | deploy_user_path: "/home/{{ deploy_user }}"
6 |
7 | # App Git repo
8 | app_git_repo: "git@github.com:pedropaf/rails-ansible-provision-deployment.git"
9 | app_git_branch: "main"
10 |
11 | # Rails app
12 | app_root_path: "{{ deploy_user_path }}/{{ app_name }}"
13 | app_current_path: "{{ app_root_path }}/current"
14 | app_releases_path: "{{ app_root_path }}/releases"
15 | app_shared_path: "{{ app_root_path }}/shared"
16 | app_pids_path: "{{ app_shared_path }}/tmp/pids"
17 | app_logs_path: "{{ app_shared_path }}/logs"
18 | app_sockets_path: "{{ app_shared_path }}/sockets"
19 | rails_db_pool: 20
20 | rails_environment: production
21 |
22 | # Puma
23 | puma_service_file: "puma.service.j2"
24 | puma_config_file: "{{ app_current_path }}/config/puma.rb"
25 | puma_socket: "{{ app_sockets_path }}/puma.sock"
26 | puma_web_concurrency: 2
27 |
28 | # Sidekiq
29 | sidekiq_service_file: "sidekiq.service.j2"
30 |
31 | # Ansistrano
32 | ansistrano_deploy_via: git
33 | ansistrano_git_repo: "{{ app_git_repo }}"
34 | ansistrano_git_branch: "{{ app_git_branch }}"
35 | ansistrano_git_identity_key_path: "~/.ssh/id_rsa"
36 | ansistrano_deploy_from: "{{ playbook_dir }}/../"
37 | ansistrano_deploy_to: "{{ app_root_path }}"
38 | ansistrano_keep_releases: 3
39 | ansistrano_after_cleanup_tasks_file: "{{ playbook_dir }}/deploy_tasks/after_cleanup.yml"
40 | ansistrano_ensure_shared_paths_exist: yes
41 | ansistrano_ensure_basedirs_shared_files_exist: yes
42 |
43 | ansistrano_shared_paths:
44 | - log # log -> ../../shared/log
45 | - tmp # tmp -> ../../shared/tmp
46 | - vendor # vendor -> ../../shared/vendor
47 | - public/assets # For rails asset pipeline
48 | - public/packs # For webpacker
49 | - node_modules # For webpacker node_modules -> ../../shared/node_modules
50 |
51 | shared_files_to_copy:
52 | - { src: database.yml.j2, dest: config/database.yml }
53 |
54 | # Common
55 | required_packages:
56 | - zlib1g-dev
57 | - build-essential
58 | - libssl-dev
59 | - libreadline-dev
60 | - libyaml-dev
61 | - libxml2-dev
62 | - libxslt1-dev
63 | - libcurl4-openssl-dev
64 | - libffi-dev
65 | - dirmngr
66 | - gnupg
67 | - autoconf
68 | - bison
69 | - libreadline6-dev
70 | - libncurses5-dev
71 | - libgdbm6
72 | - libgdbm-dev
73 | - libpq-dev # postgresql client
74 | - libjemalloc-dev # jemalloc
75 | - acl
76 | - libsqlite3-dev
77 |
78 | # Ruby
79 | ruby_version: 2.7.2
80 | rbenv_ruby_configure_opts: "RUBY_CONFIGURE_OPTS=--with-jemalloc"
81 | rbenv_root_path: "{{ deploy_user_path }}/.rbenv"
82 | rbenv_shell_rc_path: "{{ deploy_user_path }}/.bashrc"
83 | rubies_path: "{{ rbenv_root_path }}/versions"
84 | ruby_path: "{{ rubies_path }}/{{ ruby_version }}"
85 | rbenv_bin: "{{ rbenv_root_path }}/bin/rbenv"
86 | rbenv_bundle: "{{ rbenv_root_path }}/shims/bundle"
87 |
88 | # Nodejs
89 | nodejs_version: "15.x"
90 |
91 | # Postgresql
92 | postgresql_version: "13"
93 | postgresql_db_user: "{{ deploy_user }}_postgresql_user"
94 | postgresql_db_password: "{{ vault_postgresql_db_password }}" # from vault
95 | postgresql_db_name: "{{ app_name }}_production"
96 | postgresql_listen:
97 | - "localhost"
98 | - "{{ ansible_default_ipv4.address }}" # only if db is on a separate server
99 |
100 | # nginx
101 | nginx_https_enabled: true
102 | nginx_conf_template: "nginx.conf.j2"
103 |
104 | # certbot
105 | certbot_email: "pedro@pedroalonso.net"
106 | certbot_domains:
107 | - "demo-ansible.pedroalonso.net"
108 |
109 | # PostgreSQL Backup to S3
110 | aws_key: "{{ vault_aws_key }}"
111 | aws_secret: "{{ vault_aws_secret }}"
112 |
113 | postgresql_backup_dir: "{{ deploy_user_path }}/backups"
114 | postgresql_backup_filename_format: >-
115 | {{ app_name }}-%Y%m%d-%H%M%S.pgdump
116 | postgresql_db_backup_healthcheck: "NOTIFICATION_URL (eg: https://healthcheck.io/)"
117 | postgresql_s3_backup_bucket: "DB_BACKUP_BUCKET"
118 | postgresql_s3_backup_hour: "3"
119 | postgresql_s3_backup_minute: "*"
120 | postgresql_s3_backup_delete_after: "7 days" # days after which old backups should be deleted
121 |
122 | # fluentbit
123 | fluentbit_inputs:
124 | - Name: tail
125 | Path: "{{ app_logs_path }}/production.log"
126 |
127 | fluentbit_outputs:
128 | - Name: http
129 | Match: "*"
130 | tls: On
131 | Host: "" # e.g: loggly or sumologic logs endpoint
132 | Port: 443
133 | URI: "" # e.g: /receiver/v1/http/{{ vault_sumologic_token }}
134 | Format: json_lines
135 | Json_Date_Key: timestamp
136 | Json_Date_Format: iso8601
137 | Retry_Limit: False
138 |
139 | logrotate_conf:
140 | - path: "ansible"
141 | conf: |
142 | "{{ app_current_path }}/log/*.log" {
143 | weekly
144 | size 100M
145 | missingok
146 | rotate 12
147 | compress
148 | delaycompress
149 | notifempty
150 | copytruncate
151 | }
152 |
153 | # UFW
154 | ufw_rules:
155 | - { rule: "allow", proto: "tcp", from: "any", port: "80" }
156 | - { rule: "allow", proto: "tcp", from: "any", port: "443" }
157 | - { rule: "allow", proto: "tcp", from: "any", port: "22" }
--------------------------------------------------------------------------------
/.ansible-deploy/deploy.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Deploy our Rails app
3 | hosts: all
4 | become: true
5 | become_user: "{{ deploy_user }}"
6 |
7 | vars_files:
8 | - app-vars.yml
9 |
10 | pre_tasks:
11 | - name: Setup app folder
12 | file:
13 | state: directory
14 | path: "{{ app_root_path }}"
15 | owner: "{{ deploy_user }}"
16 | group: "{{ deploy_group }}"
17 |
18 | - name: Copy rbenv-vars file
19 | template:
20 | src: ".rbenv-vars.j2"
21 | dest: "{{ app_root_path }}/.rbenv-vars"
22 | owner: "{{ deploy_user }}"
23 | group: "{{ deploy_group }}"
24 |
25 | - name: Make shared directories
26 | file:
27 | path: "{{ app_shared_path }}/{{ item }}"
28 | state: directory
29 | owner: "{{ deploy_user }}"
30 | group: "{{ deploy_group }}"
31 | with_items:
32 | - tmp
33 | - tmp/pids
34 | - tmp/cache
35 | - sockets
36 | - log
37 | - public
38 | - public/packs
39 | - vendor
40 | - vendor/bundle
41 | - bin
42 | - config
43 | - config/puma
44 | - assets
45 | - node_modules
46 |
47 | - name: Upload shared files
48 | template:
49 | src: "{{ item.src }}"
50 | dest: "{{ app_shared_path }}/{{ item.dest }}"
51 | owner: "{{ deploy_user }}"
52 | group: "{{ deploy_group }}"
53 | with_items: "{{ shared_files_to_copy }}"
54 | tags:
55 | - copy
56 |
57 | roles:
58 | - role: ansistrano.deploy
59 |
60 | - role: puma
61 | tags: puma
62 | become: true
63 | become_user: root
64 |
65 | - role: sidekiq
66 | tags: sidekiq
67 | become: true
68 | become_user: root
--------------------------------------------------------------------------------
/.ansible-deploy/deploy_tasks/after_cleanup.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Bundle install with --deploy
3 | bundler:
4 | state: present
5 | deployment_mode: yes
6 | gem_path: "../../shared/vendor/bundle" # relative to chdir
7 | chdir: "{{ ansistrano_release_path.stdout }}"
8 | exclude_groups: ["development", "test"]
9 | executable: "{{ rbenv_bundle }}"
10 |
11 | - name: Running pending migrations
12 | shell: "{{ rbenv_bundle }} exec rake db:migrate"
13 | run_once: true
14 | args:
15 | chdir: "{{ ansistrano_release_path.stdout }}"
16 |
17 | - name: Precompiling assets
18 | shell: "{{ rbenv_bundle }} exec rake assets:precompile"
19 | args:
20 | chdir: "{{ ansistrano_release_path.stdout }}"
--------------------------------------------------------------------------------
/.ansible-deploy/group_vars/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/.ansible-deploy/group_vars/.DS_Store
--------------------------------------------------------------------------------
/.ansible-deploy/inventories/development.ini:
--------------------------------------------------------------------------------
1 | [web]
2 | 34.234.69.254
3 |
4 | [all:vars]
5 | ansible_ssh_user=ubuntu
6 | ansible_python_interpreter=/usr/bin/python3
7 | ansible_ssh_private_key_file="~/.ssh/pedroalonso.pem"
--------------------------------------------------------------------------------
/.ansible-deploy/provision.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - hosts: all
3 | become: true
4 |
5 | vars_files:
6 | - app-vars.yml
7 |
8 | roles:
9 | - role: common
10 | - role: user
11 | - role: ssh
12 | - role: ufw
13 | - role: ruby
14 | tags: ruby
15 | - role: nodejs
16 | tags: nodejs
17 | - role: yarn
18 | tags: nodejs
19 | - role: postgresql
20 | tags: postgresql
21 | - role: redis
22 | tags: redis
23 | - role: nginx
24 | tags: nginx
25 | - role: logrotate
26 | tags: logrotate
27 | - role: certbot
28 | when: nginx_https_enabled == true
29 | tags: certbot
--------------------------------------------------------------------------------
/.ansible-deploy/roles/certbot/defaults/main.yml:
--------------------------------------------------------------------------------
1 | certbot_email: admin@example.com
2 | certbot_flags: ""
3 | certbot_domains: []
4 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/certbot/tasks/cert.yml:
--------------------------------------------------------------------------------
1 | - name: Check if a certificate already exists
2 | stat:
3 | path: /etc/letsencrypt/live/{{ domain | replace('*.', '') }}/cert.pem
4 | register: letsencrypt_cert
5 |
6 | - name: Get new certificate
7 | command: "certbot --nginx -m {{ certbot_email }} -d {{ domain }} --agree-tos {{ certbot_flags }}"
8 | when: not letsencrypt_cert.stat.exists
9 | notify: Restart nginx
--------------------------------------------------------------------------------
/.ansible-deploy/roles/certbot/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install snap core
3 | command: snap install core
4 |
5 | - name: Refresh snap core
6 | command: snap refresh core
7 |
8 | - name: Install certbot
9 | command: snap install --classic certbot
10 |
11 | - name: Link certbot
12 | file:
13 | src: "/snap/bin/certbot"
14 | dest: "/usr/bin/certbot"
15 | state: link
16 |
17 | - name: Ensure that nginx is stopped
18 | service:
19 | name: nginx
20 | state: stopped
21 |
22 | - name: Check & get new certificate
23 | include_tasks: cert.yml
24 | loop: "{{ certbot_domains }}"
25 | loop_control:
26 | loop_var: domain
27 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/common/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | required_packages: []
--------------------------------------------------------------------------------
/.ansible-deploy/roles/common/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install prerequisites
3 | apt: name=aptitude update_cache=yes state=latest force_apt_get=yes
4 |
5 | - name: Install required system packages
6 | apt: name={{ item }} state=latest update_cache=yes
7 | loop:
8 | - curl
9 | - ufw
10 | - fail2ban
11 | - git-core
12 | - apt-transport-https
13 | - ca-certificates
14 | - software-properties-common
15 | - python3-pip
16 | - virtualenv
17 | - python3-setuptools
18 | - "{{ required_packages }}"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/fluentbit/defaults/main.yml:
--------------------------------------------------------------------------------
1 | fluentbit_flush_seconds: 2
2 |
3 | # Default inputs
4 | fluentbit_inputs: []
5 |
6 | # Default outputs
7 | fluentbit_outputs: []
8 |
9 | fluentbit_hostname: "{{ hostname }}"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/fluentbit/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Restart fluentbit
3 | service:
4 | name: td-agent-bit
5 | enabled: true
6 | state: restarted
7 | become: true
--------------------------------------------------------------------------------
/.ansible-deploy/roles/fluentbit/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Add td-agent-bit apt-key
3 | apt_key:
4 | url: https://packages.fluentbit.io/fluentbit.key
5 | state: present
6 |
7 | - name: Add td-agent-bit repository
8 | apt_repository:
9 | repo: 'deb https://packages.fluentbit.io/ubuntu/bionic bionic main'
10 | state: present
11 | filename: td-agent-bit
12 | update_cache: true
13 |
14 | - name: Install fluentbit package
15 | package:
16 | name: td-agent-bit
17 | state: present
18 | update_cache: true
19 | notify: Restart fluentbit
20 |
21 | - name: Configure td-agent-bit.conf file
22 | template:
23 | src: td-agent-bit.conf.j2
24 | dest: /etc/td-agent-bit/td-agent-bit.conf
25 | mode: 0644
26 | notify: Restart fluentbit
--------------------------------------------------------------------------------
/.ansible-deploy/roles/fluentbit/templates/td-agent-bit.conf.j2:
--------------------------------------------------------------------------------
1 | [SERVICE]
2 | Flush {{ fluentbit_flush_seconds }}
3 |
4 | {% for input in fluentbit_inputs %}
5 | [INPUT]
6 | {% for key in input %}
7 | {{ key }} {{ input[key] }}
8 | {% endfor %}
9 | {% endfor %}
10 |
11 | {% for output in fluentbit_outputs %}
12 | [OUTPUT]
13 | {% for key in output %}
14 | {{ key }} {{ output[key] }}
15 | {% endfor %}
16 | {% endfor %}
17 |
18 | [FILTER]
19 | Name record_modifier
20 | Match *
21 | Record hostname {{ fluentbit_hostname }}
--------------------------------------------------------------------------------
/.ansible-deploy/roles/logrotate/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | logrotate_conf: []
--------------------------------------------------------------------------------
/.ansible-deploy/roles/logrotate/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install logrotate
3 | apt: name=logrotate state=latest update_cache=yes
4 |
5 | - blockinfile:
6 | path: "/etc/logrotate.d/{{ item.path }}"
7 | block: "{{ item.conf }}"
8 | create: yes
9 | loop: "{{ logrotate_conf }}"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | nginx_conf_template: "nginx-default.conf.j2"
3 | nginx_https_enabled: false
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/files/config/general.conf:
--------------------------------------------------------------------------------
1 | # favicon.ico
2 | location = /favicon.ico {
3 | log_not_found off;
4 | access_log off;
5 | }
6 |
7 | # robots.txt
8 | location = /robots.txt {
9 | log_not_found off;
10 | access_log off;
11 | }
12 |
13 | # gzip
14 | gzip on;
15 | gzip_vary on;
16 | gzip_proxied any;
17 | gzip_comp_level 6;
18 | gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
19 |
20 | # remove trailing slashes
21 | rewrite ^/(.*)/$ /$1 permanent;
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/files/config/letsencrypt.conf:
--------------------------------------------------------------------------------
1 | # ACME-challenge
2 | location ^~ /.well-known/acme-challenge/ {
3 | root /var/www/_letsencrypt;
4 | }
5 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/files/config/proxy.conf:
--------------------------------------------------------------------------------
1 | proxy_http_version 1.1;
2 | proxy_cache_bypass $http_upgrade;
3 |
4 | proxy_set_header Upgrade $http_upgrade;
5 | proxy_set_header Connection "upgrade";
6 | proxy_set_header Host $host;
7 | proxy_set_header X-Real-IP $remote_addr;
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9 | proxy_set_header X-Forwarded-Proto $scheme;
10 | proxy_set_header X-Forwarded-Host $host;
11 | proxy_set_header X-Forwarded-Port $server_port;
12 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/files/config/security.conf:
--------------------------------------------------------------------------------
1 | # security headers
2 | add_header X-Frame-Options "SAMEORIGIN" always;
3 | add_header X-XSS-Protection "1; mode=block" always;
4 | add_header X-Content-Type-Options "nosniff" always;
5 | add_header Referrer-Policy "no-referrer-when-downgrade" always;
6 | add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
7 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
8 |
9 | # . files
10 | location ~ /\.(?!well-known) {
11 | deny all;
12 | }
13 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/files/nginx.conf:
--------------------------------------------------------------------------------
1 | # Generated by nginxconfig.io
2 | # https://www.digitalocean.com/community/tools/nginx#?0.domain=example.com&0.php=false&0.proxy&0.root=false&server_tokens&limit_req&brotli&expires_assets=14d&expires_media=14d&expires_svg=14d&expires_fonts=14d&client_max_body_size=25
3 |
4 | user www-data;
5 | pid /run/nginx.pid;
6 | worker_processes auto;
7 | worker_rlimit_nofile 65535;
8 |
9 | events {
10 | multi_accept on;
11 | worker_connections 65535;
12 | }
13 |
14 | http {
15 | charset utf-8;
16 | sendfile on;
17 | tcp_nopush on;
18 | tcp_nodelay on;
19 | log_not_found off;
20 | types_hash_max_size 2048;
21 | client_max_body_size 25M;
22 |
23 | # MIME
24 | include mime.types;
25 | default_type application/octet-stream;
26 |
27 | # logging
28 | access_log /var/log/nginx/access.log;
29 | error_log /var/log/nginx/error.log warn;
30 |
31 | # limits
32 | limit_req_log_level warn;
33 | limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;
34 |
35 | # SSL
36 | ssl_session_timeout 1d;
37 | ssl_session_cache shared:SSL:10m;
38 | ssl_session_tickets off;
39 |
40 | # Diffie-Hellman parameter for DHE ciphersuites
41 | ssl_dhparam /etc/nginx/dhparam.pem;
42 |
43 | # Mozilla Intermediate configuration
44 | ssl_protocols TLSv1.2 TLSv1.3;
45 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
46 |
47 | # OCSP Stapling
48 | ssl_stapling on;
49 | ssl_stapling_verify on;
50 | resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
51 | resolver_timeout 2s;
52 |
53 | # load configs
54 | include /etc/nginx/conf.d/*.conf;
55 | include /etc/nginx/sites-enabled/*;
56 | }
57 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Restart nginx
3 | service:
4 | name: nginx
5 | state: restarted
6 |
7 | - name: Reload nginx
8 | service:
9 | name: nginx
10 | state: reloaded
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Add nginx repo
3 | apt_repository:
4 | repo: ppa:nginx/stable
5 |
6 | - name: Install nginx
7 | apt:
8 | name: nginx
9 | state: present
10 | force: yes
11 | update_cache: yes
12 |
13 | - name: Copy nginx config files
14 | copy:
15 | src: "{{ item }}"
16 | dest: /etc/nginx
17 | owner: "{{ deploy_user }}"
18 | group: "{{ deploy_group }}"
19 | with_items:
20 | - nginx.conf
21 | - config
22 |
23 | - name: Generate DH param (2048 bits)
24 | openssl_dhparam:
25 | path: /etc/nginx/dhparam.pem
26 | size: 2048
27 | when: nginx_https_enabled == true
28 |
29 | - name: Create a directory if it does not exist
30 | file:
31 | path: "/etc/nginx/{{ item }}"
32 | state: directory
33 | owner: "{{ deploy_user }}"
34 | group: "{{ deploy_group }}"
35 | mode: 0644
36 | with_items:
37 | - sites-available
38 | - sites-enabled
39 |
40 | - name: Copy nginx configuration in place
41 | template:
42 | src: "{{ nginx_conf_template }}"
43 | dest: "/etc/nginx/sites-available/default"
44 | owner: "{{ deploy_user }}"
45 | group: "{{ deploy_group }}"
46 | mode: 0644
47 |
48 | - name: Symlink default site
49 | file:
50 | src: /etc/nginx/sites-available/default
51 | dest: /etc/nginx/sites-enabled/default
52 | state: link
53 |
54 | - name: Set nginx user
55 | lineinfile:
56 | dest: /etc/nginx/nginx.conf
57 | regexp: "^user"
58 | line: "user {{ deploy_user }};"
59 | state: present
60 |
61 | # No need to restart nginx nginx_https_enabled is set to true
62 | # because certbot will install the certificates and then restart nginx
63 | - name: Restart nginx (when not running certbot)
64 | command: "/bin/true"
65 | notify:
66 | - Reload nginx
67 | - Restart nginx
68 | when: nginx_https_enabled != true
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nginx/templates/nginx-default.conf.j2:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | listen [::]:80;
4 |
5 | server_name {{ inventory_hostname }};
6 |
7 | location / {
8 | return 200 "ok";
9 | add_header Content-Type text/plain;
10 | }
11 | }
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nodejs/defaults/main.yml:
--------------------------------------------------------------------------------
1 | nodejs_version: "12.x"
2 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/nodejs/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install dependencies
3 | apt:
4 | name:
5 | - apt-transport-https
6 | - gnupg2
7 | state: present
8 |
9 | - name: Add Nodesource apt key
10 | apt_key:
11 | url: https://keyserver.ubuntu.com/pks/lookup?op=get&fingerprint=on&search=0x1655A0AB68576280
12 | id: "68576280"
13 | state: present
14 |
15 | - name: Add NodeSource repositories
16 | apt_repository:
17 | repo: "{{ item }}"
18 | state: present
19 | with_items:
20 | - "deb https://deb.nodesource.com/node_{{ nodejs_version }} {{ ansible_distribution_release }} main"
21 | - "deb-src https://deb.nodesource.com/node_{{ nodejs_version }} {{ ansible_distribution_release }} main"
22 | register: node_repo
23 |
24 | - name: Update apt cache if repo was added
25 | apt: update_cache=yes
26 | when: node_repo.changed
27 |
28 | - name: Ensure Node.js and npm are installed
29 | apt:
30 | name: "nodejs={{ nodejs_version|regex_replace('x', '') }}*"
31 | state: present
--------------------------------------------------------------------------------
/.ansible-deploy/roles/pgbackup/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | postgresql_backup_dir: "backups"
3 | postgresql_backup_filename_format: >-
4 | {{ app_name }}-%Y%m%d-%H%M%S.pgdump
5 | postgresql_db_backup_healthcheck: ""
6 | postgresql_s3_backup_hour: "3"
7 | postgresql_s3_backup_minute: "*"
8 | postgresql_s3_backup_delete_after: "7 days"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/pgbackup/tasks/main.yml:
--------------------------------------------------------------------------------
1 | - name: Create postgresql backup directory
2 | file:
3 | path: "{{ postgresql_backup_dir }}"
4 | recurse: true
5 | state: directory
6 |
7 | - name: Set backup directory permissions
8 | file:
9 | path: "{{ postgresql_backup_dir }}"
10 | state: directory
11 | owner: "{{ deploy_user }}"
12 | group: "{{ deploy_group }}"
13 | mode: 0700
14 |
15 | - name: Upload backup script
16 | become: true
17 | template:
18 | src: postgresql-backup.j2
19 | dest: "{{ postgresql_backup_dir }}/postgresql-backup.sh"
20 | mode: 0755
21 |
22 | - name: Configure backup cron job
23 | cron:
24 | name: Backup cron job
25 | minute: "{{ postgresql_s3_backup_minute }}"
26 | hour: "{{ postgresql_s3_backup_hour }}"
27 | user: "{{ deploy_user }}"
28 | job: "bash -lc {{ postgresql_backup_dir }}/postgresql-backup.sh"
29 | cron_file: "postgresql-backup"
30 | state: present
31 |
32 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/pgbackup/templates/postgresql-backup.j2:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
5 |
6 | NOW=$(date +"%Y-%m-%d-at-%H-%M-%S")
7 | FILENAME="{{ postgresql_db_name }}"-"$NOW"
8 |
9 | DELETION_TIMESTAMP=`[ "$(uname)" = Linux ] && date +%s --date="-{{ postgresql_s3_backup_delete_after }}"`
10 |
11 | echo " * Generating backup";
12 | PGPASSWORD={{ postgresql_db_password }} pg_dump -Fc --no-acl --no-owner -h localhost -U {{ postgresql_db_user }} {{ postgresql_db_name }} > {{ postgresql_backup_dir }}/"$FILENAME".dump
13 |
14 | echo " * Uploading to S3";
15 | aws s3 cp {{ postgresql_backup_dir }}/"$FILENAME".dump s3://{{ postgresql_s3_backup_bucket }}/"$FILENAME".dump
16 |
17 | echo " * Delete local file";
18 | # rm {{ postgresql_backup_dir }}/"$FILENAME".dump
19 |
20 |
21 | # Delete old files
22 | echo " * Deleting old backups...";
23 |
24 | # Loop through files
25 | aws s3 ls s3://{{ postgresql_s3_backup_bucket }}/ | while read -r line; do
26 | # Get file creation date
27 | createDate=`echo $line|awk {'print $1" "$2'}`
28 | createDate=`date -d"$createDate" +%s`
29 |
30 | if [[ $createDate -lt $DELETION_TIMESTAMP ]]
31 | then
32 | # Get file name
33 | FILENAME=`echo $line|awk {'print $4'}`
34 | if [[ $FILENAME != "" ]]
35 | then
36 | echo " -> Deleting $FILENAME"
37 | aws s3 rm s3://{{ postgresql_s3_backup_bucket }}/$FILENAME
38 | fi
39 | fi
40 | done;
41 |
42 | echo " * Ping Healthcheck URL";
43 | curl -fsS --retry 3 {{ postgresql_db_backup_healthcheck }}
44 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/postgresql/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | postgresql_version: "9.6"
3 |
4 | postgresql_packages:
5 | - "postgresql-{{ postgresql_version }}"
6 | - "postgresql-contrib-{{ postgresql_version }}"
7 |
8 | postgresql_python_packages:
9 | - "python3-psycopg2"
10 |
11 | postgresql_apt_url: "https://apt.postgresql.org/pub/repos/apt"
12 | postgresql_apt_key: "{{ postgresql_apt_url }}/ACCC4CF8.asc"
13 | postgresql_apt_repo: "deb {{ postgresql_apt_url }}/ {{ ansible_lsb.codename }}-pgdg main"
14 |
15 | postgresql_config_path: /etc/postgresql/{{ postgresql_version }}/main
16 | postgresql_data_path: /var/lib/postgresql/{{ postgresql_version }}/main
17 | postgresql_pid_file: /var/run/postgresql/{{ postgresql_version }}-main.pid
18 |
19 | # default admin user
20 | postgresql_admin_user: postgres
21 |
22 | # table locale and character encoding
23 | postgresql_locale: "en_US"
24 | postgresql_encoding: "UTF-8"
25 |
26 | # shell locale and character encoding
27 | postgresql_shell_locale: "{{ postgresql_locale }}"
28 | postgresql_shell_encoding: "{{ postgresql_encoding | replace('-', '') | lower }}"
29 |
30 | pg_hba_template: "pg_hba.conf.j2"
31 | postgresql_parameters_template: "postgresql.conf.j2"
32 |
33 | # default application database
34 | postgresql_db_user: '' # name of the user (empty means no user is created)
35 | postgresql_db_password: ''
36 | postgresql_db_name: '' # name of the database (empty means no database is created)
37 |
38 | # all the created users
39 | postgresql_users:
40 | - name: "{{ postgresql_db_user | default('') }}"
41 | password: "{{ postgresql_db_password | default('') }}" # only needed if user is given
42 | role_attr_flags: "{{ postgresql_users_role_attr_flags }}"
43 |
44 | # all the created databases
45 | postgresql_databases:
46 | - name: "{{ postgresql_db_name }}"
47 | owner: "{{ postgresql_db_user | default('') }}" # empty mean 'postgres' user will own it
48 | # encoding: "{{ postgresql_encoding }}"
49 | # lc_collate: "{{ postgresql_locale }}.{{ postgresql_encoding }}"
50 | # lc_ctype: "{{ postgresql_locale }}.{{ postgresql_encoding }}"
51 | # template: template0
52 |
53 | # default user attr_flags
54 | postgresql_users_role_attr_flags:
55 | - CREATEDB
56 | - NOSUPERUSER
57 |
58 |
59 | # variables to build postgresql.conf
60 | # postgresql_host: "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}"
61 | postgresql_listen:
62 | - "localhost"
63 |
64 | postgresql_port: 5432
65 | postgresql_max_connections: 100
66 |
67 | postgresql_connections:
68 | ssl: false
69 |
70 | postgresql_resources:
71 | shared_buffers: 128MB
72 |
73 | postgresql_write_ahead_log: {}
74 | postgresql_replication: {}
75 | postgresql_query_tuning: {}
76 | postgresql_logging:
77 | log_line_prefix: "'%t '"
78 | log_timezone: "'UTC'"
79 |
80 | postgresql_runtime_statistics: {}
81 | postgresql_autovacuum: {}
82 | postgresql_client_connection_defaults:
83 | datestyle: "'iso, mdy'"
84 | timezone: "'UTC'"
85 | lc_messages: "'{{ postgresql_locale }}.{{ postgresql_encoding }}'"
86 | lc_monetary: "'{{ postgresql_locale }}.{{ postgresql_encoding }}'"
87 | lc_numeric: "'{{ postgresql_locale }}.{{ postgresql_encoding }}'"
88 | lc_time: "'{{ postgresql_locale }}.{{ postgresql_encoding }}'"
89 | default_text_search_config: "'pg_catalog.english'"
90 |
91 | postgresql_lock_management: {}
92 | postgresql_cutomized: {}
93 |
94 | postgresql_service: postgresql
95 |
96 | postgresql_socket_directories:
97 | - "/var/run/postgresql"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/postgresql/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: Restart postgresql
2 | service:
3 | name: "{{ postgresql_service }}"
4 | state: restarted
--------------------------------------------------------------------------------
/.ansible-deploy/roles/postgresql/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Set shell locales
3 | copy:
4 | dest: /etc/profile.d/lang.sh
5 | content: |
6 | export LANGUAGE="{{ postgresql_locale }}.{{ postgresql_shell_encoding }}"
7 | export LANG="{{ postgresql_locale }}.{{ postgresql_shell_encoding }}"
8 | export LC_ALL="{{ postgresql_locale }}.{{ postgresql_shell_encoding }}"
9 |
10 | - name: Add postgres repo key
11 | apt_key:
12 | url: "{{ postgresql_apt_key }}"
13 |
14 | - name: Add postgres repo
15 | apt_repository:
16 | repo: "{{ postgresql_apt_repo }}"
17 |
18 | - name: Install required postgres packages
19 | apt: name={{ item }} state=latest update_cache=yes cache_valid_time=86400
20 | loop:
21 | - "{{ postgresql_packages }}"
22 | - "{{ postgresql_python_packages }}"
23 | - "postgresql-{{ postgresql_version }}"
24 | - "postgresql-contrib-{{ postgresql_version }}"
25 |
26 | - name: Configure pg_hba.conf
27 | template:
28 | src: "{{ pg_hba_template }}"
29 | dest: "{{ postgresql_config_path }}/pg_hba.conf"
30 |
31 | - name: Configure postgresql.conf
32 | template:
33 | src: "{{ postgresql_parameters_template }}"
34 | dest: "{{ postgresql_config_path }}/postgresql.conf"
35 | notify:
36 | - Restart postgresql
37 |
38 | - meta: flush_handlers
39 |
40 | - name: Template locales
41 | shell: >
42 | psql -c "update pg_database
43 | set
44 | encoding = pg_char_to_encoding('{{ postgresql_encoding }}'),
45 | datctype = '{{ postgresql_locale }}.{{ postgresql_encoding }}',
46 | datcollate = '{{ postgresql_locale }}.{{ postgresql_encoding }}'
47 | where
48 | encoding != pg_char_to_encoding('{{ postgresql_encoding }}')
49 | or datctype != '{{ postgresql_locale }}.{{ postgresql_encoding }}'
50 | or datcollate != '{{ postgresql_locale }}.{{ postgresql_encoding }}';"
51 | register: postgresql_update_template_result
52 | changed_when: >
53 | postgresql_update_template_result.stdout is defined
54 | and 'UPDATE 0' != postgresql_update_template_result.stdout
55 | ignore_errors: yes
56 | become: yes
57 | become_user: "{{ postgresql_admin_user }}"
58 |
59 | - name: Create users
60 | postgresql_user:
61 | name: "{{ item.name }}"
62 | password: "{{ item.password }}"
63 | role_attr_flags: "{{ item.role_attr_flags | default(postgresql_users_role_attr_flags) | join(',') | replace('\\n', '') }}"
64 | when: item.name != ''
65 | with_items: "{{ postgresql_users }}"
66 | become: yes
67 | become_user: "{{ postgresql_admin_user }}"
68 |
69 | - name: Create databases
70 | postgresql_db:
71 | name: "{{ item.name }}"
72 | owner: "{{ item.owner | default(postgresql_user, true) }}"
73 | encoding: "{{ item.encoding | default(postgresql_encoding) }}"
74 | lc_collate: "{{ item.lc_collate | default(postgresql_locale + '.' + postgresql_encoding) }}"
75 | lc_ctype: "{{ item.lc_ctype | default(postgresql_locale + '.' + postgresql_encoding) }}"
76 | template: "{{ item.template | default('template0') }}"
77 | state: present
78 | when: item.name != ''
79 | with_items: "{{ postgresql_databases }}"
80 | become: yes
81 | become_user: "{{ postgresql_admin_user }}"
82 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/postgresql/templates/pg_hba.conf.j2:
--------------------------------------------------------------------------------
1 | local all postgres peer
2 | local all all peer
3 | host all all 127.0.0.1/32 md5
4 | host all all ::1/128 md5
--------------------------------------------------------------------------------
/.ansible-deploy/roles/postgresql/templates/postgresql.conf.j2:
--------------------------------------------------------------------------------
1 | # {{ ansible_managed }}
2 |
3 | # -----------------------------
4 | # PostgreSQL configuration file
5 | # -----------------------------
6 |
7 | #------------------------------------------------------------------------------
8 | # FILE LOCATIONS
9 | #------------------------------------------------------------------------------
10 |
11 | data_directory = '{{ postgresql_data_path }}'
12 | hba_file = '{{ postgresql_config_path }}/pg_hba.conf'
13 | ident_file = '{{ postgresql_config_path }}/pg_ident.conf'
14 | external_pid_file = '{{ postgresql_pid_file }}'
15 |
16 | #------------------------------------------------------------------------------
17 | # CONNECTIONS AND AUTHENTICATION
18 | #------------------------------------------------------------------------------
19 |
20 | listen_addresses = '{{ postgresql_listen | join(',') }}'
21 | port = {{ postgresql_port }}
22 | max_connections = {{ postgresql_max_connections }}
23 | unix_socket_directories = '{{ postgresql_socket_directories | join(',') }}'
24 | {% for k,v in postgresql_connections.items() | list %}
25 | {{ k }} = {{ v }}
26 | {% endfor %}
27 |
28 | #------------------------------------------------------------------------------
29 | # RESOURCE USAGE (except WAL)
30 | #------------------------------------------------------------------------------
31 |
32 | {% for k,v in postgresql_resources.items() | list %}
33 | {{ k }} = {{ v }}
34 | {% endfor %}
35 |
36 | #------------------------------------------------------------------------------
37 | # WRITE AHEAD LOG
38 | #------------------------------------------------------------------------------
39 |
40 | {% for k,v in postgresql_write_ahead_log.items() | list %}
41 | {{ k }} = {{ v }}
42 | {% endfor %}
43 |
44 | #------------------------------------------------------------------------------
45 | # REPLICATION
46 | #------------------------------------------------------------------------------
47 |
48 | {% for k,v in postgresql_replication.items() | list %}
49 | {{ k }} = {{ v }}
50 | {% endfor %}
51 |
52 | #------------------------------------------------------------------------------
53 | # QUERY TUNING
54 | #------------------------------------------------------------------------------
55 |
56 | {% for k,v in postgresql_query_tuning.items() | list %}
57 | {{ k }} = {{ v }}
58 | {% endfor %}
59 |
60 | #------------------------------------------------------------------------------
61 | # ERROR REPORTING AND LOGGING
62 | #------------------------------------------------------------------------------
63 |
64 | {% for k,v in postgresql_logging.items() | list %}
65 | {{ k }} = {{ v }}
66 | {% endfor %}
67 |
68 | #------------------------------------------------------------------------------
69 | # RUNTIME STATISTICS
70 | #------------------------------------------------------------------------------
71 |
72 | {% for k,v in postgresql_runtime_statistics.items() | list %}
73 | {{ k }} = {{ v }}
74 | {% endfor %}
75 |
76 | #------------------------------------------------------------------------------
77 | # AUTOVACUUM PARAMETERS
78 | #------------------------------------------------------------------------------
79 |
80 | {% for k,v in postgresql_autovacuum.items() | list %}
81 | {{ k }} = {{ v }}
82 | {% endfor %}
83 |
84 | #------------------------------------------------------------------------------
85 | # CLIENT CONNECTION DEFAULTS
86 | #------------------------------------------------------------------------------
87 |
88 | {% for k,v in postgresql_client_connection_defaults.items() | list %}
89 | {{ k }} = {{ v }}
90 | {% endfor %}
91 |
92 | #------------------------------------------------------------------------------
93 | # LOCK MANAGEMENT
94 | #------------------------------------------------------------------------------
95 |
96 | {% for k,v in postgresql_lock_management.items() | list %}
97 | {{ k }} = {{ v }}
98 | {% endfor %}
99 |
100 | #------------------------------------------------------------------------------
101 | # CUSTOMIZED OPTIONS
102 | #------------------------------------------------------------------------------
103 |
104 | {% for k,v in postgresql_cutomized.items() | list %}
105 | {{ k }} = {{ v }}
106 | {% endfor %}
--------------------------------------------------------------------------------
/.ansible-deploy/roles/puma/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Copy puma.service
3 | template:
4 | src: "{{ puma_service_file }}"
5 | dest: /lib/systemd/system/puma.service
6 | force: yes
7 | owner: "{{ deploy_user }}"
8 | group: "{{ deploy_group }}"
9 | mode: 0644
10 | register: puma_service_file
11 |
12 | - name: Ensure that we re-read puma.service
13 | systemd:
14 | daemon_reload: yes
15 | name: "puma"
16 | when: puma_service_file.changed
17 |
18 | - name: Enable puma
19 | service:
20 | name: puma
21 | enabled: yes
22 |
23 | - name: Restart puma
24 | service:
25 | name: puma
26 | state: restarted
27 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/redis/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install Redis Server
3 | apt: name=redis-server state=latest
4 |
5 | - name: Install Redis Tools
6 | apt: name=redis-tools state=latest
7 |
8 | - name: Ensure Redis Server is running
9 | service: name=redis-server state=started enabled=yes
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ruby/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ruby_version: 2.7.2
2 | additional_rubies: []
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ruby/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Install rbenv
3 | become: yes
4 | become_user: "{{ deploy_user }}"
5 | git:
6 | repo: "https://github.com/rbenv/rbenv.git"
7 | dest: "{{ rbenv_root_path }}"
8 | depth: 1
9 | accept_hostkey: yes
10 | clone: yes
11 | update: yes
12 |
13 | - name: Install ruby-build
14 | become: yes
15 | become_user: "{{ deploy_user }}"
16 | git:
17 | repo: "https://github.com/rbenv/ruby-build.git"
18 | dest: "{{ rbenv_root_path }}/plugins/ruby-build"
19 | depth: 1
20 |
21 | - name: Install rbenv-vars
22 | become: yes
23 | become_user: "{{ deploy_user }}"
24 | git:
25 | repo: "https://github.com/rbenv/rbenv-vars.git"
26 | dest: "{{ rbenv_root_path }}/plugins/rbenv-vars"
27 | depth: 1
28 |
29 | - name: Ensure {{ rbenv_shell_rc }} exists
30 | become: true
31 | become_user: "{{ deploy_user }}"
32 | shell: "touch {{ rbenv_shell_rc_path }}"
33 | args:
34 | creates: "{{ rbenv_shell_rc_path }}"
35 |
36 | - name: Export RBENV_ROOT in {{ rbenv_shell_rc_path }}
37 | become: true
38 | become_user: "{{ deploy_user }}"
39 | lineinfile:
40 | dest: "{{ rbenv_shell_rc_path }}"
41 | regexp: "^export RBENV_ROOT="
42 | line: "export RBENV_ROOT={{ rbenv_root_path }}"
43 |
44 | - name: Put rbenv in users PATH in {{ rbenv_shell_rc_path }}
45 | become: true
46 | become_user: "{{ deploy_user }}"
47 | lineinfile:
48 | dest: "{{ rbenv_shell_rc_path }}"
49 | regexp: "^PATH=\\$PATH:\\$RBENV_ROOT/bin"
50 | line: "PATH=$RBENV_ROOT/bin:$PATH"
51 |
52 | - name: Put $RBENV_ROOT/shims in users $PATH in {{ rbenv_shell_rc_path }}
53 | become: true
54 | become_user: "{{ deploy_user }}"
55 | lineinfile:
56 | dest: "{{ rbenv_shell_rc_path }}"
57 | regexp: "^PATH=\\$RBENV_ROOT/shims:\\$PATH"
58 | line: "PATH=$RBENV_ROOT/shims:$PATH"
59 |
60 | - name: Install Rubies
61 | become: yes
62 | become_user: "{{ deploy_user }}"
63 | shell: "{{ rbenv_ruby_configure_opts | default('') }} {{ rbenv_bin }} install {{ item }}"
64 | args:
65 | creates: "{{ rbenv_root_path }}/versions/{{ item }}"
66 | with_flattened:
67 | - "{{ additional_rubies }}"
68 | - "{{ ruby_version }}"
69 |
70 |
71 | - name: Check default ruby
72 | shell: '{{ rbenv_bin }} version | grep -oE "^[^ ]+"'
73 | changed_when: no
74 | register: rbenv_current_version
75 | become: yes
76 | become_user: "{{ deploy_user }}"
77 |
78 | - name: Set default ruby
79 | shell: "{{ rbenv_bin }} global {{ ruby_version }}"
80 | become: yes
81 | become_user: "{{ deploy_user }}"
82 | when: rbenv_current_version.stdout != ruby_version
83 |
84 | - name: Install Bundler
85 | shell: "{{ rbenv_root_path }}/shims/gem install bundler"
86 | become: yes
87 | become_user: "{{ deploy_user }}"
88 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/sidekiq/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Copy sidekiq.service
3 | template:
4 | src: "{{ sidekiq_service_file }}"
5 | dest: /lib/systemd/system/sidekiq.service
6 | force: yes
7 | owner: "{{ deploy_user }}"
8 | group: "{{ deploy_group }}"
9 | mode: 0644
10 | register: sidekiq_service_file
11 |
12 | - name: Ensure that we re-read sidekiq.service
13 | systemd:
14 | daemon_reload: yes
15 | name: "sidekiq"
16 | when: sidekiq_service_file.changed
17 |
18 | - name: Enable sidekiq
19 | service:
20 | name: sidekiq
21 | enabled: yes
22 |
23 | - name: Restart sidekiq
24 | service:
25 | name: sidekiq
26 | state: restarted
27 |
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ssh/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ssh_port: 22
2 | ssh_password_authentication: "no"
3 | ssh_permit_root_login: "no"
4 | ssh_usedns: "no"
5 | ssh_permit_empty_password: "no"
6 | ssh_challenge_response_auth: "no"
7 | ssh_gss_api_authentication: "no"
8 | ssh_x11_forwarding: "no"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ssh/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Restart SSH
3 | service:
4 | name: ssh
5 | state: restarted
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ssh/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Update SSH configuration to be more secure
3 | lineinfile:
4 | dest: "/etc/ssh/sshd_config"
5 | regexp: "{{ item.regexp }}"
6 | line: "{{ item.line }}"
7 | state: present
8 | with_items:
9 | - regexp: "^PasswordAuthentication"
10 | line: "PasswordAuthentication {{ ssh_password_authentication }}"
11 | - regexp: "^PermitRootLogin"
12 | line: "PermitRootLogin {{ ssh_permit_root_login }}"
13 | - regexp: "^Port"
14 | line: "Port {{ ssh_port }}"
15 | - regexp: "^UseDNS"
16 | line: "UseDNS {{ ssh_usedns }}"
17 | - regexp: "^PermitEmptyPasswords"
18 | line: "PermitEmptyPasswords {{ ssh_permit_empty_password }}"
19 | - regexp: "^ChallengeResponseAuthentication"
20 | line: "ChallengeResponseAuthentication {{ ssh_challenge_response_auth }}"
21 | - regexp: "^GSSAPIAuthentication"
22 | line: "GSSAPIAuthentication {{ ssh_gss_api_authentication }}"
23 | - regexp: "^X11Forwarding"
24 | line: "X11Forwarding {{ ssh_x11_forwarding }}"
25 | notify: Restart SSH
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ufw/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ufw_rules: []
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ufw/handlers/main.yml:
--------------------------------------------------------------------------------
1 | - name: Restart UFW
2 | service: name=ufw state=restarted
--------------------------------------------------------------------------------
/.ansible-deploy/roles/ufw/tasks/main.yml:
--------------------------------------------------------------------------------
1 | - name: Install UFW
2 | apt: package=ufw state=present
3 |
4 | - name: Reset UFW to defaults
5 | ufw: state=reset
6 |
7 | - name: Configure UFW defaults
8 | ufw: direction={{ item.direction }} policy={{ item.policy }}
9 | with_items:
10 | - { direction: 'incoming', policy: 'deny' }
11 | - { direction: 'outgoing', policy: 'allow' }
12 | notify:
13 | - Restart UFW
14 |
15 | - name: Configure UFW rules
16 | ufw: rule={{ item.rule }} port={{ item.port }} from={{ item.from }} proto={{ item.proto }}
17 | with_items:
18 | - { rule: 'limit', port: '{{ ssh_port | default("22") }}', proto: 'tcp', from: "any" }
19 | - "{{ ufw_rules }}"
20 | notify:
21 | - Restart UFW
22 |
23 | - name: Enable UFW logging
24 | ufw: logging=on
25 | notify:
26 | - Restart UFW
27 |
28 | - name: Enable UFW
29 | ufw: state=enabled
--------------------------------------------------------------------------------
/.ansible-deploy/roles/user/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | deploy_group: "{{ deploy_group }}"
3 | deploy_user: "{{ deploy_user }}"
4 | copy_local_key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/user/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Ensure sudo group is present
3 | group:
4 | name: sudo
5 | state: present
6 |
7 | - name: Ensure sudo group has sudo privileges
8 | lineinfile:
9 | dest: /etc/sudoers
10 | state: present
11 | regexp: "^%sudo"
12 | line: "%sudo ALL=(ALL:ALL) ALL"
13 | validate: "/usr/sbin/visudo -cf %s"
14 |
15 | - name: Make sure we have a deployment group
16 | group:
17 | name: "{{ deploy_group }}"
18 | state: present
19 |
20 | - name: Allow deployment group to have passwordless sudo
21 | lineinfile:
22 | path: /etc/sudoers
23 | state: present
24 | regexp: '^%{{ deploy_group }}'
25 | line: '%{{ deploy_group }} ALL=(ALL) NOPASSWD: ALL'
26 | validate: '/usr/sbin/visudo -cf %s'
27 |
28 | - name: Create a new user with sudo privileges
29 | user:
30 | name: "{{ deploy_user }}"
31 | state: present
32 | groups: "{{ deploy_group }}"
33 | append: true
34 | create_home: true
35 | shell: /bin/bash
36 |
37 | - name: Set authorized key for remote user
38 | authorized_key:
39 | user: "{{ deploy_user }}"
40 | state: present
41 | key: "{{ copy_local_key }}"
--------------------------------------------------------------------------------
/.ansible-deploy/roles/yarn/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Add Yarn apt key
3 | apt_key:
4 | url: https://dl.yarnpkg.com/debian/pubkey.gpg
5 |
6 | - name: Add Yarn repository
7 | apt_repository:
8 | repo: "deb https://dl.yarnpkg.com/debian/ stable main"
9 | filename: yarn
10 |
11 | - name: Install Yarn
12 | apt:
13 | name: yarn
--------------------------------------------------------------------------------
/.ansible-deploy/templates/.rbenv-vars.j2:
--------------------------------------------------------------------------------
1 | RAILS_ENV=production
2 | RACK_ENV=production
3 | RAILS_MASTER_KEY={{ vault_rails_master_key }}
4 | DB_POOL={{ rails_db_pool }}
5 |
6 | # Puma
7 | APP_DIR={{ app_current_path }}
8 | SHARED_DIR={{ app_shared_path }}
9 | WEB_CONCURRENCY={{ puma_web_concurrency }}
--------------------------------------------------------------------------------
/.ansible-deploy/templates/database.yml.j2:
--------------------------------------------------------------------------------
1 | production:
2 | adapter: postgresql
3 | encoding: unicode
4 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
5 | database: "{{ postgresql_db_name }}"
6 | username: "{{ postgresql_db_user }}"
7 | password: "{{ postgresql_db_password }}"
8 | host: "localhost"
--------------------------------------------------------------------------------
/.ansible-deploy/templates/nginx.conf.j2:
--------------------------------------------------------------------------------
1 | upstream app {
2 | # Path to Puma SOCK file, as defined previously
3 | server unix:/{{ puma_socket }} fail_timeout=0;
4 | }
5 |
6 | server {
7 | listen 80;
8 | server_name demo-ansible.pedroalonso.net;
9 |
10 | root {{ app_current_path }}/public;
11 |
12 | try_files $uri/index.html $uri @app;
13 |
14 | location /sidekiq {
15 | proxy_set_header X-Script-Name http://app/sidekiq;
16 | proxy_pass http://app/sidekiq;
17 |
18 | proxy_set_header Host $host;
19 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
20 | proxy_set_header X-Scheme $scheme;
21 | proxy_set_header X-Real-IP $remote_addr;
22 | proxy_redirect off;
23 | }
24 |
25 | location @app {
26 | proxy_pass http://app;
27 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
28 | proxy_set_header Host $http_host;
29 | proxy_set_header X-Real-IP $remote_addr;
30 | proxy_redirect off;
31 | }
32 |
33 | error_page 500 502 503 504 /500.html;
34 | client_max_body_size 4G;
35 | keepalive_timeout 10;
36 | }
--------------------------------------------------------------------------------
/.ansible-deploy/templates/puma.service.j2:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Puma HTTP Server
3 | After=network.target
4 |
5 | [Service]
6 | Type=simple
7 | User={{ deploy_user }}
8 | EnvironmentFile={{ app_root_path }}/.rbenv-vars
9 |
10 | WorkingDirectory={{ app_current_path }}
11 |
12 | ExecStart={{ rbenv_bundle }} exec puma -C {{ app_current_path }}/config/puma.rb
13 | ExecStop={{ rbenv_bundle }} exec puma -S {{ app_current_path }}/config/puma.rb
14 | PIDFile={{ app_pids_path }}/puma.pid
15 |
16 | # Should systemd restart puma?
17 | # Use "no" (the default) to ensure no interference when using
18 | # stop/start/restart via `pumactl`. The "on-failure" setting might
19 | # work better for this purpose, but you must test it.
20 | # Use "always" if only `systemctl` is used for start/stop/restart, and
21 | # reconsider if you actually need the forking config.
22 | Restart=always
23 |
24 | [Install]
25 | WantedBy=multi-user.target
26 |
27 |
--------------------------------------------------------------------------------
/.ansible-deploy/templates/sidekiq.service.j2:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Sidekiq
3 | After=network.target
4 |
5 | [Service]
6 | Type=notify
7 | User={{ deploy_user }}
8 |
9 | EnvironmentFile={{ app_root_path }}/.rbenv-vars
10 |
11 | WorkingDirectory={{ app_current_path }}
12 |
13 | ExecStart={{ rbenv_bundle }} exec sidekiq -e production -C config/sidekiq.yml
14 |
15 | # Greatly reduce Ruby memory fragmentation and heap usage
16 | # https://www.mikeperham.com/2018/04/25/taming-rails-memory-bloat/
17 | Environment=MALLOC_ARENA_MAX=2
18 |
19 | # if we crash, restart
20 | RestartSec=1
21 | Restart=on-failure
22 |
23 | [Install]
24 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | defaults
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2 |
3 | # Mark the database schema as having been generated.
4 | db/schema.rb linguist-generated
5 |
6 | # Mark the yarn lockfile as having been generated.
7 | yarn.lock linguist-generated
8 |
9 | # Mark any vendored files as having been vendored.
10 | vendor/* linguist-vendored
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 | /db/*.sqlite3-*
13 |
14 | # Ignore all logfiles and tempfiles.
15 | /log/*
16 | /tmp/*
17 | !/log/.keep
18 | !/tmp/.keep
19 |
20 | # Ignore pidfiles, but keep the directory.
21 | /tmp/pids/*
22 | !/tmp/pids/
23 | !/tmp/pids/.keep
24 |
25 | # Ignore uploaded files in development.
26 | /storage/*
27 | !/storage/.keep
28 |
29 | /public/assets
30 | .byebug_history
31 |
32 | # Ignore master key for decrypting credentials and more.
33 | /config/master.key
34 |
35 | /public/packs
36 | /public/packs-test
37 | /node_modules
38 | /yarn-error.log
39 | yarn-debug.log*
40 | .yarn-integrity
41 |
42 | # Ignore Ansible secrets
43 | .ansible-deploy/.vault_pass
44 | .ansible-deploy/group_vars/all/vault.yml
45 |
46 | .DS_Store
47 | .ansible-deploy/.DS_Store
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.7.2
2 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3 |
4 | ruby '2.7.2'
5 |
6 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7 | gem 'rails', '~> 6.1.0'
8 | # Use sqlite3 as the database for Active Record
9 | gem 'sqlite3', '~> 1.4'
10 | # Use Puma as the app server
11 | gem 'puma', '~> 5.0'
12 | # Use SCSS for stylesheets
13 | gem 'sass-rails', '>= 6'
14 | # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
15 | gem 'webpacker', '~> 5.0'
16 | # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
17 | gem 'turbolinks', '~> 5'
18 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
19 | gem 'jbuilder', '~> 2.7'
20 | # Use Redis adapter to run Action Cable in production
21 | # gem 'redis', '~> 4.0'
22 | # Use Active Model has_secure_password
23 | # gem 'bcrypt', '~> 3.1.7'
24 | gem 'sidekiq'
25 |
26 | # Use Active Storage variant
27 | # gem 'image_processing', '~> 1.2'
28 |
29 | # Reduces boot times through caching; required in config/boot.rb
30 | # gem 'bootsnap', require: false
31 |
32 | group :development, :test do
33 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console
34 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
35 | end
36 |
37 | group :development do
38 | # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
39 | gem 'web-console', '>= 4.1.0'
40 | # Display performance information such as SQL time and flame graphs for each request in your browser.
41 | # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md
42 | gem 'rack-mini-profiler', '~> 2.0'
43 | gem 'listen', '~> 3.3'
44 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
45 | gem 'spring'
46 | end
47 |
48 | group :test do
49 | # Adds support for Capybara system testing and selenium driver
50 | gem 'capybara', '>= 3.26'
51 | gem 'selenium-webdriver'
52 | # Easy installation and use of web drivers to run system tests with browsers
53 | gem 'webdrivers'
54 | end
55 |
56 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
57 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
58 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | actioncable (6.1.1)
5 | actionpack (= 6.1.1)
6 | activesupport (= 6.1.1)
7 | nio4r (~> 2.0)
8 | websocket-driver (>= 0.6.1)
9 | actionmailbox (6.1.1)
10 | actionpack (= 6.1.1)
11 | activejob (= 6.1.1)
12 | activerecord (= 6.1.1)
13 | activestorage (= 6.1.1)
14 | activesupport (= 6.1.1)
15 | mail (>= 2.7.1)
16 | actionmailer (6.1.1)
17 | actionpack (= 6.1.1)
18 | actionview (= 6.1.1)
19 | activejob (= 6.1.1)
20 | activesupport (= 6.1.1)
21 | mail (~> 2.5, >= 2.5.4)
22 | rails-dom-testing (~> 2.0)
23 | actionpack (6.1.1)
24 | actionview (= 6.1.1)
25 | activesupport (= 6.1.1)
26 | rack (~> 2.0, >= 2.0.9)
27 | rack-test (>= 0.6.3)
28 | rails-dom-testing (~> 2.0)
29 | rails-html-sanitizer (~> 1.0, >= 1.2.0)
30 | actiontext (6.1.1)
31 | actionpack (= 6.1.1)
32 | activerecord (= 6.1.1)
33 | activestorage (= 6.1.1)
34 | activesupport (= 6.1.1)
35 | nokogiri (>= 1.8.5)
36 | actionview (6.1.1)
37 | activesupport (= 6.1.1)
38 | builder (~> 3.1)
39 | erubi (~> 1.4)
40 | rails-dom-testing (~> 2.0)
41 | rails-html-sanitizer (~> 1.1, >= 1.2.0)
42 | activejob (6.1.1)
43 | activesupport (= 6.1.1)
44 | globalid (>= 0.3.6)
45 | activemodel (6.1.1)
46 | activesupport (= 6.1.1)
47 | activerecord (6.1.1)
48 | activemodel (= 6.1.1)
49 | activesupport (= 6.1.1)
50 | activestorage (6.1.1)
51 | actionpack (= 6.1.1)
52 | activejob (= 6.1.1)
53 | activerecord (= 6.1.1)
54 | activesupport (= 6.1.1)
55 | marcel (~> 0.3.1)
56 | mimemagic (~> 0.3.2)
57 | activesupport (6.1.1)
58 | concurrent-ruby (~> 1.0, >= 1.0.2)
59 | i18n (>= 1.6, < 2)
60 | minitest (>= 5.1)
61 | tzinfo (~> 2.0)
62 | zeitwerk (~> 2.3)
63 | addressable (2.7.0)
64 | public_suffix (>= 2.0.2, < 5.0)
65 | bindex (0.8.1)
66 | builder (3.2.4)
67 | byebug (11.1.3)
68 | capybara (3.35.1)
69 | addressable
70 | mini_mime (>= 0.1.3)
71 | nokogiri (~> 1.8)
72 | rack (>= 1.6.0)
73 | rack-test (>= 0.6.3)
74 | regexp_parser (>= 1.5, < 3.0)
75 | xpath (~> 3.2)
76 | childprocess (3.0.0)
77 | concurrent-ruby (1.1.8)
78 | connection_pool (2.2.3)
79 | crass (1.0.6)
80 | erubi (1.10.0)
81 | ffi (1.14.2)
82 | globalid (0.4.2)
83 | activesupport (>= 4.2.0)
84 | i18n (1.8.7)
85 | concurrent-ruby (~> 1.0)
86 | jbuilder (2.11.2)
87 | activesupport (>= 5.0.0)
88 | listen (3.4.1)
89 | rb-fsevent (~> 0.10, >= 0.10.3)
90 | rb-inotify (~> 0.9, >= 0.9.10)
91 | loofah (2.9.0)
92 | crass (~> 1.0.2)
93 | nokogiri (>= 1.5.9)
94 | mail (2.7.1)
95 | mini_mime (>= 0.1.1)
96 | marcel (0.3.3)
97 | mimemagic (~> 0.3.2)
98 | method_source (1.0.0)
99 | mimemagic (0.3.5)
100 | mini_mime (1.0.2)
101 | mini_portile2 (2.5.0)
102 | minitest (5.14.3)
103 | nio4r (2.5.4)
104 | nokogiri (1.11.1)
105 | mini_portile2 (~> 2.5.0)
106 | racc (~> 1.4)
107 | nokogiri (1.11.1-x86_64-darwin)
108 | racc (~> 1.4)
109 | public_suffix (4.0.6)
110 | puma (5.2.0)
111 | nio4r (~> 2.0)
112 | racc (1.5.2)
113 | rack (2.2.3)
114 | rack-mini-profiler (2.3.0)
115 | rack (>= 1.2.0)
116 | rack-proxy (0.6.5)
117 | rack
118 | rack-test (1.1.0)
119 | rack (>= 1.0, < 3)
120 | rails (6.1.1)
121 | actioncable (= 6.1.1)
122 | actionmailbox (= 6.1.1)
123 | actionmailer (= 6.1.1)
124 | actionpack (= 6.1.1)
125 | actiontext (= 6.1.1)
126 | actionview (= 6.1.1)
127 | activejob (= 6.1.1)
128 | activemodel (= 6.1.1)
129 | activerecord (= 6.1.1)
130 | activestorage (= 6.1.1)
131 | activesupport (= 6.1.1)
132 | bundler (>= 1.15.0)
133 | railties (= 6.1.1)
134 | sprockets-rails (>= 2.0.0)
135 | rails-dom-testing (2.0.3)
136 | activesupport (>= 4.2.0)
137 | nokogiri (>= 1.6)
138 | rails-html-sanitizer (1.3.0)
139 | loofah (~> 2.3)
140 | railties (6.1.1)
141 | actionpack (= 6.1.1)
142 | activesupport (= 6.1.1)
143 | method_source
144 | rake (>= 0.8.7)
145 | thor (~> 1.0)
146 | rake (13.0.3)
147 | rb-fsevent (0.10.4)
148 | rb-inotify (0.10.1)
149 | ffi (~> 1.0)
150 | redis (4.2.5)
151 | regexp_parser (2.0.3)
152 | rubyzip (2.3.0)
153 | sass-rails (6.0.0)
154 | sassc-rails (~> 2.1, >= 2.1.1)
155 | sassc (2.4.0)
156 | ffi (~> 1.9)
157 | sassc-rails (2.1.2)
158 | railties (>= 4.0.0)
159 | sassc (>= 2.0)
160 | sprockets (> 3.0)
161 | sprockets-rails
162 | tilt
163 | selenium-webdriver (3.142.7)
164 | childprocess (>= 0.5, < 4.0)
165 | rubyzip (>= 1.2.2)
166 | semantic_range (2.3.1)
167 | sidekiq (6.1.2)
168 | connection_pool (>= 2.2.2)
169 | rack (~> 2.0)
170 | redis (>= 4.2.0)
171 | spring (2.1.1)
172 | sprockets (4.0.2)
173 | concurrent-ruby (~> 1.0)
174 | rack (> 1, < 3)
175 | sprockets-rails (3.2.2)
176 | actionpack (>= 4.0)
177 | activesupport (>= 4.0)
178 | sprockets (>= 3.0.0)
179 | sqlite3 (1.4.2)
180 | thor (1.1.0)
181 | tilt (2.0.10)
182 | turbolinks (5.2.1)
183 | turbolinks-source (~> 5.2)
184 | turbolinks-source (5.2.0)
185 | tzinfo (2.0.4)
186 | concurrent-ruby (~> 1.0)
187 | web-console (4.1.0)
188 | actionview (>= 6.0.0)
189 | activemodel (>= 6.0.0)
190 | bindex (>= 0.4.0)
191 | railties (>= 6.0.0)
192 | webdrivers (4.5.0)
193 | nokogiri (~> 1.6)
194 | rubyzip (>= 1.3.0)
195 | selenium-webdriver (>= 3.0, < 4.0)
196 | webpacker (5.2.1)
197 | activesupport (>= 5.2)
198 | rack-proxy (>= 0.6.1)
199 | railties (>= 5.2)
200 | semantic_range (>= 2.3.0)
201 | websocket-driver (0.7.3)
202 | websocket-extensions (>= 0.1.0)
203 | websocket-extensions (0.1.5)
204 | xpath (3.2.0)
205 | nokogiri (~> 1.8)
206 | zeitwerk (2.4.2)
207 |
208 | PLATFORMS
209 | aarch64-linux
210 | x86_64-darwin-20
211 |
212 | DEPENDENCIES
213 | byebug
214 | capybara (>= 3.26)
215 | jbuilder (~> 2.7)
216 | listen (~> 3.3)
217 | puma (~> 5.0)
218 | rack-mini-profiler (~> 2.0)
219 | rails (~> 6.1.0)
220 | sass-rails (>= 6)
221 | selenium-webdriver
222 | sidekiq
223 | spring
224 | sqlite3 (~> 1.4)
225 | turbolinks (~> 5)
226 | tzinfo-data
227 | web-console (>= 4.1.0)
228 | webdrivers
229 | webpacker (~> 5.0)
230 |
231 | RUBY VERSION
232 | ruby 2.7.2p137
233 |
234 | BUNDLED WITH
235 | 2.2.4
236 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Automate Rails Provision and Deployment using Ansible
2 |
3 | You can find a more in-depth [**Blog Post Here**](https://www.pedroalonso.net/blog/automate-rails-provision-and-deployment-using-ansible)
4 |
5 | This is a sample Rails 6.1 app with 2 Ansible Playbooks, inside `.ansible-deploy` folder. Provision playbook is used to easily provision an **Ubuntu 20.04 Server**, there's another playbook for deployment and rollback your Rails app using Ansistrano.
6 |
7 | While this is meant to work out of the box, you can tweak the files in the `roles` directory in order to satisfy your project-specific requirements.
8 |
9 | ---
10 |
11 | ### What does this do?
12 | * Configure Ubuntu 20.04 Server with some sensible defaults.
13 | * Install required/useful packages. You can [**update this list here**](https://github.com/pedropaf/rails-ansible-provision-deployment/blob/bb402ad2777dc6cf9d4e7225fb85cd0eafb2a3a1/.ansible-deploy/app-vars.yml#L53-L75).
14 | * Auto upgrade all installed packages
15 | * Create a new deployment user (called 'deploy') with passwordless login
16 | * SSH hardening
17 | * Prevent password login
18 | * Change the default SSH port
19 | * Prevent root login
20 | * Setup UFW (firewall)
21 | * Setup Fail2ban
22 | * Install Logrotate
23 | * Setup Nginx with some sensible config (thanks to nginxconfig.io)
24 | * Certbot, for Let's encrypt SSL certificates.
25 | * Ruby (using Rbenv).
26 | * Defaults to `2.7.2`. You can change it in the [`app-vars.yml`](https://github.com/pedropaf/rails-ansible-provision-deployment/blob/bb402ad2777dc6cf9d4e7225fb85cd0eafb2a3a1/.ansible-deploy/app-vars.yml#L78) file
27 | * [jemmaloc](https://github.com/jemalloc/jemalloc) is also installed and configured by default
28 | * [rbenv-vars](https://github.com/rbenv/rbenv-vars) is also installed by default
29 | * Node.js
30 | * Defaults to 15.x. You can change it in the [`app-vars.yml`](https://github.com/pedropaf/rails-ansible-provision-deployment/blob/bb402ad2777dc6cf9d4e7225fb85cd0eafb2a3a1/.ansible-deploy/app-vars.yml#L88) file.
31 | * Yarn
32 | * Redis (latest)
33 | * Postgresql.
34 | * Defaults to v13. You can specify the version that you need in the `app-vars.yml` file.
35 | * Puma (with Systemd support for restarting automatically) **See Puma Config section below**.
36 | * Sidekiq (with Systemd support for restarting automatically)
37 | * Ansistrano hooks for performing the following tasks -
38 | * Installing all our gems
39 | * Precompiling assets
40 | * Migrating our database (using `run_once`)
41 |
42 | ---
43 |
44 | ## Getting started
45 | Here are the steps that you need to follow in order to get up and running with Ansible Rails.
46 |
47 | ### Step 1. Installation
48 |
49 | You can just copy the `.ansible-deploy` folder in your Rails application folder, or clone this repo.
50 |
51 | ### Step 2. Storing sensitive data for Ansible
52 | As mentioned earlier, we have one Ansible Playbook to setup the serve, so the secret variables that are needed to setup the server, are stored in an Ansible Vault. The secrets related to the Rails app, should be stored using [Custom Credentials](https://edgeguides.rubyonrails.org/security.html#custom-credentials).
53 |
54 | To create a new `Ansible Vault`(https://docs.ansible.com/ansible/latest/user_guide/vault.html) file to store sensitive information:
55 |
56 | ```bash
57 | $ ansible-vault create .ansible-deploy/group_vars/all/vault.yml
58 | ```
59 |
60 | Add the following information to this new vault file
61 | ```yaml
62 | vault_postgresql_db_password: "XXXXX_SUPER_SECURE_PASS_XXXXX"
63 | vault_rails_master_key: "XXXXX_MASTER_KEY_FOR_RAILS_XXXXX"
64 | ```
65 |
66 | ### Step 3. Configuration
67 | Configure the relevant variables in `app-vars.yml`.
68 |
69 | ```yaml
70 | app_name: YOUR_APP_NAME # Replace with name of your app
71 | app_git_repo: "YOUR_GIT_REPO"
72 | app_git_branch: "main" # branch that you want to deploy (e.g: 'production')
73 |
74 | postgresql_db_user: "{{ deploy_user }}_postgresql_user"
75 | postgresql_db_password: "{{ vault_postgresql_db_password }}" # from vault (see previous section)
76 | postgresql_db_name: "{{ app_name }}_production"
77 | ```
78 |
79 | ### Step 4. Server Provisioning
80 |
81 | If you have booted up a clean Ubuntu Server, you can install all the dependencies for your Rails application running:
82 |
83 | ```bash
84 | $ cd .ansible-deploy
85 | $ ansible-playbook -i inventories/development.ini provision.yml
86 | ```
87 |
88 | In Ansible, an inventory is called the list of server(s) where you want to run your playbook. If you want to use a different staging / production servers, you can have 2 inventory files one for each stage, called `staging.ini` / `production.ini`.
89 | To deploy this app to your production server, you can use [DigitalOcean](https://www.digitalocean.com), AWS or any other hosting provider of your preference.
90 |
91 | ```yaml
92 | [web]
93 | 192.168.0.1 # replace with IP address of your server.
94 |
95 | [all:vars]
96 | ansible_ssh_user=deployer
97 | ansible_python_interpreter=/usr/bin/python3
98 | ansible_ssh_private_key_file="~/.ssh/id_rsa"
99 | ```
100 |
101 | ### Step 5. Deploy your application
102 |
103 | After your server is setup (step 4), you can deploy your application running:
104 |
105 | ```bash
106 | $ cd .ansible-deploy
107 | $ ansible-playbook -i inventories/development.ini deploy.yml
108 | ```
109 |
110 | ## Additional Configuration
111 | ### Installing additional packages
112 | You can add/remove packages to this list by changing the `required_package` variable in `app-vars.yml`.
113 | ### Uncomplicated Firewall Configuration (UFW)
114 |
115 | Uncomplicated Firewall is enabled and accepting connections from any IP on ports 22 (ssh), 80 (http), and 443 (https). Feel free to update it in `app-vars.yml`.
116 | ### Configure Certbot (Let's Encrypt SSL certificates)
117 |
118 | Certboot is configured to request, install and set up a CRON job to update your certificate when it expires. Setup your domain DNS as well as the details for your domain / email to request the certificate in [`app-vars.yml`](https://github.com/pedropaf/rails-ansible-provision-deployment/blob/bb402ad2777dc6cf9d4e7225fb85cd0eafb2a3a1/.ansible-deploy/app-vars.yml#L103).
119 | ### PostgreSQL Database Backups
120 | By default, daily backup is enabled in the `app-vars.yml` file. In order for this to work, the following variables need to be set. If you do not wish to store backups, remove (or uncomment) these lines from `app-vars.yml`.
121 |
122 | ```yaml
123 | aws_key: "{{ vault_aws_key }}" # store this in group_vars/all/vault.yml that we created earlier
124 | aws_secret: "{{ vault_aws_secret }}"
125 |
126 | postgresql_backup_dir: "{{ deploy_user_path }}/backups"
127 | postgresql_backup_filename_format: >-
128 | {{ app_name }}-%Y%m%d-%H%M%S.pgdump
129 | postgresql_db_backup_healthcheck: "NOTIFICATION_URL (eg: https://healthcheck.io/)" # optional
130 | postgresql_s3_backup_bucket: "DB_BACKUP_BUCKET" # name of the S3 bucket to store backups
131 | postgresql_s3_backup_hour: "3"
132 | postgresql_s3_backup_minute: "*"
133 | postgresql_s3_backup_delete_after: "7 days" # days after which old backups should be deleted
134 | ```
135 |
136 | #### Puma config
137 |
138 | Update your [**config/puma.rb**](https://github.com/pedropaf/rails-ansible-provision-deployment/blob/main/config/puma.rb) with settings for production.
139 |
140 | ```ruby
141 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
142 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
143 | threads min_threads_count, max_threads_count
144 |
145 | port ENV.fetch("PORT") { 3000 }
146 |
147 | rails_env = ENV.fetch("RAILS_ENV") { "development" }
148 | environment rails_env
149 |
150 | if %w[production staging].member?(rails_env)
151 | app_dir = ENV.fetch("APP_DIR") { "YOUR_APP/current" }
152 | directory app_dir
153 |
154 | shared_dir = ENV.fetch("SHARED_DIR") { "YOUR_APP/shared" }
155 |
156 | # Logging
157 | stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
158 |
159 | pidfile "#{shared_dir}/tmp/pids/puma.pid"
160 | state_path "#{shared_dir}/tmp/pids/puma.state"
161 |
162 | # Set up socket location
163 | bind "unix://#{shared_dir}/sockets/puma.sock"
164 |
165 | workers ENV.fetch("WEB_CONCURRENCY") { 2 }
166 | preload_app!
167 |
168 | elsif rails_env == "development"
169 | # Specifies the `worker_timeout` threshold that Puma will use to wait before
170 | # terminating a worker in development environments.
171 | worker_timeout 3600
172 | plugin :tmp_restart
173 | end
174 | ```
175 |
176 | ---
177 |
178 | ### Credits
179 |
180 | These 2 repos were a useful inspiration and starting point:
181 |
182 | * [dresden-weekly/ansible-rails](https://github.com/dresden-weekly/ansible-rails)
183 | * [emailthis/ansible-rails](https://github.com/EmailThis/ansible-rails)
184 | ---
185 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative "config/application"
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | //= link_tree ../images
2 | //= link_directory ../stylesheets .css
3 |
--------------------------------------------------------------------------------
/app/assets/images/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/app/assets/images/.keep
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
6 | * vendor/assets/stylesheets directory can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10 | * files in this directory. Styles in this file should be added after the last require_* statement.
11 | * It is generally better to create a new file per style scope.
12 | *
13 | *= require_tree .
14 | *= require_self
15 | */
16 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/index.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the index controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: https://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/channels/application_cable/channel.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Channel < ActionCable::Channel::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/channels/application_cable/connection.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Connection < ActionCable::Connection::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | end
3 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/index_controller.rb:
--------------------------------------------------------------------------------
1 | class IndexController < ApplicationController
2 | def index
3 | HardWorker.perform_async('bob', 5)
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/index_helper.rb:
--------------------------------------------------------------------------------
1 | module IndexHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/javascript/channels/consumer.js:
--------------------------------------------------------------------------------
1 | // Action Cable provides the framework to deal with WebSockets in Rails.
2 | // You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
3 |
4 | import { createConsumer } from "@rails/actioncable"
5 |
6 | export default createConsumer()
7 |
--------------------------------------------------------------------------------
/app/javascript/channels/index.js:
--------------------------------------------------------------------------------
1 | // Load all the channels within this directory and all subdirectories.
2 | // Channel files must be named *_channel.js.
3 |
4 | const channels = require.context('.', true, /_channel\.js$/)
5 | channels.keys().forEach(channels)
6 |
--------------------------------------------------------------------------------
/app/javascript/packs/application.js:
--------------------------------------------------------------------------------
1 | // This file is automatically compiled by Webpack, along with any other files
2 | // present in this directory. You're encouraged to place your actual application logic in
3 | // a relevant structure within app/javascript and only use these pack files to reference
4 | // that code so it'll be compiled.
5 |
6 | import Rails from "@rails/ujs"
7 | import Turbolinks from "turbolinks"
8 | import * as ActiveStorage from "@rails/activestorage"
9 | import "channels"
10 |
11 | Rails.start()
12 | Turbolinks.start()
13 | ActiveStorage.start()
14 |
--------------------------------------------------------------------------------
/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | class ApplicationJob < ActiveJob::Base
2 | # Automatically retry jobs that encountered a deadlock
3 | # retry_on ActiveRecord::Deadlocked
4 |
5 | # Most jobs are safe to ignore if the underlying records are no longer available
6 | # discard_on ActiveJob::DeserializationError
7 | end
8 |
--------------------------------------------------------------------------------
/app/mailers/application_mailer.rb:
--------------------------------------------------------------------------------
1 | class ApplicationMailer < ActionMailer::Base
2 | default from: 'from@example.com'
3 | layout 'mailer'
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/views/index/index.html.erb:
--------------------------------------------------------------------------------
1 | Hello Rails!
--------------------------------------------------------------------------------
/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RailsAnsibleDeploy
5 |
6 | <%= csrf_meta_tags %>
7 | <%= csp_meta_tag %>
8 |
9 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
10 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
11 |
12 |
13 |
14 | <%= yield %>
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.text.erb:
--------------------------------------------------------------------------------
1 | <%= yield %>
2 |
--------------------------------------------------------------------------------
/app/workers/hard_worker.rb:
--------------------------------------------------------------------------------
1 | class HardWorker
2 | include Sidekiq::Worker
3 |
4 | def perform(*args)
5 | # Do something
6 | Rails.logger.info "Things are happening in worker."
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | var validEnv = ['development', 'test', 'production']
3 | var currentEnv = api.env()
4 | var isDevelopmentEnv = api.env('development')
5 | var isProductionEnv = api.env('production')
6 | var isTestEnv = api.env('test')
7 |
8 | if (!validEnv.includes(currentEnv)) {
9 | throw new Error(
10 | 'Please specify a valid `NODE_ENV` or ' +
11 | '`BABEL_ENV` environment variables. Valid values are "development", ' +
12 | '"test", and "production". Instead, received: ' +
13 | JSON.stringify(currentEnv) +
14 | '.'
15 | )
16 | }
17 |
18 | return {
19 | presets: [
20 | isTestEnv && [
21 | '@babel/preset-env',
22 | {
23 | targets: {
24 | node: 'current'
25 | }
26 | }
27 | ],
28 | (isProductionEnv || isDevelopmentEnv) && [
29 | '@babel/preset-env',
30 | {
31 | forceAllTransforms: true,
32 | useBuiltIns: 'entry',
33 | corejs: 3,
34 | modules: false,
35 | exclude: ['transform-typeof-symbol']
36 | }
37 | ]
38 | ].filter(Boolean),
39 | plugins: [
40 | 'babel-plugin-macros',
41 | '@babel/plugin-syntax-dynamic-import',
42 | isTestEnv && 'babel-plugin-dynamic-import-node',
43 | '@babel/plugin-transform-destructuring',
44 | [
45 | '@babel/plugin-proposal-class-properties',
46 | {
47 | loose: true
48 | }
49 | ],
50 | [
51 | '@babel/plugin-proposal-object-rest-spread',
52 | {
53 | useBuiltIns: true
54 | }
55 | ],
56 | [
57 | '@babel/plugin-transform-runtime',
58 | {
59 | helpers: false
60 | }
61 | ],
62 | [
63 | '@babel/plugin-transform-regenerator',
64 | {
65 | async: false
66 | }
67 | ]
68 | ].filter(Boolean)
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | #
5 | # This file was generated by Bundler.
6 | #
7 | # The application 'bundle' is installed as part of a gem, and
8 | # this file is here to facilitate running it.
9 | #
10 |
11 | require "rubygems"
12 |
13 | m = Module.new do
14 | module_function
15 |
16 | def invoked_as_script?
17 | File.expand_path($0) == File.expand_path(__FILE__)
18 | end
19 |
20 | def env_var_version
21 | ENV["BUNDLER_VERSION"]
22 | end
23 |
24 | def cli_arg_version
25 | return unless invoked_as_script? # don't want to hijack other binstubs
26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27 | bundler_version = nil
28 | update_index = nil
29 | ARGV.each_with_index do |a, i|
30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31 | bundler_version = a
32 | end
33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34 | bundler_version = $1
35 | update_index = i
36 | end
37 | bundler_version
38 | end
39 |
40 | def gemfile
41 | gemfile = ENV["BUNDLE_GEMFILE"]
42 | return gemfile if gemfile && !gemfile.empty?
43 |
44 | File.expand_path("../../Gemfile", __FILE__)
45 | end
46 |
47 | def lockfile
48 | lockfile =
49 | case File.basename(gemfile)
50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51 | else "#{gemfile}.lock"
52 | end
53 | File.expand_path(lockfile)
54 | end
55 |
56 | def lockfile_version
57 | return unless File.file?(lockfile)
58 | lockfile_contents = File.read(lockfile)
59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60 | Regexp.last_match(1)
61 | end
62 |
63 | def bundler_version
64 | @bundler_version ||=
65 | env_var_version || cli_arg_version ||
66 | lockfile_version
67 | end
68 |
69 | def bundler_requirement
70 | return "#{Gem::Requirement.default}.a" unless bundler_version
71 |
72 | bundler_gem_version = Gem::Version.new(bundler_version)
73 |
74 | requirement = bundler_gem_version.approximate_recommendation
75 |
76 | return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
77 |
78 | requirement += ".a" if bundler_gem_version.prerelease?
79 |
80 | requirement
81 | end
82 |
83 | def load_bundler!
84 | ENV["BUNDLE_GEMFILE"] ||= gemfile
85 |
86 | activate_bundler
87 | end
88 |
89 | def activate_bundler
90 | gem_error = activation_error_handling do
91 | gem "bundler", bundler_requirement
92 | end
93 | return if gem_error.nil?
94 | require_error = activation_error_handling do
95 | require "bundler/version"
96 | end
97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
99 | exit 42
100 | end
101 |
102 | def activation_error_handling
103 | yield
104 | nil
105 | rescue StandardError, LoadError => e
106 | e
107 | end
108 | end
109 |
110 | m.load_bundler!
111 |
112 | if m.invoked_as_script?
113 | load Gem.bin_path("bundler", "bundle")
114 | end
115 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | load File.expand_path("spring", __dir__)
3 | APP_PATH = File.expand_path('../config/application', __dir__)
4 | require_relative "../config/boot"
5 | require "rails/commands"
6 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | load File.expand_path("spring", __dir__)
3 | require_relative "../config/boot"
4 | require "rake"
5 | Rake.application.run
6 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require "fileutils"
3 |
4 | # path to your application root.
5 | APP_ROOT = File.expand_path('..', __dir__)
6 |
7 | def system!(*args)
8 | system(*args) || abort("\n== Command #{args} failed ==")
9 | end
10 |
11 | FileUtils.chdir APP_ROOT do
12 | # This script is a way to set up or update your development environment automatically.
13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14 | # Add necessary setup steps to this file.
15 |
16 | puts '== Installing dependencies =='
17 | system! 'gem install bundler --conservative'
18 | system('bundle check') || system!('bundle install')
19 |
20 | # Install JavaScript dependencies
21 | system! 'bin/yarn'
22 |
23 | # puts "\n== Copying sample files =="
24 | # unless File.exist?('config/database.yml')
25 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
26 | # end
27 |
28 | puts "\n== Preparing database =="
29 | system! 'bin/rails db:prepare'
30 |
31 | puts "\n== Removing old logs and tempfiles =="
32 | system! 'bin/rails log:clear tmp:clear'
33 |
34 | puts "\n== Restarting application server =="
35 | system! 'bin/rails restart'
36 | end
37 |
--------------------------------------------------------------------------------
/bin/spring:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
3 | # Load Spring without loading other gems in the Gemfile, for speed.
4 | require "bundler"
5 | Bundler.locked_gems.specs.find { |spec| spec.name == "spring" }&.tap do |spring|
6 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
7 | gem "spring", spring.version
8 | require "spring/binstub"
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/bin/webpack:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4 | ENV["NODE_ENV"] ||= "development"
5 |
6 | require "pathname"
7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8 | Pathname.new(__FILE__).realpath)
9 |
10 | require "bundler/setup"
11 |
12 | require "webpacker"
13 | require "webpacker/webpack_runner"
14 |
15 | APP_ROOT = File.expand_path("..", __dir__)
16 | Dir.chdir(APP_ROOT) do
17 | Webpacker::WebpackRunner.run(ARGV)
18 | end
19 |
--------------------------------------------------------------------------------
/bin/webpack-dev-server:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4 | ENV["NODE_ENV"] ||= "development"
5 |
6 | require "pathname"
7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
8 | Pathname.new(__FILE__).realpath)
9 |
10 | require "bundler/setup"
11 |
12 | require "webpacker"
13 | require "webpacker/dev_server_runner"
14 |
15 | APP_ROOT = File.expand_path("..", __dir__)
16 | Dir.chdir(APP_ROOT) do
17 | Webpacker::DevServerRunner.run(ARGV)
18 | end
19 |
--------------------------------------------------------------------------------
/bin/yarn:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 |
4 | APP_ROOT = File.expand_path('..', __dir__)
5 | Dir.chdir(APP_ROOT) do
6 | executable_path = ENV["PATH"].split(File::PATH_SEPARATOR).find do |path|
7 | normalized_path = File.expand_path(path)
8 |
9 | normalized_path != __dir__ && File.executable?(Pathname.new(normalized_path).join('yarn'))
10 | end
11 |
12 | if executable_path
13 | exec File.expand_path(Pathname.new(executable_path).join('yarn')), *ARGV
14 | else
15 | $stderr.puts "Yarn executable was not detected in the system."
16 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
17 | exit 1
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative "config/environment"
4 |
5 | run Rails.application
6 | Rails.application.load_server
7 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails/all"
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(*Rails.groups)
8 |
9 | module RailsAnsibleDeploy
10 | class Application < Rails::Application
11 | # Initialize configuration defaults for originally generated Rails version.
12 | config.load_defaults 6.1
13 |
14 | # Configuration for the application, engines, and railties goes here.
15 | #
16 | # These settings can be overridden in specific environments using the files
17 | # in config/environments, which are processed later.
18 | #
19 | # config.time_zone = "Central Time (US & Canada)"
20 | # config.eager_load_paths << Rails.root.join("extras")
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2 |
3 | require "bundler/setup" # Set up gems listed in the Gemfile.
4 | # require "bootsnap/setup" # Speed up boot time by caching expensive operations.
5 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: test
6 |
7 | production:
8 | adapter: redis
9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
10 | channel_prefix: rails_ansible_deploy_production
11 |
--------------------------------------------------------------------------------
/config/credentials.yml.enc:
--------------------------------------------------------------------------------
1 | rxelnRXV8jIOH39V8PoD7QU25b5GDf3JupyDZkv4p1FKljeQCrSOfwWxbc2IRywL1I31hWceoaQYtLXp0HLRRWnTrzJxg1d4GrJeKD/zIQG7POaZpGdz8mW8z4NFGuFMDpq+1MaCDLcQLJ0SzqlbkGwGH4pvqBHWgwvUlz2+2Ko8cbfYr8AxGCz5RY/9opspeoyXaTsDSWh2zPuYX5G1EMJb4kMFiQ52cmDV4CLI5cvvAr7S5rf5/Yf2zE8pKxSG0lG0IUDd27zJXDkNLv8fmsaz9cWipZFt1WolRGj/zPfu8TeslmFo+tcb8yCACwiHQKThf4n3LovgqbPzWTzzkLKVUitT3aENxjxOvjk5TC1QmWOPfzoyf+kIJpJRMj7P952NJ0+CWJev/VaMpLpPrFyPDg8FrAbLE9ec--jzRjCldfKsTfhiuv--8wKqrAyyj9S8bCFLQW6brA==
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite. Versions 3.8.0 and up are supported.
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: sqlite3
9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10 | timeout: 5000
11 |
12 | development:
13 | <<: *default
14 | database: db/development.sqlite3
15 |
16 | # Warning: The database defined as "test" will be erased and
17 | # re-generated from your development database when you run "rake".
18 | # Do not set this db to the same as development or production.
19 | test:
20 | <<: *default
21 | database: db/test.sqlite3
22 |
23 | production:
24 | <<: *default
25 | database: db/production.sqlite3
26 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
7 | Rails.logger = Logger.new(STDOUT)
8 | Rails.logger = ActiveSupport::Logger.new("log/#{Rails.env}.log")
9 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # In the development environment your application's code is reloaded any time
7 | # it changes. This slows down response time but is perfect for development
8 | # since you don't have to restart the web server when you make code changes.
9 | config.cache_classes = false
10 |
11 | # Do not eager load code on boot.
12 | config.eager_load = false
13 |
14 | # Show full error reports.
15 | config.consider_all_requests_local = true
16 |
17 | # Enable/disable caching. By default caching is disabled.
18 | # Run rails dev:cache to toggle caching.
19 | if Rails.root.join('tmp', 'caching-dev.txt').exist?
20 | config.action_controller.perform_caching = true
21 | config.action_controller.enable_fragment_cache_logging = true
22 |
23 | config.cache_store = :memory_store
24 | config.public_file_server.headers = {
25 | 'Cache-Control' => "public, max-age=#{2.days.to_i}"
26 | }
27 | else
28 | config.action_controller.perform_caching = false
29 |
30 | config.cache_store = :null_store
31 | end
32 |
33 | # Store uploaded files on the local file system (see config/storage.yml for options).
34 | config.active_storage.service = :local
35 |
36 | # Don't care if the mailer can't send.
37 | config.action_mailer.raise_delivery_errors = false
38 |
39 | config.action_mailer.perform_caching = false
40 |
41 | # Print deprecation notices to the Rails logger.
42 | config.active_support.deprecation = :log
43 |
44 | # Raise exceptions for disallowed deprecations.
45 | config.active_support.disallowed_deprecation = :raise
46 |
47 | # Tell Active Support which deprecation messages to disallow.
48 | config.active_support.disallowed_deprecation_warnings = []
49 |
50 | # Raise an error on page load if there are pending migrations.
51 | config.active_record.migration_error = :page_load
52 |
53 | # Highlight code that triggered database queries in logs.
54 | config.active_record.verbose_query_logs = true
55 |
56 | # Debug mode disables concatenation and preprocessing of assets.
57 | # This option may cause significant delays in view rendering with a large
58 | # number of complex assets.
59 | config.assets.debug = true
60 |
61 | # Suppress logger output for asset requests.
62 | config.assets.quiet = true
63 |
64 | # Raises error for missing translations.
65 | # config.i18n.raise_on_missing_translations = true
66 |
67 | # Annotate rendered view with file names.
68 | # config.action_view.annotate_rendered_view_with_filenames = true
69 |
70 | # Use an evented file watcher to asynchronously detect changes in source code,
71 | # routes, locales, etc. This feature depends on the listen gem.
72 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker
73 |
74 | # Uncomment if you wish to allow Action Cable access from any origin.
75 | # config.action_cable.disable_request_forgery_protection = true
76 | end
77 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # Code is not reloaded between requests.
7 | config.cache_classes = true
8 |
9 | # Eager load code on boot. This eager loads most of Rails and
10 | # your application in memory, allowing both threaded web servers
11 | # and those relying on copy on write to perform better.
12 | # Rake tasks automatically ignore this option for performance.
13 | config.eager_load = true
14 |
15 | # Full error reports are disabled and caching is turned on.
16 | config.consider_all_requests_local = false
17 | config.action_controller.perform_caching = true
18 |
19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
21 | # config.require_master_key = true
22 |
23 | # Disable serving static files from the `/public` folder by default since
24 | # Apache or NGINX already handles this.
25 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
26 |
27 | # Compress CSS using a preprocessor.
28 | # config.assets.css_compressor = :sass
29 |
30 | # Do not fallback to assets pipeline if a precompiled asset is missed.
31 | config.assets.compile = false
32 |
33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
34 | # config.asset_host = 'http://assets.example.com'
35 |
36 | # Specifies the header that your server uses for sending files.
37 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
38 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
39 |
40 | # Store uploaded files on the local file system (see config/storage.yml for options).
41 | config.active_storage.service = :local
42 |
43 | # Mount Action Cable outside main process or domain.
44 | # config.action_cable.mount_path = nil
45 | # config.action_cable.url = 'wss://example.com/cable'
46 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
47 |
48 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
49 | # config.force_ssl = true
50 |
51 | # Include generic and useful information about system operation, but avoid logging too much
52 | # information to avoid inadvertent exposure of personally identifiable information (PII).
53 | config.log_level = :info
54 |
55 | # Prepend all log lines with the following tags.
56 | config.log_tags = [ :request_id ]
57 |
58 | # Use a different cache store in production.
59 | # config.cache_store = :mem_cache_store
60 |
61 | # Use a real queuing backend for Active Job (and separate queues per environment).
62 | # config.active_job.queue_adapter = :resque
63 | # config.active_job.queue_name_prefix = "rails_ansible_deploy_production"
64 |
65 | config.action_mailer.perform_caching = false
66 |
67 | # Ignore bad email addresses and do not raise email delivery errors.
68 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
69 | # config.action_mailer.raise_delivery_errors = false
70 |
71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
72 | # the I18n.default_locale when a translation cannot be found).
73 | config.i18n.fallbacks = true
74 |
75 | # Send deprecation notices to registered listeners.
76 | config.active_support.deprecation = :notify
77 |
78 | # Log disallowed deprecations.
79 | config.active_support.disallowed_deprecation = :log
80 |
81 | # Tell Active Support which deprecation messages to disallow.
82 | config.active_support.disallowed_deprecation_warnings = []
83 |
84 | # Use default logging formatter so that PID and timestamp are not suppressed.
85 | config.log_formatter = ::Logger::Formatter.new
86 |
87 | # Use a different logger for distributed setups.
88 | # require "syslog/logger"
89 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
90 |
91 | if ENV["RAILS_LOG_TO_STDOUT"].present?
92 | logger = ActiveSupport::Logger.new(STDOUT)
93 | logger.formatter = config.log_formatter
94 | config.logger = ActiveSupport::TaggedLogging.new(logger)
95 | end
96 |
97 | # Do not dump schema after migrations.
98 | config.active_record.dump_schema_after_migration = false
99 |
100 | # Inserts middleware to perform automatic connection switching.
101 | # The `database_selector` hash is used to pass options to the DatabaseSelector
102 | # middleware. The `delay` is used to determine how long to wait after a write
103 | # to send a subsequent read to the primary.
104 | #
105 | # The `database_resolver` class is used by the middleware to determine which
106 | # database is appropriate to use based on the time delay.
107 | #
108 | # The `database_resolver_context` class is used by the middleware to set
109 | # timestamps for the last write to the primary. The resolver uses the context
110 | # class timestamps to determine how long to wait before reading from the
111 | # replica.
112 | #
113 | # By default Rails will store a last write timestamp in the session. The
114 | # DatabaseSelector middleware is designed as such you can define your own
115 | # strategy for connection switching and pass that into the middleware through
116 | # these configuration options.
117 | # config.active_record.database_selector = { delay: 2.seconds }
118 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
119 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
120 | end
121 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | # The test environment is used exclusively to run your application's
4 | # test suite. You never need to work with it otherwise. Remember that
5 | # your test database is "scratch space" for the test suite and is wiped
6 | # and recreated between test runs. Don't rely on the data there!
7 |
8 | Rails.application.configure do
9 | # Settings specified here will take precedence over those in config/application.rb.
10 |
11 | config.cache_classes = false
12 | config.action_view.cache_template_loading = true
13 |
14 | # Do not eager load code on boot. This avoids loading your whole application
15 | # just for the purpose of running a single test. If you are using a tool that
16 | # preloads Rails for running tests, you may have to set it to true.
17 | config.eager_load = false
18 |
19 | # Configure public file server for tests with Cache-Control for performance.
20 | config.public_file_server.enabled = true
21 | config.public_file_server.headers = {
22 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
23 | }
24 |
25 | # Show full error reports and disable caching.
26 | config.consider_all_requests_local = true
27 | config.action_controller.perform_caching = false
28 | config.cache_store = :null_store
29 |
30 | # Raise exceptions instead of rendering exception templates.
31 | config.action_dispatch.show_exceptions = false
32 |
33 | # Disable request forgery protection in test environment.
34 | config.action_controller.allow_forgery_protection = false
35 |
36 | # Store uploaded files on the local file system in a temporary directory.
37 | config.active_storage.service = :test
38 |
39 | config.action_mailer.perform_caching = false
40 |
41 | # Tell Action Mailer not to deliver emails to the real world.
42 | # The :test delivery method accumulates sent emails in the
43 | # ActionMailer::Base.deliveries array.
44 | config.action_mailer.delivery_method = :test
45 |
46 | # Print deprecation notices to the stderr.
47 | config.active_support.deprecation = :stderr
48 |
49 | # Raise exceptions for disallowed deprecations.
50 | config.active_support.disallowed_deprecation = :raise
51 |
52 | # Tell Active Support which deprecation messages to disallow.
53 | config.active_support.disallowed_deprecation_warnings = []
54 |
55 | # Raises error for missing translations.
56 | # config.i18n.raise_on_missing_translations = true
57 |
58 | # Annotate rendered view with file names.
59 | # config.action_view.annotate_rendered_view_with_filenames = true
60 | end
61 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ActiveSupport::Reloader.to_prepare do
4 | # ApplicationController.renderer.defaults.merge!(
5 | # http_host: 'example.org',
6 | # https: false
7 | # )
8 | # end
9 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 | # Add Yarn node_modules folder to the asset load path.
9 | Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 |
11 | # Precompile additional assets.
12 | # application.js, application.css, and all non-JS/CSS in the app/assets
13 | # folder are already added.
14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
9 |
--------------------------------------------------------------------------------
/config/initializers/content_security_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide content security policy
4 | # For further information see the following documentation
5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
6 |
7 | # Rails.application.config.content_security_policy do |policy|
8 | # policy.default_src :self, :https
9 | # policy.font_src :self, :https, :data
10 | # policy.img_src :self, :https, :data
11 | # policy.object_src :none
12 | # policy.script_src :self, :https
13 | # policy.style_src :self, :https
14 | # # If you are using webpack-dev-server then specify webpack-dev-server host
15 | # policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
16 |
17 | # # Specify URI for violation reports
18 | # # policy.report_uri "/csp-violation-report-endpoint"
19 | # end
20 |
21 | # If you are using UJS then enable automatic nonce generation
22 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
23 |
24 | # Set the nonce only to specific directives
25 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
26 |
27 | # Report CSP violations to a specified URI
28 | # For further information see the following documentation:
29 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
30 | # Rails.application.config.content_security_policy_report_only = true
31 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :json
6 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [
5 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
6 | ]
7 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # Define an application-wide HTTP permissions policy. For further
2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy
3 | #
4 | # Rails.application.config.permissions_policy do |f|
5 | # f.camera :none
6 | # f.gyroscope :none
7 | # f.microphone :none
8 | # f.usb :none
9 | # f.fullscreen :self
10 | # f.payment :self, "https://secure.example.com"
11 | # end
12 |
--------------------------------------------------------------------------------
/config/initializers/sidekiq.rb:
--------------------------------------------------------------------------------
1 | Rails.logger = Sidekiq.logger
2 | ActiveRecord::Base.logger = Sidekiq.logger
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # The following keys must be escaped otherwise they will not be retrieved by
20 | # the default I18n backend:
21 | #
22 | # true, false, on, off, yes, no
23 | #
24 | # Instead, surround them with single quotes.
25 | #
26 | # en:
27 | # 'true': 'foo'
28 | #
29 | # To learn more, please read the Rails Internationalization guide
30 | # available at https://guides.rubyonrails.org/i18n.html.
31 |
32 | en:
33 | hello: "Hello world"
34 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers: a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum; this matches the default thread size of Active Record.
6 | #
7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
9 | threads min_threads_count, max_threads_count
10 |
11 | port ENV.fetch("PORT") { 3000 }
12 |
13 | rails_env = ENV.fetch("RAILS_ENV") { "development" }
14 | environment rails_env
15 |
16 | if %w[production staging].member?(rails_env)
17 | app_dir = ENV.fetch("APP_DIR") { "YOUR_APP/current" }
18 | directory app_dir
19 |
20 | shared_dir = ENV.fetch("SHARED_DIR") { "YOUR_APP/shared" }
21 |
22 | # Logging
23 | stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
24 |
25 | pidfile "#{shared_dir}/tmp/pids/puma.pid"
26 | state_path "#{shared_dir}/tmp/pids/puma.state"
27 |
28 | # Set up socket location
29 | bind "unix://#{shared_dir}/sockets/puma.sock"
30 |
31 | workers ENV.fetch("WEB_CONCURRENCY") { 2 }
32 | preload_app!
33 |
34 | elsif rails_env == "development"
35 | # Specifies the `worker_timeout` threshold that Puma will use to wait before
36 | # terminating a worker in development environments.
37 | worker_timeout 3600
38 | plugin :tmp_restart
39 | end
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | root 'index#index'
3 |
4 | require 'sidekiq/web'
5 | mount Sidekiq::Web => '/sidekiq'
6 | end
7 |
--------------------------------------------------------------------------------
/config/sidekiq.yml:
--------------------------------------------------------------------------------
1 | ---
2 | :concurrency: 5
3 | staging:
4 | :concurrency: 10
5 | production:
6 | :concurrency: 10
7 | :queues:
8 | - critical
9 | - default
10 | - low
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | Spring.watch(
2 | ".ruby-version",
3 | ".rbenv-vars",
4 | "tmp/restart.txt",
5 | "tmp/caching-dev.txt"
6 | )
7 |
--------------------------------------------------------------------------------
/config/storage.yml:
--------------------------------------------------------------------------------
1 | test:
2 | service: Disk
3 | root: <%= Rails.root.join("tmp/storage") %>
4 |
5 | local:
6 | service: Disk
7 | root: <%= Rails.root.join("storage") %>
8 |
9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
10 | # amazon:
11 | # service: S3
12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
14 | # region: us-east-1
15 | # bucket: your_own_bucket
16 |
17 | # Remember not to checkin your GCS keyfile to a repository
18 | # google:
19 | # service: GCS
20 | # project: your_project
21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
22 | # bucket: your_own_bucket
23 |
24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
25 | # microsoft:
26 | # service: AzureStorage
27 | # storage_account_name: your_account_name
28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
29 | # container: your_container_name
30 |
31 | # mirror:
32 | # service: Mirror
33 | # primary: local
34 | # mirrors: [ amazon, google, microsoft ]
35 |
--------------------------------------------------------------------------------
/config/webpack/development.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2 |
3 | const environment = require('./environment')
4 |
5 | module.exports = environment.toWebpackConfig()
6 |
--------------------------------------------------------------------------------
/config/webpack/environment.js:
--------------------------------------------------------------------------------
1 | const { environment } = require('@rails/webpacker')
2 |
3 | module.exports = environment
4 |
--------------------------------------------------------------------------------
/config/webpack/production.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production'
2 |
3 | const environment = require('./environment')
4 |
5 | module.exports = environment.toWebpackConfig()
6 |
--------------------------------------------------------------------------------
/config/webpack/test.js:
--------------------------------------------------------------------------------
1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2 |
3 | const environment = require('./environment')
4 |
5 | module.exports = environment.toWebpackConfig()
6 |
--------------------------------------------------------------------------------
/config/webpacker.yml:
--------------------------------------------------------------------------------
1 | # Note: You must restart bin/webpack-dev-server for changes to take effect
2 |
3 | default: &default
4 | source_path: app/javascript
5 | source_entry_path: packs
6 | public_root_path: public
7 | public_output_path: packs
8 | cache_path: tmp/cache/webpacker
9 | webpack_compile_output: true
10 |
11 | # Additional paths webpack should lookup modules
12 | # ['app/assets', 'engine/foo/app/assets']
13 | additional_paths: []
14 |
15 | # Reload manifest.json on all requests so we reload latest compiled packs
16 | cache_manifest: false
17 |
18 | # Extract and emit a css file
19 | extract_css: false
20 |
21 | static_assets_extensions:
22 | - .jpg
23 | - .jpeg
24 | - .png
25 | - .gif
26 | - .tiff
27 | - .ico
28 | - .svg
29 | - .eot
30 | - .otf
31 | - .ttf
32 | - .woff
33 | - .woff2
34 |
35 | extensions:
36 | - .mjs
37 | - .js
38 | - .sass
39 | - .scss
40 | - .css
41 | - .module.sass
42 | - .module.scss
43 | - .module.css
44 | - .png
45 | - .svg
46 | - .gif
47 | - .jpeg
48 | - .jpg
49 |
50 | development:
51 | <<: *default
52 | compile: true
53 |
54 | # Reference: https://webpack.js.org/configuration/dev-server/
55 | dev_server:
56 | https: false
57 | host: localhost
58 | port: 3035
59 | public: localhost:3035
60 | hmr: false
61 | # Inline should be set to true if using HMR
62 | inline: true
63 | overlay: true
64 | compress: true
65 | disable_host_check: true
66 | use_local_ip: false
67 | quiet: false
68 | pretty: false
69 | headers:
70 | 'Access-Control-Allow-Origin': '*'
71 | watch_options:
72 | ignored: '**/node_modules/**'
73 |
74 |
75 | test:
76 | <<: *default
77 | compile: true
78 |
79 | # Compile test packs to a separate directory
80 | public_output_path: packs-test
81 |
82 | production:
83 | <<: *default
84 |
85 | # Production depends on precompilation of packs prior to booting for performance.
86 | compile: false
87 |
88 | # Extract and emit a css file
89 | extract_css: true
90 |
91 | # Cache manifest.json for performance
92 | cache_manifest: true
93 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7 | # Character.create(name: 'Luke', movie: movies.first)
8 |
--------------------------------------------------------------------------------
/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/lib/assets/.keep
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/lib/tasks/.keep
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/log/.keep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rails-ansible-deploy",
3 | "private": true,
4 | "dependencies": {
5 | "@rails/actioncable": "^6.0.0",
6 | "@rails/activestorage": "^6.0.0",
7 | "@rails/ujs": "^6.0.0",
8 | "@rails/webpacker": "5.2.1",
9 | "turbolinks": "^5.2.0"
10 | },
11 | "version": "0.1.0",
12 | "devDependencies": {
13 | "webpack-dev-server": "^3.11.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-import'),
4 | require('postcss-flexbugs-fixes'),
5 | require('postcss-preset-env')({
6 | autoprefixer: {
7 | flexbox: 'no-2009'
8 | },
9 | stage: 3
10 | })
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/public/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/public/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 |
--------------------------------------------------------------------------------
/storage/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/storage/.keep
--------------------------------------------------------------------------------
/test/application_system_test_case.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
5 | end
6 |
--------------------------------------------------------------------------------
/test/channels/application_cable/connection_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
4 | # test "connects with cookies" do
5 | # cookies.signed[:user_id] = 42
6 | #
7 | # connect
8 | #
9 | # assert_equal connection.user_id, "42"
10 | # end
11 | end
12 |
--------------------------------------------------------------------------------
/test/controllers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/controllers/.keep
--------------------------------------------------------------------------------
/test/controllers/index_controller_test.rb:
--------------------------------------------------------------------------------
1 | require "test_helper"
2 |
3 | class IndexControllerTest < ActionDispatch::IntegrationTest
4 | # test "the truth" do
5 | # assert true
6 | # end
7 | end
8 |
--------------------------------------------------------------------------------
/test/fixtures/files/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/fixtures/files/.keep
--------------------------------------------------------------------------------
/test/helpers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/helpers/.keep
--------------------------------------------------------------------------------
/test/integration/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/integration/.keep
--------------------------------------------------------------------------------
/test/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/mailers/.keep
--------------------------------------------------------------------------------
/test/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/models/.keep
--------------------------------------------------------------------------------
/test/system/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/test/system/.keep
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | ENV['RAILS_ENV'] ||= 'test'
2 | require_relative "../config/environment"
3 | require "rails/test_help"
4 |
5 | class ActiveSupport::TestCase
6 | # Run tests in parallel with specified workers
7 | parallelize(workers: :number_of_processors)
8 |
9 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
10 | fixtures :all
11 |
12 | # Add more helper methods to be used by all tests here...
13 | end
14 |
--------------------------------------------------------------------------------
/test/workers/hard_worker_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 | class HardWorkerTest < Minitest::Test
3 | def test_example
4 | skip "add some examples to (or delete) #{__FILE__}"
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/tmp/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/tmp/.keep
--------------------------------------------------------------------------------
/tmp/pids/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/tmp/pids/.keep
--------------------------------------------------------------------------------
/vendor/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pedropaf/rails-ansible-provision-deployment/68b57fd549b58ea596a0badfaf929712d5e39d36/vendor/.keep
--------------------------------------------------------------------------------