{"id":20551695,"url":"https://github.com/do-community/do-blueprint-cachet","last_synced_at":"2025-03-06T05:47:34.798Z","repository":{"id":90797606,"uuid":"126081857","full_name":"do-community/do-blueprint-cachet","owner":"do-community","description":"Blueprint for setting up the Cachet status page app w/ MySQL database","archived":false,"fork":false,"pushed_at":"2018-04-27T19:03:02.000Z","size":46,"stargazers_count":9,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-16T17:01:00.502Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/do-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-20T21:00:49.000Z","updated_at":"2020-04-16T03:39:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"e9872997-996c-47aa-b315-2ea61dd60a86","html_url":"https://github.com/do-community/do-blueprint-cachet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/do-community%2Fdo-blueprint-cachet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/do-community%2Fdo-blueprint-cachet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/do-community%2Fdo-blueprint-cachet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/do-community%2Fdo-blueprint-cachet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/do-community","download_url":"https://codeload.github.com/do-community/do-blueprint-cachet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242157191,"owners_count":20081037,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T02:33:06.814Z","updated_at":"2025-03-06T05:47:34.771Z","avatar_url":"https://github.com/do-community.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Cachet Open Source Status Page w/ Let's Encrypt and a MySQL Database\n\nWelcome to the Cachet Blueprint repository. This repository can be used to quickly set up a status page for your application or business using [Cachet](https://cachethq.io/), an open source status page app written in [PHP](http://www.php.net/) using the [Laravel](https://laravel.com/) framework.\n\nThis process should take roughly thirty minutes.\n\nBy default, after cloning this project and executing the [Terraform](https://www.terraform.io/) and [Ansible](https://www.ansible.com/) steps described below, you will have an Ubuntu 16.04 database server running MySQL, connected to an Ubuntu 16.04 application server running the Cachet app with Nginx and PHP-FPM. The two servers will communicate over DigitalOcean's private network, with Cloud Firewalls set up to restrict access where appropriate. Nginx will be configured with SSL/TLS certificates using the [Let's Encrypt](https://letsencrypt.org/) certificate authority.\n\nAdditionally, local backups will be enabled using [`laravel-backup`](https://github.com/spatie/laravel-backup), with optional support for exporting backups to DigitalOcean's [Spaces](https://www.digitalocean.com/products/spaces/) object storage service.\n\n## Architecture\n\n\u003e **Note:** architecture diagram coming soon\n\n* 1 Cachet App Droplet\n\n  * Specs: 1 VCPU, 1GB memory, 25GB SSD\n  * Datacenter: NYC3\n  * OS: Ubuntu 16.04\n  * Software: Nginx, PHP-FPM, Certbot\n\n* 1 MySQL Database Droplet\n\n  * Specs: 1 VCPU, 1GB memory, and 25GB SSD\n  * Datacenter: NYC3\n  * OS: Ubuntu 16.04\n  * Software: MySQL\n\n* 1 Spaces Bucket (optional, but off-server backups are highly recommended)\n\nUsing the given Droplet sizes, and one Spaces bucket, **this infrastructure will cost $15 a month** to run.\n\n## Quickstart\n\nHere are the steps to get up and running.\n\n### Requirements\n\nThe software required to run DigitalOcean Blueprints is provided within a Docker image. You will need to install Docker locally to run these playbooks. You can find up-to-date instructions on how to download and install Docker on your computer [on the Docker website](https://www.docker.com/community-edition#/download).\n\nIf you'd prefer not to install Docker locally, you can create a dedicated control Droplet using the [DigitalOcean Docker One-click application](https://www.digitalocean.com/products/one-click-apps/docker/) instead. You will also need [Git](https://git-scm.com/downloads) installed.\n\n### Clone the Repo\n\nTo get started, clone this repository into a writeable directory on your Docker-enabled machine:\n\n```shell\ncd ~\ngit clone https://github.com/do-community/do-blueprint-cachet\n```\n\n### Add a Bash Alias for the Infrastructure Tools Docker Container\n\nOpen your shell configuration file using your preferred text editor:\n\n```shell\nnano ~/.bashrc\n```\n\nScroll to the bottom of the file and add the following `bp()` function and `complete` definition line:\n\n```shell\nfunction bp() {\n    docker run -it --rm \\\n    -v \"${PWD}\":\"/blueprint\" \\\n    -v \"${HOME}/.terraform.d\":\"/root/.terraform.d\" \\\n    -v \"${HOME}/.bp-ssh\":\"/root/.bp-ssh\" \\\n    -v \"${HOME}/.config\":\"/root/.config\" \\\n    -e ANSIBLE_TF_DIR='./terraform' \\\n    -e HOST_HOSTNAME=\"${HOSTNAME}\" \\\n    -e HOST_UID=$(id -u)\" \\\n    -e HOST_GID=$(id -g)\" \\\n    docommunity/bp \"$@\"\n}\n\ncomplete -W \"terraform doctl ./terraform.py ansible ansible-connection ansible-doc ansible-inventory ansible-pull ansible-config ansible-console ansible-galaxy ansible-playbook ansible-vault\" \"bp\"\n```\n\nThese additions will simplify a long and complicated Docker-based command line down to a simple `bp`.\n\nSave and close the file when you are finished. Source the file to load the new function into your current session:\n\n```\nsource ~/.bashrc\n```\n\nRun the Terraform command, prefixed by `bp`, to test the setup:\n\n```\nbp terraform -v\n```\n\nTerraform should output its version number. You are now ready to run the setup playbook.\n\n### Run the `setup.yml` Local Playbook\n\nNext, enter the directory created by `git clone`, and run the `setup.yml` playbook. This will configure the local repository and credentials.\n\n\u003e **Note:** The initial run of this playbook may show some warnings since the Ansible dynamic inventory script cannot yet find a valid state file from Terraform. This is expected and the warnings will not be present once a Terraform state file is created.\n\n```\ncd do-blueprint-cachet\nbp ansible-playbook setup.yml\n```\n\nEnter your DigitalOcean read/write API key if prompted (you can generate a read/write API key by visiting the [API section of the DigitalOcean Control Panel](https://cloud.digitalocean.com/settings/api/tokens) and clicking \"Generate New Token\"). Confirm the operation to create a dedicated SSH key pair by typing \"yes\" when prompted. As part of this configuration, a dedicated SSH key pair will be generated and added to your DigitalOcean account for managing Blueprints infrastructure.\n\nThe playbook will:\n\n* Check the `doctl` configuration to try to find an existing DigitalOcean API key\n* Prompt you to enter an API key if it could not find one in the `doctl` configuration\n* Check if a dedicated `~/.ssh/blueprint-id_rsa` SSH key pair is already available locally.\n* Generate the `~/.ssh/blueprint-id_rsa` key pair if required and add it to your DigitalOcean account.\n* Install the Terraform Ansible provider and the associated Ansible dynamic inventory script that allows Ansible to read from the Terraform state file\n* Generate a `terraform/terraform.tfvars` file with your DigitalOcean API key and SSH key defined\n* Initialize the `terraform` directory so that it's ready to use.\n* Install the Ansible roles needed to run the main playbook.\n\nOnce the setup.yml playbook has finished, follow the instructions in the final output to complete the configuration. Adjust the ownership of the generated SSH keys:\n\n```\nsudo chown $USER:$USER ~/.ssh/blueprint-id_rsa*\n```\n\nYou can optionally add the key to your local SSH agent:\n\n```\neval `ssh-agent`\nssh-add ~/.ssh/blueprint-id_rsa\n```\n\nOtherwise, when SSHing into your Blueprint infrastructure, you will need to pass in the appropriate SSH key using the -i flag:\n\n```\nssh -i ~/.ssh/blueprint-id_rsa \u003cusername\u003e@\u003cserver_ip\u003e\n```\n\nWith setup complete, we can create our actual Droplets, tags, and firewalls next.\n\n### Create the Infrastructure\n\nMove into the `terraform` directory. Adjust the `terraform.tfvars` and `main.tf` file if necessary. This is when you would adjust the choice of datacenter or the size of your Droplets, for instance (See **Customizing this Blueprint** at the end of this document for details).\n\nWhen you are ready, create your infrastructure with `terraform apply`:\n\n```shell\ncd terraform\nbp terraform apply\n```\n\nTerraform will output a list of actions it will take to create your infrastructure.\n\nType `yes`, then hit `ENTER` to confirm the operation.\n\nTerraform will create the necessary Droplets, tags, and firewalls. When finished it will output some status information, along with information about the IP addresses of our Cachet app server:\n\n```\nApply complete! Resources: 11 added, 0 changed, 0 destroyed.\n\nOutputs:\n\ncachet-app-public-ipv4-address = [\n    203.0.113.11\n]\ncachet-app-public-ipv6-address = [\n    2001:0DB8:0800:00a1:0000:0000:1456:e001\n]\n```\n\nNote both addresses. We will set up DNS entries for them next.\n\n### Create DNS Records\n\nBefore configuring the servers, you will need to create DNS records to point a domain name to the Cachet server. Throughout this Blueprint we will use the example domain of `status.example.com`.\n\nThe exact procedure to set up the correct DNS records will vary depending on your DNS provider. You'll need to create an `A` record pointing to the IPv4 address that was output in the previous step. Additionally, you should create an `AAAA` record for the IPv6 address.\n\nIf you are using DigitalOcean as your DNS provider, instructions for how to create these records can be found in our tutorial [How To Set Up a Host Name with DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean). If you are using a different DNS service provider, please refer to their documentation for more information.\n\n\u003e **Note:** It is possible to create DNS records using Terraform. However, in this case it is probably simpler/safer to do so manually. You can find more information about managing DNS records with Terraform at [the documentation for DigitalOcean's `record` resource](https://www.terraform.io/docs/providers/do/r/record.html) or [this list of Terraform-enabled DNS providers](https://www.terraform.io/docs/providers/type/network-index.html).\n\nWe must set up these DNS records before running the Ansible configuration step, because Let's Encrypt needs to verify that the Cachet server is responding at `status.example.com` before it will issue an SSL/TLS certificate.\n\n### Test Connectivity\n\nMove back up to the main repository directory. Use the `ansible -m ping` command to check whether the hosts are accessible yet:\n\n```shell\nbp ansible -m ping all\n```\n\nThis command will return failures if the servers are not yet accepting SSH connections or if the userdata script that installs Python has not yet completed. Run the command again until these failures disappear from all hosts.\n\n### Set Configuration Variables\n\nThis Blueprint has some configuration variables that need to be set before it will install and function properly. Mostly these have to do with setting up Cachet to use external mail and object storage services.\n\nAll of the variables we need to configure reside in the `group_vars` directory. This directory is split into subfolders for each Ansible host group: `all` for variables shared between all hosts, `cachet` for the Cachet host, and `mysql` for the database host.\n\nIn these directories you will see `vars.yml` files, and `vault.yml` files. `vars.yml` is for non-sensitive information, and `vault.yml` is where we put our secrets (passwords and tokens) and encrypt them. This is so we don't accidentally leak secrets to the public when using version control.\n\nHere is an overview of the directory, with some annotations after the files that need updating:\n\n```shell\ngroup_vars/\n├── all\n│   ├── vars.yml\n│   └── vault.yml # database passwords\n├── cachet\n│   ├── vars.yml  # general Cachet app configuration\n│   └── vault.yml # app key, mail and object storage passwords\n└── mysql\n    └── vars.yml\n```\n\nThe files all contain comments with details and example values for each variable. Work your way through the three files that need updating, filling out all necessary information. There should be no blank values when you're done, except for possibly the four `cachet_spaces_` variables — if you choose not to export your backups to Spaces — and the `cachet_mail_host` and `cachet_mail_port` variables if you're using a transactional mail service, as seen below.\n\n#### Example Mail Driver Configurations\n\nCachet uses a mail service to send out verification emails to your users, as well as status updates to those who've signed up to be emailed when updates are posted. The mail driver can be configured to use SMTP servers, transactional email services, or even a local log file. Two example configurations are shown below. For more detailed help please look at [the official Cachet mail configuration docs](https://docs.cachethq.io/docs/configuring-mail).\n\nAn SMTP-based configuration using Gmail (for example) would look like the following (this works for both regular Gmail and corporate Gsuite accounts):\n\n```yaml\ncachet_mail_driver: smtp\ncachet_mail_host: smtp.gmail.com\ncachet_mail_port: 587\ncachet_mail_username: username@example.com\ncachet_mail_password: \"{{ vault_cachet_mail_password }}\"\ncachet_mail_from_address: username@example.com\ncachet_mail_from_name: \"Example Status\"\ncachet_mail_encryption: tls\n```\n\nBe sure to add your password to the `vault_cachet_mail_password` variable in `group_vars/cachet/vault.yml` as well. If you use two-factor authentication with Gmail or Gsuite, you'll need to make an \"App password\" for this purpose. You can do so [here](https://security.google.com/settings/security/apppasswords).\n\nHere is a setup that uses the [Mailgun](https://www.mailgun.com/) transactional email service:\n\n```yaml\ncachet_mail_driver: mailgun\ncachet_mail_host:\ncachet_mail_port:\ncachet_mail_username: mail.example.com\ncachet_mail_password: \"{{ vault_cachet_mail_password }}\"\ncachet_mail_from_address: status@example.com\ncachet_mail_from_name: \"Example Status\"\ncachet_mail_encryption: tls\n```\n\nAgain, be sure to edit the `vault_cachet_mail_password` variable in `group_vars/cachet/vault.yml` as well. For Mailgun this will be an API token.\n\n#### Encrypting the Vault Files\n\nWhen all of your configuration is filled out, encrypt your vault files using `ansible-vault`:\n\n```shell\nbp ansible-vault encrypt group_vars/*/vault.yml\n```\n\nYou will be prompted twice for a password. Enter a strong password.\n\n\u003e **Note:** For more information on using Ansible Vault files, take a look at [the official Ansible Vault documentation](http://docs.ansible.com/ansible/latest/playbooks_vault.html). Many text editors have plugin support for vault files, so you can easily decrypt, edit then re-encrypt the files. You can also run `bp ansible-vault decrypt group_vars/*/vault.yml` to decrypt your vault files at any time.\n\n#### Running the Playbook\n\nWe are now ready to run the main Ansible Playbook. We will use the `ansible-playbook` command:\n\n```shell\nbp ansible-playbook site.yml --ask-vault-pass\n```\n\nYou will be prompted for your Vault password. After you enter it, Ansible will connect to the hosts and run the required tasks to set up the infrastructure.\n\n### Finishing the Deployment\n\nAfter the Droplets are set up, you'll still need to walk through Cachet's web-based setup. It's a short, three-step process where you'll choose some additional settings and set up a user account.\n\n\u003e **Important: Step 1 will ask you for some cache and mail driver information, _despite the fact that we've already configured this_**.\n\u003e\n\u003e Whatever you enter here will overwrite the configuration that Ansible just generated. Leave the **Cache Driver** and **Session Driver** settings as is (`APC(u)`), and fill in the mail settings with the same values entered in the previous step.\n\nThe following steps will prompt you for new information about time zones and language choices, then set up the first user. When done, you'll be taken to the Cachet dashboard. Your installation is finished!\n\n### Testing and Operating the Deployment\n\nOnce the infrastructure is configured, you can SSH into the Cachet server to check the setup. SSH into the host from the same computer as your Blueprint repository (this machine will have the correct SSH credentials):\n\n```shell\nssh -i ~/.ssh/blueprint-id_rsa root@your-cachet-droplet-ip-or-domain\n```\n\nThough any configuration changes should be done through Ansible, there are a few Laravel commands you might want to run on the server to operate your installation. First change to the Cachet directory:\n\n```shell\ncd /var/www/cachet\n```\n\nIt's a good idea to run the following commands as the **www-data** user. If there are any directories or logs inadvertently created as the **root** user it could cause errors later on. To run commands as **www-data** we will prepend them with `sudo -u www-data`.\n\nIf you're just trying out Cachet and want to load some sample data in the interface, you can use the following command to seed the database with demo data:\n\n```shell\nsudo -u www-data php artisan cachet:seed\n```\n\nTo manually run a backup, enter the following:\n\n```shell\nsudo -u www-data php artisan backup:run\n```\n\nYou can also list out your backups and their status with:\n\n```shell\nsudo -u www-data php artisan backup:list\n```\n\n### Deprovisioning the Infrastructure\n\nTo destroy all of the servers in this Blueprint, move into the `terraform` directory again and use the `destroy` action:\n\n```shell\ncd terraform\nbp terraform destroy\n```\n\nYou will be prompted to confirm the action. While you can easily spin up the infrastructure again using the Terraform and Ansible steps, keep in mind that any data you added will be lost when your Droplets are destroyed.\n\n## Ansible Roles\n\nThis repository uses the following role to configure the MySQL database server:\n\n* [MySQL role](https://github.com/geerlingguy/ansible-role-mysql)\n\nYou can read the README file associated with this role to understand how to adjust the configuration further.\n\n## Customizing this Blueprint\n\nYou can customize this Blueprint in a number of ways depending on your needs.\n\n### Modifying Infrastructure Scale\n\nThis infrastructure is designed to scale vertically. That is, if you need to serve more simultaneous users, you should choose a larger, more performant Droplet. As Cachet is not a database-heavy application, most of your compute power should be put into the application server.\n\n\u003e **Note:** Adjusting the scale will affect the cost of your deployment.\n\nTo adjust the scale of your infrastructure, open the `terraform/main.tf` file in a text editor:\n\n```shell\nnano terraform/main.tf\n```\n\nYou can change the `size` property of the `cachet_app` resource:\n\n```terraform\nresource \"digitalocean_droplet\" \"cachet_app\" {\n  . . .\n  size       = \"s-1vcpu-1gb\"\n  . . .\n```\n\nTo retrieve a list of possible Droplet sizes, use the `bp doctl compute size list` command.\n\n\u003e **Note:** If you update this property and rerun `bp terraform apply` on a live site, there will be some downtime as the Droplet is resized.\n\n### Restricting Management Firewall Rules\n\nYou could limit SSH access to only certain IPs, a jump or bastion host for instance, or your office IP range. To do so, open the `terraform/main.tf` file and update the `inbound_rule` block of the `digitalocean_firewall` `management` resource:\n\n```terraform\ninbound_rule = [\n  {\n    protocol         = \"tcp\"\n    port_range       = \"22\"\n    source_addresses = [\"0.0.0.0/0\", \"::/0\"]\n  },\n]\n```\n\nPut the correct address or range in place of the `0.0.0.0/0` catchall in `source_addresses`. If you've already provisioned your infrastructure, save the file and rerun `bp terraform apply` from the `terraform` directory to apply the changes.\n\n### Changing Datacenters\n\nTo launch this infrastructure in a different datacenter, again open the `terraform/main.tf` file. Update the `region` key of the two `digitalocean_droplet` resources. Both Droplets need to be in the same region, as private networking only works within one region.\n\nYou can list out all available regions using `doctl`:\n\n```\nbp doctl compute region list\n```\n\n### Changing Backup Timing\n\nBy default, your Cachet installation will create a new backup once a day, and will send an email if anything goes wrong. It will also monitor existing backup files and email with any problems. So if, for instance, you accidentally deleted your Spaces bucket, you would be notified of the issue.\n\nThis backup schedule is handled in the `roles/cachet/files/console-kernel.php` file in the Blueprint repository. Look for the `schedule` function if you want to adjust when these tasks run:\n\n```php\nprotected function schedule(Schedule $schedule)\n{\n    $schedule-\u003ecommand('queue:work --sleep=3 --tries=3')-\u003eeveryMinute();\n    $schedule-\u003ecommand('backup:clean')-\u003edaily()-\u003eat('01:43');\n    $schedule-\u003ecommand('backup:run')-\u003edaily()-\u003eat('02:24');\n    $schedule-\u003ecommand('backup:monitor')-\u003edaily()-\u003eat('05:19');\n}\n```\n\nThis function is kicked off every minute from an entry in the `www-data` user's crontab. The `queue:work` task handles the mail queue and should not be adjusted or removed.\n\n\u003e **Note:** after updating any files or templates in the `cachet` role, you'll need to rerun `bp ansible-playbook site.yml --ask-vault-pass` to push the changes to the server.\n\n## Common Issues\n\n### Let's Encrypt\n\nIf you get an error during the `Get Let's Encrypt certificate` Ansible task, there is most likely an issue with your DNS configuration. Either your records are not pointing to the correct IP address, or perhaps you updated an existing record and the changes are taking a while to propagate. Double-check the IP addresses you entered, or try the `ansible-playbook` command again after giving the DNS system some more time to update.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdo-community%2Fdo-blueprint-cachet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdo-community%2Fdo-blueprint-cachet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdo-community%2Fdo-blueprint-cachet/lists"}