diff --git a/README.md b/README.md index 70b2baa..39febe7 100644 --- a/README.md +++ b/README.md @@ -156,21 +156,62 @@ In the [github actions](.github/workflows/release.yaml) files, you can check tha Tracking the `mix.exs` version is essential to allow hot-upgrades. -### 7. HTTPS certificates +### 7. Setting Up HTTPS Certificates with Let's Encrypt -*__ATTENTION: For this step to work, be sure that the DNS is pointing to the EC2 instance.__* +*__Before proceeding, ensure that the DNS is correctly pointing to the EC2 instance__* For HTTPS, the project can set Free certificates from [Let's encrypt](https://letsencrypt.org/getting-started/). In this deployment, we are going to use the [cert bot for ubuntu](https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal): ```bash -sudo apt update -sudo apt install snapd -sudo snap install --classic certbot -sudo ln -s /snap/bin/certbot /usr/bin/certbot -sudo certbot --nginx +sudo su +apt update +apt install snapd +snap install --classic certbot +ln -s /snap/bin/certbot /usr/bin/certbot +certbot --nginx +``` + +This will install Certbot and automatically configure Nginx to use the obtained certificates. After Nginx finishes setup, it will create paths for the certificates. They will typically look like this: + +```bash +vi /etc/nginx/sites-available/default +... + ssl_certificate /etc/letsencrypt/live/calori.com.br/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/calori.com.br/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +``` + +It's possible that Nginx has modified the configuration file `/etc/nginx/sites-available/default` in a way that it won't work as expected. You'll need to retrieve the original file [nginx file](devops/terraform/modules/standard-account/cloud-config.tpl) and update it with the Let's Encrypt certificate paths. Find the section where it mentions: + +and where it mentions: + +```bash + # Add here the letsencrypt paths +``` +Replace this comment with the certificate paths obtained in the previous step. + +```bash + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_pass http://deployex; + } + ssl_certificate /etc/letsencrypt/live/calori.com.br/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/calori.com.br/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + } +``` + +Also, for both servers, re-enable port 443, e. g: + +```bash + server { + listen 443 ssl; # managed by Certbot ``` -Nginx will automatically generate certificates and modify your configuration files during installation. After installation, verify if the contents of the nginx configuration file match those specified in the original [nginx file ](devops/terraform/modules/standard-account/cloud-config.tpl). If any discrepancies are found, edit the file accordingly and restart Nginx to apply the changes. +After modifying the configuration file, save the changes and restart Nginx: ```bash sudo su @@ -179,6 +220,8 @@ vi /etc/nginx/sites-available/default systemctl reload nginx ``` +__PS: After the changes, It may require a reboot__ + The comands above will modify nginx file for the correct routing. Once it is all set, you need to check if the [runtime.exs](apps/calori/config/runtime.exs) is pointing to the correct SCHEME/HOST/PORT, e. g.: ```elixir @@ -202,10 +245,11 @@ Avoid the execute a hotupgrade in the following situations: #### 1. IEX shell Access to Deployex App -Connecting the iex shell: +To connect to the iex shell, you may need to export the cookie if AWS is configured with a value different from the default 'cookie', which is highly recommended to change. ```bash ubuntu@ip-10-0-1-56:~$ sudo su +root@ip-10-0-1-56:/home/ubuntu$ export RELEASE_COOKIE=COOKIE12345678912345789 root@ip-10-0-1-56:/home/ubuntu$ /opt/deployex/bin/deployex remote Erlang/OTP 26 [erts-14.2.1] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [jit:ns] @@ -215,15 +259,16 @@ iex(deployex@ip-10-0-1-56)1> ##### 2. IEX shell Access to Calori App -Connecting the iex shell: +To connect to the iex shell, you may need to export the cookie if AWS is configured with a value different from the default 'cookie', which is highly recommended to change. ```bash -root@ip-10-0-1-56:/home/ubuntu$ sudo -su deployex -deployex@ip-10-0-1-56:$ /var/lib/deployex/service/calori/current/bin/calori remote -Erlang/OTP 26 [erts-14.2.1] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [jit:ns] +ubuntu@ip-10-0-1-56:~$ sudo su +root@ip-10-0-1-56:/home/ubuntu$ export RELEASE_COOKIE=COOKIE12345678912345789 +root@ip-10-0-1-56:/home/ubuntu$ /var/lib/deployex/service/calori/current/bin/calori remote +Erlang/OTP 26 [erts-14.1.1] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [jit:ns] Interactive Elixir (1.16.0) - press Ctrl+C to exit (type h() ENTER for help) -iex(calori@ip-10-0-1-56)1> +iex(calori@ip-10-0-1-174)1> ``` ##### 3. Logs @@ -262,7 +307,7 @@ root@ip-10-0-1-56:/home/ubuntu$ tail -f /var/log/calori-stdout.log ##### 4. Updating CALORI_PHX_HOST -In case you need to update the *__CALORI_PHX_HOST__*, there are 2 files that need to be updated: `/etc/systemd/system/deployex.service` and `/etc/nginx/sites-available/default` (you need to be `root`` user to update them). +In case you need to update the *__CALORI_PHX_HOST__*, there are 2 files that need to be updated: `/etc/systemd/system/deployex.service` and `/etc/nginx/sites-available/default` (you need to be `root` user to update them). ```bash ubuntu@ip-10-0-1-56:~$ sudo su diff --git a/config/dev.exs b/config/dev.exs index 008a137..aad0c04 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -6,7 +6,7 @@ import Config # The watchers configuration can be used to run external # watchers to your application. For example, we can use it # to bundle .js and .css sources. -phx_port = String.to_integer(System.get_env("CALORI_PHX_PORT") || "4000") +phx_port = String.to_integer(System.get_env("PORT") || "4000") config :calori, CaloriWeb.Endpoint, # Binding to loopback ipv4 address prevents access from other machines. diff --git a/config/runtime.exs b/config/runtime.exs index 8bcda38..b6550ba 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -30,7 +30,7 @@ if config_env() == :prod do # to check this value into version control, so we use an environment # variable instead. host = System.get_env("CALORI_PHX_HOST") || "example.com" - port = String.to_integer(System.fetch_env!("CALORI_PHX_PORT")) + port = String.to_integer(System.fetch_env!("PORT")) config :calori, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") diff --git a/devops/terraform/environments/prod/main_example.tf_ b/devops/terraform/environments/prod/main_example.tf_ index d87c8fb..172f9e7 100644 --- a/devops/terraform/environments/prod/main_example.tf_ +++ b/devops/terraform/environments/prod/main_example.tf_ @@ -10,4 +10,5 @@ module "standard_account" { account_name = "stage" server_dns = "example.com" deployex_dns = "deployex.example.com" + replicas = "3" } diff --git a/devops/terraform/modules/standard-account/cloud-config.tpl b/devops/terraform/modules/standard-account/cloud-config.tpl index b6f8f87..1c2c846 100644 --- a/devops/terraform/modules/standard-account/cloud-config.tpl +++ b/devops/terraform/modules/standard-account/cloud-config.tpl @@ -22,7 +22,7 @@ write_files: # Check if the version was passed as an argument if [ -z "$1" ]; then # If not passed, use the default value - VERSION="0.2.0" + VERSION="0.3.0-rc1" else # If passed, use the passed value VERSION="$1" @@ -86,14 +86,14 @@ write_files: "timestamp_format": "%H: %M: %S%Y%b%-d" }, { - "file_path": "/var/log/calori-stdout.log", + "file_path": "/var/log/calori/calori-*-stdout.log", "log_group_name": "${log_group_name}", "log_stream_name": "{instance_id}-calori-stdout-log", "timezone": "UTC", "timestamp_format": "%H: %M: %S%Y%b%-d" }, { - "file_path": "/var/log/calori-stderr.log", + "file_path": "/var/log/calori/calori-*-stderr.log", "log_group_name": "${log_group_name}", "log_stream_name": "{instance_id}-calori-stderr-log", "timezone": "UTC", @@ -110,6 +110,8 @@ write_files: content: | upstream phoenix { server 127.0.0.1:4000 max_fails=5 fail_timeout=60s; + server 127.0.0.1:4001 max_fails=5 fail_timeout=60s; + server 127.0.0.1:4002 max_fails=5 fail_timeout=60s; } upstream deployex { @@ -132,10 +134,11 @@ write_files: return 404; # managed by Certbot } - server { + server { + #listen 443 ssl; # managed by Certbot server_name deployex.calori.com.br; - client_max_body_size 30M; + location / { allow all; @@ -151,17 +154,15 @@ write_files: proxy_pass http://deployex; } - - ssl_certificate /etc/letsencrypt/live/calori.com.br/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/calori.com.br/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + + # Add here the letsencrypt paths } server { + #listen 443 ssl; # managed by Certbot server_name calori.com.br; - client_max_body_size 30M; + location / { allow all; @@ -177,11 +178,7 @@ write_files: proxy_pass http://phoenix; } - - ssl_certificate /etc/letsencrypt/live/calori.com.br/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/calori.com.br/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + # Add here the letsencrypt paths } - path: /etc/systemd/system/deployex.service owner: root:root @@ -196,16 +193,13 @@ write_files: Environment=AWS_REGION=${aws_region} Environment=CALORI_PHX_HOST=${hostname} Environment=CALORI_PHX_SERVER=true - Environment=CALORI_PHX_PORT=4000 Environment=CALORI_CLOUD_ENVIRONMENT=${account_name} Environment=CALORI_OTP_TLS_CERT_PATH=/usr/local/share/ca-certificates Environment=DEPLOYEX_CLOUD_ENVIRONMENT=${account_name} Environment=DEPLOYEX_OTP_TLS_CERT_PATH=/usr/local/share/ca-certificates - Environment=DEPLOYEX_STORAGE_ADAPTER=s3 Environment=DEPLOYEX_MONITORED_APP_NAME=calori - Environment=DEPLOYEX_PHX_SERVER=true Environment=DEPLOYEX_PHX_HOST=${deployex_hostname} - Environment=DEPLOYEX_PHX_PORT=5001 + Environment=DEPLOYEX_MONITORED_REPLICAS=${replicas} ExecStart=/opt/deployex/bin/deployex start StandardOutput=append:/var/log/deployex.log KillMode=process @@ -232,10 +226,8 @@ runcmd: - mkdir /var/lib/deployex - chown deployex:deployex /var/lib/deployex - touch /var/log/deployex.log - - touch /var/log/calori-stdout.log - - touch /var/log/calori-stderr.log - - chown deployex:deployex /var/log/calori-stdout.log - - chown deployex:deployex /var/log/calori-stderr.log + - mkdir /var/log/calori/ + - chown deployex:deployex /var/log/calori/ - wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb - dpkg -i -E ./amazon-cloudwatch-agent.deb - /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ubuntu/config.json -s diff --git a/devops/terraform/modules/standard-account/ec2.tf b/devops/terraform/modules/standard-account/ec2.tf index e9068bb..3996f79 100644 --- a/devops/terraform/modules/standard-account/ec2.tf +++ b/devops/terraform/modules/standard-account/ec2.tf @@ -95,6 +95,7 @@ data "cloudinit_config" "server_config" { log_group_name = aws_cloudwatch_log_group.ec2_instance_logs.name account_name = "${var.account_name}" aws_region = "${var.aws_region}" + replicas = "${var.replicas}" }) } } diff --git a/devops/terraform/modules/standard-account/variables.tf b/devops/terraform/modules/standard-account/variables.tf index ed76a81..64b3d51 100644 --- a/devops/terraform/modules/standard-account/variables.tf +++ b/devops/terraform/modules/standard-account/variables.tf @@ -8,6 +8,16 @@ variable "server_dns" { nullable = false } +variable "deployex_dns" { + type = string + nullable = false +} + +variable "replicas" { + type = string + nullable = false +} + # ec2 key pair name variable "aws_key_name" { default = "calori-web-ec2" diff --git a/lib/calori_web/components/core_components.ex b/lib/calori_web/components/core_components.ex index f534035..488b6af 100644 --- a/lib/calori_web/components/core_components.ex +++ b/lib/calori_web/components/core_components.ex @@ -678,21 +678,27 @@ defmodule CaloriWeb.CoreComponents do @doc """ Copied/Modified from https://fullstackphoenix.com/tutorials/tailwind-navbar-new-liveview-0-18-components """ - attr :name, :string, default: "Calori App" + attr :name, :string, default: "Calori Software" def logo(assigns) do ~H""" - + + + + + + + @@ -702,6 +708,7 @@ defmodule CaloriWeb.CoreComponents do end slot :logo + slot(:link, required: true) do attr :to, :string attr :label, :string diff --git a/lib/calori_web/components/layouts/app.html.heex b/lib/calori_web/components/layouts/app.html.heex index ccd17bf..3c48711 100644 --- a/lib/calori_web/components/layouts/app.html.heex +++ b/lib/calori_web/components/layouts/app.html.heex @@ -6,17 +6,25 @@ <:link label="Home" to={~p"/home"} /> - <:link label="About" to={~p"/home"} /> + <:link label="Supervisor" to={~p"/supervisor"} />
-
+
<.flash_group flash={@flash} /> <%= @inner_content %>
+ +
diff --git a/lib/calori_web/components/layouts/root.html.heex b/lib/calori_web/components/layouts/root.html.heex index fa54287..7902584 100644 --- a/lib/calori_web/components/layouts/root.html.heex +++ b/lib/calori_web/components/layouts/root.html.heex @@ -4,8 +4,8 @@ - <.live_title suffix=" · Beam"> - <%= assigns[:page_title] || "Calori" %> + <.live_title suffix=""> + <%= assigns[:page_title] || "Calori Software" %>